From 04870e8fbf27ba44032bcfb4baaeb3b900037b57 Mon Sep 17 00:00:00 2001 From: Jan Laupetin Date: Sat, 14 Mar 2026 23:22:50 +0100 Subject: [PATCH 1/4] chore: use templated code for t5 techset dumping --- src/Common/Game/T5/T5.h | 5 + src/Common/Game/T5/T5_Assets.h | 24 +- .../Game/T5/Techset/TechsetConstantsT5.h | 49 ++++ .../Game/T5/Techset/TechsetDumperT5.cpp | 272 ------------------ .../Game/T5/Techset/TechsetDumperT5.h | 21 -- .../Techset/TechsetDumper.cpp.template | 3 +- .../Techset/TechsetDumper.h.template | 2 +- 7 files changed, 74 insertions(+), 302 deletions(-) delete mode 100644 src/ObjWriting/Game/T5/Techset/TechsetDumperT5.cpp delete mode 100644 src/ObjWriting/Game/T5/Techset/TechsetDumperT5.h diff --git a/src/Common/Game/T5/T5.h b/src/Common/Game/T5/T5.h index 962a87ad..5b611c26 100644 --- a/src/Common/Game/T5/T5.h +++ b/src/Common/Game/T5/T5.h @@ -207,6 +207,11 @@ namespace T5 using AssetDDL = Asset; using AssetGlasses = Asset; using AssetEmblemSet = Asset; + + using SubAssetTechnique = SubAsset; + using SubAssetVertexDecl = SubAsset; + using SubAssetVertexShader = SubAsset; + using SubAssetPixelShader = SubAsset; } // namespace T5 DEFINE_ASSET_NAME_ACCESSOR(T5::AssetPhysPreset, name); diff --git a/src/Common/Game/T5/T5_Assets.h b/src/Common/Game/T5/T5_Assets.h index 58bdd757..1e42c95b 100644 --- a/src/Common/Game/T5/T5_Assets.h +++ b/src/Common/Game/T5/T5_Assets.h @@ -1487,6 +1487,16 @@ namespace T5 MaterialArgumentDef u; }; + enum CustomSampler + { + CUSTOM_SAMPLER_REFLECTION_PROBE = 0x0, + CUSTOM_SAMPLER_LIGHTMAP_PRIMARY = 0x1, + CUSTOM_SAMPLER_LIGHTMAP_SECONDARY = 0x2, + CUSTOM_SAMPLER_LIGHTMAP_SECONDARYB = 0x3, + + CUSTOM_SAMPLER_COUNT + }; + enum MaterialType : unsigned char { MTL_TYPE_DEFAULT = 0x0, @@ -1506,16 +1516,16 @@ namespace T5 enum TechniqueFlags { - TECHNIQUE_FLAG_1 = 0x1, - TECHNIQUE_FLAG_2 = 0x2, - TECHNIQUE_FLAG_4 = 0x4, + MTL_TECHFLAG_NEEDS_RESOLVED_POST_SUN = 0x1, + MTL_TECHFLAG_NEEDS_RESOLVED_SCENE = 0x2, + MTL_TECHFLAG_ZPREPASS = 0x4, // Vertex decl has optional source - TECHNIQUE_FLAG_8 = 0x8, + MTL_TECHFLAG_DECL_HAS_OPTIONAL_SOURCE = 0x8, - TECHNIQUE_FLAG_10 = 0x10, - TECHNIQUE_FLAG_20 = 0x20, - TECHNIQUE_FLAG_40 = 0x40, + MTL_TECHFLAG_USES_LIGHT_SPOT_FACTORS = 0x10, + MTL_TECHFLAG_USES_GRASS = 0x20, + MTL_TECHFLAG_USES_FLOATZ = 0x40, // Any material that has statebits according to any of the following sets this: // - GFXS1_DEPTHWRITE set diff --git a/src/ObjCommon/Game/T5/Techset/TechsetConstantsT5.h b/src/ObjCommon/Game/T5/Techset/TechsetConstantsT5.h index 8c89b218..8ea418de 100644 --- a/src/ObjCommon/Game/T5/Techset/TechsetConstantsT5.h +++ b/src/ObjCommon/Game/T5/Techset/TechsetConstantsT5.h @@ -2,6 +2,7 @@ #include "Game/T5/T5.h" #include "Techset/CommonTechnique.h" +#include "Techset/CommonTechset.h" namespace T5 { @@ -138,6 +139,7 @@ namespace T5 "impact mask", }; static_assert(std::extent_v == TECHNIQUE_COUNT); + static inline techset::CommonTechniqueTypeNames commonTechniqueTypeNames(techniqueTypeNames, std::extent_v); static techset::CommonStreamRoutingSourceInfo streamRoutingSources[]{ { @@ -312,6 +314,7 @@ namespace T5 .accessor = "lightSpotFactors", .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::RARELY, + .techFlags = MTL_TECHFLAG_USES_LIGHT_SPOT_FACTORS, }, { .value = CONST_SRC_CODE_LIGHT_ATTENUATION, @@ -726,24 +729,28 @@ namespace T5 .accessor = "grassParms", .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::RARELY, + .techFlags = MTL_TECHFLAG_USES_GRASS, }, { .value = CONST_SRC_CODE_GRASS_FORCE0, .accessor = "grassForce0", .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::RARELY, + .techFlags = MTL_TECHFLAG_USES_GRASS, }, { .value = CONST_SRC_CODE_GRASS_FORCE1, .accessor = "grassForce1", .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::RARELY, + .techFlags = MTL_TECHFLAG_USES_GRASS, }, { .value = CONST_SRC_CODE_GRASS_WIND_FORCE0, .accessor = "grassWindForce0", .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::RARELY, + .techFlags = MTL_TECHFLAG_USES_GRASS, }, { .value = CONST_SRC_CODE_MOTIONBLUR_DIRECTION_AND_MAGNITUDE, @@ -834,6 +841,7 @@ namespace T5 .accessor = "destructibleParms", .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::RARELY, + .techFlags = TECHNIQUE_FLAG_200, }, { .value = CONST_SRC_CODE_CLOUD_WORLD_AREA, @@ -858,6 +866,7 @@ namespace T5 .accessor = "__characterCharredAmount", .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::RARELY, + .techFlags = TECHNIQUE_FLAG_200, }, { .value = CONST_SRC_CODE_TREECANOPY_PARMS, @@ -1332,192 +1341,224 @@ namespace T5 .accessor = "worldMatrix", .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::PER_PRIM, + .transposedMatrix = CONST_SRC_CODE_TRANSPOSE_WORLD_MATRIX, }, { .value = CONST_SRC_CODE_INVERSE_WORLD_MATRIX, .accessor = "inverseWorldMatrix", .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::PER_PRIM, + .transposedMatrix = CONST_SRC_CODE_INVERSE_TRANSPOSE_WORLD_MATRIX, }, { .value = CONST_SRC_CODE_TRANSPOSE_WORLD_MATRIX, .accessor = "transposeWorldMatrix", .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::PER_PRIM, + .transposedMatrix = CONST_SRC_CODE_WORLD_MATRIX, }, { .value = CONST_SRC_CODE_INVERSE_TRANSPOSE_WORLD_MATRIX, .accessor = "inverseTransposeWorldMatrix", .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::PER_PRIM, + .transposedMatrix = CONST_SRC_CODE_INVERSE_WORLD_MATRIX, }, { .value = CONST_SRC_CODE_VIEW_MATRIX, .accessor = "viewMatrix", .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::PER_OBJECT, + .transposedMatrix = CONST_SRC_CODE_TRANSPOSE_VIEW_MATRIX, }, { .value = CONST_SRC_CODE_INVERSE_VIEW_MATRIX, .accessor = "inverseViewMatrix", .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::PER_OBJECT, + .transposedMatrix = CONST_SRC_CODE_INVERSE_TRANSPOSE_VIEW_MATRIX, }, { .value = CONST_SRC_CODE_TRANSPOSE_VIEW_MATRIX, .accessor = "transposeViewMatrix", .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::PER_OBJECT, + .transposedMatrix = CONST_SRC_CODE_VIEW_MATRIX, }, { .value = CONST_SRC_CODE_INVERSE_TRANSPOSE_VIEW_MATRIX, .accessor = "inverseTransposeViewMatrix", .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::PER_OBJECT, + .transposedMatrix = CONST_SRC_CODE_INVERSE_VIEW_MATRIX, }, { .value = CONST_SRC_CODE_PROJECTION_MATRIX, .accessor = "projectionMatrix", .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::PER_OBJECT, + .transposedMatrix = CONST_SRC_CODE_TRANSPOSE_PROJECTION_MATRIX, }, { .value = CONST_SRC_CODE_INVERSE_PROJECTION_MATRIX, .accessor = "inverseProjectionMatrix", .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::PER_OBJECT, + .transposedMatrix = CONST_SRC_CODE_INVERSE_TRANSPOSE_PROJECTION_MATRIX, }, { .value = CONST_SRC_CODE_TRANSPOSE_PROJECTION_MATRIX, .accessor = "transposeProjectionMatrix", .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::PER_OBJECT, + .transposedMatrix = CONST_SRC_CODE_PROJECTION_MATRIX, }, { .value = CONST_SRC_CODE_INVERSE_TRANSPOSE_PROJECTION_MATRIX, .accessor = "inverseTransposeProjectionMatrix", .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::PER_OBJECT, + .transposedMatrix = CONST_SRC_CODE_INVERSE_PROJECTION_MATRIX, }, { .value = CONST_SRC_CODE_WORLD_VIEW_MATRIX, .accessor = "worldViewMatrix", .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::PER_PRIM, + .transposedMatrix = CONST_SRC_CODE_TRANSPOSE_WORLD_VIEW_MATRIX, }, { .value = CONST_SRC_CODE_INVERSE_WORLD_VIEW_MATRIX, .accessor = "inverseWorldViewMatrix", .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::PER_PRIM, + .transposedMatrix = CONST_SRC_CODE_INVERSE_TRANSPOSE_WORLD_VIEW_MATRIX, }, { .value = CONST_SRC_CODE_TRANSPOSE_WORLD_VIEW_MATRIX, .accessor = "transposeWorldViewMatrix", .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::PER_PRIM, + .transposedMatrix = CONST_SRC_CODE_WORLD_VIEW_MATRIX, }, { .value = CONST_SRC_CODE_INVERSE_TRANSPOSE_WORLD_VIEW_MATRIX, .accessor = "inverseTransposeWorldViewMatrix", .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::PER_PRIM, + .transposedMatrix = CONST_SRC_CODE_INVERSE_WORLD_VIEW_MATRIX, }, { .value = CONST_SRC_CODE_VIEW_PROJECTION_MATRIX, .accessor = "viewProjectionMatrix", .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::PER_OBJECT, + .transposedMatrix = CONST_SRC_CODE_TRANSPOSE_VIEW_PROJECTION_MATRIX, }, { .value = CONST_SRC_CODE_INVERSE_VIEW_PROJECTION_MATRIX, .accessor = "inverseViewProjectionMatrix", .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::PER_OBJECT, + .transposedMatrix = CONST_SRC_CODE_INVERSE_TRANSPOSE_VIEW_PROJECTION_MATRIX, }, { .value = CONST_SRC_CODE_TRANSPOSE_VIEW_PROJECTION_MATRIX, .accessor = "transposeViewProjectionMatrix", .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::PER_OBJECT, + .transposedMatrix = CONST_SRC_CODE_VIEW_PROJECTION_MATRIX, }, { .value = CONST_SRC_CODE_INVERSE_TRANSPOSE_VIEW_PROJECTION_MATRIX, .accessor = "inverseTransposeViewProjectionMatrix", .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::PER_OBJECT, + .transposedMatrix = CONST_SRC_CODE_INVERSE_VIEW_PROJECTION_MATRIX, }, { .value = CONST_SRC_CODE_WORLD_VIEW_PROJECTION_MATRIX, .accessor = "worldViewProjectionMatrix", .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::PER_PRIM, + .transposedMatrix = CONST_SRC_CODE_TRANSPOSE_WORLD_VIEW_PROJECTION_MATRIX, }, { .value = CONST_SRC_CODE_INVERSE_WORLD_VIEW_PROJECTION_MATRIX, .accessor = "inverseWorldViewProjectionMatrix", .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::PER_PRIM, + .transposedMatrix = CONST_SRC_CODE_INVERSE_TRANSPOSE_WORLD_VIEW_PROJECTION_MATRIX, }, { .value = CONST_SRC_CODE_TRANSPOSE_WORLD_VIEW_PROJECTION_MATRIX, .accessor = "transposeWorldViewProjectionMatrix", .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::PER_PRIM, + .transposedMatrix = CONST_SRC_CODE_WORLD_VIEW_PROJECTION_MATRIX, }, { .value = CONST_SRC_CODE_INVERSE_TRANSPOSE_WORLD_VIEW_PROJECTION_MATRIX, .accessor = "inverseTransposeWorldViewProjectionMatrix", .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::PER_PRIM, + .transposedMatrix = CONST_SRC_CODE_INVERSE_WORLD_VIEW_PROJECTION_MATRIX, }, { .value = CONST_SRC_CODE_SHADOW_LOOKUP_MATRIX, .accessor = "shadowLookupMatrix", .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::PER_OBJECT, + .transposedMatrix = CONST_SRC_CODE_TRANSPOSE_SHADOW_LOOKUP_MATRIX, }, { .value = CONST_SRC_CODE_INVERSE_SHADOW_LOOKUP_MATRIX, .accessor = "inverseShadowLookupMatrix", .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::PER_OBJECT, + .transposedMatrix = CONST_SRC_CODE_INVERSE_TRANSPOSE_SHADOW_LOOKUP_MATRIX, }, { .value = CONST_SRC_CODE_TRANSPOSE_SHADOW_LOOKUP_MATRIX, .accessor = "transposeShadowLookupMatrix", .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::PER_OBJECT, + .transposedMatrix = CONST_SRC_CODE_SHADOW_LOOKUP_MATRIX, }, { .value = CONST_SRC_CODE_INVERSE_TRANSPOSE_SHADOW_LOOKUP_MATRIX, .accessor = "inverseTransposeShadowLookupMatrix", .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::PER_OBJECT, + .transposedMatrix = CONST_SRC_CODE_INVERSE_SHADOW_LOOKUP_MATRIX, }, { .value = CONST_SRC_CODE_WORLD_OUTDOOR_LOOKUP_MATRIX, .accessor = "worldOutdoorLookupMatrix", .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::PER_PRIM, + .transposedMatrix = CONST_SRC_CODE_TRANSPOSE_WORLD_OUTDOOR_LOOKUP_MATRIX, }, { .value = CONST_SRC_CODE_INVERSE_WORLD_OUTDOOR_LOOKUP_MATRIX, .accessor = "inverseWorldOutdoorLookupMatrix", .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::PER_PRIM, + .transposedMatrix = CONST_SRC_CODE_INVERSE_TRANSPOSE_WORLD_OUTDOOR_LOOKUP_MATRIX, }, { .value = CONST_SRC_CODE_TRANSPOSE_WORLD_OUTDOOR_LOOKUP_MATRIX, .accessor = "transposeWorldOutdoorLookupMatrix", .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::PER_PRIM, + .transposedMatrix = CONST_SRC_CODE_WORLD_OUTDOOR_LOOKUP_MATRIX, }, { .value = CONST_SRC_CODE_INVERSE_TRANSPOSE_WORLD_OUTDOOR_LOOKUP_MATRIX, .accessor = "inverseTransposeWorldOutdoorLookupMatrix", .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::PER_PRIM, + .transposedMatrix = CONST_SRC_CODE_INVERSE_WORLD_OUTDOOR_LOOKUP_MATRIX, }, }; @@ -1546,11 +1587,13 @@ namespace T5 .value = TEXTURE_SRC_CODE_LIGHTMAP_PRIMARY, .accessor = "lightmapSamplerPrimary", .updateFrequency = techset::CommonCodeSourceUpdateFrequency::CUSTOM, + .customSamplerIndex = CUSTOM_SAMPLER_LIGHTMAP_SECONDARY, }, { .value = TEXTURE_SRC_CODE_LIGHTMAP_SECONDARY, .accessor = "lightmapSamplerSecondary", .updateFrequency = techset::CommonCodeSourceUpdateFrequency::CUSTOM, + .customSamplerIndex = CUSTOM_SAMPLER_LIGHTMAP_SECONDARY, }, { .value = TEXTURE_SRC_CODE_SHADOWMAP_SUN, @@ -1571,11 +1614,13 @@ namespace T5 .value = TEXTURE_SRC_CODE_RESOLVED_POST_SUN, .accessor = "resolvedPostSun", .updateFrequency = techset::CommonCodeSourceUpdateFrequency::RARELY, + .techFlags = MTL_TECHFLAG_NEEDS_RESOLVED_POST_SUN, }, { .value = TEXTURE_SRC_CODE_RESOLVED_SCENE, .accessor = "resolvedScene", .updateFrequency = techset::CommonCodeSourceUpdateFrequency::RARELY, + .techFlags = MTL_TECHFLAG_NEEDS_RESOLVED_SCENE, }, { .value = TEXTURE_SRC_CODE_POST_EFFECT_SRC, @@ -1621,16 +1666,19 @@ namespace T5 .value = TEXTURE_SRC_CODE_FLOATZ, .accessor = "floatZSampler", .updateFrequency = techset::CommonCodeSourceUpdateFrequency::RARELY, + .techFlags = MTL_TECHFLAG_USES_FLOATZ, }, { .value = TEXTURE_SRC_CODE_PROCESSED_FLOATZ, .accessor = "processedFloatZSampler", .updateFrequency = techset::CommonCodeSourceUpdateFrequency::RARELY, + .techFlags = MTL_TECHFLAG_USES_FLOATZ, }, { .value = TEXTURE_SRC_CODE_RAW_FLOATZ, .accessor = "rawFloatZSampler", .updateFrequency = techset::CommonCodeSourceUpdateFrequency::RARELY, + .techFlags = MTL_TECHFLAG_USES_FLOATZ, }, { .value = TEXTURE_SRC_CODE_CASE_TEXTURE, @@ -1691,6 +1739,7 @@ namespace T5 .value = TEXTURE_SRC_CODE_LIGHTMAP_SECONDARYB, .accessor = "lightmapSamplerSecondaryB", .updateFrequency = techset::CommonCodeSourceUpdateFrequency::CUSTOM, + .customSamplerIndex = CUSTOM_SAMPLER_LIGHTMAP_SECONDARYB, }, { .value = TEXTURE_SRC_CODE_TEXTURE_0, diff --git a/src/ObjWriting/Game/T5/Techset/TechsetDumperT5.cpp b/src/ObjWriting/Game/T5/Techset/TechsetDumperT5.cpp deleted file mode 100644 index d7586677..00000000 --- a/src/ObjWriting/Game/T5/Techset/TechsetDumperT5.cpp +++ /dev/null @@ -1,272 +0,0 @@ -#include "TechsetDumperT5.h" - -#include "Game/T5/Material/MaterialConstantZoneStateT5.h" -#include "Game/T5/Techset/TechsetConstantsT5.h" -#include "Shader/ShaderCommon.h" -#include "Techset/CommonTechniqueDumper.h" -#include "Techset/CommonTechsetDumper.h" -#include "Techset/ShaderDumpingZoneState.h" -#include "Techset/TechniqueDumpingZoneState.h" - -#include - -using namespace T5; - -namespace -{ - void DumpPixelShader(const AssetDumpingContext& context, const MaterialPixelShader& pixelShader) - { - const auto shaderFile = context.OpenAssetFile(shader::GetFileNameForPixelShaderAssetName(pixelShader.name)); - - if (!shaderFile) - return; - - shaderFile->write(reinterpret_cast(pixelShader.prog.loadDef.program), pixelShader.prog.loadDef.programSize * sizeof(uint32_t)); - } - - void DumpVertexShader(const AssetDumpingContext& context, const MaterialVertexShader& vertexShader) - { - const auto shaderFile = context.OpenAssetFile(shader::GetFileNameForVertexShaderAssetName(vertexShader.name)); - - if (!shaderFile) - return; - - shaderFile->write(reinterpret_cast(vertexShader.prog.loadDef.program), vertexShader.prog.loadDef.programSize * sizeof(uint32_t)); - } - - void DumpShaders(AssetDumpingContext& context, const MaterialTechniqueSet& techset) - { - auto* shaderState = context.GetZoneAssetDumperState(); - - for (const auto* technique : techset.techniques) - { - if (!technique || !shaderState->ShouldDumpTechnique(technique)) - continue; - - for (auto passIndex = 0u; passIndex < technique->passCount; passIndex++) - { - const auto* pixelShader = technique->passArray[passIndex].pixelShader; - if (pixelShader && shaderState->ShouldDumpPixelShader(pixelShader)) - DumpPixelShader(context, *pixelShader); - - const auto* vertexShader = technique->passArray[passIndex].vertexShader; - if (vertexShader && shaderState->ShouldDumpVertexShader(vertexShader)) - DumpVertexShader(context, *vertexShader); - } - } - } - - techset::CommonVertexDeclaration ConvertToCommonVertexDeclaration(const MaterialVertexDeclaration* vertexDecl) - { - std::vector commonRouting; - - if (vertexDecl) - { - const auto streamCount = std::min(static_cast(vertexDecl->streamCount), std::extent_v); - for (auto streamIndex = 0u; streamIndex < streamCount; streamIndex++) - { - const auto& routing = vertexDecl->routing.data[streamIndex]; - commonRouting.emplace_back(static_cast(routing.source), - static_cast(routing.dest)); - } - } - - return techset::CommonVertexDeclaration(std::move(commonRouting)); - } - - techset::CommonShaderArg ConvertToCommonArg(const MaterialShaderArgument& arg) - { - const techset::CommonShaderArgDestination destination{.dx9 = {.m_destination_register = arg.dest}}; - - switch (arg.type) - { - case MTL_ARG_CODE_VERTEX_CONST: - case MTL_ARG_CODE_PIXEL_CONST: - { - const techset::CommonShaderArgCodeConstValue codeConstValue{ - .m_index = static_cast(arg.u.codeConst.index), - .m_first_row = arg.u.codeConst.firstRow, - .m_row_count = arg.u.codeConst.rowCount, - }; - const techset::CommonShaderArgValue value{.code_const_source = codeConstValue}; - - return techset::CommonShaderArg(commonArgumentTypes[arg.type], destination, value); - } - - case MTL_ARG_MATERIAL_VERTEX_CONST: - case MTL_ARG_MATERIAL_PIXEL_CONST: - { - const techset::CommonShaderArgValue value{ - .name_hash = arg.u.nameHash, - }; - - return techset::CommonShaderArg(commonArgumentTypes[arg.type], destination, value); - } - - case MTL_ARG_CODE_PIXEL_SAMPLER: - { - const techset::CommonShaderArgValue value{ - .code_sampler_source = static_cast(arg.u.codeSampler), - }; - - return techset::CommonShaderArg(commonArgumentTypes[arg.type], destination, value); - } - - case MTL_ARG_MATERIAL_PIXEL_SAMPLER: - { - const techset::CommonShaderArgValue value{ - .name_hash = arg.u.nameHash, - }; - - return techset::CommonShaderArg(commonArgumentTypes[arg.type], destination, value); - } - - default: - case MTL_ARG_LITERAL_VERTEX_CONST: - case MTL_ARG_LITERAL_PIXEL_CONST: - { - techset::CommonShaderArgValue value{}; - if (arg.u.literalConst) - { - value.literal_value = { - (*arg.u.literalConst)[0], - (*arg.u.literalConst)[1], - (*arg.u.literalConst)[2], - (*arg.u.literalConst)[3], - }; - } - - return techset::CommonShaderArg(commonArgumentTypes[arg.type], destination, value); - } - } - } - - techset::CommonTechniqueShader ConvertToCommonShader(const MaterialVertexShader* vertexShader) - { - techset::CommonTechniqueShader result{}; - if (!vertexShader) - return result; - - if (vertexShader->name) - result.m_name = vertexShader->name; - - if (vertexShader->prog.loadDef.program) - { - result.m_bin = techset::CommonTechniqueShaderBin{ - .m_shader_bin = vertexShader->prog.loadDef.program, - .m_shader_bin_size = vertexShader->prog.loadDef.programSize * sizeof(uint32_t), - }; - } - - return result; - } - - techset::CommonTechniqueShader ConvertToCommonShader(const MaterialPixelShader* pixelShader) - { - techset::CommonTechniqueShader result{}; - if (!pixelShader) - return result; - - if (pixelShader->name) - result.m_name = pixelShader->name; - - if (pixelShader->prog.loadDef.program) - { - result.m_bin = techset::CommonTechniqueShaderBin{ - .m_shader_bin = pixelShader->prog.loadDef.program, - .m_shader_bin_size = pixelShader->prog.loadDef.programSize * sizeof(uint32_t), - }; - } - - return result; - } - - techset::CommonTechnique ConvertToCommonTechnique(const MaterialTechnique& technique) - { - techset::CommonTechnique commonTechnique(technique.name ? technique.name : std::string(), technique.flags); - - for (auto passIndex = 0u; passIndex < technique.passCount; passIndex++) - { - const auto& pass = technique.passArray[passIndex]; - techset::CommonPass commonPass(pass.customSamplerFlags, - // No clue what the actual state map was - "passthrough", - ConvertToCommonShader(pass.vertexShader), - ConvertToCommonShader(pass.pixelShader), - ConvertToCommonVertexDeclaration(pass.vertexDecl), - std::string()); - - if (pass.args) - { - const size_t totalArgCount = pass.perPrimArgCount + pass.perObjArgCount + pass.stableArgCount; - commonPass.m_args.reserve(totalArgCount); - for (auto argIndex = 0uz; argIndex < totalArgCount; argIndex++) - commonPass.m_args.emplace_back(ConvertToCommonArg(pass.args[argIndex])); - } - - commonTechnique.m_passes.emplace_back(std::move(commonPass)); - } - - return commonTechnique; - } - - void DumpTechniques(AssetDumpingContext& context, const MaterialTechniqueSet& techset, const bool debug) - { - auto* techniqueState = context.GetZoneAssetDumperState(); - const auto* materialConstantState = context.GetZoneAssetDumperState(); - for (const auto* technique : techset.techniques) - { - if (technique && techniqueState->ShouldDumpTechnique(technique)) - { - const auto commonTechnique = ConvertToCommonTechnique(*technique); - - techset::DumpCommonTechnique( - context, commonTechnique, techset::DxVersion::DX9, commonCodeSourceInfos, commonRoutingInfos, *materialConstantState, debug); - } - } - } - - techset::CommonTechset ConvertToCommonTechset(const MaterialTechniqueSet& techset) - { - std::vector techniqueNames(std::extent_v); - - for (auto techniqueIndex = 0u; techniqueIndex < std::extent_v; techniqueIndex++) - { - const auto* technique = techset.techniques[techniqueIndex]; - if (technique && technique->name) - techniqueNames[techniqueIndex] = technique->name; - } - - return techset::CommonTechset(techset.name, std::move(techniqueNames)); - } - - void DumpTechset(const AssetDumpingContext& context, const MaterialTechniqueSet& techset) - { - static techset::CommonTechniqueTypeNames commonNames(techniqueTypeNames, std::extent_v); - const auto commonTechset = ConvertToCommonTechset(techset); - - techset::DumpCommonTechset(commonNames, context, commonTechset); - } -} // namespace - -namespace techset -{ - DumperT5::DumperT5(const bool debug) - : m_debug(debug) - { - } - - void DumperT5::Dump(AssetDumpingContext& context) - { - context.GetZoneAssetDumperState()->EnsureInitialized(); - AbstractAssetDumper::Dump(context); - } - - void DumperT5::DumpAsset(AssetDumpingContext& context, const XAssetInfo& asset) - { - const auto* techniqueSet = asset.Asset(); - DumpTechset(context, *techniqueSet); - DumpTechniques(context, *techniqueSet, m_debug); - DumpShaders(context, *techniqueSet); - } -} // namespace techset diff --git a/src/ObjWriting/Game/T5/Techset/TechsetDumperT5.h b/src/ObjWriting/Game/T5/Techset/TechsetDumperT5.h deleted file mode 100644 index bbaadf35..00000000 --- a/src/ObjWriting/Game/T5/Techset/TechsetDumperT5.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include "Dumping/AbstractAssetDumper.h" -#include "Game/T5/T5.h" - -namespace techset -{ - class DumperT5 final : public AbstractAssetDumper - { - public: - explicit DumperT5(bool debug); - - void Dump(AssetDumpingContext& context) override; - - protected: - void DumpAsset(AssetDumpingContext& context, const XAssetInfo& asset) override; - - private: - bool m_debug; - }; -} // namespace techset diff --git a/src/ObjWriting/Techset/TechsetDumper.cpp.template b/src/ObjWriting/Techset/TechsetDumper.cpp.template index 81c9792b..9bc7ba7c 100644 --- a/src/ObjWriting/Techset/TechsetDumper.cpp.template +++ b/src/ObjWriting/Techset/TechsetDumper.cpp.template @@ -1,4 +1,4 @@ -#options GAME(IW3, IW4, T6) +#options GAME(IW3, IW4, T5, T6) #filename "Game/" + GAME + "/Techset/TechsetDumper" + GAME + ".cpp" @@ -19,6 +19,7 @@ #elif GAME == "T5" #define FEATURE_T5 #define IS_DX9 +#define DUMP_SHADERS "1" #elif GAME == "T6" #define FEATURE_T6 #define IS_DX11 diff --git a/src/ObjWriting/Techset/TechsetDumper.h.template b/src/ObjWriting/Techset/TechsetDumper.h.template index 2139bc0c..f8eeb69b 100644 --- a/src/ObjWriting/Techset/TechsetDumper.h.template +++ b/src/ObjWriting/Techset/TechsetDumper.h.template @@ -1,4 +1,4 @@ -#options GAME(IW3, IW4, T6) +#options GAME(IW3, IW4, T5, T6) #filename "Game/" + GAME + "/Techset/TechsetDumper" + GAME + ".h" From e8b9ece6bd3341a08aba0ad0c215a91635d4d9be Mon Sep 17 00:00:00 2001 From: Jan Laupetin Date: Sat, 14 Mar 2026 23:23:30 +0100 Subject: [PATCH 2/4] feat: t5 techset compiling --- src/ObjCompiling/Game/T5/ObjCompilerT5.cpp | 9 ++++++++- .../Techset/TechniqueCompiler.cpp.template | 16 +++++++++++++--- .../Techset/TechniqueCompiler.h.template | 2 +- .../Techset/TechsetCompiler.cpp.template | 2 +- .../Techset/TechsetCompiler.h.template | 2 +- .../Techset/VertexDeclCompiler.cpp.template | 3 ++- .../Techset/VertexDeclCompiler.h.template | 3 ++- src/ObjLoading/Game/T5/ObjLoaderT5.cpp | 5 +++++ .../Techset/PixelShaderLoader.cpp.template | 3 ++- .../Techset/PixelShaderLoader.h.template | 3 ++- .../Techset/VertexShaderLoader.cpp.template | 3 ++- .../Techset/VertexShaderLoader.h.template | 3 ++- 12 files changed, 41 insertions(+), 13 deletions(-) diff --git a/src/ObjCompiling/Game/T5/ObjCompilerT5.cpp b/src/ObjCompiling/Game/T5/ObjCompilerT5.cpp index 0442c1e8..12a63556 100644 --- a/src/ObjCompiling/Game/T5/ObjCompilerT5.cpp +++ b/src/ObjCompiling/Game/T5/ObjCompilerT5.cpp @@ -1,6 +1,9 @@ #include "ObjCompilerT5.h" #include "Game/T5/T5.h" +#include "Game/T5/Techset/TechniqueCompilerT5.h" +#include "Game/T5/Techset/TechsetCompilerT5.h" +#include "Game/T5/Techset/VertexDeclCompilerT5.h" #include "Image/ImageIwdPostProcessor.h" #include @@ -13,7 +16,10 @@ namespace { auto& memory = zone.Memory(); - // No compilers yet + collection.AddAssetCreator(techset::CreateTechsetCompilerT5(memory, searchPath)); + + collection.AddSubAssetCreator(techset::CreateTechniqueCompilerT5(memory, zone, searchPath)); + collection.AddSubAssetCreator(techset::CreateVertexDeclCompilerT5(memory)); } void ConfigurePostProcessors(AssetCreatorCollection& collection, @@ -39,5 +45,6 @@ void ObjCompiler::ConfigureCreatorCollection(AssetCreatorCollection& collection, IOutputPath& outDir, IOutputPath& cacheDir) const { + ConfigureCompilers(collection, zone, searchPath); ConfigurePostProcessors(collection, zone, zoneDefinition, searchPath, zoneStates, outDir); } diff --git a/src/ObjCompiling/Techset/TechniqueCompiler.cpp.template b/src/ObjCompiling/Techset/TechniqueCompiler.cpp.template index 14d6facc..7728ac01 100644 --- a/src/ObjCompiling/Techset/TechniqueCompiler.cpp.template +++ b/src/ObjCompiling/Techset/TechniqueCompiler.cpp.template @@ -1,4 +1,4 @@ -#options GAME(IW3, IW4, T6) +#options GAME(IW3, IW4, T5, T6) #filename "Game/" + GAME + "/Techset/TechniqueCompiler" + GAME + ".cpp" @@ -297,6 +297,14 @@ namespace if (ShouldApplyFlag200(technique)) technique.flags |= TECHNIQUE_FLAG_200; +#elif defined(FEATURE_T5) + // Not a particularly cool way to do this but... + // the game actually does this :shrug: + if (lowerTechniqueName == "zprepass" || lowerTechniqueName.starts_with("pimp_technique_zprepass_") + || lowerTechniqueName.starts_with("pimp_technique_layer_zprepass_")) + { + technique.flags |= MTL_TECHFLAG_ZPREPASS; + } #elif defined(FEATURE_T6) // Not a particularly cool way to do this but... // the game actually does this :shrug: @@ -332,7 +340,7 @@ namespace return technique; } -#if defined(FEATURE_T6) +#if defined(FEATURE_T5) || defined(FEATURE_T6) void ApplyTechFlagsFromMaterial(const Material& material, const Zone& zone) { if (!material.techniqueSet || !material.techniqueSet->name || !material.stateBitsTable) @@ -458,13 +466,15 @@ namespace void FinalizeZone(AssetCreationContext& context) override { -#if defined(FEATURE_T6) +#if defined(FEATURE_T5) || defined(FEATURE_T6) const auto materials = m_zone.m_pools.PoolAssets(); for (auto* materialAsset : materials) { ApplyTechFlagsFromMaterial(*materialAsset->Asset(), m_zone); } +#endif +#if defined(FEATURE_T6) const auto techniques = context.PoolSubAssets(); for (auto* techniqueSubAsset : techniques) { diff --git a/src/ObjCompiling/Techset/TechniqueCompiler.h.template b/src/ObjCompiling/Techset/TechniqueCompiler.h.template index 300d599e..b299555e 100644 --- a/src/ObjCompiling/Techset/TechniqueCompiler.h.template +++ b/src/ObjCompiling/Techset/TechniqueCompiler.h.template @@ -1,4 +1,4 @@ -#options GAME(IW3, IW4, T6) +#options GAME(IW3, IW4, T5, T6) #filename "Game/" + GAME + "/Techset/TechniqueCompiler" + GAME + ".h" diff --git a/src/ObjCompiling/Techset/TechsetCompiler.cpp.template b/src/ObjCompiling/Techset/TechsetCompiler.cpp.template index 980926d0..74d49327 100644 --- a/src/ObjCompiling/Techset/TechsetCompiler.cpp.template +++ b/src/ObjCompiling/Techset/TechsetCompiler.cpp.template @@ -1,4 +1,4 @@ -#options GAME(IW3, IW4, T6) +#options GAME(IW3, IW4, T5, T6) #filename "Game/" + GAME + "/Techset/TechsetCompiler" + GAME + ".cpp" diff --git a/src/ObjCompiling/Techset/TechsetCompiler.h.template b/src/ObjCompiling/Techset/TechsetCompiler.h.template index ce6ff411..0bc5dc42 100644 --- a/src/ObjCompiling/Techset/TechsetCompiler.h.template +++ b/src/ObjCompiling/Techset/TechsetCompiler.h.template @@ -1,4 +1,4 @@ -#options GAME(IW3, IW4, T6) +#options GAME(IW3, IW4, T5, T6) #filename "Game/" + GAME + "/Techset/TechsetCompiler" + GAME + ".h" diff --git a/src/ObjCompiling/Techset/VertexDeclCompiler.cpp.template b/src/ObjCompiling/Techset/VertexDeclCompiler.cpp.template index ad6dcc04..4413cd01 100644 --- a/src/ObjCompiling/Techset/VertexDeclCompiler.cpp.template +++ b/src/ObjCompiling/Techset/VertexDeclCompiler.cpp.template @@ -1,4 +1,4 @@ -#options GAME(IW3, IW4, T6) +#options GAME(IW3, IW4, T5, T6) #filename "Game/" + GAME + "/Techset/VertexDeclCompiler" + GAME + ".cpp" @@ -15,6 +15,7 @@ #define FEATURE_IW5 #elif GAME == "T5" #define FEATURE_T5 +#define IS_SUB_ASSET #elif GAME == "T6" #define FEATURE_T6 #define IS_SUB_ASSET diff --git a/src/ObjCompiling/Techset/VertexDeclCompiler.h.template b/src/ObjCompiling/Techset/VertexDeclCompiler.h.template index 32f66784..05341b40 100644 --- a/src/ObjCompiling/Techset/VertexDeclCompiler.h.template +++ b/src/ObjCompiling/Techset/VertexDeclCompiler.h.template @@ -1,4 +1,4 @@ -#options GAME(IW3, IW4, T6) +#options GAME(IW3, IW4, T5, T6) #filename "Game/" + GAME + "/Techset/VertexDeclCompiler" + GAME + ".h" @@ -11,6 +11,7 @@ #define FEATURE_IW5 #elif GAME == "T5" #define FEATURE_T5 +#define IS_SUB_ASSET #elif GAME == "T6" #define FEATURE_T6 #define IS_SUB_ASSET diff --git a/src/ObjLoading/Game/T5/ObjLoaderT5.cpp b/src/ObjLoading/Game/T5/ObjLoaderT5.cpp index 01d22d5f..b50a9a53 100644 --- a/src/ObjLoading/Game/T5/ObjLoaderT5.cpp +++ b/src/ObjLoading/Game/T5/ObjLoaderT5.cpp @@ -6,6 +6,8 @@ #include "Game/T5/Image/ImageLoaderEmbeddedT5.h" #include "Game/T5/Image/ImageLoaderExternalT5.h" #include "Game/T5/T5.h" +#include "Game/T5/Techset/PixelShaderLoaderT5.h" +#include "Game/T5/Techset/VertexShaderLoaderT5.h" #include "Game/T5/XModel/LoaderXModelT5.h" #include "Localize/LoaderLocalizeT5.h" #include "Material/LoaderMaterialT5.h" @@ -136,6 +138,9 @@ namespace // collection.AddAssetCreator(std::make_unique(memory)); // collection.AddAssetCreator(std::make_unique(memory)); // collection.AddAssetCreator(std::make_unique(memory)); + + collection.AddSubAssetCreator(techset::CreateVertexShaderLoaderT5(memory, searchPath)); + collection.AddSubAssetCreator(techset::CreatePixelShaderLoaderT5(memory, searchPath)); } } // namespace diff --git a/src/ObjLoading/Techset/PixelShaderLoader.cpp.template b/src/ObjLoading/Techset/PixelShaderLoader.cpp.template index d02e87bb..7cb348bc 100644 --- a/src/ObjLoading/Techset/PixelShaderLoader.cpp.template +++ b/src/ObjLoading/Techset/PixelShaderLoader.cpp.template @@ -1,4 +1,4 @@ -#options GAME(IW3, IW4, T6) +#options GAME(IW3, IW4, T5, T6) #filename "Game/" + GAME + "/Techset/PixelShaderLoader" + GAME + ".cpp" @@ -18,6 +18,7 @@ #elif GAME == "T5" #define FEATURE_T5 #define IS_DX9 +#define IS_SUB_ASSET #elif GAME == "T6" #define FEATURE_T6 #define IS_DX11 diff --git a/src/ObjLoading/Techset/PixelShaderLoader.h.template b/src/ObjLoading/Techset/PixelShaderLoader.h.template index bc2a1731..8acc4180 100644 --- a/src/ObjLoading/Techset/PixelShaderLoader.h.template +++ b/src/ObjLoading/Techset/PixelShaderLoader.h.template @@ -1,4 +1,4 @@ -#options GAME(IW3, IW4, T6) +#options GAME(IW3, IW4, T5, T6) #filename "Game/" + GAME + "/Techset/PixelShaderLoader" + GAME + ".h" @@ -11,6 +11,7 @@ #define FEATURE_IW5 #elif GAME == "T5" #define FEATURE_T5 +#define IS_SUB_ASSET #elif GAME == "T6" #define FEATURE_T6 #define IS_SUB_ASSET diff --git a/src/ObjLoading/Techset/VertexShaderLoader.cpp.template b/src/ObjLoading/Techset/VertexShaderLoader.cpp.template index 3e02b330..671f478a 100644 --- a/src/ObjLoading/Techset/VertexShaderLoader.cpp.template +++ b/src/ObjLoading/Techset/VertexShaderLoader.cpp.template @@ -1,4 +1,4 @@ -#options GAME(IW3, IW4, T6) +#options GAME(IW3, IW4, T5, T6) #filename "Game/" + GAME + "/Techset/VertexShaderLoader" + GAME + ".cpp" @@ -18,6 +18,7 @@ #elif GAME == "T5" #define FEATURE_T5 #define IS_DX9 +#define IS_SUB_ASSET #elif GAME == "T6" #define FEATURE_T6 #define IS_DX11 diff --git a/src/ObjLoading/Techset/VertexShaderLoader.h.template b/src/ObjLoading/Techset/VertexShaderLoader.h.template index 83957393..0bddf735 100644 --- a/src/ObjLoading/Techset/VertexShaderLoader.h.template +++ b/src/ObjLoading/Techset/VertexShaderLoader.h.template @@ -1,4 +1,4 @@ -#options GAME(IW3, IW4, T6) +#options GAME(IW3, IW4, T5, T6) #filename "Game/" + GAME + "/Techset/VertexShaderLoader" + GAME + ".h" @@ -11,6 +11,7 @@ #define FEATURE_IW5 #elif GAME == "T5" #define FEATURE_T5 +#define IS_SUB_ASSET #elif GAME == "T6" #define FEATURE_T6 #define IS_SUB_ASSET From f4ed3e6c93a38edc64d82b5b97da1ff6539d9a8d Mon Sep 17 00:00:00 2001 From: Jan Laupetin Date: Sun, 15 Mar 2026 12:56:13 +0100 Subject: [PATCH 3/4] fix: warn but accept invalid argument types in shaders cheers to T5 mc_sw4_3d_char_skin_gas that uses a sampler in the vertex shader --- .../Techset/CommonShaderArgCreator.cpp | 84 ++++++++++++++++++- 1 file changed, 82 insertions(+), 2 deletions(-) diff --git a/src/ObjCompiling/Techset/CommonShaderArgCreator.cpp b/src/ObjCompiling/Techset/CommonShaderArgCreator.cpp index 43045cd7..adcbc615 100644 --- a/src/ObjCompiling/Techset/CommonShaderArgCreator.cpp +++ b/src/ObjCompiling/Techset/CommonShaderArgCreator.cpp @@ -12,6 +12,35 @@ namespace { + const char* ShaderTypeName(const techset::CommonTechniqueShaderType shaderType) + { + switch (shaderType) + { + case techset::CommonTechniqueShaderType::VERTEX: + return "vertex"; + case techset::CommonTechniqueShaderType::PIXEL: + return "pixel"; + } + + return ""; + } + + const char* ArgTypeName(const techset::CommonShaderValueType valueType) + { + switch (valueType) + { + case techset::CommonShaderValueType::CODE_CONST: + case techset::CommonShaderValueType::LITERAL_CONST: + case techset::CommonShaderValueType::MATERIAL_CONST: + return "constant"; + case techset::CommonShaderValueType::CODE_SAMPLER: + case techset::CommonShaderValueType::MATERIAL_SAMPLER: + return "sampler"; + } + + return ""; + } + class BaseCommonShaderArgCreator : public techset::CommonShaderArgCreator { public: @@ -28,6 +57,7 @@ namespace result::Expected EnterShader(const techset::CommonTechniqueShaderType shaderType, const std::string& name) override { m_shader_type = shaderType; + m_shader_name = name; std::optional maybeShader; if (shaderType == techset::CommonTechniqueShaderType::VERTEX) @@ -109,6 +139,9 @@ namespace .m_value_type = techset::CommonShaderValueType::LITERAL_CONST, }; + if (!IsArgumentTypeSupported(argumentType)) + return result::Unexpected(std::format("{} constants are unsupported", ShaderTypeName(argumentType.m_shader_type))); + techset::CommonShaderArgValue value{.literal_value = literalValue}; m_args.emplace_back(argumentType, commonDestination, value); @@ -143,6 +176,12 @@ namespace } } + if (!IsArgumentTypeSupported(argumentType)) + { + return result::Unexpected( + std::format("{} {} are unsupported", ShaderTypeName(argumentType.m_shader_type), ArgTypeName(argumentType.m_value_type))); + } + techset::CommonShaderArgValue value{.name_hash = nameHash}; m_args.emplace_back(argumentType, commonDestination, value); @@ -205,6 +244,9 @@ namespace .m_value_type = techset::CommonShaderValueType::CODE_CONST, }; + if (!IsArgumentTypeSupported(argumentType)) + return result::Unexpected(std::format("{} constants are unsupported", ShaderTypeName(argumentType.m_shader_type))); + const auto maybeInfo = m_common_code_source_infos.GetInfoForCodeConstSource(codeConstSource); if (!maybeInfo) return result::Unexpected("Could not find info for code constant"); @@ -249,6 +291,9 @@ namespace .m_value_type = techset::CommonShaderValueType::CODE_SAMPLER, }; + if (!IsArgumentTypeSupported(argumentType)) + return result::Unexpected(std::format("{} samplers are unsupported", ShaderTypeName(argumentType.m_shader_type))); + const auto maybeInfo = m_common_code_source_infos.GetInfoForCodeSamplerSource(codeSamplerSource); if (!maybeInfo) return result::Unexpected("Could not find info for code sampler"); @@ -262,6 +307,24 @@ namespace return NoResult{}; } + static bool IsArgumentTypeSupported(const techset::CommonShaderArgumentType& argumentType) + { + if (argumentType.m_shader_type == techset::CommonTechniqueShaderType::PIXEL) + return true; + + switch (argumentType.m_value_type) + { + case techset::CommonShaderValueType::LITERAL_CONST: + case techset::CommonShaderValueType::MATERIAL_CONST: + case techset::CommonShaderValueType::CODE_CONST: + return true; + case techset::CommonShaderValueType::MATERIAL_SAMPLER: + case techset::CommonShaderValueType::CODE_SAMPLER: + default: + return false; + } + } + [[nodiscard]] virtual size_t CompareArgumentDestinations(const techset::CommonShaderArg& arg0, const techset::CommonShaderArg& arg1) const = 0; [[nodiscard]] virtual bool FindDestinationForConstant(techset::CommonShaderArgDestination& commonDestination, @@ -279,6 +342,7 @@ namespace techset::CommonCodeSourceInfos& m_common_code_source_infos; techset::CommonTechniqueShaderType m_shader_type; + std::string m_shader_name; techset::CommonTechniqueShaderBin m_bin; std::vector m_args; @@ -341,8 +405,6 @@ namespace if (foundConstant == m_shader_info->m_constants.end()) return false; - const auto variableElementCount = std::max(foundConstant->m_register_count, 1); - commonDestination.dx9.m_destination_register = foundConstant->m_register_index; isTransposed = foundConstant->m_class == d3d9::ParameterClass::MATRIX_COLUMNS; rowCount = foundConstant->m_register_count; @@ -409,6 +471,15 @@ namespace private: result::Expected AutoCreateConstantArg(const d3d9::ShaderConstant& shaderArg) { + if (!IsArgumentTypeSupported( + techset::CommonShaderArgumentType{.m_shader_type = m_shader_type, .m_value_type = techset::CommonShaderValueType::CODE_CONST})) + { + con::warn("Shader {} uses unsupported argument type \"{} constant\". This may cause unstable behaviour.", + m_shader_name, + ShaderTypeName(m_shader_type)); + return NoResult{}; + } + const auto maybeCodeConst = m_common_code_source_infos.GetCodeConstSourceForAccessor(shaderArg.m_name); if (!maybeCodeConst) { @@ -464,6 +535,15 @@ namespace result::Expected AutoCreateSamplerArg(const d3d9::ShaderConstant& shaderArg) { + if (!IsArgumentTypeSupported( + techset::CommonShaderArgumentType{.m_shader_type = m_shader_type, .m_value_type = techset::CommonShaderValueType::CODE_SAMPLER})) + { + con::warn("Shader {} uses unsupported argument type \"{} sampler\". This may cause unstable behaviour.", + m_shader_name, + ShaderTypeName(m_shader_type)); + return NoResult{}; + } + const auto maybeCodeSampler = m_common_code_source_infos.GetCodeSamplerSourceForAccessor(shaderArg.m_name); if (!maybeCodeSampler) return result::Unexpected(std::format("Missing assignment to shader texture {}", shaderArg.m_name)); From b93925c3061301f4a771a04579cfbbec5e78f993 Mon Sep 17 00:00:00 2001 From: Jan Laupetin Date: Sun, 15 Mar 2026 15:31:01 +0100 Subject: [PATCH 4/4] fix: inconsistencies on t5 technique compilation --- src/Common/Game/T5/T5_Assets.h | 6 +++-- .../Game/T5/Techset/TechsetConstantsT5.h | 16 ++++++++++--- src/ObjCommon/Techset/CommonTechnique.h | 1 + .../Techset/CommonShaderArgCreator.cpp | 24 ++++++++++++++++--- .../Material/MaterialConstantZoneStateT5.cpp | 18 ++++++++++++++ .../Techset/CommonTechniqueDumper.cpp | 13 +++++----- 6 files changed, 64 insertions(+), 14 deletions(-) diff --git a/src/Common/Game/T5/T5_Assets.h b/src/Common/Game/T5/T5_Assets.h index 1e42c95b..077a82ef 100644 --- a/src/Common/Game/T5/T5_Assets.h +++ b/src/Common/Game/T5/T5_Assets.h @@ -1533,8 +1533,10 @@ namespace T5 // - Any polygon offset that is not GFXS1_POLYGON_OFFSET_0 TECHNIQUE_FLAG_80 = 0x80, - TECHNIQUE_FLAG_100 = 0x100, - TECHNIQUE_FLAG_200 = 0x200, + // Uses marksHitNormal + MTL_TECHFLAG_USES_MARKS_HIT_NORMAL = 0x100, + // Uses __characterCharredAmount or destructibleParms. Not sure how those two relate? + MTL_TECHFLAG_200 = 0x200, }; struct MaterialPass diff --git a/src/ObjCommon/Game/T5/Techset/TechsetConstantsT5.h b/src/ObjCommon/Game/T5/Techset/TechsetConstantsT5.h index 8ea418de..a382caeb 100644 --- a/src/ObjCommon/Game/T5/Techset/TechsetConstantsT5.h +++ b/src/ObjCommon/Game/T5/Techset/TechsetConstantsT5.h @@ -315,6 +315,7 @@ namespace T5 .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::RARELY, .techFlags = MTL_TECHFLAG_USES_LIGHT_SPOT_FACTORS, + .techFlagShaderType = techset::CommonTechniqueShaderType::PIXEL, }, { .value = CONST_SRC_CODE_LIGHT_ATTENUATION, @@ -730,6 +731,7 @@ namespace T5 .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::RARELY, .techFlags = MTL_TECHFLAG_USES_GRASS, + .techFlagShaderType = techset::CommonTechniqueShaderType::VERTEX, }, { .value = CONST_SRC_CODE_GRASS_FORCE0, @@ -737,6 +739,7 @@ namespace T5 .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::RARELY, .techFlags = MTL_TECHFLAG_USES_GRASS, + .techFlagShaderType = techset::CommonTechniqueShaderType::VERTEX, }, { .value = CONST_SRC_CODE_GRASS_FORCE1, @@ -744,6 +747,7 @@ namespace T5 .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::RARELY, .techFlags = MTL_TECHFLAG_USES_GRASS, + .techFlagShaderType = techset::CommonTechniqueShaderType::VERTEX, }, { .value = CONST_SRC_CODE_GRASS_WIND_FORCE0, @@ -751,6 +755,7 @@ namespace T5 .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::RARELY, .techFlags = MTL_TECHFLAG_USES_GRASS, + .techFlagShaderType = techset::CommonTechniqueShaderType::VERTEX, }, { .value = CONST_SRC_CODE_MOTIONBLUR_DIRECTION_AND_MAGNITUDE, @@ -841,7 +846,8 @@ namespace T5 .accessor = "destructibleParms", .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::RARELY, - .techFlags = TECHNIQUE_FLAG_200, + .techFlags = MTL_TECHFLAG_200, + .techFlagShaderType = techset::CommonTechniqueShaderType::VERTEX, }, { .value = CONST_SRC_CODE_CLOUD_WORLD_AREA, @@ -866,7 +872,8 @@ namespace T5 .accessor = "__characterCharredAmount", .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::RARELY, - .techFlags = TECHNIQUE_FLAG_200, + .techFlags = MTL_TECHFLAG_200, + .techFlagShaderType = techset::CommonTechniqueShaderType::VERTEX, }, { .value = CONST_SRC_CODE_TREECANOPY_PARMS, @@ -879,6 +886,8 @@ namespace T5 .accessor = "marksHitNormal", .arrayCount = 0, .updateFrequency = techset::CommonCodeSourceUpdateFrequency::PER_PRIM, + .techFlags = MTL_TECHFLAG_USES_MARKS_HIT_NORMAL, + .techFlagShaderType = techset::CommonTechniqueShaderType::VERTEX, }, { .value = CONST_SRC_CODE_POSTFX_CONTROL0, @@ -1587,7 +1596,7 @@ namespace T5 .value = TEXTURE_SRC_CODE_LIGHTMAP_PRIMARY, .accessor = "lightmapSamplerPrimary", .updateFrequency = techset::CommonCodeSourceUpdateFrequency::CUSTOM, - .customSamplerIndex = CUSTOM_SAMPLER_LIGHTMAP_SECONDARY, + .customSamplerIndex = CUSTOM_SAMPLER_LIGHTMAP_PRIMARY, }, { .value = TEXTURE_SRC_CODE_LIGHTMAP_SECONDARY, @@ -1709,6 +1718,7 @@ namespace T5 .value = TEXTURE_SRC_CODE_REFLECTION_PROBE, .accessor = "reflectionProbeSampler", .updateFrequency = techset::CommonCodeSourceUpdateFrequency::CUSTOM, + .customSamplerIndex = CUSTOM_SAMPLER_REFLECTION_PROBE, }, { .value = TEXTURE_SRC_CODE_FEATHER_FLOAT_Z, diff --git a/src/ObjCommon/Techset/CommonTechnique.h b/src/ObjCommon/Techset/CommonTechnique.h index 8e54aa40..3f2153a5 100644 --- a/src/ObjCommon/Techset/CommonTechnique.h +++ b/src/ObjCommon/Techset/CommonTechnique.h @@ -79,6 +79,7 @@ namespace techset std::uint8_t arrayCount; CommonCodeSourceUpdateFrequency updateFrequency; std::optional techFlags; + std::optional techFlagShaderType; std::optional transposedMatrix; }; diff --git a/src/ObjCompiling/Techset/CommonShaderArgCreator.cpp b/src/ObjCompiling/Techset/CommonShaderArgCreator.cpp index adcbc615..87ae4f3e 100644 --- a/src/ObjCompiling/Techset/CommonShaderArgCreator.cpp +++ b/src/ObjCompiling/Techset/CommonShaderArgCreator.cpp @@ -277,7 +277,7 @@ namespace } m_args.emplace_back(argumentType, commonDestination, techset::CommonShaderArgValue{.code_const_source = value}); - if (maybeInfo->techFlags) + if (maybeInfo->techFlags && (!maybeInfo->techFlagShaderType || *maybeInfo->techFlagShaderType == m_shader_type)) m_tech_flags |= *maybeInfo->techFlags; return NoResult{}; @@ -515,7 +515,7 @@ namespace return std::move(result); } - if (constInfo->techFlags) + if (constInfo->techFlags && (!constInfo->techFlagShaderType || *constInfo->techFlagShaderType == m_shader_type)) m_tech_flags |= *constInfo->techFlags; return NoResult{}; @@ -825,6 +825,15 @@ namespace result::Expected AutoCreateConstantArg(const d3d11::ConstantBufferVariable& variable, const size_t bufferIndex) { + if (!IsArgumentTypeSupported( + techset::CommonShaderArgumentType{.m_shader_type = m_shader_type, .m_value_type = techset::CommonShaderValueType::CODE_CONST})) + { + con::warn("Shader {} uses unsupported argument type \"{} constant\". This may cause unstable behaviour.", + m_shader_name, + ShaderTypeName(m_shader_type)); + return NoResult{}; + } + const auto maybeCodeConst = m_common_code_source_infos.GetCodeConstSourceForAccessor(variable.m_name); if (!maybeCodeConst) { @@ -862,7 +871,7 @@ namespace return std::move(result); } - if (constInfo->techFlags) + if (constInfo->techFlags && (!constInfo->techFlagShaderType || *constInfo->techFlagShaderType == m_shader_type)) m_tech_flags |= *constInfo->techFlags; return NoResult{}; @@ -870,6 +879,15 @@ namespace result::Expected AutoCreateSamplerArg(const d3d11::BoundResource& textureResource, const unsigned samplerBindPoint) { + if (!IsArgumentTypeSupported( + techset::CommonShaderArgumentType{.m_shader_type = m_shader_type, .m_value_type = techset::CommonShaderValueType::CODE_SAMPLER})) + { + con::warn("Shader {} uses unsupported argument type \"{} sampler\". This may cause unstable behaviour.", + m_shader_name, + ShaderTypeName(m_shader_type)); + return NoResult{}; + } + const auto maybeCodeSampler = m_common_code_source_infos.GetCodeSamplerSourceForAccessor(textureResource.m_name); if (!maybeCodeSampler) return result::Unexpected(std::format("Missing assignment to shader texture {}", textureResource.m_name)); diff --git a/src/ObjWriting/Game/T5/Material/MaterialConstantZoneStateT5.cpp b/src/ObjWriting/Game/T5/Material/MaterialConstantZoneStateT5.cpp index 3293c570..37fe8827 100644 --- a/src/ObjWriting/Game/T5/Material/MaterialConstantZoneStateT5.cpp +++ b/src/ObjWriting/Game/T5/Material/MaterialConstantZoneStateT5.cpp @@ -33,6 +33,7 @@ namespace "DarkenPower", "Detail_Amount", "Detail_Normal_Tile", + "Diffuse_MapSampler", "Diffuse_Normal_Height_Facing", "Dimensions", "DispersionAmount", @@ -44,6 +45,7 @@ namespace "EdgeMinDist", "EdgeSize", "Edge_Color_Multiplier", + "Edge_Intensity", "Emissive_Amount", "EnemiesColor", "Exposure", @@ -143,6 +145,7 @@ namespace "NormalHeightMultiplier", "Normal_Detail_Height", "Normal_Detail_Scale", + "Normal_MapSampler", "Normal_Map_Size_Scale", "Normal_Variance_Scale", "NumFrames", @@ -157,6 +160,7 @@ namespace "Player_Lookup_Scale", "PositiveColor", "Power", + "PreviewCompID", "PulseColor", "PulseInterval", "PulseTime", @@ -165,6 +169,7 @@ namespace "Radius", "ReflectionAmount", "Reflection_Amount", + "Reflection_Amt", "Reflection_Blur", "Reticle_Alt_Color", "Reticle_Color", @@ -177,6 +182,7 @@ namespace "ScanlineSpeed", "ScatterAmount", "ScatterSize", + "Scatter_Intensity", "SceneNoise", "SparkleBrightness", "SparkleDensity", @@ -189,6 +195,7 @@ namespace "SpecularAmount", "SpecularColor", "Specular_Amount", + "Specular_Color", "Specular_Decay_Threshold", "Speed", "StaticAmount", @@ -202,6 +209,7 @@ namespace "TearLookupSpeed", "TearMultiplier", "TearPower", + "Temporal_Sharpness", "Thickness", "TickMarkColorAndHarshness", "Tint", @@ -221,6 +229,9 @@ namespace "WaterScale2", "WaterSpeed1", "WaterSpeed2", + "Wetness_Color", + "Wetness_Color_Gloss_Bias", + "Wetness_Specular_Swatch_Scale", "Zoom", "alphaDissolveParms", "alphaRevealParms", @@ -230,6 +241,11 @@ namespace "alphaRevealParms4", "clipSpaceLookupOffset", "clipSpaceLookupScale", + "cloakTextureControl0", + "cloakTextureControl1", + "clothcharrColorMapScale", + "clothcharrEmberColorAndBrightness", + "clothcharrMaskMapScale", "cloudsFeather", "cloudsHeights", "cloudsUVMad1", @@ -333,6 +349,7 @@ namespace "CompassMap", "Detail_Map", "Diffuse", + "DiffuseBurnt2", "Diffuse_Map", "DpadTexture", "FontTextutre", @@ -374,6 +391,7 @@ namespace "Static", "StaticMap", "Static_Noise_Map", + "Stretch_Map", "SunShadowSamplerState", "SunShadowState", "Surface_Normal_Map", diff --git a/src/ObjWriting/Techset/CommonTechniqueDumper.cpp b/src/ObjWriting/Techset/CommonTechniqueDumper.cpp index 0be6f401..2c6c9ffc 100644 --- a/src/ObjWriting/Techset/CommonTechniqueDumper.cpp +++ b/src/ObjWriting/Techset/CommonTechniqueDumper.cpp @@ -231,6 +231,7 @@ namespace static_cast(arg.m_type.m_value_type)); return; } + const auto buffer = std::ranges::find_if(shaderInfo.m_constant_buffers, [&boundResource](const d3d11::ConstantBuffer& constantBuffer) { @@ -409,15 +410,15 @@ namespace Indent(); std::string materialPropertyName; - if (m_constant_zone_state.GetConstantName(arg.m_value.name_hash, materialPropertyName) - || m_constant_zone_state.GetTextureDefName(arg.m_value.name_hash, materialPropertyName)) - { - m_stream << std::format("{} = material.{};\n", codeDestAccessor, materialPropertyName); - } - else if (m_constant_zone_state.HashString(codeDestAccessor) == arg.m_value.name_hash) + if (m_constant_zone_state.HashString(codeDestAccessor) == arg.m_value.name_hash) { m_stream << std::format("{} = material.{};\n", codeDestAccessor, codeDestAccessor); } + else if (m_constant_zone_state.GetConstantName(arg.m_value.name_hash, materialPropertyName) + || m_constant_zone_state.GetTextureDefName(arg.m_value.name_hash, materialPropertyName)) + { + m_stream << std::format("{} = material.{};\n", codeDestAccessor, materialPropertyName); + } else { m_stream << std::format("{} = material.#0x{:x};\n", codeDestAccessor, arg.m_value.name_hash);