通过SPRIV-Cross获取shader中顶点输入变量名称和类型等,自动创建VertexInputState。提供根据名称获取binding,location的功能
This commit is contained in:
parent
bb1bc4f7a0
commit
d485dd90e3
@ -1,53 +1,90 @@
|
||||
#include"VKShader.h"
|
||||
#include"VKVertexInput.h"
|
||||
#include"spirv_cross.hpp"
|
||||
|
||||
VK_NAMESPACE_BEGIN
|
||||
const VkFormat GetVecFormat(const spirv_cross::SPIRType &type)
|
||||
{
|
||||
if(type.basetype==spirv_cross::SPIRType::Float)
|
||||
{
|
||||
constexpr VkFormat format[4]={FMT_R32F,FMT_RG32F,FMT_RGB32F,FMT_RGB32F};
|
||||
|
||||
void shader_dump(const void *spv_data,const uint32_t spv_size)
|
||||
return format[type.vecsize-1];
|
||||
}
|
||||
else
|
||||
if(type.basetype==spirv_cross::SPIRType::Half)
|
||||
{
|
||||
constexpr VkFormat format[4]={FMT_R16F,FMT_RG16F,FMT_RGB16F,FMT_RGB16F};
|
||||
|
||||
return format[type.vecsize-1];
|
||||
}
|
||||
else
|
||||
if(type.basetype==spirv_cross::SPIRType::UInt)
|
||||
{
|
||||
constexpr VkFormat format[4]={FMT_R32U,FMT_RG32U,FMT_RGB32U,FMT_RGB32U};
|
||||
|
||||
return format[type.vecsize-1];
|
||||
}
|
||||
else
|
||||
if(type.basetype==spirv_cross::SPIRType::Int)
|
||||
{
|
||||
constexpr VkFormat format[4]={FMT_R32I,FMT_RG32I,FMT_RGB32I,FMT_RGB32I};
|
||||
|
||||
return format[type.vecsize-1];
|
||||
}
|
||||
else
|
||||
if(type.basetype==spirv_cross::SPIRType::UShort)
|
||||
{
|
||||
constexpr VkFormat format[4]={FMT_R16U,FMT_RG16U,FMT_RGB16U,FMT_RGB16U};
|
||||
|
||||
return format[type.vecsize-1];
|
||||
}
|
||||
else
|
||||
if(type.basetype==spirv_cross::SPIRType::Short)
|
||||
{
|
||||
constexpr VkFormat format[4]={FMT_R16I,FMT_RG16I,FMT_RGB16I,FMT_RGB16I};
|
||||
|
||||
return format[type.vecsize-1];
|
||||
}
|
||||
|
||||
return VK_FORMAT_UNDEFINED;
|
||||
}
|
||||
|
||||
bool Shader::CreateVIS(const void *spv_data,const uint32_t spv_size)
|
||||
{
|
||||
spirv_cross::Compiler comp((const uint32_t *)spv_data,spv_size/sizeof(uint32_t));
|
||||
|
||||
spirv_cross::ShaderResources res=comp.get_shader_resources();
|
||||
|
||||
for(auto &ref:res.sampled_images)
|
||||
for(auto &si:res.stage_inputs)
|
||||
{
|
||||
unsigned set=comp.get_decoration(ref.id,spv::DecorationDescriptorSet);
|
||||
unsigned binding=comp.get_decoration(ref.id,spv::DecorationBinding);
|
||||
const std::string name=comp.get_name(ref.id);
|
||||
const spirv_cross::SPIRType & type =comp.get_type(si.type_id);
|
||||
const VkFormat format =GetVecFormat(type);
|
||||
|
||||
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();
|
||||
|
||||
const int binding=vertex_input_state->Add(name,location,format);
|
||||
|
||||
std::cout<<"sampled image ["<<ref.id<<":"<<name.c_str()<<"] set="<<set<<",binding="<<binding<<",type:"<<ref.type_id<<",base type:"<<ref.base_type_id<<std::endl;
|
||||
}
|
||||
|
||||
for(auto &ref:res.stage_inputs)
|
||||
{
|
||||
unsigned set=comp.get_decoration(ref.id,spv::DecorationDescriptorSet);
|
||||
unsigned location=comp.get_decoration(ref.id,spv::DecorationLocation);
|
||||
const std::string name=comp.get_name(ref.id);
|
||||
return(true);
|
||||
}
|
||||
|
||||
std::cout<<"stage input ["<<ref.id<<":"<<name.c_str()<<"] set="<<set<<",location="<<location<<",type:"<<ref.type_id<<",base type:"<<ref.base_type_id<<std::endl;
|
||||
}
|
||||
Shader::Shader(VkDevice dev)
|
||||
{
|
||||
device=dev;
|
||||
|
||||
for(auto &ref:res.uniform_buffers)
|
||||
{
|
||||
unsigned set=comp.get_decoration(ref.id,spv::DecorationDescriptorSet);
|
||||
unsigned binding=comp.get_decoration(ref.id,spv::DecorationBinding);
|
||||
const std::string name=comp.get_name(ref.id);
|
||||
|
||||
std::cout<<"UBO ["<<ref.id<<":"<<name.c_str()<<"] set="<<set<<",binding="<<binding<<",type:"<<ref.type_id<<",base type:"<<ref.base_type_id<<std::endl;
|
||||
}
|
||||
|
||||
for(auto &ref:res.stage_outputs)
|
||||
{
|
||||
unsigned set=comp.get_decoration(ref.id,spv::DecorationDescriptorSet);
|
||||
unsigned location=comp.get_decoration(ref.id,spv::DecorationLocation);
|
||||
const std::string name=comp.get_name(ref.id);
|
||||
|
||||
std::cout<<"stage output ["<<ref.id<<":"<<name.c_str()<<"] set="<<set<<",location="<<location<<",type:"<<ref.type_id<<",base type:"<<ref.base_type_id<<std::endl;
|
||||
}
|
||||
vertex_input_state=new VertexInputState();
|
||||
}
|
||||
|
||||
Shader::~Shader()
|
||||
{
|
||||
delete vertex_input_state;
|
||||
|
||||
const int count=shader_stage_list.GetCount();
|
||||
|
||||
if(count>0)
|
||||
@ -63,7 +100,8 @@ Shader::~Shader()
|
||||
|
||||
bool Shader::Add(const VkShaderStageFlagBits shader_stage_bit,const void *spv_data,const uint32_t spv_size)
|
||||
{
|
||||
shader_dump(spv_data,spv_size);
|
||||
if(shader_stage_bit==VK_SHADER_STAGE_VERTEX_BIT)
|
||||
CreateVIS(spv_data,spv_size);
|
||||
|
||||
VkPipelineShaderStageCreateInfo shader_stage;
|
||||
shader_stage.sType=VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||
@ -87,4 +125,10 @@ bool Shader::Add(const VkShaderStageFlagBits shader_stage_bit,const void *spv_da
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
void Shader::Clear()
|
||||
{
|
||||
shader_stage_list.Clear();
|
||||
vertex_input_state->Clear();
|
||||
}
|
||||
VK_NAMESPACE_END
|
||||
|
@ -2,6 +2,9 @@
|
||||
#include"VK.h"
|
||||
|
||||
VK_NAMESPACE_BEGIN
|
||||
|
||||
class VertexInputState;
|
||||
|
||||
/**
|
||||
* Shader ´´½¨Æ÷
|
||||
*/
|
||||
@ -11,9 +14,15 @@ class Shader
|
||||
|
||||
List<VkPipelineShaderStageCreateInfo> shader_stage_list;
|
||||
|
||||
VertexInputState *vertex_input_state=nullptr;
|
||||
|
||||
private:
|
||||
|
||||
bool CreateVIS(const void *,const uint32_t);
|
||||
|
||||
public:
|
||||
|
||||
Shader(VkDevice dev):device(dev){}
|
||||
Shader(VkDevice);
|
||||
~Shader();
|
||||
|
||||
bool Add(const VkShaderStageFlagBits shader_stage_bit,const void *spv_data,const uint32_t spv_size);
|
||||
@ -38,12 +47,11 @@ public:
|
||||
ADD_NV_SHADER_FUNC(Mesh, MESH);
|
||||
#undef ADD_NV_SHADER_FUNC
|
||||
|
||||
void Clear()
|
||||
{
|
||||
shader_stage_list.Clear();
|
||||
}
|
||||
void Clear();
|
||||
|
||||
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;}
|
||||
};//class ShaderCreater
|
||||
VK_NAMESPACE_END
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
VK_NAMESPACE_BEGIN
|
||||
|
||||
void VertexInputState::Add(const uint32_t shader_location,const VkFormat format,uint32_t offset,bool instance)
|
||||
int VertexInputState::Add(const UTF8String &name,const uint32_t shader_location,const VkFormat format,uint32_t offset,bool instance)
|
||||
{
|
||||
const int binding_index=binding_list.GetCount(); //参考opengl vab,binding_index必须从0开始,紧密排列。对应在vkCmdBindVertexBuffer中的缓冲区索引
|
||||
|
||||
@ -25,7 +25,35 @@ void VertexInputState::Add(const uint32_t shader_location,const VkFormat format,
|
||||
attrib->binding=binding_index;
|
||||
attrib->location=shader_location;
|
||||
attrib->format=format;
|
||||
attrib->offset=offset;
|
||||
attrib->offset=offset;
|
||||
|
||||
stage_input_locations.Add(name,StageInput(binding_index,shader_location,format));
|
||||
|
||||
return binding_index;
|
||||
}
|
||||
|
||||
const int VertexInputState::GetLocation(const UTF8String &name)const
|
||||
{
|
||||
if(name.IsEmpty())return -1;
|
||||
|
||||
StageInput si;
|
||||
|
||||
if(!stage_input_locations.Get(name,si))
|
||||
return -1;
|
||||
|
||||
return si.location;
|
||||
}
|
||||
|
||||
const int VertexInputState::GetBinding(const UTF8String &name)const
|
||||
{
|
||||
if(name.IsEmpty())return -1;
|
||||
|
||||
StageInput si;
|
||||
|
||||
if(!stage_input_locations.Get(name,si))
|
||||
return -1;
|
||||
|
||||
return si.binding;
|
||||
}
|
||||
|
||||
void VertexInputState::Write(VkPipelineVertexInputStateCreateInfo &vis) const
|
||||
@ -58,7 +86,7 @@ VertexInput::~VertexInput()
|
||||
delete[] buf_list;
|
||||
}
|
||||
|
||||
bool VertexInput::Set(uint32_t index,VertexBuffer *buf,VkDeviceSize offset)
|
||||
bool VertexInput::Set(int index,VertexBuffer *buf,VkDeviceSize offset)
|
||||
{
|
||||
if(index<0||index>=buf_count)return(false);
|
||||
|
||||
|
@ -2,6 +2,8 @@
|
||||
#define HGL_GRAPH_VULKAN_VERTEX_INPUT_INCLUDE
|
||||
|
||||
#include"VK.h"
|
||||
#include<hgl/type/BaseString.h>
|
||||
#include<hgl/type/Map.h>
|
||||
VK_NAMESPACE_BEGIN
|
||||
class VertexBuffer;
|
||||
class IndexBuffer;
|
||||
@ -15,17 +17,48 @@ class VertexInputState
|
||||
List<VkVertexInputBindingDescription> binding_list;
|
||||
List<VkVertexInputAttributeDescription> attribute_list;
|
||||
|
||||
struct StageInput
|
||||
{
|
||||
int binding;
|
||||
VkFormat format;
|
||||
|
||||
uint32_t location;
|
||||
|
||||
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<UTF8String,StageInput> stage_input_locations;
|
||||
public:
|
||||
|
||||
VertexInputState()=default;
|
||||
~VertexInputState()=default;
|
||||
|
||||
void Add(const uint32_t shader_location,const VkFormat format,uint32_t offset=0,bool instance=false);
|
||||
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;
|
||||
|
||||
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);}
|
||||
|
||||
@ -40,7 +73,7 @@ class VertexInput
|
||||
{
|
||||
VertexInputState *vis;
|
||||
|
||||
uint32_t buf_count=0;
|
||||
int buf_count=0;
|
||||
VkBuffer *buf_list=nullptr;
|
||||
VkDeviceSize *buf_offset=nullptr;
|
||||
|
||||
@ -52,7 +85,9 @@ public:
|
||||
VertexInput(VertexInputState *);
|
||||
virtual ~VertexInput();
|
||||
|
||||
bool Set(uint32_t index,VertexBuffer *,VkDeviceSize offset=0);
|
||||
bool Set(int binding,VertexBuffer *,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)
|
||||
{
|
||||
if(!ib)return(false);
|
||||
@ -64,7 +99,7 @@ public:
|
||||
|
||||
public:
|
||||
|
||||
const uint32_t GetCount ()const{return buf_count;}
|
||||
const int GetCount ()const{return buf_count;}
|
||||
const VkBuffer * GetBuffer ()const{return buf_list;}
|
||||
const VkDeviceSize * GetOffset ()const{return buf_offset;}
|
||||
|
||||
|
@ -102,9 +102,6 @@ vulkan::Buffer *CreateUBO(vulkan::Device *dev)
|
||||
return ubo;
|
||||
}
|
||||
|
||||
constexpr uint32_t SHADER_LOCATION_POSITION =0; //对应shader中的layout(locaiton=0,暂时这样写
|
||||
constexpr uint32_t SHADER_LOCATION_COLOR =1;
|
||||
|
||||
constexpr float vertex_data[]=
|
||||
{
|
||||
SCREEN_WIDTH*0.5, SCREEN_HEIGHT*0.25,
|
||||
@ -113,16 +110,6 @@ constexpr float vertex_data[]=
|
||||
};
|
||||
constexpr float color_data[]={1,0,0, 0,1,0, 0,0,1 };
|
||||
|
||||
vulkan::VertexInputState *InitVertexInput()
|
||||
{
|
||||
vulkan::VertexInputState *vis=new vulkan::VertexInputState();
|
||||
|
||||
vis->Add(SHADER_LOCATION_POSITION, FMT_RG32F);
|
||||
vis->Add(SHADER_LOCATION_COLOR, FMT_RGB32F);
|
||||
|
||||
return vis;
|
||||
}
|
||||
|
||||
vulkan::VertexBuffer *vertex_buffer=nullptr;
|
||||
vulkan::VertexBuffer *color_buffer=nullptr;
|
||||
|
||||
@ -133,8 +120,8 @@ vulkan::VertexInput *CreateVertexBuffer(vulkan::Device *dev,vulkan::VertexInputS
|
||||
|
||||
vulkan::VertexInput *vi=new vulkan::VertexInput(vis);
|
||||
|
||||
vi->Set(SHADER_LOCATION_POSITION, vertex_buffer);
|
||||
vi->Set(SHADER_LOCATION_COLOR, color_buffer);
|
||||
vi->Set("Vertex", vertex_buffer);
|
||||
vi->Set("Color", color_buffer);
|
||||
|
||||
return vi;
|
||||
}
|
||||
@ -201,7 +188,7 @@ int main(int,char **)
|
||||
|
||||
vulkan::Buffer *ubo=CreateUBO(device);
|
||||
|
||||
vulkan::VertexInputState *vis=InitVertexInput();
|
||||
vulkan::VertexInputState *vis=shader->GetVIS();
|
||||
|
||||
vulkan::VertexInput *vi=CreateVertexBuffer(device,vis);
|
||||
|
||||
@ -259,7 +246,6 @@ int main(int,char **)
|
||||
delete dsl;
|
||||
|
||||
delete vi;
|
||||
delete vis;
|
||||
delete ubo;
|
||||
|
||||
delete shader;
|
||||
|
Loading…
x
Reference in New Issue
Block a user