ULRE/src/SceneGraph/Vulkan/VKDeviceMaterial.cpp

153 lines
4.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include<hgl/graph/VKDevice.h>
#include<hgl/graph/VKMaterial.h>
#include<hgl/graph/VKMaterialDescriptorManager.h>
#include<hgl/graph/VKMaterialParameters.h>
#include<hgl/graph/VKDescriptorSet.h>
#include<hgl/graph/VKShaderModuleMap.h>
#include<hgl/graph/VKVertexInputLayout.h>
#include"VKPipelineLayoutData.h"
VK_NAMESPACE_BEGIN
DescriptorSet *GPUDevice::CreateDS(const PipelineLayoutData *pld,const DescriptorSetType &type)const
{
RANGE_CHECK_RETURN_NULLPTR(type);
const uint32_t binding_count=pld->binding_count[size_t(type)];
if(!binding_count)
return(nullptr);
DescriptorSetAllocateInfo alloc_info;
alloc_info.descriptorPool = attr->desc_pool;
alloc_info.descriptorSetCount = 1;
alloc_info.pSetLayouts = pld->layouts+size_t(type);
VkDescriptorSet desc_set;
if(vkAllocateDescriptorSets(attr->device,&alloc_info,&desc_set)!=VK_SUCCESS)
return(nullptr);
return(new DescriptorSet(attr->device,binding_count,pld->pipeline_layout,desc_set));
}
MaterialParameters *GPUDevice::CreateMP(const MaterialDescriptorManager *desc_manager,const PipelineLayoutData *pld,const DescriptorSetType &desc_set_type)
{
if(!desc_manager||!pld)return(nullptr);
if(!RangeCheck<DescriptorSetType>(desc_set_type))
return(nullptr);
DescriptorSet *ds=CreateDS(pld,desc_set_type);
if(!ds)return(nullptr);
#ifdef _DEBUG
const UTF8String addr_string=HexToString<char,uint64_t>((uint64_t)(ds->GetDescriptorSet()));
LOG_INFO(U8_TEXT("Create [DescriptSets:")+addr_string+("] OK! Material Name: \"")+desc_manager->GetMaterialName()+U8_TEXT("\" Type: ")+GetDescriptorSetTypeName(desc_set_type));
#endif//_DEBUG
return(new MaterialParameters(desc_manager,desc_set_type,ds));
}
MaterialParameters *GPUDevice::CreateMP(Material *mtl,const DescriptorSetType &desc_set_type)
{
if(!mtl)return(nullptr);
return CreateMP(mtl->GetDescriptorSets(),mtl->GetPipelineLayoutData(),desc_set_type);
}
void CreateShaderStageList(List<VkPipelineShaderStageCreateInfo> &shader_stage_list,ShaderModuleMap *shader_maps)
{
const ShaderModule *sm;
const int shader_count=shader_maps->GetCount();
shader_stage_list.SetCount(shader_count);
VkPipelineShaderStageCreateInfo *p=shader_stage_list.GetData();
auto **itp=shader_maps->GetDataList();
for(int i=0;i<shader_count;i++)
{
sm=(*itp)->value;
hgl_cpy(p,sm->GetCreateInfo(),1);
++p;
++itp;
}
}
Material *GPUDevice::CreateMaterial(const UTF8String &mtl_name,ShaderModuleMap *shader_maps,MaterialDescriptorManager *desc_manager,VertexInput *vi)
{
const int shader_count=shader_maps->GetCount();
if(shader_count<1)
return(nullptr);
PipelineLayoutData *pld=CreatePipelineLayoutData(desc_manager);
if(!pld)
{
delete shader_maps;
SAFE_CLEAR(desc_manager);
return(nullptr);
}
MaterialData *data=new MaterialData;
data->name =mtl_name;
data->shader_maps =shader_maps;
data->desc_manager =desc_manager;
data->vertex_input =vi;
CreateShaderStageList(data->shader_stage_list,shader_maps);
data->pipeline_layout_data=pld;
if(desc_manager)
{
ENUM_CLASS_FOR(DescriptorSetType,int,dst)
{
if(desc_manager->hasSet((DescriptorSetType)dst))
data->mp_array[dst]=CreateMP(desc_manager,pld,(DescriptorSetType)dst);
else
data->mp_array[dst]=nullptr;
}
}
else
hgl_zero(data->mp_array);
const VkDeviceSize ubo_range=this->GetUBORange();
// ubo_range大致分为三档:
//
// 16k: Mali-T系列或更早、Mali-G71、nVidia GeForce RTX 3070 Laptop为16k
//
// 64k: 大部分手机与PC均为64k
//
// >64k: Intel 核显与 PowerVR 为128MBAMD显卡为4GB可视为随显存无上限。
//
// 我们使用uint8类型在vertex input中保存MaterialInstance ID表示范围0-255。
// 所以MaterialInstance结构容量按16k/64k分为两个档次64字节和256字节
// 如果一定要使用超过16K/64K硬件限制的容量有两种办法
// 一、分多次渲染使用UBO Offset偏移UBO数据区。
// 二、使用SSBO但这样会导致性能下降所以不推荐使用。
// 但只要我们限制一个MI数据不超过64/256字节一次渲染不超过256种材质实例就无需解决此问题。
if(desc_manager->hasSet(DescriptorSetType::PerMaterial))
{
data->mi_size
data->mi_data=new uint8[data->mi_size*256];
}
else
{
data->mi_size=0;
data->mi_data=nullptr;
}
return(new Material(data));
}
VK_NAMESPACE_END