#include #include #include #include #include #include #include #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(desc_set_type)) return(nullptr); DescriptorSet *ds=CreateDS(pld,desc_set_type); if(!ds)return(nullptr); #ifdef _DEBUG const UTF8String addr_string=HexToString((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 &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;ivalue; 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 为128MB,AMD显卡为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