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

View File

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

View File

@ -16,7 +16,7 @@ struct Material2DCreateConfig:public MaterialCreateConfig
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.depth=false; //不输出深度

View File

@ -17,7 +17,7 @@ struct Material3DCreateConfig:public MaterialCreateConfig
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.depth=true; //不输出深度

View File

@ -19,6 +19,8 @@ struct MaterialCreateConfig
AnsiString mtl_name; ///<材质名称
bool material_instance; ///<是否包含材质实例
RenderTargetOutputConfig rt_output; ///<渲染目标输出配置
uint32 shader_stage_flag_bit; ///<需要的shader
@ -27,12 +29,14 @@ struct MaterialCreateConfig
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;
mtl_name=name;
material_instance=mi;
shader_stage_flag_bit=VK_SHADER_STAGE_VERTEX_BIT|VK_SHADER_STAGE_FRAGMENT_BIT;
prim=p;

View File

@ -5,12 +5,14 @@
#define STD_MTL_NAMESPACE_BEGIN namespace hgl{namespace graph{namespace mtl{
#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_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
{

View File

@ -42,10 +42,24 @@ constexpr const ShaderBufferSource SBS_CameraInfo=
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必须严格指定数组的大小
// SSBO则不需要使用[]方式指定为动态大小数组
constexpr const char MaterialInstanceStruct[]="MaterialInstance";
constexpr const DescriptorSetType DST_MaterialInstance=DescriptorSetType::PerMaterial;
constexpr const ShaderBufferSource SBS_MaterialInstance=
{

View File

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

View File

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

View File

@ -53,15 +53,7 @@ MaterialRenderList::MaterialRenderList(GPUDevice *d,bool l2w,Material *m)
cmd_buf=nullptr;
material=m;
if(l2w)
l2w_buffer=new RenderL2WBuffer(device);
else
l2w_buffer=nullptr;
if(material->HasMI())
mi_buffer=new RenderMIBuffer(device,material->GetMIDataBytes());
else
mi_buffer=nullptr;
assign_buffer=new RenderAssignBuffer(device,material);
vbo_list=new VBOList(material->GetVertexInput()->GetCount());
}
@ -69,8 +61,7 @@ MaterialRenderList::MaterialRenderList(GPUDevice *d,bool l2w,Material *m)
MaterialRenderList::~MaterialRenderList()
{
SAFE_CLEAR(vbo_list);
SAFE_CLEAR(mi_buffer);
SAFE_CLEAR(l2w_buffer);
SAFE_CLEAR(assign_buffer);
}
void MaterialRenderList::Add(Renderable *ri,const Matrix4f &mat)
@ -94,16 +85,8 @@ void MaterialRenderList::End()
Stat();
if(l2w_buffer)
{
l2w_buffer->WriteNode(rn_list.GetData(),node_count);
}
if(mi_buffer)
{
StatMI();
mi_buffer->WriteNode(rn_list.GetData(),node_count,mi_set);
}
if(assign_buffer)
assign_buffer->WriteNode(rn_list);
}
void MaterialRenderList::RenderItem::Set(Renderable *ri)
@ -113,19 +96,6 @@ void MaterialRenderList::RenderItem::Set(Renderable *ri)
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()
{
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);
}
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(l2w_buffer->GetVBO(),l2w_buffer_size,4);
}
if(mi_buffer) //材质实例组
vbo_list->Add(mi_buffer->GetVBO(),MI_VAB_STRIDE_BYTES*ri_index);
if(assign_buffer) //L2W/MI分发组
vbo_list->Add(assign_buffer->GetVAB(),ASSIGN_VAB_STRIDE_BYTES*ri_index);
//if(!vbo_list.IsFull()) //Joint组暂未支持
//{
@ -282,8 +244,8 @@ void MaterialRenderList::Render(RenderCmdBuffer *rcb)
last_pipeline =nullptr;
last_vid =nullptr;
if(mi_buffer)
mi_buffer->Bind(material);
if(assign_buffer)
assign_buffer->Bind(material);
cmd_buf->BindDescriptorSets(material);

View File

@ -8,184 +8,186 @@
#include<hgl/graph/mtl/UBOCommon.h>
VK_NAMESPACE_BEGIN
RenderL2WBuffer::RenderL2WBuffer(GPUDevice *dev)
{
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)
RenderAssignBuffer::RenderAssignBuffer(GPUDevice *dev,Material *mtl)
{
hgl_zero(*this);
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;
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(mi_vab);
mi_count=0;
node_count=0;
SAFE_CLEAR(l2w_buffer);
SAFE_CLEAR(mi_buffer);
SAFE_CLEAR(assign_vab);
}
void RenderMIBuffer::Alloc(const uint nc,const uint mc)
void RenderAssignBuffer::StatL2W(const RenderNodeList &rn_list)
{
Clear();
node_count=nc;
if(mi_data_bytes>0&&mc>0)
if(!l2w_buffer)
{
mi_count=mc;
mi_data_buffer=device->CreateUBO(mi_data_bytes*mi_count);
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);
}
mi_vab=device->CreateVAB(MI_VAB_FMT,node_count);
mi_buffer=mi_vab->GetBuffer();
if(!l2w_buffer)
{
l2w_buffer=device->CreateUBO(sizeof(Matrix4f)*l2w_buffer_max_count);
#ifdef _DEBUG
DebugUtils *du=device->GetDebugUtils();
if(du)
{
du->SetBuffer(mi_data_buffer->GetBuffer(),"UBO:Buffer:MaterialInstance");
du->SetDeviceMemory(mi_data_buffer->GetVkMemory(),"UBO:Memory:MaterialInstance");
du->SetBuffer(mi_vab->GetBuffer(),"VAB:Buffer:MaterialInstanceID");
du->SetDeviceMemory(mi_vab->GetVkMemory(),"VAB:Memory:MaterialInstanceID");
du->SetBuffer(l2w_buffer->GetBuffer(),"UBO:Buffer:LocalToWorld");
du->SetDeviceMemory(l2w_buffer->GetVkMemory(),"UBO:Memory:LocalToWorld");
}
#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;
for(uint i=0;i<count;i++)
if(!assign_vab)
{
*idp=mi_set.Find(rn->ri->GetMaterialInstance());
++idp;
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++)
{
adp->l2w=i;
adp->mi=mi_set.Find(rn->ri->GetMaterialInstance());
++adp;
++rn;
}
}
mi_vab->Unmap();
assign_vab->Unmap();
}
}
VK_NAMESPACE_END

View File

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

View File

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

View File

@ -1,4 +1,4 @@
#include"Std2DMaterial.h"
#include"Std2DMaterial.h"
#include<hgl/shadergen/MaterialCreateInfo.h>
#include<hgl/graph/mtl/Material2DCreateConfig.h>
#include<hgl/graph/mtl/UBOCommon.h>
@ -13,10 +13,18 @@ bool Std2DMaterial::CustomVertexShader(ShaderCreateInfoVertex *vsc)
vsc->AddInput(cfg->position_format,VAN::Position);
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)
{
vsc->AddLocalToWorld();
mci->SetLocalToWorld(VK_SHADER_STAGE_ALL_GRAPHICS);
if(is_rect)

View File

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

View File

@ -1,4 +1,4 @@
#include"Std3DMaterial.h"
#include"Std3DMaterial.h"
#include<hgl/shadergen/MaterialCreateInfo.h>
#include<hgl/graph/mtl/Material3DCreateConfig.h>
#include<hgl/graph/mtl/UBOCommon.h>
@ -10,6 +10,15 @@ STD_MTL_NAMESPACE_BEGIN
bool Std3DMaterial::CustomVertexShader(ShaderCreateInfoVertex *vsc)
{
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)
{
@ -24,7 +33,6 @@ bool Std3DMaterial::CustomVertexShader(ShaderCreateInfoVertex *vsc)
{
mci->SetLocalToWorld(VK_SHADER_STAGE_ALL_GRAPHICS);
vsc->AddLocalToWorld();
vsc->AddFunction(cfg->camera?func::GetPosition3DL2WCamera:func::GetPosition3DL2W);
}
else

View File

@ -16,8 +16,8 @@ namespace
public:
Std3DMaterialLoader(material_file::MaterialFileData *data,const Material3DCreateConfig *cfg)
: Std3DMaterial(cfg)
Std3DMaterialLoader(material_file::MaterialFileData *data,const Material3DCreateConfig *c)
: Std3DMaterial(c)
{
mfd=data;
}
@ -77,9 +77,6 @@ namespace
for(auto &ua:mfd->vi)
vsc->AddInput(ua.vat,ua.name);
if(mfd->mi.mi_bytes>0)
vsc->AddMaterialInstanceID();
if(!Std3DMaterial::CustomVertexShader(vsc))
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);
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();
@ -182,7 +182,7 @@ bool MaterialCreateInfo::SetMaterialInstance(const AnsiString &glsl_codes,const
{
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);
}
@ -198,6 +198,28 @@ bool MaterialCreateInfo::SetLocalToWorld(const uint32_t shader_stage_flag_bits)
{
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;
return(true);

View File

@ -156,10 +156,11 @@ bool ShaderCreateInfo::ProcSubpassInput()
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_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_OTHER[]= "\nvoid HandoverMI(){Output.MaterialInstanceID=Input.MaterialInstanceID;}\n";
}//namespace
@ -176,7 +177,7 @@ void ShaderCreateInfo::SetMaterialInstance(UBODescriptor *ubo,const AnsiString &
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_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/graph/VertexAttrib.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);
}
namespace
void ShaderCreateInfoVertex::AddAssign()
{
constexpr const char MF_GetLocalToWorld_ByID[]="\nmat4 GetLocalToWorld(){return l2w.mats[LocalToWorld_ID];}\n";
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,
AddInput( ASSIGN_VAT_FMT,
ASSIGN_VIS_NAME,
VK_VERTEX_INPUT_RATE_INSTANCE,
VertexInputGroup::MaterialInstanceID);
VertexInputGroup::Assign);
AddFunction(STD_MTL_FUNC_NAMESPACE::MF_GetLocalToWorld_ByAssign);
}
bool ShaderCreateInfoVertex::ProcInput(ShaderCreateInfo *)

View File

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