From 998fdec6e801f18fee30ba38cd449adebc33a63c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Mon, 13 Jan 2025 21:02:33 -0300 Subject: [PATCH] unify layouts (and move in/out variables to c++) in preparation for gpu sprite traces --- .../rendering/vulkan/shaders/vk_shader.cpp | 136 +++++++++++++++++- .../rendering/vulkan/shaders/vk_shader.h | 8 +- .../rendering/vulkan/vk_renderstate.cpp | 6 +- wadsrc/static/shaders/scene/layout_frag.glsl | 57 -------- .../static/shaders/scene/layout_shared.glsl | 38 +++++ wadsrc/static/shaders/scene/layout_vert.glsl | 33 ----- 6 files changed, 176 insertions(+), 102 deletions(-) delete mode 100644 wadsrc/static/shaders/scene/layout_frag.glsl delete mode 100644 wadsrc/static/shaders/scene/layout_vert.glsl diff --git a/src/common/rendering/vulkan/shaders/vk_shader.cpp b/src/common/rendering/vulkan/shaders/vk_shader.cpp index 1ac965aa8..96e5569c1 100644 --- a/src/common/rendering/vulkan/shaders/vk_shader.cpp +++ b/src/common/rendering/vulkan/shaders/vk_shader.cpp @@ -172,8 +172,100 @@ VkShaderProgram* VkShaderManager::Get(const VkShaderKey& key) return &program; } +enum class FieldCondition +{ + ALWAYS, + NOTSIMPLE, + HAS_CLIPDISTANCE, + USELEVELMESH, + GBUFFER_PASS, + SHADE_VERTEX, +}; + +struct BuiltinFieldDesc : public VaryingFieldDesc +{ + FieldCondition cond; +}; + +static std::vector vertexShaderInputs +{ + {"aPosition", "", UniformType::Vec4}, //0, VATTR_VERTEX + {"aTexCoord", "", UniformType::Vec2}, //1, VATTR_TEXCOORD + {"aColor", "", UniformType::Vec4}, //2, VATTR_COLOR + {"aVertex2", "", UniformType::Vec4}, //3, VATTR_VERTEX2 + {"aNormal", "", UniformType::Vec4}, //4, VATTR_NORMAL + {"aNormal2", "", UniformType::Vec4}, //5, VATTR_NORMAL2 + {"aLightmap", "", UniformType::Vec2}, //6, VATTR_LIGHTMAP + {"aBoneWeight", "", UniformType::Vec4}, //7, VATTR_BONEWEIGHT + {"aBoneSelector", "", UniformType::UVec4}, //8, VATTR_BONESELECTOR + {"aDataIndex", "", UniformType::Int}, //9, VATTR_UNIFORM_INDEXES +}; + +static std::vector vertexShaderOutputs +{ + {"vTexCoord", "", UniformType::Vec4, FieldCondition::ALWAYS}, //0 + {"vColor", "", UniformType::Vec4, FieldCondition::ALWAYS}, //1 + {"pixelpos", "", UniformType::Vec4, FieldCondition::NOTSIMPLE}, //2 + {"glowdist", "", UniformType::Vec3, FieldCondition::NOTSIMPLE}, //3 + {"gradientdist", "", UniformType::Vec3, FieldCondition::NOTSIMPLE}, //4 + {"vWorldNormal", "", UniformType::Vec4, FieldCondition::NOTSIMPLE}, //5 + {"vEyeNormal", "", UniformType::Vec4, FieldCondition::NOTSIMPLE}, //6 + {"ClipDistanceA", "", UniformType::Vec4, FieldCondition::HAS_CLIPDISTANCE}, //7 + {"ClipDistanceB", "", UniformType::Vec4, FieldCondition::HAS_CLIPDISTANCE}, //8 + {"vLightmap", "", UniformType::Vec3, FieldCondition::ALWAYS}, //9 + {"uDataIndex", "flat", UniformType::Int, FieldCondition::USELEVELMESH}, //10 +}; + +static std::vector fragShaderOutputs +{ + {"FragColor", "", UniformType::Vec4, FieldCondition::ALWAYS}, //0 + {"FragFog", "", UniformType::Vec4, FieldCondition::GBUFFER_PASS}, //1 + {"FragNormal", "", UniformType::Vec4, FieldCondition::GBUFFER_PASS}, //2 +}; + +void AddFields(FString &layoutBlock, int &index, bool is_in, const std::vector &fields) +{ + for(auto &field : fields) + { + layoutBlock.AppendFormat("layout(location = %d) %s %s %s %s;\n", index, field.Property.GetChars(), is_in ? "in" : "out", GetTypeStr(field.Type), field.Name.GetChars()); + index++; + } +} + +void AddBuiltinFields(FString &layoutBlock, int &index, bool is_in, const std::vector &fields, const VkShaderKey& key, bool hasClipDistance) +{ + for(auto &field : fields) + { + switch(field.cond) + { + case FieldCondition::NOTSIMPLE: + if(key.Simple) continue; + break; + case FieldCondition::HAS_CLIPDISTANCE: + if(!hasClipDistance) continue; + break; + case FieldCondition::GBUFFER_PASS: + if(!key.GBufferPass) continue; + break; + case FieldCondition::USELEVELMESH: + if(!key.UseLevelMesh) continue; + break; + case FieldCondition::SHADE_VERTEX: + if(!key.ShadeVertex) continue; + break; + default: + break; + } + + layoutBlock.AppendFormat("layout(location = %d) %s %s %s %s;\n", index, field.Property.GetChars(), is_in ? "in" : "out", GetTypeStr(field.Type), field.Name.GetChars()); + index++; + } +} + void VkShaderManager::BuildLayoutBlock(FString &layoutBlock, bool isFrag, const VkShaderKey& key, const UserShaderDesc *shader) { + bool hasClipDistance = fb->GetDevice()->EnabledFeatures.Features.shaderClipDistance; + layoutBlock << "// This must match the PushConstants struct\n"; layoutBlock << "layout(push_constant) uniform PushConstants\n"; layoutBlock << "{\n"; @@ -198,15 +290,31 @@ void VkShaderManager::BuildLayoutBlock(FString &layoutBlock, bool isFrag, const } } layoutBlock << "};\n"; + layoutBlock << "#line 1\n"; layoutBlock << LoadPrivateShaderLump("shaders/scene/layout_shared.glsl").GetChars() << "\n"; - layoutBlock << LoadPrivateShaderLump(isFrag ? "shaders/scene/layout_frag.glsl" : "shaders/scene/layout_vert.glsl").GetChars() << "\n"; - int varyingLocation = 11; - if(shader) for(auto &varying : shader->Varyings) + if(!isFrag) { - layoutBlock.AppendFormat("layout(location = %d) %s %s %s %s;\n", varyingLocation, varying.Property.GetChars(), isFrag ? "in" : "out", GetTypeStr(varying.Type), varying.Name.GetChars()); - varyingLocation++; + int index = 0; + AddFields(layoutBlock, index, true, vertexShaderInputs); + } + + { + int index = 0; + + AddBuiltinFields(layoutBlock, index, isFrag, vertexShaderOutputs, key, hasClipDistance); + + if(shader) + { + AddFields(layoutBlock, index, isFrag, shader->Varyings); + } + } + + if(isFrag) + { + int index = 0; + AddBuiltinFields(layoutBlock, index, false, fragShaderOutputs, key, hasClipDistance); } } @@ -223,6 +331,11 @@ void VkShaderManager::BuildDefinesBlock(FString &definesBlock, const char *defin definesBlock << "#define MAX_LIGHT_DATA " << std::to_string(MAX_LIGHT_DATA).c_str() << "\n"; definesBlock << "#define MAX_FOGBALL_DATA " << std::to_string(MAX_FOGBALL_DATA).c_str() << "\n"; + if(isFrag) + { + definesBlock << "#define FRAGSHADER\n"; + } + #ifdef NPOT_EMULATION definesBlock << "#define NPOT_EMULATION\n"; #endif @@ -235,7 +348,8 @@ void VkShaderManager::BuildDefinesBlock(FString &definesBlock, const char *defin if (!key.AlphaTest) definesBlock << "#define NO_ALPHATEST\n"; if (key.GBufferPass) definesBlock << "#define GBUFFER_PASS\n"; if (key.AlphaTestOnly) definesBlock << "#define ALPHATEST_ONLY\n"; - if (key.Simple3D) definesBlock << "#define SIMPLE\n#define SIMPLE3D\n"; + if (key.Simple) definesBlock << "#define SIMPLE\n"; + if (key.Simple3D) definesBlock << "#define SIMPLE3D\n"; switch(key.LightBlendMode) { @@ -304,6 +418,14 @@ void VkShaderManager::BuildDefinesBlock(FString &definesBlock, const char *defin if (key.SWLightBanded) definesBlock << "#define SWLIGHT_BANDED\n"; if (key.FogBalls) definesBlock << "#define FOGBALLS\n"; + + switch (key.ShadeVertex) + { + case 1: definesBlock << "#define SHADE_VERTEX\n"; break; + case 2: definesBlock << "#define SHADE_VERTEX_CENTER\n"; break; + //case 3: definesBlock << "#define ???\n"; break; + } + definesBlock << ((key.Simple2D) ? "#define uFogEnabled -3\n" : "#define uFogEnabled 0\n"); } @@ -334,7 +456,7 @@ std::unique_ptr VkShaderManager::LoadVertShader(FString shadername .DebugName(shadername.GetChars()) .AddSource("VersionBlock", GetVersionBlock().GetChars()) .AddSource("DefinesBlock", definesBlock.GetChars()) - .AddSource("LayoutBlock", layoutBlock.GetChars()) + .AddSource("shaders/scene/layout_shared.glsl", layoutBlock.GetChars()) .AddSource(vert_lump_custom ? vert_lump_custom : vert_lump, codeBlock.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); }) diff --git a/src/common/rendering/vulkan/shaders/vk_shader.h b/src/common/rendering/vulkan/shaders/vk_shader.h index 98123930c..2caf5c762 100644 --- a/src/common/rendering/vulkan/shaders/vk_shader.h +++ b/src/common/rendering/vulkan/shaders/vk_shader.h @@ -80,7 +80,9 @@ public: struct { uint64_t AlphaTest : 1; // !NO_ALPHATEST - uint64_t Simple2D : 1; // uFogEnabled == -3 + uint64_t Simple : 1; // SIMPLE + uint64_t Simple2D : 1; // SIMPLE2D, uFogEnabled == -3 + uint64_t Simple3D : 1; // SIMPLE3D uint64_t TextureMode : 3; // uTextureMode & 0xffff uint64_t ClampY : 1; // uTextureMode & TEXF_ClampY uint64_t Brightmap : 1; // uTextureMode & TEXF_Brightmap @@ -104,8 +106,8 @@ public: uint64_t LightAttenuationMode : 1; // LIGHT_ATTENUATION_LINEAR , LIGHT_ATTENUATION_INVERSE_SQUARE uint64_t UseRaytracePrecise : 1; // USE_RAYTRACE_PRECISE uint64_t ShadowmapFilter : 4; // SHADOWMAP_FILTER - uint64_t Simple3D : 1; // SIMPLE3D - uint64_t Unused : 31; + uint64_t ShadeVertex : 2; // 0 = nothing, 1 = SHADE_VERTEX, 2 = SHADE_VERTEX_CENTER + uint64_t Unused : 28; }; uint64_t AsQWORD = 0; }; diff --git a/src/common/rendering/vulkan/vk_renderstate.cpp b/src/common/rendering/vulkan/vk_renderstate.cpp index 7afe9b69e..c65f959f4 100644 --- a/src/common/rendering/vulkan/vk_renderstate.cpp +++ b/src/common/rendering/vulkan/vk_renderstate.cpp @@ -264,6 +264,7 @@ void VkRenderState::ApplyRenderPass(int dt) { pipelineKey.ShaderKey.SpecialEffect = mSpecialEffect; pipelineKey.ShaderKey.EffectState = 0; + pipelineKey.ShaderKey.Simple = (mSpecialEffect == EFF_BURN || mSpecialEffect == EFF_STENCIL || mSpecialEffect == EFF_PORTAL); pipelineKey.ShaderKey.AlphaTest = false; } else @@ -274,6 +275,9 @@ void VkRenderState::ApplyRenderPass(int dt) if (r_skipmats && pipelineKey.ShaderKey.EffectState >= 3 && pipelineKey.ShaderKey.EffectState <= 4) pipelineKey.ShaderKey.EffectState = 0; pipelineKey.ShaderKey.AlphaTest = mSurfaceUniforms.uAlphaThreshold >= 0.f; + + pipelineKey.ShaderKey.Simple = mWireframe; + pipelineKey.ShaderKey.Simple3D = mWireframe; // simple notexture drawing for wireframe } int uTextureMode = GetTextureModeAndFlags((mMaterial.mMaterial && mMaterial.mMaterial->Source()->isHardwareCanvas()) ? TM_OPAQUE : TM_NORMAL); @@ -283,8 +287,6 @@ void VkRenderState::ApplyRenderPass(int dt) pipelineKey.ShaderKey.Detailmap = (uTextureMode & TEXF_Detailmap) != 0; pipelineKey.ShaderKey.Glowmap = (uTextureMode & TEXF_Glowmap) != 0; - pipelineKey.ShaderKey.Simple3D = mWireframe; // simple notexture drawing for wireframe - pipelineKey.ShaderKey.DepthFadeThreshold = mSurfaceUniforms.uDepthFadeThreshold > 0.0f; // The way GZDoom handles state is just plain insanity! diff --git a/wadsrc/static/shaders/scene/layout_frag.glsl b/wadsrc/static/shaders/scene/layout_frag.glsl deleted file mode 100644 index f769a1fbd..000000000 --- a/wadsrc/static/shaders/scene/layout_frag.glsl +++ /dev/null @@ -1,57 +0,0 @@ - -layout(location = 0) in vec4 vTexCoord; -layout(location = 1) in vec4 vColor; -layout(location = 9) in vec3 vLightmap; - -#ifndef SIMPLE -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 - -#ifdef NO_CLIPDISTANCE_SUPPORT -layout(location = 7) in vec4 ClipDistanceA; -layout(location = 8) in vec4 ClipDistanceB; -#endif - -#if defined(USE_LEVELMESH) -layout(location = 10) in flat int uDataIndex; -#endif - -layout(location=0) out vec4 FragColor; -#ifdef GBUFFER_PASS -layout(location=1) out vec4 FragFog; -layout(location=2) out vec4 FragNormal; -#endif - -vec4 texture(int index, vec2 p) -{ - return texture(textures[uTextureIndex + index], p); -} - -vec4 texture(int index, vec2 p, float bias) -{ - return texture(textures[uTextureIndex + index], p, bias); -} - -ivec2 textureSize(int index, int lod) -{ - return textureSize(textures[uTextureIndex + index], lod); -} - -vec4 textureGrad(int index, vec2 P, vec2 dPdx, vec2 dPdy) -{ - return textureGrad(textures[uTextureIndex + index], P, dPdx, dPdy); -} - -vec4 textureLod(int index, vec2 P, float lod) -{ - return textureLod(textures[uTextureIndex + index], P, lod); -} - -vec4 texelFetch(int index, ivec2 P, int lod) -{ - return texelFetch(textures[uTextureIndex + index], P, lod); -} diff --git a/wadsrc/static/shaders/scene/layout_shared.glsl b/wadsrc/static/shaders/scene/layout_shared.glsl index 6760f1b5e..7d57809ba 100644 --- a/wadsrc/static/shaders/scene/layout_shared.glsl +++ b/wadsrc/static/shaders/scene/layout_shared.glsl @@ -81,3 +81,41 @@ float noise1(float) { return 0; } vec2 noise2(vec2) { return vec2(0); } vec3 noise3(vec3) { return vec3(0); } vec4 noise4(vec4) { return vec4(0); } + +vec4 texture(int index, vec2 p) +{ +#ifndef FRAGSHADER + return textureLod(textures[uTextureIndex + index], p, 0.0); +#else + return texture(textures[uTextureIndex + index], p); +#endif +} + +vec4 texture(int index, vec2 p, float bias) +{ +#ifndef FRAGSHADER + return textureLod(textures[uTextureIndex + index], p, 0.0); +#else + return texture(textures[uTextureIndex + index], p, bias); +#endif +} + +ivec2 textureSize(int index, int lod) +{ + return textureSize(textures[uTextureIndex + index], lod); +} + +vec4 textureGrad(int index, vec2 P, vec2 dPdx, vec2 dPdy) +{ + return textureGrad(textures[uTextureIndex + index], P, dPdx, dPdy); +} + +vec4 textureLod(int index, vec2 P, float lod) +{ + return textureLod(textures[uTextureIndex + index], P, lod); +} + +vec4 texelFetch(int index, ivec2 P, int lod) +{ + return texelFetch(textures[uTextureIndex + index], P, lod); +} diff --git a/wadsrc/static/shaders/scene/layout_vert.glsl b/wadsrc/static/shaders/scene/layout_vert.glsl deleted file mode 100644 index 62ed8196b..000000000 --- a/wadsrc/static/shaders/scene/layout_vert.glsl +++ /dev/null @@ -1,33 +0,0 @@ - -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; -layout(location = 9) out vec3 vLightmap; - -#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; -layout(location = 6) in vec2 aLightmap; -layout(location = 7) in vec4 aBoneWeight; -layout(location = 8) in uvec4 aBoneSelector; - -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 - -#ifdef NO_CLIPDISTANCE_SUPPORT -layout(location = 7) out vec4 ClipDistanceA; -layout(location = 8) out vec4 ClipDistanceB; -#endif - -#if defined(USE_LEVELMESH) -layout(location = 9) in int aDataIndex; -layout(location = 10) out flat int uDataIndex; -#endif