ULRE/src/SceneGraph/render/RenderAssignBuffer.cpp

233 lines
5.5 KiB
C++

#include"RenderAssignBuffer.h"
#include<hgl/graph/VKVertexAttribBuffer.h>
#include<hgl/graph/VKDevice.h>
#include<hgl/graph/VKMaterialInstance.h>
#include<hgl/graph/SceneNode.h>
#include<hgl/graph/RenderNode.h>
#include<hgl/graph/Mesh.h>
#include<hgl/graph/VKRenderAssign.h>
#include<hgl/graph/mtl/UBOCommon.h>
VK_NAMESPACE_BEGIN
RenderAssignBuffer::RenderAssignBuffer(VulkanDevice *dev,Material *mtl)
{
hgl_zero(*this);
device=dev;
material=mtl;
mi_data_bytes=mtl->GetMIDataBytes();
LW2_MAX_COUNT=dev->GetUBORange()/sizeof(Matrix4f);
l2w_buffer_max_count=0;
l2w_buffer=nullptr;
mi_buffer=nullptr;
}
void RenderAssignBuffer::Bind(Material *mtl)const
{
if(!mtl)return;
mtl->BindUBO(&mtl::SBS_LocalToWorld, l2w_buffer);
mtl->BindUBO(&mtl::SBS_MaterialInstance, mi_buffer);
}
void RenderAssignBuffer::Clear()
{
SAFE_CLEAR(l2w_buffer);
SAFE_CLEAR(mi_buffer);
SAFE_CLEAR(assign_vab);
}
void RenderAssignBuffer::StatL2W(const RenderNodeList &rn_list)
{
if(!l2w_buffer)
{
l2w_buffer_max_count=power_to_2(rn_list.GetCount());
}
else if(rn_list.GetCount()>l2w_buffer_max_count)
{
l2w_buffer_max_count=power_to_2(rn_list.GetCount());
SAFE_CLEAR(l2w_buffer);
}
if(!l2w_buffer)
{
l2w_buffer=device->CreateUBO(sizeof(Matrix4f)*l2w_buffer_max_count);
#ifdef _DEBUG
DebugUtils *du=device->GetDebugUtils();
if(du)
{
du->SetBuffer(l2w_buffer->GetBuffer(),"UBO:Buffer:LocalToWorld");
du->SetDeviceMemory(l2w_buffer->GetVkMemory(),"UBO:Memory:LocalToWorld");
}
#endif//_DEBUG
}
RenderNode *rn=rn_list.GetData();
Matrix4f *l2wp=(Matrix4f *)(l2w_buffer->DeviceBuffer::Map());
for(int i=0;i<rn_list.GetCount();i++)
{
*l2wp=rn->scene_node->GetLocalToWorldMatrix();
++l2wp;
++rn;
}
l2w_buffer->Unmap();
}
void RenderAssignBuffer::UpdateLocalToWorld(const RenderNodePointerList &rnp_list,const int first,const int last)
{
if(!l2w_buffer)
return;
if(rnp_list.IsEmpty())
return;
const uint count=rnp_list.GetCount();
RenderNode **rn=rnp_list.GetData();
Matrix4f *l2wp=(Matrix4f *)(l2w_buffer->DeviceBuffer::Map( sizeof(Matrix4f)*first,
sizeof(Matrix4f)*(last-first+1)));
for(uint i=0;i<count;i++)
{
l2wp[(*rn)->l2w_index-first]=(*rn)->scene_node->GetLocalToWorldMatrix();
++rn;
}
l2w_buffer->Unmap();
}
void RenderAssignBuffer::UpdateMaterialInstance(const RenderNode *rn)
{
if(!rn)
return;
AssignData *adp=(AssignData *)(assign_vab->DeviceBuffer::Map(sizeof(AssignData)*rn->index,sizeof(AssignData)));
adp->mi=mi_set.Find(rn->scene_node->GetRenderable()->GetMaterialInstance());
assign_vab->Unmap();
}
void RenderAssignBuffer::StatMI(const RenderNodeList &rn_list)
{
mi_set.Clear();
if(mi_data_bytes<=0) //没有材质实例数据
return;
if(!mi_buffer)
{
mi_set.PreAlloc(power_to_2(rn_list.GetCount()));
}
else if(rn_list.GetCount()>mi_set.GetAllocCount())
{
mi_set.PreAlloc(power_to_2(rn_list.GetCount()));
SAFE_CLEAR(mi_buffer);
}
if(!mi_buffer)
{
mi_buffer=device->CreateUBO(mi_data_bytes*mi_set.GetAllocCount());
#ifdef _DEBUG
DebugUtils *du=device->GetDebugUtils();
if(du)
{
du->SetBuffer(mi_buffer->GetBuffer(),"UBO:Buffer:MaterialInstanceData");
du->SetDeviceMemory(mi_buffer->GetVkMemory(),"UBO:Memory:MaterialInstanceData");
}
#endif//_DEBUG
}
mi_set.PreAlloc(rn_list.GetCount());
for(RenderNode &rn:rn_list)
mi_set.Add(rn.scene_node->GetRenderable()->GetMaterialInstance());
if(mi_set.GetCount()>material->GetMIMaxCount())
{
//超出最大数量了怎么办???
}
//合并材质实例数据
{
uint8 *mip=(uint8 *)(mi_buffer->Map());
for(MaterialInstance *mi:mi_set)
{
memcpy(mip,mi->GetMIData(),mi_data_bytes);
mip+=mi_data_bytes;
}
mi_buffer->Unmap();
}
}
void RenderAssignBuffer::WriteNode(const RenderNodeList &rn_list)
{
if(rn_list.GetCount()<=0)
return;
StatL2W(rn_list);
StatMI(rn_list);
{
if(!assign_vab)
{
node_count=power_to_2(rn_list.GetCount());
}
else if(node_count<rn_list.GetCount())
{
node_count=power_to_2(rn_list.GetCount());
SAFE_CLEAR(assign_vab);
}
if(!assign_vab)
{
assign_vab=device->CreateVAB(ASSIGN_VAB_FMT,node_count);
assign_buffer=assign_vab->GetBuffer();
#ifdef _DEBUG
DebugUtils *du=device->GetDebugUtils();
if(du)
{
du->SetBuffer(assign_vab->GetBuffer(),"VAB:Buffer:AssignData");
du->SetDeviceMemory(assign_vab->GetVkMemory(),"VAB:Memory:AssignData");
}
#endif//_DEBUG
}
}
//生成材质实例ID列表
{
RenderNode *rn=rn_list.GetData();
AssignData *adp=(AssignData *)(assign_vab->DeviceBuffer::Map());
for(uint i=0;i<rn_list.GetCount();i++)
{
rn->l2w_index=i;
adp->l2w=i;
adp->mi=mi_set.Find(rn->scene_node->GetRenderable()->GetMaterialInstance());
++adp;
++rn;
}
assign_vab->Unmap();
}
}
VK_NAMESPACE_END