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);