Add support for using #include in postprocess shaders

This commit is contained in:
Magnus Norddahl 2023-12-14 12:28:11 +01:00
commit dfae2a25b0
2 changed files with 48 additions and 0 deletions

View file

@ -38,12 +38,16 @@ VkPPShader::VkPPShader(VulkanRenderDevice* fb, PPShader *shader) : fb(fb)
VertexShader = ShaderBuilder()
.Type(ShaderType::Vertex)
.AddSource(shader->VertexShader.GetChars(), LoadShaderCode(shader->VertexShader, "", shader->Version).GetChars())
.OnIncludeLocal([=](std::string headerName, std::string includerName, size_t depth) { return OnInclude(headerName.c_str(), includerName.c_str(), depth, false); })
.OnIncludeSystem([=](std::string headerName, std::string includerName, size_t depth) { return OnInclude(headerName.c_str(), includerName.c_str(), depth, true); })
.DebugName(shader->VertexShader.GetChars())
.Create(shader->VertexShader.GetChars(), fb->GetDevice());
FragmentShader = ShaderBuilder()
.Type(ShaderType::Fragment)
.AddSource(shader->FragmentShader.GetChars(), LoadShaderCode(shader->FragmentShader, prolog, shader->Version).GetChars())
.OnIncludeLocal([=](std::string headerName, std::string includerName, size_t depth) { return OnInclude(headerName.c_str(), includerName.c_str(), depth, false); })
.OnIncludeSystem([=](std::string headerName, std::string includerName, size_t depth) { return OnInclude(headerName.c_str(), includerName.c_str(), depth, true); })
.DebugName(shader->FragmentShader.GetChars())
.Create(shader->FragmentShader.GetChars(), fb->GetDevice());
@ -65,6 +69,45 @@ void VkPPShader::Reset()
}
}
ShaderIncludeResult VkPPShader::OnInclude(FString headerName, FString includerName, size_t depth, bool system)
{
if (depth > 8)
I_Error("Too much include recursion!");
FString includeguardname;
includeguardname << "_HEADERGUARD_" << headerName.GetChars();
includeguardname.ReplaceChars("/\\.", '_');
FString code;
code << "#ifndef " << includeguardname.GetChars() << "\n";
code << "#define " << includeguardname.GetChars() << "\n";
code << "#line 1\n";
if (system)
code << LoadPrivateShaderLump(headerName.GetChars()).GetChars() << "\n";
else
code << LoadPublicShaderLump(headerName.GetChars()).GetChars() << "\n";
code << "#endif\n";
return ShaderIncludeResult(headerName.GetChars(), code.GetChars());
}
FString VkPPShader::LoadPublicShaderLump(const char* lumpname)
{
int lump = fileSystem.CheckNumForFullName(lumpname, 0);
if (lump == -1) lump = fileSystem.CheckNumForFullName(lumpname);
if (lump == -1) I_Error("Unable to load '%s'", lumpname);
return GetStringFromLump(lump);
}
FString VkPPShader::LoadPrivateShaderLump(const char* lumpname)
{
int lump = fileSystem.CheckNumForFullName(lumpname, 0);
if (lump == -1) I_Error("Unable to load '%s'", lumpname);
return GetStringFromLump(lump);
}
FString VkPPShader::LoadShaderCode(const FString &lumpName, const FString &defines, int version)
{
int lump = fileSystem.CheckNumForFullName(lumpName.GetChars());

View file

@ -6,6 +6,7 @@
#include <list>
class VulkanRenderDevice;
class ShaderIncludeResult;
class VkPPShader : public PPShaderBackend
{
@ -25,4 +26,8 @@ private:
FString LoadShaderCode(const FString &lumpname, const FString &defines, int version);
static FString CreateUniformBlockDecl(const char* name, const std::vector<UniformFieldDesc>& fields, int bindingpoint);
static const char* GetTypeStr(UniformType type);
ShaderIncludeResult OnInclude(FString headerName, FString includerName, size_t depth, bool system);
FString LoadPublicShaderLump(const char* lumpname);
FString LoadPrivateShaderLump(const char* lumpname);
};