diff --git a/src/common/rendering/vulkan/shaders/vk_ppshader.cpp b/src/common/rendering/vulkan/shaders/vk_ppshader.cpp index dcf72a06d..5366481f7 100644 --- a/src/common/rendering/vulkan/shaders/vk_ppshader.cpp +++ b/src/common/rendering/vulkan/shaders/vk_ppshader.cpp @@ -39,12 +39,16 @@ VkPPShader::VkPPShader(VulkanRenderDevice* fb, PPShader *shader) : fb(fb) .Type(ShaderType::Vertex) .AddSource(shader->VertexShader.GetChars(), LoadShaderCode(shader->VertexShader, "", shader->Version).GetChars()) .DebugName(shader->VertexShader.GetChars()) + .OnIncludeLocal(VkShaderManager::OnInclude) + .OnIncludeSystem(VkShaderManager::OnInclude) .Create(shader->VertexShader.GetChars(), fb->device.get()); FragmentShader = ShaderBuilder() .Type(ShaderType::Fragment) .AddSource(shader->FragmentShader.GetChars(), LoadShaderCode(shader->FragmentShader, prolog, shader->Version).GetChars()) .DebugName(shader->FragmentShader.GetChars()) + .OnIncludeLocal(VkShaderManager::OnInclude) + .OnIncludeSystem(VkShaderManager::OnInclude) .Create(shader->FragmentShader.GetChars(), fb->device.get()); fb->GetShaderManager()->AddVkPPShader(this); @@ -72,7 +76,7 @@ FString VkPPShader::LoadShaderCode(const FString &lumpName, const FString &defin FString code = GetStringFromLump(lump); FString patchedCode; - patchedCode.AppendFormat("#version %d\n", 450); + patchedCode.AppendFormat("#version %d\n#extension GL_GOOGLE_include_directive : enable\n", 450); patchedCode << defines; patchedCode << "#line 1\n"; patchedCode << code; diff --git a/src/common/rendering/vulkan/shaders/vk_shader.cpp b/src/common/rendering/vulkan/shaders/vk_shader.cpp index 00734ac7f..8206e4137 100644 --- a/src/common/rendering/vulkan/shaders/vk_shader.cpp +++ b/src/common/rendering/vulkan/shaders/vk_shader.cpp @@ -30,6 +30,32 @@ #include "version.h" #include "cmdlib.h" +ShaderIncludeResult VkShaderManager::OnInclude(FString headerName, FString includerName, size_t depth) +{ + 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"; + + int lumpNum = fileSystem.FindFile(headerName.GetChars()); + + if(lumpNum >= 0) + { + code << GetStringFromLump(lumpNum, false); + } + + code << "\n#endif\n"; + + return ShaderIncludeResult(headerName.GetChars(), code.GetChars()); +} + bool VkShaderManager::CompileNextShader() { const char *mainvp = "shaders/glsl/main.vp"; @@ -341,6 +367,7 @@ static const char *shaderBindings = R"( std::unique_ptr VkShaderManager::LoadVertShader(FString shadername, const char *vert_lump, const char *defines) { FString code = GetTargetGlslVersion(); + code << "#extension GL_GOOGLE_include_directive : enable\n"; code << defines; code << "\n#define MAX_STREAM_DATA " << std::to_string(MAX_STREAM_DATA).c_str() << "\n"; #ifdef NPOT_EMULATION @@ -355,12 +382,15 @@ std::unique_ptr VkShaderManager::LoadVertShader(FString shadername .Type(ShaderType::Vertex) .AddSource(shadername.GetChars(), code.GetChars()) .DebugName(shadername.GetChars()) + .OnIncludeLocal(OnInclude) + .OnIncludeSystem(OnInclude) .Create(shadername.GetChars(), fb->device.get()); } std::unique_ptr VkShaderManager::LoadFragShader(FString shadername, const char *frag_lump, const char *material_lump, const char *light_lump, const char *defines, bool alphatest, bool gbufferpass) { FString code = GetTargetGlslVersion(); + code << "#extension GL_GOOGLE_include_directive : enable\n"; if (fb->RaytracingEnabled()) code << "\n#define SUPPORTS_RAYTRACING\n"; code << defines; @@ -448,6 +478,8 @@ std::unique_ptr VkShaderManager::LoadFragShader(FString shadername .Type(ShaderType::Fragment) .AddSource(shadername.GetChars(), code.GetChars()) .DebugName(shadername.GetChars()) + .OnIncludeLocal(OnInclude) + .OnIncludeSystem(OnInclude) .Create(shadername.GetChars(), fb->device.get()); } diff --git a/src/common/rendering/vulkan/shaders/vk_shader.h b/src/common/rendering/vulkan/shaders/vk_shader.h index cac924916..8880daeea 100644 --- a/src/common/rendering/vulkan/shaders/vk_shader.h +++ b/src/common/rendering/vulkan/shaders/vk_shader.h @@ -7,6 +7,7 @@ #include "matrix.h" #include "name.h" #include "hw_renderstate.h" +#include "zvulkan/vulkanbuilders.h" #include #define SHADER_MIN_REQUIRED_TEXTURE_LAYERS 11 @@ -89,6 +90,8 @@ private: FString LoadPublicShaderLump(const char *lumpname); FString LoadPrivateShaderLump(const char *lumpname); + static ShaderIncludeResult OnInclude(FString headerName, FString includerName, size_t depth); + VulkanRenderDevice* fb = nullptr; std::vector mMaterialShaders[MAX_PASS_TYPES]; @@ -98,4 +101,5 @@ private: int compileIndex = 0; std::list PPShaders; + friend class VkPPShader; };