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!