From d54aff2a424af17977df49e6baf9d388ecc2a5db Mon Sep 17 00:00:00 2001
From: "HuYingzhuo(hugo/hyzboy)"
Date: Fri, 3 Mar 2023 23:02:40 +0800
Subject: [PATCH] first added codes of ShaderGen
---
CMSceneGraph | 2 +-
inc/hgl/shadergen/MaterialDescriptorManager.h | 51 +++++
inc/hgl/shadergen/ShaderCommon.h | 13 ++
inc/hgl/shadergen/ShaderDescriptorManager.h | 77 ++++++++
src/ShaderGen/CMakeLists.txt | 9 +-
src/ShaderGen/MaterialCreater.cpp | 185 ++++++++++++++++++
src/ShaderGen/MaterialDescriptorManager.cpp | 109 +++++++++++
src/ShaderGen/ShaderDescriptorManager.cpp | 151 ++++++++++++++
8 files changed, 594 insertions(+), 3 deletions(-)
create mode 100644 inc/hgl/shadergen/MaterialDescriptorManager.h
create mode 100644 inc/hgl/shadergen/ShaderCommon.h
create mode 100644 inc/hgl/shadergen/ShaderDescriptorManager.h
create mode 100644 src/ShaderGen/MaterialCreater.cpp
create mode 100644 src/ShaderGen/MaterialDescriptorManager.cpp
create mode 100644 src/ShaderGen/ShaderDescriptorManager.cpp
diff --git a/CMSceneGraph b/CMSceneGraph
index 861d1668..062c9cd6 160000
--- a/CMSceneGraph
+++ b/CMSceneGraph
@@ -1 +1 @@
-Subproject commit 861d1668cb6d8f730c89158933a133ba2c8ad426
+Subproject commit 062c9cd64239ada350cce73dd50b833759c48e56
diff --git a/inc/hgl/shadergen/MaterialDescriptorManager.h b/inc/hgl/shadergen/MaterialDescriptorManager.h
new file mode 100644
index 00000000..939252be
--- /dev/null
+++ b/inc/hgl/shadergen/MaterialDescriptorManager.h
@@ -0,0 +1,51 @@
+#pragma once
+
+#include
+#include
+#include
+#include
+
+using namespace hgl;
+using namespace hgl::graph;
+
+SHADERGEN_NAMESPACE_BEGIN
+/**
+* 材质描述符管理
+* 该类使用于SHADER生成前,用于统计编号set/binding
+*/
+class MaterialDescriptorManager
+{
+ struct ShaderDescriptorSet
+ {
+ DescriptorSetType set_type;
+
+ int set;
+ int count;
+
+ ObjectMap descriptor_map;
+
+ List ubo_list;
+ List sampler_list;
+
+ public:
+
+ const ShaderDescriptor *AddDescriptor(VkShaderStageFlagBits ssb,ShaderDescriptor *new_sd); ///<添加一个描述符,如果它本身存在,则返回false
+ };
+
+ using ShaderDescriptorSetArray=ShaderDescriptorSet[size_t(DescriptorSetType::RANGE_SIZE)];
+
+ ShaderDescriptorSetArray desc_set_array;
+
+public:
+
+ MaterialDescriptorManager();
+ ~MaterialDescriptorManager()=default;
+
+ const UBODescriptor *AddUBO(VkShaderStageFlagBits ssb,DescriptorSetType type,UBODescriptor *sd);
+ const SamplerDescriptor *AddSampler(VkShaderStageFlagBits ssb,DescriptorSetType type,SamplerDescriptor *sd);
+
+ const DescriptorSetType GetSetType(const AnsiString &)const;
+
+ void Resort(); //排序产生set号与binding号
+};
+SHADERGEN_NAMESPACE_END
diff --git a/inc/hgl/shadergen/ShaderCommon.h b/inc/hgl/shadergen/ShaderCommon.h
new file mode 100644
index 00000000..1230db29
--- /dev/null
+++ b/inc/hgl/shadergen/ShaderCommon.h
@@ -0,0 +1,13 @@
+#ifndef HGL_SHADER_GEN_COMMON_INCLUDE
+#define HGL_SHADER_GEN_COMMON_INCLUDE
+
+#include
+#include
+
+#define SHADERGEN_NAMESPACE_BEGIN namespace hgl{namespace shadergen{
+#define SHADERGEN_NAMESPACE_END }}
+#define SHADERGEN_NAMESPACE_USING using namespace hgl::shadergen;
+
+SHADERGEN_NAMESPACE_BEGIN
+SHADERGEN_NAMESPACE_END
+#endif//HGL_SHADER_GEN_COMMON_INCLUDE
diff --git a/inc/hgl/shadergen/ShaderDescriptorManager.h b/inc/hgl/shadergen/ShaderDescriptorManager.h
new file mode 100644
index 00000000..31306a22
--- /dev/null
+++ b/inc/hgl/shadergen/ShaderDescriptorManager.h
@@ -0,0 +1,77 @@
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+
+SHADERGEN_NAMESPACE_BEGIN
+/**
+* Shader数据管理器,用于生成正式Shader前的资源统计
+*/
+class ShaderDescriptorManager
+{
+ ShaderStageIO stage_io;
+
+ MaterialDescriptorManager * material_descriptor_manager;
+
+ //ubo/object在这里以及MaterialDescriptorManager中均有一份,mdm中的用于产生set/binding号,这里的用于产生shader
+ List ubo_list;
+ List sampler_list;
+
+ ObjectList const_value_list;
+ ObjectList subpass_input;
+
+ ShaderPushConstant push_constant;
+
+ AnsiString source_codes;
+
+public:
+
+ ShaderDescriptorManager(VkShaderStageFlagBits,MaterialDescriptorManager *);
+ ~ShaderDescriptorManager()=default;
+
+ const VkShaderStageFlagBits GetStageBits()const { return stage_io.cur; }
+ const AnsiString GetStageName()const { return AnsiString(GetShaderStageName(stage_io.cur)); }
+
+ void SetPrevShader(VkShaderStageFlagBits prev) { stage_io.prev=prev; }
+ void SetNextShader(VkShaderStageFlagBits next) { stage_io.next=next; }
+
+public:
+
+ const ShaderStageIO & GetShaderStageIO()const{return stage_io;}
+
+ const List & GetUBOList()const{return ubo_list;}
+ const List & GetSamplerList()const{return sampler_list;}
+
+ const ObjectList & GetConstList()const{return const_value_list;}
+
+ const ObjectList & GetSubpassInputList()const { return subpass_input; }
+
+ const AnsiString &GetSources()const{return source_codes;}
+
+public:
+
+ bool AddInput(ShaderStage *);
+ bool AddOutput(ShaderStage *);
+
+ bool AddUBO(DescriptorSetType type,UBODescriptor *sd);
+ bool AddSampler(DescriptorSetType type,SamplerDescriptor *sd);
+
+ bool AddConstValue(ConstValueDescriptor *sd);
+ bool AddSubpassInput(const AnsiString name,uint8_t index);
+
+ void SetPushConstant(const AnsiString name,uint8_t offset,uint8_t size);
+
+ void AddSource(const AnsiString &str)
+ {
+ source_codes+=str;
+ source_codes+="\n";
+ }
+
+#ifdef _DEBUG
+ void DebugOutput(int);
+#endif//_DEBUG
+};//class ShaderDescriptorManager
+SHADERGEN_NAMESPACE_END
diff --git a/src/ShaderGen/CMakeLists.txt b/src/ShaderGen/CMakeLists.txt
index 3c5813c4..924f873a 100644
--- a/src/ShaderGen/CMakeLists.txt
+++ b/src/ShaderGen/CMakeLists.txt
@@ -8,9 +8,13 @@ SET(SHADERGEN_HEADER_FILES ${SHADERGEN_INCLUDE_PATH}/ShadingProgram.h
${SHADERGEN_INCLUDE_PATH}/ShaderCommon.h
${SHADERGEN_INCLUDE_PATH}/ShaderDescriptorManager.h
${SHADERGEN_INCLUDE_PATH}/MaterialDescriptorManager.h
+ ${SHADERGEN_INCLUDE_PATH}/VertexPolicy.h
+ ${SHADERGEN_INCLUDE_PATH}/MaterialGen.h
)
-SET(SHADERGEN_SOURCE_FILES PMC.cpp
+SET(SHADERGEN_SOURCE_FILES
+#PMC.cpp
+# VertexPolicy.cpp
ShaderDescriptorManager.cpp
MaterialDescriptorManager.cpp
)
@@ -20,4 +24,5 @@ SET(SHADERGEN_SOURCE_FILES PMC.cpp
add_cm_library(ULRE.ShaderGen "ULRE" ${SHADERGEN_HEADER_FILES}
${SHADERGEN_SOURCE_FILES}
- ShaderGen.cpp)
+ ShaderGen.cpp
+ MaterialCreater.cpp)
diff --git a/src/ShaderGen/MaterialCreater.cpp b/src/ShaderGen/MaterialCreater.cpp
new file mode 100644
index 00000000..cb09c21b
--- /dev/null
+++ b/src/ShaderGen/MaterialCreater.cpp
@@ -0,0 +1,185 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+using namespace hgl;
+using namespace hgl::graph;
+
+SHADERGEN_NAMESPACE_BEGIN
+class ShaderCreater
+{
+ VkShaderStageFlagBits shader_stage; ///<着色器阶段
+
+public:
+
+ ShaderDescriptorManager sdm;
+
+ VkShaderStageFlagBits GetShaderStage()const{return shader_stage;}
+
+public:
+
+ ShaderCreater(VkShaderStageFlagBits ss,MaterialDescriptorManager *mdm):sdm(ss,mdm)
+ {
+ shader_stage=ss;
+ }
+
+ ~ShaderCreater()
+ {
+ }
+};
+
+class ShaderCreaterMap:public ObjectMap
+{
+public:
+
+ using ObjectMap::ObjectMap;
+
+ bool Add(ShaderCreater *sc)
+ {
+ if(!sc)return(false);
+
+ VkShaderStageFlagBits flag=sc->GetShaderStage();
+
+ if(KeyExist(flag))
+ return(false);
+
+ ObjectMap::Add(flag,sc);
+ return(true);
+ }
+};
+
+class VertexShaderCreater:public ShaderCreater
+{
+ List input;
+
+public:
+
+ VertexShaderCreater(MaterialDescriptorManager *mdm):ShaderCreater(VK_SHADER_STAGE_VERTEX_BIT,mdm){}
+ ~VertexShaderCreater()=default;
+
+ int AddInput(const AnsiString &name,const VertexAttribType &type)
+ {
+ ShaderStage ss;
+
+ hgl::strcpy(ss.name,sizeof(ss.name),name.c_str());
+
+ ss.location=input.GetCount();
+ ss.basetype=(uint8) type.basetype;
+ ss.vec_size= type.vec_size;
+
+ return input.Add(ss);
+ }
+};
+
+class GeometryShaderCreater:public ShaderCreater
+{
+public:
+
+ GeometryShaderCreater(MaterialDescriptorManager *mdm):ShaderCreater(VK_SHADER_STAGE_GEOMETRY_BIT,mdm){}
+ ~GeometryShaderCreater()=default;
+};
+
+class FragmentShaderCreater:public ShaderCreater
+{
+public:
+
+ FragmentShaderCreater(MaterialDescriptorManager *mdm):ShaderCreater(VK_SHADER_STAGE_FRAGMENT_BIT,mdm){}
+ ~FragmentShaderCreater()=default;
+};
+
+class MaterialCreater
+{
+ uint rt_count; ///<输出的RT数量
+
+ uint32_t shader_stage; ///<着色器阶段
+
+ MaterialDescriptorManager MDM; ///<材质描述符管理器
+
+ ShaderCreaterMap shader_map; ///<着色器列表
+
+ VertexShaderCreater *vert;
+ GeometryShaderCreater *geom;
+ FragmentShaderCreater *frag;
+
+public:
+
+ bool hasShader(const VkShaderStageFlagBits ss)const{return shader_stage&ss;}
+
+ bool hasVertex ()const{return hasShader(VK_SHADER_STAGE_VERTEX_BIT);}
+// bool hasTessCtrl()const{return hasShader(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);}
+// bool hasTessEval()const{return hasShader(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT);}
+ bool hasGeometry()const{return hasShader(VK_SHADER_STAGE_GEOMETRY_BIT);}
+ bool hasFragment()const{return hasShader(VK_SHADER_STAGE_FRAGMENT_BIT);}
+// bool hasCompute ()const{return hasShader(VK_SHADER_STAGE_COMPUTE_BIT);}
+
+public:
+
+ MaterialCreater(const uint rc,const uint32 ss)
+ {
+ rt_count=rc;
+ shader_stage=ss;
+
+ if(hasVertex ())shader_map.Add(vert=new VertexShaderCreater (&MDM));else vert=nullptr;
+ if(hasGeometry ())shader_map.Add(geom=new GeometryShaderCreater(&MDM));else geom=nullptr;
+ if(hasFragment ())shader_map.Add(frag=new FragmentShaderCreater(&MDM));else frag=nullptr;
+ }
+
+ ~MaterialCreater()
+ {
+ }
+
+ int AddVertexInput(const AnsiString &name,const VertexAttribType &type)
+ {
+ if(!vert)return(-1);
+
+ return vert->AddInput(name,type);
+ }
+
+ bool AddUBO(const VkShaderStageFlagBits flag_bits,const DescriptorSetType set_type,const AnsiString &type_name,const AnsiString &name)
+ {
+ if(!shader_map.KeyExist(flag_bits))
+ return(false);
+
+ ShaderCreater *sc=shader_map[flag_bits];
+
+ if(!sc)
+ return(false);
+
+ UBODescriptor *ubo=new UBODescriptor();
+
+ ubo->type=type_name;
+ ubo->name=name;
+
+ return sc->sdm.AddUBO(set_type,ubo);
+ }
+
+ bool AddSampler(const VkShaderStageFlagBits flag_bits,const DescriptorSetType set_type,const AnsiString &type_name,const AnsiString &name)
+ {
+ if(!shader_map.KeyExist(flag_bits))
+ return(false);
+
+ ShaderCreater *sc=shader_map[flag_bits];
+
+ if(!sc)
+ return(false);
+
+ SamplerDescriptor *sampler=new SamplerDescriptor();
+
+ sampler->type=type_name;
+ sampler->name=name;
+
+ return sc->sdm.AddSampler(set_type,sampler);
+ }
+};//class MaterialCreater
+
+int main()
+{
+ MaterialCreater mc(1,VK_SHADER_STAGE_VERTEX_BIT|VK_SHADER_STAGE_FRAGMENT_BIT);
+
+ return 0;
+}
+SHADERGEN_NAMESPACE_END
diff --git a/src/ShaderGen/MaterialDescriptorManager.cpp b/src/ShaderGen/MaterialDescriptorManager.cpp
new file mode 100644
index 00000000..e623c527
--- /dev/null
+++ b/src/ShaderGen/MaterialDescriptorManager.cpp
@@ -0,0 +1,109 @@
+#include
+
+SHADERGEN_NAMESPACE_BEGIN
+MaterialDescriptorManager::MaterialDescriptorManager()
+{
+ int set_type=(int)DescriptorSetType::BEGIN_RANGE;
+
+ for(auto &p:desc_set_array)
+ {
+ p.set_type=(DescriptorSetType)set_type;
+
+ ++set_type;
+
+ p.set=-1;
+ p.count=0;
+ }
+}
+
+const DescriptorSetType MaterialDescriptorManager::GetSetType(const AnsiString &name)const
+{
+ for(auto &sds:desc_set_array)
+ if(sds.descriptor_map.KeyExist(name))
+ return(sds.set_type);
+
+ return DescriptorSetType::Global;
+}
+
+/**
+* 添加一个描述符,如果它本身存在,则返回false
+*/
+const ShaderDescriptor *MaterialDescriptorManager::ShaderDescriptorSet::AddDescriptor(VkShaderStageFlagBits ssb,ShaderDescriptor *new_sd)
+{
+ ShaderDescriptor *sd;
+
+ if(descriptor_map.Get(new_sd->name,sd))
+ {
+ sd->stage_flag|=ssb;
+ return(sd);
+ }
+ else
+ {
+ new_sd->set_type=set_type;
+ new_sd->stage_flag=ssb;
+
+ descriptor_map.Add(new_sd->name, new_sd);
+
+ count++;
+
+ return(new_sd);
+ }
+}
+
+const UBODescriptor *MaterialDescriptorManager::AddUBO(VkShaderStageFlagBits ssb,DescriptorSetType type,UBODescriptor *sd)
+{
+ RANGE_CHECK_RETURN_NULLPTR(type);
+ if(!sd)return(nullptr);
+
+ ShaderDescriptorSet *sds=desc_set_array+(size_t)type;
+
+ const ShaderDescriptor *obj=sds->AddDescriptor(ssb,sd);
+
+ if(!obj)return(nullptr);
+
+ sds->ubo_list.Add((UBODescriptor *)obj);
+ return((UBODescriptor *)obj);
+}
+
+const SamplerDescriptor *MaterialDescriptorManager::AddSampler(VkShaderStageFlagBits ssb,DescriptorSetType type,SamplerDescriptor *sd)
+{
+ RANGE_CHECK_RETURN_NULLPTR(type);
+ if(!sd)return(nullptr);
+
+ ShaderDescriptorSet *sds=desc_set_array+(size_t)type;
+
+ const ShaderDescriptor *obj=sds->AddDescriptor(ssb,sd);
+
+ if(!obj)return(nullptr);
+
+ sds->sampler_list.Add((SamplerDescriptor *)obj);
+ return((SamplerDescriptor *)obj);
+}
+
+void MaterialDescriptorManager::Resort()
+{
+ //重新生成set/binding
+ {
+ int set=0;
+
+ for(auto &p:desc_set_array)
+ {
+ if(p.count>0)
+ {
+ p.set=set;
+
+ auto *sdp=p.descriptor_map.GetDataList();
+ for(int i=0;iright->set=set;
+ (*sdp)->right->binding=i;
+
+ ++sdp;
+ }
+
+ ++set;
+ }
+ }
+ }
+}
+SHADERGEN_NAMESPACE_END
\ No newline at end of file
diff --git a/src/ShaderGen/ShaderDescriptorManager.cpp b/src/ShaderGen/ShaderDescriptorManager.cpp
new file mode 100644
index 00000000..c9a15adf
--- /dev/null
+++ b/src/ShaderGen/ShaderDescriptorManager.cpp
@@ -0,0 +1,151 @@
+#include
+
+SHADERGEN_NAMESPACE_BEGIN
+ShaderDescriptorManager::ShaderDescriptorManager(VkShaderStageFlagBits cur,MaterialDescriptorManager *mdm)
+{
+ material_descriptor_manager=mdm;
+
+ stage_io.cur=cur;
+ stage_io.prev=(VkShaderStageFlagBits)0;
+ stage_io.next=(VkShaderStageFlagBits)0;
+
+ hgl_zero(push_constant);
+}
+
+namespace
+{
+ bool Find(ObjectList &ol,const ShaderStage *ss)
+ {
+ for(int i=0;iname,ss->name)==0)
+ return(true);
+
+ return(false);
+ }
+}//namespace
+
+bool ShaderDescriptorManager::AddInput(ShaderStage *ss)
+{
+ if(!ss)return(false);
+
+ if(Find(stage_io.input,ss))return(false);
+
+ ss->location=stage_io.input.GetCount();
+ stage_io.input.Add(ss);
+ return(true);
+}
+
+bool ShaderDescriptorManager::AddOutput(ShaderStage *ss)
+{
+ if(!ss)return(false);
+
+ if(Find(stage_io.output,ss))return(false);
+
+ ss->location=stage_io.output.GetCount();
+ stage_io.output.Add(ss);
+ return(true);
+}
+
+bool ShaderDescriptorManager::AddUBO(DescriptorSetType type,UBODescriptor *sd)
+{
+ const UBODescriptor *obj=material_descriptor_manager->AddUBO(stage_io.cur,type,sd);
+
+ if(!obj)
+ return(false);
+
+ ubo_list.Add(obj);
+ return obj;
+}
+
+bool ShaderDescriptorManager::AddSampler(DescriptorSetType type,SamplerDescriptor *sd)
+{
+ const SamplerDescriptor *obj=material_descriptor_manager->AddSampler(stage_io.cur,type,sd);
+
+ if(!obj)
+ return(false);
+
+ sampler_list.Add(obj);
+ return obj;
+}
+
+bool ShaderDescriptorManager::AddConstValue(ConstValueDescriptor *sd)
+{
+ if(!sd)return(false);
+
+ for(auto *p:const_value_list)
+ if(p->name.Comp(sd->name)==0)
+ return(false);
+
+ sd->constant_id=const_value_list.Add(sd);
+ return(true);
+}
+
+bool ShaderDescriptorManager::AddSubpassInput(const UTF8String name,uint8_t index)
+{
+ for(auto *si:subpass_input)
+ {
+ if(si->input_attachment_index==index)return(false);
+ if(si->name.Comp(name))return(false);
+ }
+
+ SubpassInputDescriptor *ssi=new SubpassInputDescriptor;
+
+ ssi->name=name;
+ ssi->input_attachment_index=index;
+
+ subpass_input.Add(ssi);
+ return(true);
+}
+
+void ShaderDescriptorManager::SetPushConstant(const UTF8String name,uint8_t offset,uint8_t size)
+{
+ push_constant.name =name;
+ push_constant.offset=offset;
+ push_constant.size =size;
+}
+
+#ifdef _DEBUG
+void ShaderDescriptorManager::DebugOutput(int index)
+{
+ UTF8String name=GetShaderStageName(stage_io.cur);
+ UTF8String prev_name=GetShaderStageName(stage_io.prev);
+ UTF8String next_name=GetShaderStageName(stage_io.next);
+
+ LOG_INFO(UTF8String::numberOf(index)+": "+name+" shader");
+ LOG_INFO("\tprev next is "+prev_name);
+ LOG_INFO("\tnext next is "+next_name);
+
+ if(stage_io.input.GetCount()>0)
+ {
+ LOG_INFO("\tStage Input "+UTF8String::numberOf(stage_io.input.GetCount()));
+
+ for(auto *ss:stage_io.input)
+ LOG_INFO("\t\tlayout(location="+UTF8String::numberOf(ss->location)+") in "+UTF8String(GetShaderStageTypeName(ss))+"\t"+UTF8String(ss->name));
+ }
+
+ if(stage_io.output.GetCount()>0)
+ {
+ LOG_INFO("\tStage Output "+UTF8String::numberOf(stage_io.output.GetCount()));
+
+ for(auto *ss:stage_io.output)
+ LOG_INFO("\t\tlayout(location="+UTF8String::numberOf(ss->location)+") out "+UTF8String(GetShaderStageTypeName(ss))+"\t"+UTF8String(ss->name));
+ }
+
+ if(ubo_list.GetCount()>0)
+ {
+ LOG_INFO("\tUBO "+UTF8String::numberOf(ubo_list.GetCount()));
+
+ for(auto *ubo:ubo_list)
+ LOG_INFO("\t\tlayout(set="+UTF8String::numberOf(ubo->set)+",binding="+UTF8String::numberOf(ubo->binding)+") uniform "+ubo->type+"\t"+ubo->type);
+ }
+
+ if(sampler_list.GetCount()>0)
+ {
+ LOG_INFO("\tSampler "+UTF8String::numberOf(sampler_list.GetCount()));
+
+ for(auto *ubo:ubo_list)
+ LOG_INFO("\t\tlayout(set="+UTF8String::numberOf(ubo->set)+",binding="+UTF8String::numberOf(ubo->binding)+") uniform "+ubo->type+"\t"+ubo->type);
+ }
+}
+#endif//_DEBUG
+SHADERGEN_NAMESPACE_END
\ No newline at end of file