resume Assign instead of local2world and materialinstanceId in VertexInputStream

This commit is contained in:
hyzboy 2024-05-25 17:58:39 +08:00
parent 08a348392d
commit a5e76988c7
23 changed files with 293 additions and 318 deletions

2
CMCore

@ -1 +1 @@
Subproject commit 3d27b60c13162ac2167cc84e9846088a18664312 Subproject commit d70d31288f601061a69f93b4970af6692e53a34b

@ -1 +1 @@
Subproject commit f220bd8370781f791b3c3a27bd7daa4dc96817e6 Subproject commit a6a368031209ce23dc14e88acf45dd8298a19886

View File

@ -64,7 +64,7 @@ private:
bool InitVertexLumMP() bool InitVertexLumMP()
{ {
mtl::Material3DCreateConfig cfg(device->GetDeviceAttribute(),"VertexLuminance3D",Prim::Lines); mtl::Material3DCreateConfig cfg(device->GetDeviceAttribute(),"VertexLuminance3D",false,Prim::Lines);
cfg.local_to_world=true; cfg.local_to_world=true;
@ -92,7 +92,7 @@ private:
bool InitBlinnPhongSunLightMP() bool InitBlinnPhongSunLightMP()
{ {
mtl::Material3DCreateConfig cfg(device->GetDeviceAttribute(),"BlinnPhong3D",Prim::Triangles); mtl::Material3DCreateConfig cfg(device->GetDeviceAttribute(),"BlinnPhong3D",true,Prim::Triangles);
cfg.local_to_world=true; cfg.local_to_world=true;

View File

@ -4,7 +4,7 @@
VK_NAMESPACE_BEGIN VK_NAMESPACE_BEGIN
class RenderL2WBuffer; class RenderL2WBuffer;
class RenderMIBuffer; class RenderAssignBuffer;
/** /**
* *
@ -20,8 +20,7 @@ class MaterialRenderList
private: private:
RenderL2WBuffer *l2w_buffer; RenderAssignBuffer *assign_buffer;
RenderMIBuffer *mi_buffer;
struct RenderItem struct RenderItem
{ {
@ -37,13 +36,9 @@ private:
void Set(Renderable *); void Set(Renderable *);
}; };
MaterialInstanceSets mi_set;
DataArray<RenderItem> ri_array; DataArray<RenderItem> ri_array;
uint ri_count; uint ri_count;
VkDeviceSize l2w_buffer_size[4];
void StatMI();
void Stat(); void Stat();
protected: protected:

View File

@ -16,7 +16,7 @@ struct Material2DCreateConfig:public MaterialCreateConfig
public: public:
Material2DCreateConfig(const GPUDeviceAttribute *da,const AnsiString &name,const Prim &p):MaterialCreateConfig(da,name,p) Material2DCreateConfig(const GPUDeviceAttribute *da,const AnsiString &name,const bool &mi,const Prim &p):MaterialCreateConfig(da,name,mi,p)
{ {
rt_output.color=1; //输出一个颜色 rt_output.color=1; //输出一个颜色
rt_output.depth=false; //不输出深度 rt_output.depth=false; //不输出深度

View File

@ -17,7 +17,7 @@ struct Material3DCreateConfig:public MaterialCreateConfig
public: public:
Material3DCreateConfig(const GPUDeviceAttribute *da,const AnsiString &name,const Prim &p):MaterialCreateConfig(da,name,p) Material3DCreateConfig(const GPUDeviceAttribute *da,const AnsiString &name,const bool &mi,const Prim &p):MaterialCreateConfig(da,name,mi,p)
{ {
rt_output.color=1; //输出一个颜色 rt_output.color=1; //输出一个颜色
rt_output.depth=true; //不输出深度 rt_output.depth=true; //不输出深度

View File

@ -19,6 +19,8 @@ struct MaterialCreateConfig
AnsiString mtl_name; ///<材质名称 AnsiString mtl_name; ///<材质名称
bool material_instance; ///<是否包含材质实例
RenderTargetOutputConfig rt_output; ///<渲染目标输出配置 RenderTargetOutputConfig rt_output; ///<渲染目标输出配置
uint32 shader_stage_flag_bit; ///<需要的shader uint32 shader_stage_flag_bit; ///<需要的shader
@ -27,12 +29,14 @@ struct MaterialCreateConfig
public: public:
MaterialCreateConfig(const GPUDeviceAttribute *da,const AnsiString &name,const Prim &p) MaterialCreateConfig(const GPUDeviceAttribute *da,const AnsiString &name,const bool mi,const Prim &p)
{ {
dev_attr=da; dev_attr=da;
mtl_name=name; mtl_name=name;
material_instance=mi;
shader_stage_flag_bit=VK_SHADER_STAGE_VERTEX_BIT|VK_SHADER_STAGE_FRAGMENT_BIT; shader_stage_flag_bit=VK_SHADER_STAGE_VERTEX_BIT|VK_SHADER_STAGE_FRAGMENT_BIT;
prim=p; prim=p;

View File

@ -5,12 +5,14 @@
#define STD_MTL_NAMESPACE_BEGIN namespace hgl{namespace graph{namespace mtl{ #define STD_MTL_NAMESPACE_BEGIN namespace hgl{namespace graph{namespace mtl{
#define STD_MTL_NAMESPACE_END }}} #define STD_MTL_NAMESPACE_END }}}
#define STD_MTL_NAMESPACE_USING using namespace hgl::graph::mtl; #define STD_MTL_NAMESPACE hgl::graph::mtl
#define STD_MTL_NAMESPACE_USING using namespace STD_MTL_NAMESPACE;
#define STD_MTL_FUNC_NAMESPACE_BEGIN namespace hgl{namespace graph{namespace mtl{namespace func{ #define STD_MTL_FUNC_NAMESPACE_BEGIN namespace hgl{namespace graph{namespace mtl{namespace func{
#define STD_MTL_FUNC_NAMESPACE_END }}}} #define STD_MTL_FUNC_NAMESPACE_END }}}}
#define STD_MTL_FUNC NAMESPACE_USING using namespace hgl::graph::mtl::func; #define STD_MTL_FUNC_NAMESPACE hgl::graph::mtl::func
#define STD_MTL_FUNC_NAMESPACE_USING using namespace STD_MTL_FUNC_NAMESPACE;
namespace hgl namespace hgl
{ {

View File

@ -42,10 +42,24 @@ constexpr const ShaderBufferSource SBS_CameraInfo=
float znear,zfar;)" float znear,zfar;)"
}; };
constexpr const char LocalToWorldStruct[]="LocalToWorld";
constexpr const DescriptorSetType DST_LocalToWorld=DescriptorSetType::PerFrame;
constexpr const ShaderBufferSource SBS_LocalToWorld=
{
"LocalToWorldData",
"l2w",
R"(
mat4 mats[L2W_MAX_COUNT];
)"
};
// UBO必须严格指定数组的大小 // UBO必须严格指定数组的大小
// SSBO则不需要使用[]方式指定为动态大小数组 // SSBO则不需要使用[]方式指定为动态大小数组
constexpr const char MaterialInstanceStruct[]="MaterialInstance"; constexpr const char MaterialInstanceStruct[]="MaterialInstance";
constexpr const DescriptorSetType DST_MaterialInstance=DescriptorSetType::PerMaterial;
constexpr const ShaderBufferSource SBS_MaterialInstance= constexpr const ShaderBufferSource SBS_MaterialInstance=
{ {

View File

@ -1,4 +1,4 @@
#pragma once #pragma once
#include<hgl/shadergen/MaterialDescriptorInfo.h> #include<hgl/shadergen/MaterialDescriptorInfo.h>
#include<hgl/shadergen/ShaderCreateInfoVertex.h> #include<hgl/shadergen/ShaderCreateInfoVertex.h>
@ -33,7 +33,9 @@ namespace hgl{namespace graph
uint32_t mi_max_count; uint32_t mi_max_count;
UBODescriptor *mi_ubo; UBODescriptor *mi_ubo;
uint32_t l2w_max_count;
uint32_t l2w_shader_stage; uint32_t l2w_shader_stage;
UBODescriptor *l2w_ubo;
ShaderCreateInfoMap shader_map; ///<着色器列表 ShaderCreateInfoMap shader_map; ///<着色器列表

View File

@ -21,8 +21,7 @@ namespace hgl
int hasInput(const char *); int hasInput(const char *);
void AddLocalToWorld(); void AddAssign();
void AddMaterialInstanceID();
void AddJoint(); void AddJoint();
};//class ShaderCreateInfoVertex:public ShaderCreateInfo };//class ShaderCreateInfoVertex:public ShaderCreateInfo

View File

@ -53,15 +53,7 @@ MaterialRenderList::MaterialRenderList(GPUDevice *d,bool l2w,Material *m)
cmd_buf=nullptr; cmd_buf=nullptr;
material=m; material=m;
if(l2w) assign_buffer=new RenderAssignBuffer(device,material);
l2w_buffer=new RenderL2WBuffer(device);
else
l2w_buffer=nullptr;
if(material->HasMI())
mi_buffer=new RenderMIBuffer(device,material->GetMIDataBytes());
else
mi_buffer=nullptr;
vbo_list=new VBOList(material->GetVertexInput()->GetCount()); vbo_list=new VBOList(material->GetVertexInput()->GetCount());
} }
@ -69,8 +61,7 @@ MaterialRenderList::MaterialRenderList(GPUDevice *d,bool l2w,Material *m)
MaterialRenderList::~MaterialRenderList() MaterialRenderList::~MaterialRenderList()
{ {
SAFE_CLEAR(vbo_list); SAFE_CLEAR(vbo_list);
SAFE_CLEAR(mi_buffer); SAFE_CLEAR(assign_buffer);
SAFE_CLEAR(l2w_buffer);
} }
void MaterialRenderList::Add(Renderable *ri,const Matrix4f &mat) void MaterialRenderList::Add(Renderable *ri,const Matrix4f &mat)
@ -94,16 +85,8 @@ void MaterialRenderList::End()
Stat(); Stat();
if(l2w_buffer) if(assign_buffer)
{ assign_buffer->WriteNode(rn_list);
l2w_buffer->WriteNode(rn_list.GetData(),node_count);
}
if(mi_buffer)
{
StatMI();
mi_buffer->WriteNode(rn_list.GetData(),node_count,mi_set);
}
} }
void MaterialRenderList::RenderItem::Set(Renderable *ri) void MaterialRenderList::RenderItem::Set(Renderable *ri)
@ -113,19 +96,6 @@ void MaterialRenderList::RenderItem::Set(Renderable *ri)
vid =ri->GetVertexInputData(); vid =ri->GetVertexInputData();
} }
void MaterialRenderList::StatMI()
{
mi_set.Clear();
for(RenderNode &rn:rn_list)
mi_set.Add(rn.ri->GetMaterialInstance());
if(mi_set.GetCount()>material->GetMIMaxCount())
{
//超出最大数量了怎么办???
}
}
void MaterialRenderList::Stat() void MaterialRenderList::Stat()
{ {
const uint count=rn_list.GetCount(); const uint count=rn_list.GetCount();
@ -187,16 +157,8 @@ bool MaterialRenderList::Bind(const VertexInputData *vid,const uint ri_index)
vbo_list->Add(vid->buffer_list,vid->buffer_offset,vid->binding_count); vbo_list->Add(vid->buffer_list,vid->buffer_offset,vid->binding_count);
} }
if(l2w_buffer)//LocalToWorld组由RenderList合成 if(assign_buffer) //L2W/MI分发组
{ vbo_list->Add(assign_buffer->GetVAB(),ASSIGN_VAB_STRIDE_BYTES*ri_index);
for(uint i=0;i<4;i++)
l2w_buffer_size[i]=ri_index*16; //mat4每列都是rgba32f自然是16字节
vbo_list->Add(l2w_buffer->GetVBO(),l2w_buffer_size,4);
}
if(mi_buffer) //材质实例组
vbo_list->Add(mi_buffer->GetVBO(),MI_VAB_STRIDE_BYTES*ri_index);
//if(!vbo_list.IsFull()) //Joint组暂未支持 //if(!vbo_list.IsFull()) //Joint组暂未支持
//{ //{
@ -282,8 +244,8 @@ void MaterialRenderList::Render(RenderCmdBuffer *rcb)
last_pipeline =nullptr; last_pipeline =nullptr;
last_vid =nullptr; last_vid =nullptr;
if(mi_buffer) if(assign_buffer)
mi_buffer->Bind(material); assign_buffer->Bind(material);
cmd_buf->BindDescriptorSets(material); cmd_buf->BindDescriptorSets(material);

View File

@ -8,184 +8,186 @@
#include<hgl/graph/mtl/UBOCommon.h> #include<hgl/graph/mtl/UBOCommon.h>
VK_NAMESPACE_BEGIN VK_NAMESPACE_BEGIN
RenderL2WBuffer::RenderL2WBuffer(GPUDevice *dev) RenderAssignBuffer::RenderAssignBuffer(GPUDevice *dev,Material *mtl)
{
hgl_zero(*this);
device=dev;
}
void RenderL2WBuffer::Clear()
{
SAFE_CLEAR(l2w_vbo[0])
SAFE_CLEAR(l2w_vbo[1])
SAFE_CLEAR(l2w_vbo[2])
SAFE_CLEAR(l2w_vbo[3])
node_count=0;
}
#ifdef _DEBUG
namespace
{
constexpr const char *l2w_buffer_name[]=
{
"VAB:Buffer:LocalToWorld:0",
"VAB:Buffer:LocalToWorld:1",
"VAB:Buffer:LocalToWorld:2",
"VAB:Buffer:LocalToWorld:3"
};
constexpr const char *l2w_memory_name[]=
{
"VAB:Memory:LocalToWorld:0",
"VAB:Memory:LocalToWorld:1",
"VAB:Memory:LocalToWorld:2",
"VAB:Memory:LocalToWorld:3"
};
}
#endif//_DEBUG
void RenderL2WBuffer::Alloc(const uint nc)
{
Clear();
{
node_count=nc;
for(uint i=0;i<4;i++)
{
l2w_vbo[i]=device->CreateVAB(VF_V4F,node_count);
l2w_buffer[i]=l2w_vbo[i]->GetBuffer();
}
}
#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]->DeviceBuffer::Map());
rn=render_node;
for(uint i=0;i<count;i++)
{
*tp=rn->local_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); hgl_zero(*this);
device=dev; device=dev;
mi_data_bytes=mi_bytes; 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 RenderMIBuffer::Bind(Material *mtl)const void RenderAssignBuffer::Bind(Material *mtl)const
{ {
if(!mtl)return; if(!mtl)return;
mtl->BindUBO(DescriptorSetType::PerMaterial,mtl::SBS_MaterialInstance.name,mi_data_buffer); mtl->BindUBO(mtl::DST_LocalToWorld, mtl::SBS_LocalToWorld.name, l2w_buffer);
mtl->BindUBO(mtl::DST_MaterialInstance, mtl::SBS_MaterialInstance.name, mi_buffer);
} }
void RenderMIBuffer::Clear() void RenderAssignBuffer::Clear()
{ {
SAFE_CLEAR(mi_data_buffer); SAFE_CLEAR(l2w_buffer);
SAFE_CLEAR(mi_vab); SAFE_CLEAR(mi_buffer);
SAFE_CLEAR(assign_vab);
mi_count=0;
node_count=0;
} }
void RenderMIBuffer::Alloc(const uint nc,const uint mc) void RenderAssignBuffer::StatL2W(const RenderNodeList &rn_list)
{ {
Clear(); if(!l2w_buffer)
node_count=nc;
if(mi_data_bytes>0&&mc>0)
{ {
mi_count=mc; l2w_buffer_max_count=power_to_2(rn_list.GetCount());
}
mi_data_buffer=device->CreateUBO(mi_data_bytes*mi_count); else if(rn_list.GetCount()>l2w_buffer_max_count)
{
l2w_buffer_max_count=power_to_2(rn_list.GetCount());
SAFE_CLEAR(l2w_buffer);
} }
mi_vab=device->CreateVAB(MI_VAB_FMT,node_count); if(!l2w_buffer)
mi_buffer=mi_vab->GetBuffer(); {
l2w_buffer=device->CreateUBO(sizeof(Matrix4f)*l2w_buffer_max_count);
#ifdef _DEBUG #ifdef _DEBUG
DebugUtils *du=device->GetDebugUtils(); DebugUtils *du=device->GetDebugUtils();
if(du) if(du)
{ {
du->SetBuffer(mi_data_buffer->GetBuffer(),"UBO:Buffer:MaterialInstance"); du->SetBuffer(l2w_buffer->GetBuffer(),"UBO:Buffer:LocalToWorld");
du->SetDeviceMemory(mi_data_buffer->GetVkMemory(),"UBO:Memory:MaterialInstance"); du->SetDeviceMemory(l2w_buffer->GetVkMemory(),"UBO:Memory:LocalToWorld");
du->SetBuffer(mi_vab->GetBuffer(),"VAB:Buffer:MaterialInstanceID");
du->SetDeviceMemory(mi_vab->GetVkMemory(),"VAB:Memory:MaterialInstanceID");
} }
#endif//_DEBUG #endif//_DEBUG
}
void RenderMIBuffer::WriteNode(RenderNode *render_node,const uint count,const MaterialInstanceSets &mi_set)
{
RenderNode *rn;
Alloc(count,mi_set.GetCount());
uint8 *mip=(uint8 *)(mi_data_buffer->Map());
for(MaterialInstance *mi:mi_set)
{
memcpy(mip,mi->GetMIData(),mi_data_bytes);
mip+=mi_data_bytes;
} }
mi_data_buffer->Unmap(); RenderNode *rn=rn_list.GetData();
Matrix4f *l2wp=(Matrix4f *)(l2w_buffer->DeviceBuffer::Map());
uint16 *idp=(uint16 *)(mi_vab->DeviceBuffer::Map()); for(uint i=0;i<rn_list.GetCount();i++)
{
*l2wp=rn->local_to_world;
++l2wp;
++rn;
}
l2w_buffer->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.ri->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);
{ {
rn=render_node; if(!assign_vab)
for(uint i=0;i<count;i++)
{ {
*idp=mi_set.Find(rn->ri->GetMaterialInstance()); node_count=power_to_2(rn_list.GetCount());
++idp; }
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++)
{
adp->l2w=i;
adp->mi=mi_set.Find(rn->ri->GetMaterialInstance());
++adp;
++rn; ++rn;
} }
}
mi_vab->Unmap(); assign_vab->Unmap();
}
} }
VK_NAMESPACE_END VK_NAMESPACE_END

View File

@ -16,6 +16,7 @@ VK_NAMESPACE_BEGIN
// 如果一定要使用超过16K/64K硬件限制的容量有两种办法 // 如果一定要使用超过16K/64K硬件限制的容量有两种办法
// 一、分多次渲染使用UBO Offset偏移UBO数据区。 // 一、分多次渲染使用UBO Offset偏移UBO数据区。
// 二、使用SSBO但这样会导致性能下降所以不推荐使用。 // 二、使用SSBO但这样会导致性能下降所以不推荐使用。
// 三、使用纹理保存材质实例数据,但这样会导致性能下降,所以不推荐使用。
// 但我们不解决这个问题 // 但我们不解决这个问题
// 我们天然要求将材质实例数据分为两个等级同时要求一次渲染不能超过256种材质实例。 // 我们天然要求将材质实例数据分为两个等级同时要求一次渲染不能超过256种材质实例。
@ -25,73 +26,71 @@ VK_NAMESPACE_BEGIN
struct RenderNode; struct RenderNode;
class MaterialInstance; class MaterialInstance;
class RenderL2WBuffer
{
GPUDevice *device;
uint node_count; ///<渲染节点数量
VAB *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 class RenderAssignBuffer
{ {
struct AssignData
{
uint16 l2w;
uint16 mi;
};
uint LW2_MAX_COUNT;
private: private:
GPUDevice *device; GPUDevice *device;
uint node_count; ///<渲染节点数量 Material *material;
uint32_t mi_data_bytes; ///<材质实例数据字节数 private: //LocalToWorld矩阵数据
uint32_t mi_count; ///<材质实例数量
DeviceBuffer *mi_data_buffer; ///<材质实例数据(UBO/SSBO)
VAB *mi_vab; ///<材质实例ID(R16UI格式) uint32 l2w_buffer_max_count; ///<LocalToWorld矩阵最大数量
VkBuffer mi_buffer; DeviceBuffer *l2w_buffer; ///<LocalToWorld矩阵数据(UBO/SSBO)
void StatL2W(const RenderNodeList &);
private: //材质实例数据
MaterialInstanceSets mi_set;
uint32_t mi_data_bytes; ///<单个材质实例数据字节数
DeviceBuffer *mi_buffer; ///<材质实例数据(UBO/SSBO)
void StatMI(const RenderNodeList &);
private: //分发数据
uint32 node_count; ///<节点数量
VAB *assign_vab; ///<分发数据VAB(RG16UI格式R存L2W IDG存材质实例ID)
VkBuffer assign_buffer; ///<分发数据Buffer
private: private:
void Alloc(const uint nc,const uint mc);
void Clear(); void Clear();
public: public:
const VkBuffer GetVBO()const{return mi_buffer;} const VkBuffer GetVAB()const{return assign_buffer;}
void Bind(Material *)const; void Bind(Material *)const;
public: public:
RenderMIBuffer(GPUDevice *dev,const uint32_t mi_bytes); RenderAssignBuffer(GPUDevice *dev,Material *);
~RenderMIBuffer(){Clear();} ~RenderAssignBuffer(){Clear();}
//下一代将MaterialInstanceSets使用提前化这样不用每一次绘制都重新写入MI DATA可以提升效率。 //下一代将MaterialInstanceSets使用提前化这样不用每一次绘制都重新写入MI DATA可以提升效率。
//虽然这样就不自动化了,但我们要的就是不自动化。 //虽然这样就不自动化了,但我们要的就是不自动化。
//必须在外部全部准备好MaterialInstanceSets然后一次性写入。 //必须在外部全部准备好MaterialInstanceSets然后一次性写入。
//渲染时找不到就直接用0号材质实例 //渲染时找不到就直接用0号材质实例
void WriteNode(RenderNode *render_node,const uint nc,const MaterialInstanceSets &mi_set); //同样的LocalToWorld矩阵也可以提前化处理这样对于静态物体就只需要写入一次LocalToWorld矩阵了。
};//struct RenderMIBuffer
void WriteNode(const RenderNodeList &);
};//struct RenderAssignBuffer
VK_NAMESPACE_END VK_NAMESPACE_END

View File

@ -39,7 +39,7 @@ void main()
if(!Std2DMaterial::CustomVertexShader(vsc)) if(!Std2DMaterial::CustomVertexShader(vsc))
return(false); return(false);
vsc->AddMaterialInstanceID(); vsc->AddAssign();
vsc->SetMain(vs_main); vsc->SetMain(vs_main);
return(true); return(true);
} }

View File

@ -1,4 +1,4 @@
#include"Std2DMaterial.h" #include"Std2DMaterial.h"
#include<hgl/shadergen/MaterialCreateInfo.h> #include<hgl/shadergen/MaterialCreateInfo.h>
#include<hgl/graph/mtl/Material2DCreateConfig.h> #include<hgl/graph/mtl/Material2DCreateConfig.h>
#include<hgl/graph/mtl/UBOCommon.h> #include<hgl/graph/mtl/UBOCommon.h>
@ -14,9 +14,17 @@ bool Std2DMaterial::CustomVertexShader(ShaderCreateInfoVertex *vsc)
const bool is_rect=(cfg->prim==Prim::SolidRectangles||cfg->prim==Prim::WireRectangles); const bool is_rect=(cfg->prim==Prim::SolidRectangles||cfg->prim==Prim::WireRectangles);
if(cfg->local_to_world||cfg->material_instance)
{
mci->AddStruct(SBS_LocalToWorld);
mci->AddUBO(VK_SHADER_STAGE_ALL_GRAPHICS,DescriptorSetType::PerFrame,SBS_LocalToWorld);
vsc->AddAssign();
}
if(cfg->local_to_world) if(cfg->local_to_world)
{ {
vsc->AddLocalToWorld();
mci->SetLocalToWorld(VK_SHADER_STAGE_ALL_GRAPHICS); mci->SetLocalToWorld(VK_SHADER_STAGE_ALL_GRAPHICS);
if(is_rect) if(is_rect)

View File

@ -16,7 +16,7 @@ namespace
public: public:
Std2DMaterialLoader(material_file::MaterialFileData *data,const Material2DCreateConfig *cfg):Std2DMaterial(cfg) Std2DMaterialLoader(material_file::MaterialFileData *data,const Material2DCreateConfig *c):Std2DMaterial(c)
{ {
mfd=data; mfd=data;
} }
@ -76,9 +76,6 @@ namespace
for(auto &ua:mfd->vi) for(auto &ua:mfd->vi)
vsc->AddInput(ua.vat,ua.name); vsc->AddInput(ua.vat,ua.name);
if(mfd->mi.mi_bytes>0)
vsc->AddMaterialInstanceID();
if(!Std2DMaterial::CustomVertexShader(vsc)) if(!Std2DMaterial::CustomVertexShader(vsc))
return(false); return(false);

View File

@ -1,4 +1,4 @@
#include"Std3DMaterial.h" #include"Std3DMaterial.h"
#include<hgl/shadergen/MaterialCreateInfo.h> #include<hgl/shadergen/MaterialCreateInfo.h>
#include<hgl/graph/mtl/Material3DCreateConfig.h> #include<hgl/graph/mtl/Material3DCreateConfig.h>
#include<hgl/graph/mtl/UBOCommon.h> #include<hgl/graph/mtl/UBOCommon.h>
@ -11,6 +11,15 @@ bool Std3DMaterial::CustomVertexShader(ShaderCreateInfoVertex *vsc)
{ {
vsc->AddInput(cfg->position_format,VAN::Position); vsc->AddInput(cfg->position_format,VAN::Position);
if(cfg->camera||cfg->local_to_world||cfg->material_instance)
{
mci->AddStruct(SBS_LocalToWorld);
mci->AddUBO(VK_SHADER_STAGE_ALL_GRAPHICS,DescriptorSetType::PerFrame,SBS_LocalToWorld);
vsc->AddAssign();
}
if(cfg->camera) if(cfg->camera)
{ {
mci->AddStruct(SBS_CameraInfo); mci->AddStruct(SBS_CameraInfo);
@ -24,7 +33,6 @@ bool Std3DMaterial::CustomVertexShader(ShaderCreateInfoVertex *vsc)
{ {
mci->SetLocalToWorld(VK_SHADER_STAGE_ALL_GRAPHICS); mci->SetLocalToWorld(VK_SHADER_STAGE_ALL_GRAPHICS);
vsc->AddLocalToWorld();
vsc->AddFunction(cfg->camera?func::GetPosition3DL2WCamera:func::GetPosition3DL2W); vsc->AddFunction(cfg->camera?func::GetPosition3DL2WCamera:func::GetPosition3DL2W);
} }
else else

View File

@ -16,8 +16,8 @@ namespace
public: public:
Std3DMaterialLoader(material_file::MaterialFileData *data,const Material3DCreateConfig *cfg) Std3DMaterialLoader(material_file::MaterialFileData *data,const Material3DCreateConfig *c)
: Std3DMaterial(cfg) : Std3DMaterial(c)
{ {
mfd=data; mfd=data;
} }
@ -77,9 +77,6 @@ namespace
for(auto &ua:mfd->vi) for(auto &ua:mfd->vi)
vsc->AddInput(ua.vat,ua.name); vsc->AddInput(ua.vat,ua.name);
if(mfd->mi.mi_bytes>0)
vsc->AddMaterialInstanceID();
if(!Std3DMaterial::CustomVertexShader(vsc)) if(!Std3DMaterial::CustomVertexShader(vsc))
return (false); return (false);

View File

@ -172,9 +172,9 @@ bool MaterialCreateInfo::SetMaterialInstance(const AnsiString &glsl_codes,const
mi_ubo=CreateUBODescriptor(SBS_MaterialInstance,shader_stage_flag_bits); mi_ubo=CreateUBODescriptor(SBS_MaterialInstance,shader_stage_flag_bits);
mdi.AddUBO(shader_stage_flag_bits,DescriptorSetType::PerMaterial,mi_ubo); mdi.AddUBO(shader_stage_flag_bits,DST_MaterialInstance,mi_ubo);
const AnsiString MI_MAX_COUNT=AnsiString::numberOf(mi_max_count); const AnsiString MI_MAX_COUNT_STRING=AnsiString::numberOf(mi_max_count);
auto *it=shader_map.GetDataList(); auto *it=shader_map.GetDataList();
@ -182,7 +182,7 @@ bool MaterialCreateInfo::SetMaterialInstance(const AnsiString &glsl_codes,const
{ {
if((*it)->key&shader_stage_flag_bits) if((*it)->key&shader_stage_flag_bits)
{ {
(*it)->value->AddDefine("MI_MAX_COUNT",MI_MAX_COUNT); (*it)->value->AddDefine("MI_MAX_COUNT",MI_MAX_COUNT_STRING);
(*it)->value->SetMaterialInstance(mi_ubo,mi_codes); (*it)->value->SetMaterialInstance(mi_ubo,mi_codes);
} }
@ -198,6 +198,28 @@ bool MaterialCreateInfo::SetLocalToWorld(const uint32_t shader_stage_flag_bits)
{ {
if(shader_stage_flag_bits==0)return(false); if(shader_stage_flag_bits==0)return(false);
l2w_max_count=hgl_min<uint32_t>(ubo_range/sizeof(Matrix4f),HGL_U16_MAX);
mdi.AddStruct(SBS_LocalToWorld);
l2w_ubo=CreateUBODescriptor(SBS_LocalToWorld,shader_stage_flag_bits);
mdi.AddUBO(shader_stage_flag_bits,DST_LocalToWorld,l2w_ubo);
const AnsiString L2W_MAX_COUNT_STRING=AnsiString::numberOf(l2w_max_count);
auto *it=shader_map.GetDataList();
for(int i=0;i<shader_map.GetCount();i++)
{
if((*it)->key&shader_stage_flag_bits)
{
(*it)->value->AddDefine("L2W_MAX_COUNT",L2W_MAX_COUNT_STRING);
}
++it;
}
l2w_shader_stage=shader_stage_flag_bits; l2w_shader_stage=shader_stage_flag_bits;
return(true); return(true);

View File

@ -156,10 +156,11 @@ bool ShaderCreateInfo::ProcSubpassInput()
namespace namespace
{ {
constexpr const char MF_GetMI_VS []="\nMaterialInstance GetMI(){return mtl.mi[MaterialInstanceID];}\n"; constexpr const char MI_ID_OUTPUT[]="MaterialInstanceID";
constexpr const char MF_GetMI_VS []="\nMaterialInstance GetMI(){return mtl.mi[Assign.y];}\n";
constexpr const char MF_GetMI_Other []="\nMaterialInstance GetMI(){return mtl.mi[Input.MaterialInstanceID];}\n"; constexpr const char MF_GetMI_Other []="\nMaterialInstance GetMI(){return mtl.mi[Input.MaterialInstanceID];}\n";
constexpr const char MF_HandoverMI_VS[]= "\nvoid HandoverMI(){Output.MaterialInstanceID=MaterialInstanceID;}\n"; constexpr const char MF_HandoverMI_VS[]= "\nvoid HandoverMI(){Output.MaterialInstanceID=Assign.y;}\n";
constexpr const char MF_HandoverMI_GS[]= "\nvoid HandoverMI(){Output.MaterialInstanceID=Input[0].MaterialInstanceID;}\n"; constexpr const char MF_HandoverMI_GS[]= "\nvoid HandoverMI(){Output.MaterialInstanceID=Input[0].MaterialInstanceID;}\n";
constexpr const char MF_HandoverMI_OTHER[]= "\nvoid HandoverMI(){Output.MaterialInstanceID=Input.MaterialInstanceID;}\n"; constexpr const char MF_HandoverMI_OTHER[]= "\nvoid HandoverMI(){Output.MaterialInstanceID=Input.MaterialInstanceID;}\n";
}//namespace }//namespace
@ -176,7 +177,7 @@ void ShaderCreateInfo::SetMaterialInstance(UBODescriptor *ubo,const AnsiString &
void ShaderCreateInfo::AddMaterialInstanceOutput() void ShaderCreateInfo::AddMaterialInstanceOutput()
{ {
AddOutput(VAT_UINT,mtl::func::MaterialInstanceID,Interpolation::Flat); AddOutput(VAT_UINT,MI_ID_OUTPUT,Interpolation::Flat);
if(shader_stage==VK_SHADER_STAGE_VERTEX_BIT) AddFunction(MF_HandoverMI_VS);else if(shader_stage==VK_SHADER_STAGE_VERTEX_BIT) AddFunction(MF_HandoverMI_VS);else
if(shader_stage==VK_SHADER_STAGE_GEOMETRY_BIT) AddFunction(MF_HandoverMI_GS);else if(shader_stage==VK_SHADER_STAGE_GEOMETRY_BIT) AddFunction(MF_HandoverMI_GS);else

View File

@ -1,4 +1,4 @@
#include<hgl/shadergen/ShaderCreateInfoVertex.h> #include<hgl/shadergen/ShaderCreateInfoVertex.h>
#include<hgl/shadergen/ShaderDescriptorInfo.h> #include<hgl/shadergen/ShaderDescriptorInfo.h>
#include<hgl/graph/VertexAttrib.h> #include<hgl/graph/VertexAttrib.h>
#include<hgl/graph/VKShaderStage.h> #include<hgl/graph/VKShaderStage.h>
@ -48,41 +48,14 @@ void ShaderCreateInfoVertex::AddJoint()
AddInput(VAT_VEC4, VAN::JointWeight,VK_VERTEX_INPUT_RATE_VERTEX,VertexInputGroup::JointWeight); AddInput(VAT_VEC4, VAN::JointWeight,VK_VERTEX_INPUT_RATE_VERTEX,VertexInputGroup::JointWeight);
} }
namespace void ShaderCreateInfoVertex::AddAssign()
{ {
constexpr const char MF_GetLocalToWorld_ByID[]="\nmat4 GetLocalToWorld(){return l2w.mats[LocalToWorld_ID];}\n"; AddInput( ASSIGN_VAT_FMT,
ASSIGN_VIS_NAME,
constexpr const char MF_GetLocalToWorld_by4VI[]=R"(
mat4 GetLocalToWorld()
{
return mat4(LocalToWorld_0,
LocalToWorld_1,
LocalToWorld_2,
LocalToWorld_3);
}
)";
}
void ShaderCreateInfoVertex::AddLocalToWorld()
{
char name[]= "LocalToWorld_?";
for(uint i=0;i<4;i++)
{
name[sizeof(name)-2]='0'+i;
AddInput(VAT_VEC4,name,VK_VERTEX_INPUT_RATE_INSTANCE,VertexInputGroup::LocalToWorld);
}
AddFunction(MF_GetLocalToWorld_by4VI);
}
void ShaderCreateInfoVertex::AddMaterialInstanceID()
{
AddInput( MI_VAT_FMT,
MI_VIS_NAME,
VK_VERTEX_INPUT_RATE_INSTANCE, VK_VERTEX_INPUT_RATE_INSTANCE,
VertexInputGroup::MaterialInstanceID); VertexInputGroup::Assign);
AddFunction(STD_MTL_FUNC_NAMESPACE::MF_GetLocalToWorld_ByAssign);
} }
bool ShaderCreateInfoVertex::ProcInput(ShaderCreateInfo *) bool ShaderCreateInfoVertex::ProcInput(ShaderCreateInfo *)

View File

@ -2,21 +2,11 @@
#include<hgl/graph/mtl/StdMaterial.h> #include<hgl/graph/mtl/StdMaterial.h>
STD_MTL_NAMESPACE_BEGIN STD_MTL_FUNC_NAMESPACE_BEGIN
namespace func
{
//C++端使用一个RG8UI或RGB16UI格式的顶点输入流来传递Assign数据其中x为LocalToWorld IDy为MaterialInstance ID //C++端使用一个RG8UI或RGB16UI格式的顶点输入流来传递Assign数据其中x为LocalToWorld IDy为MaterialInstance ID
constexpr const char MaterialInstanceID[]="MaterialInstanceID"; constexpr const char MF_GetLocalToWorld_ByAssign[]= "\nmat4 GetLocalToWorld(){return l2w.mats[Assign.x];}\n";
constexpr const char GetLocalToWorld[]=R"( constexpr const char MF_GetMaterialInstance_ByAssign[]= "\nMaterialInstance GetMaterialInstance(){return mi_set[Assign.y];}\n";
mat4 GetLocalToWorld()
{ STD_MTL_FUNC_NAMESPACE_END
return mat4(LocalToWorld_0,
LocalToWorld_1,
LocalToWorld_2,
LocalToWorld_3);
}
)";
}//namespace func
STD_MTL_NAMESPACE_END