From 3bd896e99783fbdecae4969c5886e752c5471061 Mon Sep 17 00:00:00 2001 From: HuYingzhuo Date: Fri, 26 Apr 2019 21:43:22 +0800 Subject: [PATCH] =?UTF-8?q?VertexInput=E6=8B=86=E5=88=86=E4=B8=BAVertexInp?= =?UTF-8?q?tuState,VertexInputStateInstance?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- example/Vulkan/VKMaterial.cpp | 10 +++- example/Vulkan/VKMaterial.h | 7 ++- example/Vulkan/VKPipeline.cpp | 2 +- example/Vulkan/VKPipeline.h | 4 +- example/Vulkan/VKShader.cpp | 7 ++- example/Vulkan/VKShader.h | 9 ++-- example/Vulkan/VKVertexInput.cpp | 91 ++++++++++++++++++++++++++------ example/Vulkan/VKVertexInput.h | 83 +++++++++++++++++------------ example/Vulkan/main.cpp | 8 +-- 9 files changed, 156 insertions(+), 65 deletions(-) diff --git a/example/Vulkan/VKMaterial.cpp b/example/Vulkan/VKMaterial.cpp index 61ba7428..a05516a0 100644 --- a/example/Vulkan/VKMaterial.cpp +++ b/example/Vulkan/VKMaterial.cpp @@ -1,6 +1,7 @@ #include"VKMaterial.h" #include"VKDescriptorSets.h" #include"VKShader.h" +#include"VKVertexInput.h" VK_NAMESPACE_BEGIN Material::~Material() { @@ -10,6 +11,13 @@ Material::~Material() MaterialInstance *Material::CreateInstance() { - return(nullptr); + VertexInputStateInstance *vis_instance=vis->CreateInstance(); + + return(new MaterialInstance(this,vis_instance)); +} + +MaterialInstance::~MaterialInstance() +{ + delete vis_instance; } VK_NAMESPACE_END diff --git a/example/Vulkan/VKMaterial.h b/example/Vulkan/VKMaterial.h index 1f5382eb..0c8de14e 100644 --- a/example/Vulkan/VKMaterial.h +++ b/example/Vulkan/VKMaterial.h @@ -7,6 +7,7 @@ class Shader; class DescriptorSetLayoutCreater; class MaterialInstance; class VertexInputState; +class VertexInputStateInstance; /** * 材质类
@@ -37,13 +38,15 @@ public: */ class MaterialInstance { - Material *mat; + const Material *mat; ///<这里的是对material的完全引用,不做任何修改 + VertexInputStateInstance *vis_instance; ///<这里的vis是Material中vis的复制体 public: - MaterialInstance(Material *m) + MaterialInstance(Material *m,VertexInputStateInstance *vi) { mat=m; + vis_instance=vi; } ~MaterialInstance(); diff --git a/example/Vulkan/VKPipeline.cpp b/example/Vulkan/VKPipeline.cpp index e7e71ae6..511f1fff 100644 --- a/example/Vulkan/VKPipeline.cpp +++ b/example/Vulkan/VKPipeline.cpp @@ -162,7 +162,7 @@ bool PipelineCreater::Set(const Shader *s) return(true); } -bool PipelineCreater::Set(const VertexInputState *vis) +bool PipelineCreater::Set(const VertexInputStateInstance *vis) { if(!vis) return(false); diff --git a/example/Vulkan/VKPipeline.h b/example/Vulkan/VKPipeline.h index 4bb49708..bef10740 100644 --- a/example/Vulkan/VKPipeline.h +++ b/example/Vulkan/VKPipeline.h @@ -6,7 +6,7 @@ VK_NAMESPACE_BEGIN class Device; class RenderPass; -class VertexInputState; +class VertexInputStateInstance; class Pipeline { @@ -60,7 +60,7 @@ public: ~PipelineCreater()=default; bool Set(const Shader *); - bool Set(const VertexInputState *); + bool Set(const VertexInputStateInstance *); bool Set(const VkPrimitiveTopology,bool=false); bool Set(VkPipelineLayout pl); diff --git a/example/Vulkan/VKShader.cpp b/example/Vulkan/VKShader.cpp index bb8feba1..e557a7e2 100644 --- a/example/Vulkan/VKShader.cpp +++ b/example/Vulkan/VKShader.cpp @@ -1,4 +1,4 @@ -#include"VKShader.h" +#include"VKShader.h" #include"VKVertexInput.h" #include"spirv_cross.hpp" @@ -111,4 +111,9 @@ void Shader::Clear() shader_stage_list.Clear(); vertex_input_state->Clear(); } + +VertexInputStateInstance *Shader::CreateVertexInputStateInstance() +{ + return vertex_input_state->CreateInstance(); +} VK_NAMESPACE_END diff --git a/example/Vulkan/VKShader.h b/example/Vulkan/VKShader.h index 44c79093..86e7981f 100644 --- a/example/Vulkan/VKShader.h +++ b/example/Vulkan/VKShader.h @@ -1,12 +1,12 @@ -#pragma once +#pragma once #include"VK.h" VK_NAMESPACE_BEGIN - class VertexInputState; +class VertexInputStateInstance; /** - * Shader + * Shader 创建器 */ class Shader { @@ -52,6 +52,7 @@ public: const uint32_t GetCount ()const{return shader_stage_list.GetCount();} const VkPipelineShaderStageCreateInfo * GetStages ()const{return shader_stage_list.GetData();} - VertexInputState *GetVIS(){return vertex_input_state;} + const VertexInputState *GetVertexInputState()const{return vertex_input_state;} + VertexInputStateInstance *CreateVertexInputStateInstance(); };//class ShaderCreater VK_NAMESPACE_END diff --git a/example/Vulkan/VKVertexInput.cpp b/example/Vulkan/VKVertexInput.cpp index 6231f49d..2ed4416e 100644 --- a/example/Vulkan/VKVertexInput.cpp +++ b/example/Vulkan/VKVertexInput.cpp @@ -2,9 +2,19 @@ #include"VKBuffer.h" VK_NAMESPACE_BEGIN +VertexInputState::~VertexInputState() +{ + if(instance_set.GetCount()>0) + { + //还有在用的,这是个错误 + } +} 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); @@ -27,7 +37,7 @@ int VertexInputState::Add(const UTF8String &name,const uint32_t shader_location, attrib->format=format; attrib->offset=offset; - stage_input_locations.Add(name,StageInput(binding_index,shader_location,format)); + stage_input_locations.Add(name,attrib); return binding_index; } @@ -36,38 +46,85 @@ const int VertexInputState::GetLocation(const UTF8String &name)const { if(name.IsEmpty())return -1; - StageInput si; + VkVertexInputAttributeDescription *attr; - if(!stage_input_locations.Get(name,si)) + if(!stage_input_locations.Get(name,attr)) return -1; - return si.location; + return attr->location; } const int VertexInputState::GetBinding(const UTF8String &name)const { if(name.IsEmpty())return -1; - StageInput si; + VkVertexInputAttributeDescription *attr; - if(!stage_input_locations.Get(name,si)) + if(!stage_input_locations.Get(name,attr)) return -1; - return si.binding; + return attr->binding; } -void VertexInputState::Write(VkPipelineVertexInputStateCreateInfo &vis) const +VertexInputStateInstance *VertexInputState::CreateInstance() { - vis.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + VertexInputStateInstance *vis_instance=new VertexInputStateInstance(this); - vis.vertexBindingDescriptionCount = binding_list.GetCount(); - vis.pVertexBindingDescriptions = binding_list.GetData(); + instance_set.Add(vis_instance); - vis.vertexAttributeDescriptionCount = attribute_list.GetCount(); - vis.pVertexAttributeDescriptions = attribute_list.GetData(); + return(vis_instance); } -VertexInput::VertexInput(VertexInputState *state) +bool VertexInputState::Release(VertexInputStateInstance *vis_instance) +{ + return instance_set.Delete(vis_instance); +} + +VertexInputStateInstance::VertexInputStateInstance(VertexInputState *_vis) +{ + vis=_vis; + + const int count=vis->GetCount(); + + if(count<=0) + { + binding_list=nullptr; + return; + } + + binding_list=hgl_copy_new(count,vis->GetDescList()); +} + +VertexInputStateInstance::~VertexInputStateInstance() +{ + delete[] binding_list; + + vis->Release(this); +} + +bool VertexInputStateInstance::SetInstance(const uint index,bool instance) +{ + if(index>=vis->GetCount())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 +{ + vis_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + + const uint32_t count=vis->GetCount(); + + vis_create_info.vertexBindingDescriptionCount = count; + vis_create_info.pVertexBindingDescriptions = binding_list; + + vis_create_info.vertexAttributeDescriptionCount = count; + vis_create_info.pVertexAttributeDescriptions = vis->GetAttrList(); +} + +VertexInput::VertexInput(const VertexInputState *state) { vis=state; @@ -86,12 +143,12 @@ VertexInput::~VertexInput() delete[] buf_list; } -bool VertexInput::Set(int index,VertexBuffer *buf,VkDeviceSize offset) +bool VertexInput::Set(const int index,VertexBuffer *buf,VkDeviceSize offset) { if(index<0||index>=buf_count)return(false); - VkVertexInputBindingDescription *desc=vis->GetDesc(index); - VkVertexInputAttributeDescription *attr=vis->GetAttr(index); + const VkVertexInputBindingDescription *desc=vis->GetDesc(index); + const VkVertexInputAttributeDescription *attr=vis->GetAttr(index); if(buf->GetFormat()!=attr->format)return(false); if(buf->GetStride()!=desc->stride)return(false); diff --git a/example/Vulkan/VKVertexInput.h b/example/Vulkan/VKVertexInput.h index 3d96e476..9ef287d1 100644 --- a/example/Vulkan/VKVertexInput.h +++ b/example/Vulkan/VKVertexInput.h @@ -4,44 +4,30 @@ #include"VK.h" #include #include +#include VK_NAMESPACE_BEGIN class VertexBuffer; class IndexBuffer; +class VertexInputStateInstance; /** * 顶点输入状态
- * 顶点输入状态用于记录数据是如果传递给Pipeline的,并不包含具体数据 + * 顶点输入状态用于记录数据是如果传递给Pipeline的,并不包含具体数据
+ * 本类对象用于存放在Material中,只记录格式,并不能直接供pipeline使用 */ class VertexInputState { List binding_list; List attribute_list; - struct StageInput - { - int binding; - VkFormat format; + Map stage_input_locations; - uint32_t location; + Set instance_set; - public: - - StageInput(){} - StageInput(const int b,const uint32_t l,const VkFormat f) - { - binding=b; - location=l; - format=f; - } - - CompOperatorMemcmp(const StageInput &); - };//struct StageInput - - Map stage_input_locations; public: VertexInputState()=default; - ~VertexInputState()=default; + ~VertexInputState(); int Add(const UTF8String &name,const uint32_t shader_location,const VkFormat format,uint32_t offset=0,bool instance=false); @@ -53,25 +39,56 @@ public: attribute_list.Clear(); } - const uint32_t GetCount()const{return binding_list.GetCount();} + const uint32_t GetCount ()const{return binding_list.GetCount();} + const int GetLocation (const UTF8String &)const; + const int GetBinding (const UTF8String &)const; - 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();} - VkVertexInputBindingDescription * GetDesc(const int index){return (index<0||index>=binding_list.GetCount()?nullptr:binding_list.GetData()+index);} - VkVertexInputAttributeDescription * GetAttr(const int index){return (index<0||index>=attribute_list.GetCount()?nullptr:attribute_list.GetData()+index);} + 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);} - void Write(VkPipelineVertexInputStateCreateInfo &vis)const; -};//class VertexInputStateCreater +public: + + VertexInputStateInstance * CreateInstance(); + bool Release(VertexInputStateInstance *); + const uint32_t GetInstanceCount()const{return instance_set.GetCount();} +};//class VertexInputState /** - * 顶点输入配置,类似于OpenGL的VAB
- * 注:本引擎不支持一个BUFFER中包括多种数据 + * 顶点输入状态实例
+ * 本对象用于传递给MaterialInstance,用于已经确定好顶点格式的情况下,依然可修改部分设定(如instance)。 + */ +class VertexInputStateInstance +{ + VertexInputState *vis; + VkVertexInputBindingDescription *binding_list; + +private: + + friend class VertexInputState; + + VertexInputStateInstance(VertexInputState *); + +public: + + ~VertexInputStateInstance(); + + bool SetInstance(const uint index,bool instance); + bool SetInstance(const UTF8String &name,bool instance){return SetInstance(vis->GetBinding(name),instance);} + + void Write(VkPipelineVertexInputStateCreateInfo &vis)const; +};//class VertexInputStateInstance + +/** + * 顶点输入配置,负责具体的buffer绑定,提供给CommandBuffer使用
+ * 注:本引擎不支持一个Buffer中包括多种数据 */ class VertexInput { - VertexInputState *vis; + const VertexInputState *vis; int buf_count=0; VkBuffer *buf_list=nullptr; @@ -82,10 +99,10 @@ class VertexInput public: - VertexInput(VertexInputState *); + VertexInput(const VertexInputState *); virtual ~VertexInput(); - bool Set(int binding,VertexBuffer *,VkDeviceSize offset=0); + 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(IndexBuffer *ib,VkDeviceSize offset=0) diff --git a/example/Vulkan/main.cpp b/example/Vulkan/main.cpp index d61fd107..b235fd7e 100644 --- a/example/Vulkan/main.cpp +++ b/example/Vulkan/main.cpp @@ -113,7 +113,7 @@ 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,vulkan::VertexInputState *vis) +vulkan::VertexInput *CreateVertexBuffer(vulkan::Device *dev,const vulkan::VertexInputState *vis) { vertex_buffer =dev->CreateVBO(FMT_RG32F, 3,vertex_data); color_buffer =dev->CreateVBO(FMT_RGB32F, 3,color_data); @@ -188,9 +188,9 @@ int main(int,char **) vulkan::Buffer *ubo=CreateUBO(device); - vulkan::VertexInputState *vis=shader->GetVIS(); + vulkan::VertexInputStateInstance *vis_instance=shader->CreateVertexInputStateInstance(); - vulkan::VertexInput *vi=CreateVertexBuffer(device,vis); + vulkan::VertexInput *vi=CreateVertexBuffer(device,shader->GetVertexInputState()); vulkan::PipelineCreater pc(device); @@ -211,7 +211,7 @@ int main(int,char **) pc.CloseCullFace(); pc.Set(shader); - pc.Set(vis); + pc.Set(vis_instance); pc.Set(PRIM_TRIANGLES); pc.Set(*pl);