diff --git a/src/rendering/vulkan/shaders/vk_shader.cpp b/src/rendering/vulkan/shaders/vk_shader.cpp index e231d6e8f..c5e7e9756 100644 --- a/src/rendering/vulkan/shaders/vk_shader.cpp +++ b/src/rendering/vulkan/shaders/vk_shader.cpp @@ -1,32 +1,209 @@ #include "vk_shader.h" #include "vulkan/system/vk_builders.h" +#include "hwrenderer/utility/hw_shaderpatcher.h" +#include "w_wad.h" +#include "doomerrors.h" #include -VkShaderManager::VkShaderManager() +VkShaderManager::VkShaderManager(VulkanDevice *device) : device(device) { ShInitialize(); -#if 0 - { - const char *lumpName = "shaders/glsl/screenquad.vp"; - int lump = Wads.CheckNumForFullName(lumpName, 0); - if (lump == -1) I_FatalError("Unable to load '%s'", lumpName); - FString code = Wads.ReadLump(lump).GetString().GetChars(); - - FString patchedCode; - patchedCode.AppendFormat("#version %d\n", 450); - patchedCode << "#line 1\n"; - patchedCode << code; - - ShaderBuilder builder; - builder.setVertexShader(patchedCode); - auto shader = builder.create(dev); - } -#endif + vert = LoadVertShader("shaders/glsl/main.vp", ""); + frag = LoadFragShader("shaders/glsl/main.fp", "shaders/glsl/func_normal.fp", "shaders/glsl/material_normal.fp", ""); } VkShaderManager::~VkShaderManager() { ShFinalize(); } + +static const char *shaderBindings = R"( + + // This must match the HWViewpointUniforms struct + layout(set = 0, binding = 0, std140) uniform ViewpointUBO { + mat4 ProjectionMatrix; + mat4 ViewMatrix; + mat4 NormalViewMatrix; + + vec4 uCameraPos; + vec4 uClipLine; + + float uGlobVis; // uGlobVis = R_GetGlobVis(r_visibility) / 32.0 + int uPalLightLevels; + int uViewHeight; // Software fuzz scaling + float uClipHeight; + float uClipHeightDirection; + int uShadowmapFilter; + + float timer; // timer data for material shaders + }; + + // light buffers + layout(set = 0, binding = 1, std430) buffer LightBufferSSO + { + vec4 lights[]; + }; + + // textures + layout(set = 1, binding = 0) uniform sampler2D tex; + layout(set = 1, binding = 1) uniform sampler2D texture2; + layout(set = 1, binding = 2) uniform sampler2D texture3; + layout(set = 1, binding = 3) uniform sampler2D texture4; + layout(set = 1, binding = 4) uniform sampler2D texture5; + layout(set = 1, binding = 5) uniform sampler2D texture6; + layout(set = 1, binding = 16) uniform sampler2D ShadowMap; + + // This must match the PushConstants struct + layout(push_constant, std140) uniform PushConstants + { + int uTextureMode; + vec2 uClipSplit; + float uAlphaThreshold; + + // colors + vec4 uObjectColor; + vec4 uObjectColor2; + vec4 uDynLightColor; + vec4 uAddColor; + vec4 uFogColor; + float uDesaturationFactor; + float uInterpolationFactor; + + // Glowing walls stuff + vec4 uGlowTopPlane; + vec4 uGlowTopColor; + vec4 uGlowBottomPlane; + vec4 uGlowBottomColor; + + vec4 uGradientTopPlane; + vec4 uGradientBottomPlane; + + vec4 uSplitTopPlane; + vec4 uSplitBottomPlane; + + // Lighting + Fog + float uLightLevel; + float uFogDensity; + float uLightFactor; + float uLightDist; + int uFogEnabled; + + // dynamic lights + int uLightIndex; + + // Blinn glossiness and specular level + vec2 uSpecularMaterial; + + // matrices + mat4 ModelMatrix; + mat4 NormalModelMatrix; + mat4 TextureMatrix; + }; + + // material types + #if defined(SPECULAR) + #define normaltexture texture2 + #define speculartexture texture3 + #define brighttexture texture4 + #elif defined(PBR) + #define normaltexture texture2 + #define metallictexture texture3 + #define roughnesstexture texture4 + #define aotexture texture5 + #define brighttexture texture6 + #else + #define brighttexture texture2 + #endif + + #define SUPPORTS_SHADOWMAPS +)"; + + +std::unique_ptr VkShaderManager::LoadVertShader(const char *vert_lump, const char *defines) +{ + FString code = GetTargetGlslVersion(); + code << defines << shaderBindings; + code << "#line 1\n"; + code << LoadShaderLump(vert_lump).GetChars() << "\n"; + + ShaderBuilder builder; + builder.setVertexShader(code); + return builder.create(device); +} + +std::unique_ptr VkShaderManager::LoadFragShader(const char *frag_lump, const char *material_lump, const char *light_lump, const char *defines) +{ + FString code = GetTargetGlslVersion(); + code << defines << shaderBindings; + code << "\n#line 1\n"; + code << LoadShaderLump(frag_lump).GetChars() << "\n"; + + if (material_lump) + { + if (material_lump[0] != '#') + { + FString pp_code = LoadShaderLump(material_lump); + + if (pp_code.IndexOf("ProcessMaterial") < 0) + { + // this looks like an old custom hardware shader. + // add ProcessMaterial function that calls the older ProcessTexel function + code << "\n" << LoadShaderLump("shaders/glsl/func_defaultmat.fp").GetChars() << "\n"; + + if (pp_code.IndexOf("ProcessTexel") < 0) + { + // this looks like an even older custom hardware shader. + // We need to replace the ProcessTexel call to make it work. + + code.Substitute("material.Base = ProcessTexel();", "material.Base = Process(vec4(1.0));"); + } + + if (pp_code.IndexOf("ProcessLight") >= 0) + { + // The ProcessLight signatured changed. Forward to the old one. + code << "\nvec4 ProcessLight(vec4 color);\n"; + code << "\nvec4 ProcessLight(Material material, vec4 color) { return ProcessLight(color); }\n"; + } + } + + code << "\n#line 1\n"; + code << RemoveLegacyUserUniforms(pp_code).GetChars(); + code.Substitute("gl_TexCoord[0]", "vTexCoord"); // fix old custom shaders. + + if (pp_code.IndexOf("ProcessLight") < 0) + { + code << "\n" << LoadShaderLump("shaders/glsl/func_defaultlight.fp").GetChars() << "\n"; + } + } + else + { + // material_lump is not a lump name but the source itself (from generated shaders) + code << (material_lump + 1) << "\n"; + } + } + + if (light_lump) + { + code << "\n#line 1\n"; + code << LoadShaderLump(light_lump).GetChars(); + } + + ShaderBuilder builder; + builder.setFragmentShader(code); + return builder.create(device); +} + +FString VkShaderManager::GetTargetGlslVersion() +{ + return "#version 450 core\n"; +} + +FString VkShaderManager::LoadShaderLump(const char *lumpname) +{ + int lump = Wads.CheckNumForFullName(lumpname, 0); + if (lump == -1) I_Error("Unable to load '%s'", lumpname); + FMemLump data = Wads.ReadLump(lump); + return data.GetString(); +} diff --git a/src/rendering/vulkan/shaders/vk_shader.h b/src/rendering/vulkan/shaders/vk_shader.h index 2b39322a9..2d1e8b530 100644 --- a/src/rendering/vulkan/shaders/vk_shader.h +++ b/src/rendering/vulkan/shaders/vk_shader.h @@ -5,6 +5,9 @@ #include "r_data/matrix.h" #include "name.h" +class VulkanDevice; +class VulkanShader; + struct PushConstants { int uTextureMode; @@ -54,6 +57,18 @@ struct PushConstants class VkShaderManager { public: - VkShaderManager(); + VkShaderManager(VulkanDevice *device); ~VkShaderManager(); + + std::unique_ptr vert; + std::unique_ptr frag; + +private: + std::unique_ptr LoadVertShader(const char *vert_lump, const char *defines); + std::unique_ptr LoadFragShader(const char *frag_lump, const char *material_lump, const char *light_lump, const char *defines); + + FString GetTargetGlslVersion(); + FString LoadShaderLump(const char *lumpname); + + VulkanDevice *device; }; diff --git a/src/rendering/vulkan/system/vk_framebuffer.cpp b/src/rendering/vulkan/system/vk_framebuffer.cpp index b36890457..ff0f52617 100644 --- a/src/rendering/vulkan/system/vk_framebuffer.cpp +++ b/src/rendering/vulkan/system/vk_framebuffer.cpp @@ -71,7 +71,7 @@ void VulkanFrameBuffer::InitializeState() mViewpoints = new GLViewpointBuffer; mLights = new FLightBuffer(); - mShaderManager.reset(new VkShaderManager()); + mShaderManager.reset(new VkShaderManager(device)); mSamplerManager.reset(new VkSamplerManager(device)); mRenderState.reset(new VkRenderState()); } diff --git a/wadsrc/static/shaders/glsl/main.fp b/wadsrc/static/shaders/glsl/main.fp index ab4d16e91..d952e2b7b 100644 --- a/wadsrc/static/shaders/glsl/main.fp +++ b/wadsrc/static/shaders/glsl/main.fp @@ -1,11 +1,14 @@ -in vec4 pixelpos; -in vec3 glowdist; -in vec3 gradientdist; -in vec4 vWorldNormal; -in vec4 vEyeNormal; -in vec4 vTexCoord; -in vec4 vColor; +layout(location = 0) in vec4 vTexCoord; +layout(location = 1) in vec4 vColor; + +#ifndef SIMPLE // we do not need these for simple shaders +layout(location = 2) in vec4 pixelpos; +layout(location = 3) in vec3 glowdist; +layout(location = 4) in vec3 gradientdist; +layout(location = 5) in vec4 vWorldNormal; +layout(location = 6) in vec4 vEyeNormal; +#endif layout(location=0) out vec4 FragColor; #ifdef GBUFFER_PASS diff --git a/wadsrc/static/shaders/glsl/main.vp b/wadsrc/static/shaders/glsl/main.vp index 81d4022f0..0335c9354 100644 --- a/wadsrc/static/shaders/glsl/main.vp +++ b/wadsrc/static/shaders/glsl/main.vp @@ -2,21 +2,22 @@ layout(location = 0) in vec4 aPosition; layout(location = 1) in vec2 aTexCoord; layout(location = 2) in vec4 aColor; + +layout(location = 0) out vec4 vTexCoord; +layout(location = 1) out vec4 vColor; + #ifndef SIMPLE // we do not need these for simple shaders layout(location = 3) in vec4 aVertex2; layout(location = 4) in vec4 aNormal; layout(location = 5) in vec4 aNormal2; -out vec4 pixelpos; -out vec3 glowdist; -out vec3 gradientdist; -out vec4 vWorldNormal; -out vec4 vEyeNormal; +layout(location = 2) out vec4 pixelpos; +layout(location = 3) out vec3 glowdist; +layout(location = 4) out vec3 gradientdist; +layout(location = 5) out vec4 vWorldNormal; +layout(location = 6) out vec4 vEyeNormal; #endif -out vec4 vTexCoord; -out vec4 vColor; - void main() { vec2 parmTexCoord;