From c01f46df5ca06087ae568e1c8e1d2596c0a24b95 Mon Sep 17 00:00:00 2001 From: HuYingzhuo Date: Fri, 26 Apr 2019 22:34:51 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=A0=E9=99=A4VertexInputState=E7=B1=BB?= =?UTF-8?q?=EF=BC=8C=E5=85=B6=E5=86=85=E5=AE=B9=E5=B9=B6=E5=85=A5Shader?= =?UTF-8?q?=E7=B1=BB=E3=80=82=20VertexInputStateInstance=E7=B1=BB=E6=9B=B4?= =?UTF-8?q?=E5=90=8D=E4=B8=BAVertexAttributeBinding?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- example/Vulkan/VKMaterial.cpp | 2 +- example/Vulkan/VKMaterial.h | 10 +-- example/Vulkan/VKPipeline.cpp | 10 +-- example/Vulkan/VKPipeline.h | 4 +- example/Vulkan/VKShader.cpp | 83 ++++++++++++++++++--- example/Vulkan/VKShader.h | 41 ++++++++--- example/Vulkan/VKVertexInput.cpp | 123 +++++++------------------------ example/Vulkan/VKVertexInput.h | 71 +++--------------- example/Vulkan/main.cpp | 8 +- 9 files changed, 159 insertions(+), 193 deletions(-) diff --git a/example/Vulkan/VKMaterial.cpp b/example/Vulkan/VKMaterial.cpp index a05516a0..a3a0ea21 100644 --- a/example/Vulkan/VKMaterial.cpp +++ b/example/Vulkan/VKMaterial.cpp @@ -11,7 +11,7 @@ Material::~Material() MaterialInstance *Material::CreateInstance() { - VertexInputStateInstance *vis_instance=vis->CreateInstance(); + VertexAttributeBinding *vis_instance=shader->CreateVertexAttributeBinding(); return(new MaterialInstance(this,vis_instance)); } diff --git a/example/Vulkan/VKMaterial.h b/example/Vulkan/VKMaterial.h index 0c8de14e..10ec4d38 100644 --- a/example/Vulkan/VKMaterial.h +++ b/example/Vulkan/VKMaterial.h @@ -7,7 +7,7 @@ class Shader; class DescriptorSetLayoutCreater; class MaterialInstance; class VertexInputState; -class VertexInputStateInstance; +class VertexAttributeBinding; /** * 材质类
@@ -16,15 +16,13 @@ class VertexInputStateInstance; class Material { Shader *shader; - VertexInputState *vis; DescriptorSetLayoutCreater *dsl_creater; public: - Material(Shader *s,VertexInputState *state,DescriptorSetLayoutCreater *dslc) + Material(Shader *s,DescriptorSetLayoutCreater *dslc) { shader=s; - vis=state; dsl_creater=dslc; } ~Material(); @@ -39,11 +37,11 @@ public: class MaterialInstance { const Material *mat; ///<这里的是对material的完全引用,不做任何修改 - VertexInputStateInstance *vis_instance; ///<这里的vis是Material中vis的复制体 + VertexAttributeBinding *vis_instance; ///<这里的vis是Material中vis的复制体 public: - MaterialInstance(Material *m,VertexInputStateInstance *vi) + MaterialInstance(Material *m,VertexAttributeBinding *vi) { mat=m; vis_instance=vi; diff --git a/example/Vulkan/VKPipeline.cpp b/example/Vulkan/VKPipeline.cpp index 511f1fff..1cdefadc 100644 --- a/example/Vulkan/VKPipeline.cpp +++ b/example/Vulkan/VKPipeline.cpp @@ -156,18 +156,18 @@ bool PipelineCreater::Set(const Shader *s) shader=s; - pipelineInfo.stageCount=shader->GetCount(); - pipelineInfo.pStages=shader->GetStages(); + pipelineInfo.stageCount=shader->GetStageCount(); + pipelineInfo.pStages=shader->GetShaderStages(); return(true); } -bool PipelineCreater::Set(const VertexInputStateInstance *vis) +bool PipelineCreater::Set(const VertexAttributeBinding *vab) { - if(!vis) + if(!vab) return(false); - vis->Write(vis_create_info); + vab->Write(vis_create_info); return(true); } diff --git a/example/Vulkan/VKPipeline.h b/example/Vulkan/VKPipeline.h index bef10740..5dc13962 100644 --- a/example/Vulkan/VKPipeline.h +++ b/example/Vulkan/VKPipeline.h @@ -6,7 +6,7 @@ VK_NAMESPACE_BEGIN class Device; class RenderPass; -class VertexInputStateInstance; +class VertexAttributeBinding; class Pipeline { @@ -60,7 +60,7 @@ public: ~PipelineCreater()=default; bool Set(const Shader *); - bool Set(const VertexInputStateInstance *); + bool Set(const VertexAttributeBinding *); bool Set(const VkPrimitiveTopology,bool=false); bool Set(VkPipelineLayout pl); diff --git a/example/Vulkan/VKShader.cpp b/example/Vulkan/VKShader.cpp index e557a7e2..9c7a82e9 100644 --- a/example/Vulkan/VKShader.cpp +++ b/example/Vulkan/VKShader.cpp @@ -37,6 +37,17 @@ bool Shader::CreateVIS(const void *spv_data,const uint32_t spv_size) spirv_cross::ShaderResources res=comp.get_shader_resources(); + attr_count=res.stage_inputs.size(); + binding_list=new VkVertexInputBindingDescription[attr_count]; + attribute_list=new VkVertexInputAttributeDescription[attr_count]; + + VkVertexInputBindingDescription *bind=binding_list; + VkVertexInputAttributeDescription *attr=attribute_list; + + uint32_t binding_index=0; + + + for(auto &si:res.stage_inputs) { const spirv_cross::SPIRType & type =comp.get_type(si.type_id); @@ -45,10 +56,28 @@ bool Shader::CreateVIS(const void *spv_data,const uint32_t spv_size) if(format==VK_FORMAT_UNDEFINED) return(false); - const uint32_t location=comp.get_decoration(si.id,spv::DecorationLocation); const UTF8String & name =comp.get_name(si.id).c_str(); - vertex_input_state->Add(name,location,format); + bind->binding =binding_index; //binding对应在vkCmdBindVertexBuffer中设置的缓冲区序列号,所以这个数字必须从0开始,而且紧密排列。 + //在VertexInput类中,buf_list需要严格按照本此binding为序列号排列 + bind->stride =GetStrideByFormat(format); + bind->inputRate =VK_VERTEX_INPUT_RATE_VERTEX; + + //实际使用可以一个binding绑多个attrib,但我们仅支持1v1。 + //一个binding是指在vertex shader中,由一个vertex输入流输入数据,attrib指其中的数据成分 + //比如在一个流中传递{pos,color}这样两个数据,就需要两个attrib + //但我们在一个流中,仅支持一个attrib传递 + + attr->binding =binding_index; + attr->location =comp.get_decoration(si.id,spv::DecorationLocation); + attr->format =format; + attr->offset =0; + + stage_input_locations.Add(name,attr); + + ++attr; + ++bind; + ++binding_index; } return(true); @@ -57,13 +86,20 @@ bool Shader::CreateVIS(const void *spv_data,const uint32_t spv_size) Shader::Shader(VkDevice dev) { device=dev; - - vertex_input_state=new VertexInputState(); + attr_count=0; + binding_list=nullptr; + attribute_list=nullptr; } Shader::~Shader() { - delete vertex_input_state; + if(instance_set.GetCount()>0) + { + //还有在用的,这是个错误 + } + + SAFE_CLEAR_ARRAY(binding_list); + SAFE_CLEAR_ARRAY(attribute_list); const int count=shader_stage_list.GetCount(); @@ -106,14 +142,41 @@ bool Shader::Add(const VkShaderStageFlagBits shader_stage_bit,const void *spv_da return(true); } -void Shader::Clear() +VertexAttributeBinding *Shader::CreateVertexAttributeBinding() { - shader_stage_list.Clear(); - vertex_input_state->Clear(); + VertexAttributeBinding *vis_instance=new VertexAttributeBinding(this); + + instance_set.Add(vis_instance); + + return(vis_instance); } -VertexInputStateInstance *Shader::CreateVertexInputStateInstance() +bool Shader::Release(VertexAttributeBinding *vis_instance) { - return vertex_input_state->CreateInstance(); + return instance_set.Delete(vis_instance); +} + +const int Shader::GetLocation(const UTF8String &name)const +{ + if(name.IsEmpty())return -1; + + VkVertexInputAttributeDescription *attr; + + if(!stage_input_locations.Get(name,attr)) + return -1; + + return attr->location; +} + +const int Shader::GetBinding(const UTF8String &name)const +{ + if(name.IsEmpty())return -1; + + VkVertexInputAttributeDescription *attr; + + if(!stage_input_locations.Get(name,attr)) + return -1; + + return attr->binding; } VK_NAMESPACE_END diff --git a/example/Vulkan/VKShader.h b/example/Vulkan/VKShader.h index 86e7981f..9de681d9 100644 --- a/example/Vulkan/VKShader.h +++ b/example/Vulkan/VKShader.h @@ -1,9 +1,10 @@ #pragma once #include"VK.h" - +#include +#include +#include VK_NAMESPACE_BEGIN -class VertexInputState; -class VertexInputStateInstance; +class VertexAttributeBinding; /** * Shader 创建器 @@ -14,7 +15,15 @@ class Shader List shader_stage_list; - VertexInputState *vertex_input_state=nullptr; +private: + + uint32_t attr_count; + VkVertexInputBindingDescription *binding_list; + VkVertexInputAttributeDescription *attribute_list; + + Map stage_input_locations; + + Set instance_set; private: @@ -47,12 +56,26 @@ public: ADD_NV_SHADER_FUNC(Mesh, MESH); #undef ADD_NV_SHADER_FUNC - void Clear(); +public: //shader部分 - const uint32_t GetCount ()const{return shader_stage_list.GetCount();} - const VkPipelineShaderStageCreateInfo * GetStages ()const{return shader_stage_list.GetData();} + const uint32_t GetStageCount ()const{return shader_stage_list.GetCount();} + const VkPipelineShaderStageCreateInfo * GetShaderStages ()const{return shader_stage_list.GetData();} - const VertexInputState *GetVertexInputState()const{return vertex_input_state;} - VertexInputStateInstance *CreateVertexInputStateInstance(); +public: //Vertex Input部分 + + VertexAttributeBinding * CreateVertexAttributeBinding(); + bool Release(VertexAttributeBinding *); + const uint32_t GetInstanceCount()const{return instance_set.GetCount();} + + const uint32_t GetAttrCount()const{return attr_count;} + + const int GetLocation (const UTF8String &)const; + const int GetBinding (const UTF8String &)const; + + const VkVertexInputBindingDescription * GetDescList ()const{return binding_list;} + const VkVertexInputAttributeDescription * GetAttrList ()const{return attribute_list;} + + const VkVertexInputBindingDescription * GetDesc (const uint32_t index)const{return (index>=attr_count?nullptr:binding_list+index);} + const VkVertexInputAttributeDescription * GetAttr (const uint32_t index)const{return (index>=attr_count?nullptr:attribute_list+index);} };//class ShaderCreater VK_NAMESPACE_END diff --git a/example/Vulkan/VKVertexInput.cpp b/example/Vulkan/VKVertexInput.cpp index 2ed4416e..91a631ee 100644 --- a/example/Vulkan/VKVertexInput.cpp +++ b/example/Vulkan/VKVertexInput.cpp @@ -1,90 +1,13 @@ #include"VKVertexInput.h" #include"VKBuffer.h" +#include"VKShader.h" VK_NAMESPACE_BEGIN -VertexInputState::~VertexInputState() +VertexAttributeBinding::VertexAttributeBinding(Shader *s) { - if(instance_set.GetCount()>0) - { - //还有在用的,这是个错误 - } -} + shader=s; -int VertexInputState::Add(const UTF8String &name,const uint32_t shader_location,const VkFormat format,uint32_t offset,bool instance) -{ - //binding对应在vkCmdBindVertexBuffer中设置的缓冲区序列号,所以这个数字必须从0开始,而且紧密排列。 - //在VertexInput类中,buf_list需要严格按照本类产生的binding为序列号 - - const int binding_index=binding_list.GetCount(); //参考opengl vab,binding_index必须从0开始,紧密排列。对应在vkCmdBindVertexBuffer中的缓冲区索引 - - binding_list.SetCount(binding_index+1); - attribute_list.SetCount(binding_index+1); - - VkVertexInputBindingDescription *binding=binding_list.GetData()+binding_index; - VkVertexInputAttributeDescription *attrib=attribute_list.GetData()+binding_index; - - binding->binding=binding_index; - binding->stride=GetStrideByFormat(format); - binding->inputRate=instance?VK_VERTEX_INPUT_RATE_INSTANCE:VK_VERTEX_INPUT_RATE_VERTEX; - - //实际使用可以一个binding绑多个attrib,但我们仅支持1v1。 - //一个binding是指在vertex shader中,由一个vertex输入流输入数据,attrib指其中的数据成分 - //比如在一个流中传递{pos,color}这样两个数据,就需要两个attrib - //但我们在一个流中,仅支持一个attrib传递 - - attrib->binding=binding_index; - attrib->location=shader_location; - attrib->format=format; - attrib->offset=offset; - - stage_input_locations.Add(name,attrib); - - return binding_index; -} - -const int VertexInputState::GetLocation(const UTF8String &name)const -{ - if(name.IsEmpty())return -1; - - VkVertexInputAttributeDescription *attr; - - if(!stage_input_locations.Get(name,attr)) - return -1; - - return attr->location; -} - -const int VertexInputState::GetBinding(const UTF8String &name)const -{ - if(name.IsEmpty())return -1; - - VkVertexInputAttributeDescription *attr; - - if(!stage_input_locations.Get(name,attr)) - return -1; - - return attr->binding; -} - -VertexInputStateInstance *VertexInputState::CreateInstance() -{ - VertexInputStateInstance *vis_instance=new VertexInputStateInstance(this); - - instance_set.Add(vis_instance); - - return(vis_instance); -} - -bool VertexInputState::Release(VertexInputStateInstance *vis_instance) -{ - return instance_set.Delete(vis_instance); -} - -VertexInputStateInstance::VertexInputStateInstance(VertexInputState *_vis) -{ - vis=_vis; - - const int count=vis->GetCount(); + const int count=shader->GetAttrCount(); if(count<=0) { @@ -92,46 +15,51 @@ VertexInputStateInstance::VertexInputStateInstance(VertexInputState *_vis) return; } - binding_list=hgl_copy_new(count,vis->GetDescList()); + binding_list=hgl_copy_new(count,shader->GetDescList()); } -VertexInputStateInstance::~VertexInputStateInstance() +VertexAttributeBinding::~VertexAttributeBinding() { delete[] binding_list; - vis->Release(this); + shader->Release(this); } -bool VertexInputStateInstance::SetInstance(const uint index,bool instance) +bool VertexAttributeBinding::SetInstance(const uint index,bool instance) { - if(index>=vis->GetCount())return(false); + if(index>=shader->GetAttrCount())return(false); binding_list[index].inputRate=instance?VK_VERTEX_INPUT_RATE_INSTANCE:VK_VERTEX_INPUT_RATE_VERTEX; return(true); } -void VertexInputStateInstance::Write(VkPipelineVertexInputStateCreateInfo &vis_create_info) const +bool VertexAttributeBinding::SetInstance(const UTF8String &name,bool instance) +{ + return SetInstance(shader->GetBinding(name),instance); +} + +void VertexAttributeBinding::Write(VkPipelineVertexInputStateCreateInfo &vis_create_info) const { vis_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - const uint32_t count=vis->GetCount(); + const uint32_t count=shader->GetAttrCount(); vis_create_info.vertexBindingDescriptionCount = count; vis_create_info.pVertexBindingDescriptions = binding_list; vis_create_info.vertexAttributeDescriptionCount = count; - vis_create_info.pVertexAttributeDescriptions = vis->GetAttrList(); + vis_create_info.pVertexAttributeDescriptions = shader->GetAttrList(); } -VertexInput::VertexInput(const VertexInputState *state) +VertexInput::VertexInput(const Shader *s) { - vis=state; + shader=s; - if(!vis) + if(!shader) return; - buf_count=vis->GetCount(); + buf_count=shader->GetAttrCount(); buf_list=hgl_zero_new(buf_count); buf_offset=hgl_zero_new(buf_count); @@ -147,8 +75,8 @@ bool VertexInput::Set(const int index,VertexBuffer *buf,VkDeviceSize offset) { if(index<0||index>=buf_count)return(false); - const VkVertexInputBindingDescription *desc=vis->GetDesc(index); - const VkVertexInputAttributeDescription *attr=vis->GetAttr(index); + const VkVertexInputBindingDescription *desc=shader->GetDesc(index); + const VkVertexInputAttributeDescription *attr=shader->GetAttr(index); if(buf->GetFormat()!=attr->format)return(false); if(buf->GetStride()!=desc->stride)return(false); @@ -158,4 +86,9 @@ bool VertexInput::Set(const int index,VertexBuffer *buf,VkDeviceSize offset) return(true); } + +bool VertexInput::Set(const UTF8String &name,VertexBuffer *vb,VkDeviceSize offset) +{ + return Set(shader->GetBinding(name),vb,offset); +} VK_NAMESPACE_END diff --git a/example/Vulkan/VKVertexInput.h b/example/Vulkan/VKVertexInput.h index b77e66d2..8e964610 100644 --- a/example/Vulkan/VKVertexInput.h +++ b/example/Vulkan/VKVertexInput.h @@ -3,83 +3,32 @@ #include"VK.h" #include -#include -#include VK_NAMESPACE_BEGIN class VertexBuffer; class IndexBuffer; -class VertexInputStateInstance; - -/** - * 顶点输入状态
- * 顶点输入状态用于记录数据是如果传递给Pipeline的,并不包含具体数据
- * 本类对象用于存放在Material中,只记录格式,并不能直接供pipeline使用 - */ -class VertexInputState -{ - List binding_list; - List attribute_list; - - Map stage_input_locations; - - Set instance_set; - -private: - - friend class Shader; - - VertexInputState()=default; - ~VertexInputState(); - - int Add(const UTF8String &name,const uint32_t shader_location,const VkFormat format,uint32_t offset=0,bool instance=false); - -public: - - void Clear() - { - binding_list.Clear(); - attribute_list.Clear(); - } - - const uint32_t GetCount ()const{return binding_list.GetCount();} - - const int GetLocation (const UTF8String &)const; - const int GetBinding (const UTF8String &)const; - - const VkVertexInputBindingDescription * GetDescList ()const{return binding_list.GetData();} - const VkVertexInputAttributeDescription * GetAttrList ()const{return attribute_list.GetData();} - - const VkVertexInputBindingDescription * GetDesc (const int index)const{return (index<0||index>=binding_list.GetCount()?nullptr:binding_list.GetData()+index);} - const VkVertexInputAttributeDescription * GetAttr (const int index)const{return (index<0||index>=attribute_list.GetCount()?nullptr:attribute_list.GetData()+index);} - -public: - - VertexInputStateInstance * CreateInstance(); - bool Release(VertexInputStateInstance *); - const uint32_t GetInstanceCount()const{return instance_set.GetCount();} -};//class VertexInputState +class Shader; /** * 顶点输入状态实例
* 本对象用于传递给MaterialInstance,用于已经确定好顶点格式的情况下,依然可修改部分设定(如instance)。 */ -class VertexInputStateInstance +class VertexAttributeBinding { - VertexInputState *vis; + Shader *shader; VkVertexInputBindingDescription *binding_list; private: - friend class VertexInputState; + friend class Shader; - VertexInputStateInstance(VertexInputState *); + VertexAttributeBinding(Shader *); public: - ~VertexInputStateInstance(); + ~VertexAttributeBinding(); bool SetInstance(const uint index,bool instance); - bool SetInstance(const UTF8String &name,bool instance){return SetInstance(vis->GetBinding(name),instance);} + bool SetInstance(const UTF8String &name,bool instance); void Write(VkPipelineVertexInputStateCreateInfo &vis)const; };//class VertexInputStateInstance @@ -90,7 +39,7 @@ public: */ class VertexInput { - const VertexInputState *vis; + const Shader *shader; int buf_count=0; VkBuffer *buf_list=nullptr; @@ -101,11 +50,11 @@ class VertexInput public: - VertexInput(const VertexInputState *); + VertexInput(const Shader *); virtual ~VertexInput(); bool Set(const int binding, VertexBuffer *vb,VkDeviceSize offset=0); - bool Set(const UTF8String &name,VertexBuffer *vb,VkDeviceSize offset=0){return Set(vis->GetBinding(name),vb,offset);} + bool Set(const UTF8String &name,VertexBuffer *vb,VkDeviceSize offset=0); bool Set(IndexBuffer *ib,VkDeviceSize offset=0) { diff --git a/example/Vulkan/main.cpp b/example/Vulkan/main.cpp index b235fd7e..6d16934a 100644 --- a/example/Vulkan/main.cpp +++ b/example/Vulkan/main.cpp @@ -113,12 +113,12 @@ constexpr float color_data[]={1,0,0, 0,1,0, 0,0,1 }; vulkan::VertexBuffer *vertex_buffer=nullptr; vulkan::VertexBuffer *color_buffer=nullptr; -vulkan::VertexInput *CreateVertexBuffer(vulkan::Device *dev,const vulkan::VertexInputState *vis) +vulkan::VertexInput *CreateVertexBuffer(vulkan::Device *dev,const vulkan::Shader *shader) { vertex_buffer =dev->CreateVBO(FMT_RG32F, 3,vertex_data); color_buffer =dev->CreateVBO(FMT_RGB32F, 3,color_data); - vulkan::VertexInput *vi=new vulkan::VertexInput(vis); + vulkan::VertexInput *vi=new vulkan::VertexInput(shader); vi->Set("Vertex", vertex_buffer); vi->Set("Color", color_buffer); @@ -188,9 +188,9 @@ int main(int,char **) vulkan::Buffer *ubo=CreateUBO(device); - vulkan::VertexInputStateInstance *vis_instance=shader->CreateVertexInputStateInstance(); + vulkan::VertexAttributeBinding *vis_instance=shader->CreateVertexAttributeBinding(); - vulkan::VertexInput *vi=CreateVertexBuffer(device,shader->GetVertexInputState()); + vulkan::VertexInput *vi=CreateVertexBuffer(device,shader); vulkan::PipelineCreater pc(device);