diff --git a/inc/hgl/graph/MaterialRenderList.h b/inc/hgl/graph/MaterialRenderList.h index 5f6980c6..1534291a 100644 --- a/inc/hgl/graph/MaterialRenderList.h +++ b/inc/hgl/graph/MaterialRenderList.h @@ -3,7 +3,8 @@ #include VK_NAMESPACE_BEGIN -class RenderAssignBuffer; +class RenderL2WBuffer; +class RenderMIBuffer; /** * 同一材质的对象渲染列表 @@ -19,7 +20,8 @@ class MaterialRenderList private: - RenderAssignBuffer *assign_buffer; + RenderL2WBuffer *l2w_buffer; + RenderMIBuffer *mi_buffer; struct RenderItem { @@ -39,8 +41,6 @@ private: DataArray ri_array; uint ri_count; - bool has_l2w; - bool has_mi; VkDeviceSize l2w_buffer_size[4]; void StatMI(); diff --git a/src/SceneGraph/MaterialRenderList.cpp b/src/SceneGraph/MaterialRenderList.cpp index 1a8908fe..9d347a9d 100644 --- a/src/SceneGraph/MaterialRenderList.cpp +++ b/src/SceneGraph/MaterialRenderList.cpp @@ -53,13 +53,15 @@ MaterialRenderList::MaterialRenderList(GPUDevice *d,bool l2w,Material *m) cmd_buf=nullptr; material=m; - has_l2w=l2w; - has_mi=material->HasMI(); - - if(has_l2w||has_mi) - assign_buffer=new RenderAssignBuffer(d,has_l2w,material->GetMIDataBytes()); + if(l2w) + l2w_buffer=new RenderL2WBuffer(device); else - assign_buffer=nullptr; + l2w_buffer=nullptr; + + if(material->HasMI()) + mi_buffer=new RenderMIBuffer(device,material->GetMIDataBytes()); + else + mi_buffer=nullptr; vbo_list=new VBOList(material->GetVertexInput()->GetCount()); } @@ -67,7 +69,8 @@ MaterialRenderList::MaterialRenderList(GPUDevice *d,bool l2w,Material *m) MaterialRenderList::~MaterialRenderList() { SAFE_CLEAR(vbo_list); - SAFE_CLEAR(assign_buffer) + SAFE_CLEAR(mi_buffer); + SAFE_CLEAR(l2w_buffer); } void MaterialRenderList::Add(Renderable *ri,const Matrix4f &mat) @@ -91,13 +94,15 @@ void MaterialRenderList::End() Stat(); - if(assign_buffer) + if(l2w_buffer) { - if(has_mi) - StatMI(); + l2w_buffer->WriteNode(rn_list.GetData(),node_count); + } - //写入LocalToWorld数据 - assign_buffer->WriteNode(rn_list.GetData(),node_count,mi_set); + if(mi_buffer) + { + StatMI(); + mi_buffer->WriteNode(rn_list.GetData(),node_count,mi_set); } } @@ -182,16 +187,16 @@ bool MaterialRenderList::Bind(const VertexInputData *vid,const uint ri_index) vbo_list->Add(vid->buffer_list,vid->buffer_offset,vid->binding_count); } - if(has_l2w)//LocalToWorld组,由RenderList合成 + if(l2w_buffer)//LocalToWorld组,由RenderList合成 { for(uint i=0;i<4;i++) l2w_buffer_size[i]=ri_index*16; //mat4每列都是rgba32f,自然是16字节 - vbo_list->Add(assign_buffer->GetLocalToWorldVBO(),l2w_buffer_size,4); + vbo_list->Add(l2w_buffer->GetVBO(),l2w_buffer_size,4); } - if(has_mi) //材质实例组 - vbo_list->Add(assign_buffer->GetMIVBO(),MI_VBO_STRIDE_BYTES*ri_index); + if(mi_buffer) //材质实例组 + vbo_list->Add(mi_buffer->GetVBO(),MI_VBO_STRIDE_BYTES*ri_index); //if(!vbo_list.IsFull()) //Joint组,暂未支持 //{ @@ -281,8 +286,8 @@ void MaterialRenderList::Render(RenderCmdBuffer *rcb) last_pipeline =nullptr; last_vid =nullptr; - if(assign_buffer) - assign_buffer->Bind(material); + if(mi_buffer) + mi_buffer->Bind(material); cmd_buf->BindDescriptorSets(material); diff --git a/src/SceneGraph/RenderAssignBuffer.cpp b/src/SceneGraph/RenderAssignBuffer.cpp index 16b039a7..332d1b01 100644 --- a/src/SceneGraph/RenderAssignBuffer.cpp +++ b/src/SceneGraph/RenderAssignBuffer.cpp @@ -8,37 +8,21 @@ #include VK_NAMESPACE_BEGIN -RenderAssignBuffer::RenderAssignBuffer(GPUDevice *dev,const bool has_l2w,const uint mi_bytes) +RenderL2WBuffer::RenderL2WBuffer(GPUDevice *dev) { hgl_zero(*this); device=dev; - - mi_data_bytes=mi_bytes; } -void RenderAssignBuffer::Bind(Material *mtl)const +void RenderL2WBuffer::Clear() { - if(!mtl)return; - - if(!mtl->HasMI()) - return; - - mtl->BindUBO(DescriptorSetType::PerMaterial,mtl::SBS_MaterialInstance.name,ubo_mi); -} - -void RenderAssignBuffer::Clear() -{ - SAFE_CLEAR(ubo_mi); - SAFE_CLEAR(vbo_mi); - SAFE_CLEAR(l2w_vbo[0]) SAFE_CLEAR(l2w_vbo[1]) SAFE_CLEAR(l2w_vbo[2]) SAFE_CLEAR(l2w_vbo[3]) node_count=0; - mi_count=0; } #ifdef _DEBUG @@ -62,7 +46,7 @@ namespace } #endif//_DEBUG -void RenderAssignBuffer::Alloc(const uint nc,const uint mc) +void RenderL2WBuffer::Alloc(const uint nc) { Clear(); @@ -76,6 +60,78 @@ void RenderAssignBuffer::Alloc(const uint nc,const uint mc) } } +#ifdef _DEBUG + DebugUtils *du=device->GetDebugUtils(); + + if(du) + { + for(int i=0;i<4;i++) + { + du->SetBuffer(l2w_buffer[i],l2w_buffer_name[i]); + du->SetDeviceMemory(l2w_vbo[i]->GetVkMemory(),l2w_memory_name[i]); + } + } +#endif//_DEBUG +} + +void RenderL2WBuffer::WriteNode(RenderNode *render_node,const uint count) +{ + RenderNode *rn; + + Alloc(count); + + glm::vec4 *tp; + + for(uint col=0;col<4;col++) + { + tp=(glm::vec4 *)(l2w_vbo[col]->Map()); + + rn=render_node; + + for(uint i=0;ilocal_to_world[col]; + ++tp; + ++rn; + } + + l2w_vbo[col]->Unmap(); + } +} +VK_NAMESPACE_END + +VK_NAMESPACE_BEGIN +RenderMIBuffer::RenderMIBuffer(GPUDevice *dev,const uint mi_bytes) +{ + hgl_zero(*this); + + device=dev; + + mi_data_bytes=mi_bytes; +} + +void RenderMIBuffer::Bind(Material *mtl)const +{ + if(!mtl)return; + + mtl->BindUBO(DescriptorSetType::PerMaterial,mtl::SBS_MaterialInstance.name,ubo_mi); +} + +void RenderMIBuffer::Clear() +{ + SAFE_CLEAR(ubo_mi); + SAFE_CLEAR(vbo_mi); + + mi_count=0; + node_count=0; +} + +void RenderMIBuffer::Alloc(const uint nc,const uint mc) +{ + Clear(); + + node_count=nc; + if(mi_data_bytes>0&&mc>0) { mi_count=mc; @@ -91,84 +147,45 @@ void RenderAssignBuffer::Alloc(const uint nc,const uint mc) if(du) { - if(l2w_buffer[0]) - { - for(int i=0;i<4;i++) - { - du->SetBuffer(l2w_buffer[i],l2w_buffer_name[i]); - du->SetDeviceMemory(l2w_vbo[i]->GetVkMemory(),l2w_memory_name[i]); - } - } + du->SetBuffer(ubo_mi->GetBuffer(),"UBO:Buffer:MaterialInstance"); + du->SetDeviceMemory(ubo_mi->GetVkMemory(),"UBO:Memory:MaterialInstance"); - if(ubo_mi) - { - du->SetBuffer(ubo_mi->GetBuffer(),"UBO:Buffer:MaterialInstance"); - du->SetDeviceMemory(ubo_mi->GetVkMemory(),"UBO:Memory:MaterialInstance"); - } - - if(vbo_mi) - { - du->SetBuffer(vbo_mi->GetBuffer(),"VBO:Buffer:MaterialInstanceID"); - du->SetDeviceMemory(vbo_mi->GetVkMemory(),"VBO:Memory:MaterialInstanceID"); - } + du->SetBuffer(vbo_mi->GetBuffer(),"VBO:Buffer:MaterialInstanceID"); + du->SetDeviceMemory(vbo_mi->GetVkMemory(),"VBO:Memory:MaterialInstanceID"); } #endif//_DEBUG } -void RenderAssignBuffer::WriteNode(RenderNode *render_node,const uint count,const MaterialInstanceSets &mi_set) +void RenderMIBuffer::WriteNode(RenderNode *render_node,const uint count,const MaterialInstanceSets &mi_set) { RenderNode *rn; Alloc(count,mi_set.GetCount()); - if(l2w_buffer[0]) + uint8 *mip=(uint8 *)(ubo_mi->Map()); + + for(MaterialInstance *mi:mi_set) { - glm::vec4 *tp; + memcpy(mip,mi->GetMIData(),mi_data_bytes); + mip+=mi_data_bytes; + } - for(uint col=0;col<4;col++) + ubo_mi->Unmap(); + + uint16 *idp=(uint16 *)(vbo_mi->Map()); + + { + rn=render_node; + + for(uint i=0;iMap()); + *idp=mi_set.Find(rn->ri->GetMaterialInstance()); + ++idp; - rn=render_node; - - for(uint i=0;ilocal_to_world[col]; - ++tp; - ++rn; - } - - l2w_vbo[col]->Unmap(); + ++rn; } } - if(ubo_mi) - { - uint8 *mip=(uint8 *)(ubo_mi->Map()); - - for(MaterialInstance *mi:mi_set) - { - memcpy(mip,mi->GetMIData(),mi_data_bytes); - mip+=mi_data_bytes; - } - - ubo_mi->Unmap(); - - uint16 *idp=(uint16 *)(vbo_mi->Map()); - - { - rn=render_node; - - for(uint i=0;iri->GetMaterialInstance()); - ++idp; - - ++rn; - } - } - - vbo_mi->Unmap(); - } + vbo_mi->Unmap(); } VK_NAMESPACE_END diff --git a/src/SceneGraph/RenderAssignBuffer.h b/src/SceneGraph/RenderAssignBuffer.h index 4a10593a..a4a45695 100644 --- a/src/SceneGraph/RenderAssignBuffer.h +++ b/src/SceneGraph/RenderAssignBuffer.h @@ -25,13 +25,8 @@ VK_NAMESPACE_BEGIN struct RenderNode; class MaterialInstance; -/* -* 渲染节点额外提供的数据 -*/ -class RenderAssignBuffer +class RenderL2WBuffer { -private: - GPUDevice *device; uint node_count; ///<渲染节点数量 @@ -39,6 +34,35 @@ private: VBO *l2w_vbo[4]; VkBuffer l2w_buffer[4]; +private: + + void Alloc(const uint nc); + + void Clear(); + +public: + + const VkBuffer *GetVBO()const{return l2w_buffer;} + +public: + + RenderL2WBuffer(GPUDevice *dev); + ~RenderL2WBuffer(){Clear();} + + void WriteNode(RenderNode *render_node,const uint count); +};//class RenderL2WBuffer + +/* +* 渲染节点额外提供的数据 +*/ +class RenderMIBuffer +{ +private: + + GPUDevice *device; + + uint node_count; ///<渲染节点数量 + uint32_t mi_data_bytes; ///<材质实例数据字节数 uint32_t mi_count; ///<材质实例数量 DeviceBuffer *ubo_mi; ///<材质实例数据 @@ -54,17 +78,20 @@ private: public: - const VkBuffer *GetLocalToWorldVBO()const{return l2w_buffer;} - const VkBuffer GetMIVBO ()const{return mi_buffer;} + const VkBuffer GetVBO()const{return mi_buffer;} void Bind(Material *)const; public: - RenderAssignBuffer(GPUDevice *dev,const bool has_l2w,const uint32_t mi_bytes); - ~RenderAssignBuffer(){Clear();} + RenderMIBuffer(GPUDevice *dev,const uint32_t mi_bytes); + ~RenderMIBuffer(){Clear();} - void WriteNode(RenderNode *render_node,const uint count,const MaterialInstanceSets &mi_set); + //下一代,将MaterialInstanceSets使用提前化,这样不用每一次绘制都重新写入MI DATA,可以提升效率。 + //虽然这样就不自动化了,但我们要的就是不自动化。 + //必须在外部全部准备好MaterialInstanceSets,然后一次性写入。 + //渲染时找不到就直接用0号材质实例 -};//struct RenderAssignBuffer + void WriteNode(RenderNode *render_node,const uint nc,const MaterialInstanceSets &mi_set); +};//struct RenderMIBuffer VK_NAMESPACE_END