ULRE/src/SceneGraph/Vulkan/VKRenderResourceMaterial.cpp

282 lines
7.2 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include<hgl/graph/VKShaderModule.h>
#include<hgl/graph/VKMaterial.h>
#include<hgl/graph/VKDevice.h>
#include<hgl/graph/VKShaderModuleMap.h>
#include<hgl/graph/VKShaderResource.h>
#include<hgl/graph/VKMaterialDescriptorManager.h>
#include<hgl/graph/VKVertexInput.h>
#include<hgl/filesystem/FileSystem.h>
#include<hgl/graph/VKRenderResource.h>
#include<hgl/io/ConstBufferReader.h>
#include<hgl/shadergen/MaterialCreateInfo.h>
#include<hgl/shadergen/ShaderDescriptorInfo.h>
VK_NAMESPACE_BEGIN
const ShaderModule *RenderResource::CreateShaderModule(const OSString &filename,VkShaderStageFlagBits shader_stage,const uint32_t *spv_data,const size_t spv_size)
{
if(!device)return(nullptr);
if(filename.IsEmpty())return(nullptr);
if(!spv_data)return(nullptr);
if(spv_size<4)return(nullptr);
ShaderModule *sm;
if(shader_module_by_name.Get(filename,sm))
return sm;
sm=device->CreateShaderModule(shader_stage,spv_data,spv_size);
shader_module_by_name.Add(filename,sm);
#ifdef _DEBUG
{
auto da=device->GetDeviceAttribute();
const UTF8String sn=ToUTF8String(filename);
if(da->debug_maker)
da->debug_maker->SetShaderModule(*sm,sn);
if(da->debug_utils)
da->debug_utils->SetShaderModule(*sm,sn);
}
#endif//_DEBUG
return sm;
}
void LoadShaderDescriptor(io::ConstBufferReader &cbr,ShaderDescriptor *sd_list,const uint count,const uint8 ver)
{
ShaderDescriptor *sd=sd_list;
for(uint i=0;i<count;i++)
{
cbr.CastRead<uint8>(sd->desc_type);
cbr.ReadTinyString(sd->name);
if(ver==3)
cbr.CastRead<uint8>(sd->set_type);
else
if(ver==2) //以下是旧的,未来不用了,现仅保证能运行
{
if(sd->name[0]=='g')sd->set_type=DescriptorSetType::Global;else
//if(sd->name[0]=='m')sd->set_type=DescriptorSetType::PerMaterial;else
//if(sd->name[0]=='r')sd->set_type=DescriptorSetType::PerObject;else
sd->set_type=DescriptorSetType::PerMaterial;
}
cbr.Read(sd->set);
cbr.Read(sd->binding);
cbr.Read(sd->stage_flag);
//if(sd->set_type>=DescriptorSetType::PerObject)
//{
// if(sd->desc_type==VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER)sd->desc_type=VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;else
// if(sd->desc_type==VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)sd->desc_type=VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
//}
++sd;
}
}
ShaderResource *LoadShaderResource(io::ConstBufferReader &cbr);
Material *RenderResource::CreateMaterial(const OSString &filename)
{
Material *mtl;
if(material_by_name.Get(filename,mtl))
return mtl;
constexpr char MaterialFileHeader[]=u8"Material\x1A";
constexpr uint MaterialFileHeaderLength=sizeof(MaterialFileHeader)-1;
int64 filesize;
uint8 *filedata=(uint8 *)filesystem::LoadFileToMemory(filename+OS_TEXT(".material"),filesize);
if(!filedata)
{
material_by_name.Add(filename,nullptr);
return(nullptr);
}
AutoDeleteArray<uint8> origin_filedata(filedata,filesize);
if(filesize<MaterialFileHeaderLength)
return(nullptr);
io::ConstBufferReader cbr(filedata,filesize);
if(memcmp(cbr.CurPointer(),MaterialFileHeader,MaterialFileHeaderLength)!=0)
return(nullptr);
cbr.Skip(MaterialFileHeaderLength);
uint8 ver;
cbr.Read(ver);
if(ver<2||ver>3)
return(nullptr);
uint32_t shader_bits;
cbr.Read(shader_bits);
const uint count=GetShaderCountByBits(shader_bits);
uint32_t size;
ShaderResource *sr;
const ShaderModule *sm;
bool result=true;
ShaderModuleMap *smm=new ShaderModuleMap;
VertexInput *vertex_input=nullptr;
OSString shader_name;
for(uint i=0;i<count;i++)
{
cbr.Read(size);
sr=LoadShaderResource(io::ConstBufferReader(cbr,size)); //有一个stage output没读放弃了所以不能直接用上一级的cbr
cbr.Skip(size);
if(sr)
{
shader_name=filename+OS_TEXT("?")+ToOSString(sr->GetStageName());
sm=CreateShaderModule(shader_name,sr->GetStage(),sr->GetSPVData(),sr->GetSPVSize());
if(sm)
{
if(smm->Add(sm))
{
if(sr->GetStage()==VK_SHADER_STAGE_VERTEX_BIT)
vertex_input=new VertexInput(sr->GetInputs());
continue;
}
}
}
result=false;
break;
}
const UTF8String mtl_name=ToUTF8String(filename);
MaterialDescriptorManager *desc_manager=nullptr;
{
uint8 count;
cbr.Read(count);
if(count>0)
{
ShaderDescriptor *sd_list=new ShaderDescriptor[count];
LoadShaderDescriptor(cbr,sd_list,count,ver);
desc_manager=new MaterialDescriptorManager(mtl_name,sd_list,count);
delete[] sd_list;
}
}
if(result&&vertex_input)
{
mtl=device->CreateMaterial(mtl_name,smm,desc_manager,vertex_input);
Add(mtl);
}
else
{
SAFE_CLEAR(desc_manager);
delete smm;
mtl=nullptr;
}
material_by_name.Add(filename,mtl);
return(mtl);
}
Material *RenderResource::CreateMaterial(const MaterialCreateInfo *mci)
{
if(!mci)
return(nullptr);
Material *mtl;
const OSString mtl_name=ToOSString(mci->GetName());
if(material_by_name.Get(mtl_name,mtl))
return mtl;
const uint count=GetShaderCountByBits(mci->GetShaderStage());
const ShaderModule *sm;
ShaderModuleMap *smm=new ShaderModuleMap;
VertexInput *vertex_input=nullptr;
const ShaderCreateInfoVertex *vert=mci->GetVS();
if(vert)
{
sm=CreateShaderModule( mtl_name+OS_TEXT("?Vertex"),
VK_SHADER_STAGE_VERTEX_BIT,
vert->GetSPVData(),vert->GetSPVSize());
if(!sm)
return(false);
if(smm->Add(sm))
vertex_input=new VertexInput(vert->sdm->GetShaderStageIO().input);
}
const ShaderCreateInfoGeometry *geom=mci->GetGS();
if(geom)
{
sm=CreateShaderModule( mtl_name+OS_TEXT("?Geometry"),
VK_SHADER_STAGE_GEOMETRY_BIT,
geom->GetSPVData(),geom->GetSPVSize());
smm->Add(sm);
}
const ShaderCreateInfoFragment *frag=mci->GetFS();
if(frag)
{
sm=CreateShaderModule( mtl_name+OS_TEXT("?Fragment"),
VK_SHADER_STAGE_FRAGMENT_BIT,
frag->GetSPVData(),frag->GetSPVSize());
smm->Add(sm);
}
MaterialDescriptorManager *mdm=nullptr;
{
const auto &mdi=mci->GetMDI();
if(mdi.GetCount()>0)
mdm=new MaterialDescriptorManager(mci->GetName(),mdi.Get());
}
mtl=device->CreateMaterial(mci->GetName(),smm,mdm,vertex_input);
if(!mtl)
{
delete mdm;
delete smm;
}
else
{
Add(mtl);
}
material_by_name.Add(mtl_name,mtl);
return mtl;
}
VK_NAMESPACE_END