unify layouts (and move in/out variables to c++) in preparation for gpu sprite traces

This commit is contained in:
Ricardo Luís Vaz Silva 2025-01-13 21:02:33 -03:00 committed by Magnus Norddahl
commit 998fdec6e8
6 changed files with 176 additions and 102 deletions

View file

@ -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<VaryingFieldDesc> 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<BuiltinFieldDesc> 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<BuiltinFieldDesc> 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<VaryingFieldDesc> &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<BuiltinFieldDesc> &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<VulkanShader> 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); })

View file

@ -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;
};

View file

@ -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!

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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