diff --git a/src/Common/Game/T6/T6_Assets.h b/src/Common/Game/T6/T6_Assets.h index 8ab7f84f..d38ed38e 100644 --- a/src/Common/Game/T6/T6_Assets.h +++ b/src/Common/Game/T6/T6_Assets.h @@ -3001,7 +3001,7 @@ namespace T6 VERTEX_SHADER_MODEL_UNLIT, }; - enum CustomSamplers + enum CustomSampler { CUSTOM_SAMPLER_REFLECTION_PROBE = 0, CUSTOM_SAMPLER_LIGHTMAP_SECONDARY, @@ -6191,7 +6191,7 @@ namespace T6 unsigned int nameHash; }; - enum MaterialShaderArgumentType + enum MaterialShaderArgumentType : uint16_t { MTL_ARG_MATERIAL_VERTEX_CONST = 0x0, MTL_ARG_LITERAL_VERTEX_CONST = 0x1, @@ -6213,7 +6213,7 @@ namespace T6 struct MaterialShaderArgument { - uint16_t type; + MaterialShaderArgumentType type; MaterialArgumentLocation location; uint16_t size; uint16_t buffer; diff --git a/src/ObjCommon/Techset/CommonTechnique.cpp b/src/ObjCommon/Techset/CommonTechnique.cpp index d67d5617..52ef6f5f 100644 --- a/src/ObjCommon/Techset/CommonTechnique.cpp +++ b/src/ObjCommon/Techset/CommonTechnique.cpp @@ -280,12 +280,14 @@ namespace techset std::string stateMap, CommonTechniqueShader vertexShader, CommonTechniqueShader pixelShader, - CommonVertexDeclaration vertexDeclaration) + CommonVertexDeclaration vertexDeclaration, + std::string comment) : m_sampler_flags(samplerFlags), m_state_map(std::move(stateMap)), m_vertex_shader(std::move(vertexShader)), m_pixel_shader(std::move(pixelShader)), - m_vertex_declaration(std::move(vertexDeclaration)) + m_vertex_declaration(std::move(vertexDeclaration)), + m_comment(std::move(comment)) { } diff --git a/src/ObjCommon/Techset/CommonTechnique.h b/src/ObjCommon/Techset/CommonTechnique.h index ab8950d6..8e54aa40 100644 --- a/src/ObjCommon/Techset/CommonTechnique.h +++ b/src/ObjCommon/Techset/CommonTechnique.h @@ -283,7 +283,8 @@ namespace techset std::string stateMap, CommonTechniqueShader vertexShader, CommonTechniqueShader pixelShader, - CommonVertexDeclaration vertexDeclaration); + CommonVertexDeclaration vertexDeclaration, + std::string comment); [[nodiscard]] FrequencyCounts_t GetFrequencyCounts(const CommonCodeSourceInfos& infos) const; @@ -292,6 +293,7 @@ namespace techset CommonTechniqueShader m_vertex_shader; CommonTechniqueShader m_pixel_shader; CommonVertexDeclaration m_vertex_declaration; + std::string m_comment; std::vector m_args; }; diff --git a/src/ObjCompiling/Game/T6/Techset/TechniqueCompilerT6.cpp b/src/ObjCompiling/Game/T6/Techset/TechniqueCompilerT6.cpp index 0a243db9..44640a04 100644 --- a/src/ObjCompiling/Game/T6/Techset/TechniqueCompilerT6.cpp +++ b/src/ObjCompiling/Game/T6/Techset/TechniqueCompilerT6.cpp @@ -8,12 +8,218 @@ #include "Utils/StringUtils.h" #include +#include #include +#include using namespace T6; namespace { + class PrecompiledIndexMapping + { + public: + [[nodiscard]] bool + Matches(const MaterialType materialType, const std::vector& passCodeConsts, const unsigned samplerFlags) const + { + if (m_material_type && materialType != *m_material_type) + return false; + if (m_vertex_const_constraints.size() > passCodeConsts.size()) + return false; + + auto passCodeConstIndex = 0u; + for (const auto codeConstConstraint : m_vertex_const_constraints) + { + if (passCodeConsts[passCodeConstIndex++] != codeConstConstraint) + return false; + } + + auto expectedSamplerFlags = 0u; + for (const auto customSampler : m_custom_sampler_constraints) + expectedSamplerFlags |= (1 << customSampler); + + return samplerFlags == expectedSamplerFlags; + } + + VertexShaderPrecompiledIndex m_value; + std::optional m_material_type; + std::vector m_vertex_const_constraints; + std::vector m_custom_sampler_constraints; + }; + + // clang-format off + inline PrecompiledIndexMapping precompiledIndexMappings[]{ + { + .m_value = VERTEX_SHADER_MODEL_LIT, + .m_material_type = MTL_TYPE_MODEL_VERTCOL, + .m_vertex_const_constraints = { + CONST_SRC_CODE_WORLD_MATRIX, + CONST_SRC_CODE_GRID_LIGHTING_SH_0, + CONST_SRC_CODE_GRID_LIGHTING_SH_1, + CONST_SRC_CODE_GRID_LIGHTING_SH_2, + }, + .m_custom_sampler_constraints = {}, + }, + { + .m_value = VERTEX_SHADER_MODEL_LIT, + .m_material_type = MTL_TYPE_MODEL_VERTCOL, + .m_vertex_const_constraints = { + CONST_SRC_CODE_WORLD_MATRIX, + CONST_SRC_CODE_GRID_LIGHTING_COORDS_AND_VIS, + }, + .m_custom_sampler_constraints = {}, + }, + { + .m_value = VERTEX_SHADER_MODEL_LIT, + .m_material_type = MTL_TYPE_MODEL_VERTCOL, + .m_vertex_const_constraints = { + CONST_SRC_CODE_WORLD_MATRIX, + CONST_SRC_CODE_GRID_LIGHTING_COORDS_AND_VIS, + CONST_SRC_CODE_GRID_LIGHTING_SH_0, + CONST_SRC_CODE_GRID_LIGHTING_SH_1, + CONST_SRC_CODE_GRID_LIGHTING_SH_2, + }, + .m_custom_sampler_constraints = {}, + }, + { + .m_value = VERTEX_SHADER_MODEL_LIT, + .m_material_type = MTL_TYPE_MODEL_VERTCOL, + .m_vertex_const_constraints = { + CONST_SRC_CODE_WORLD_MATRIX, + CONST_SRC_CODE_GRID_LIGHTING_COORDS_AND_VIS, + CONST_SRC_CODE_GRID_LIGHTING_SH_0, + CONST_SRC_CODE_GRID_LIGHTING_SH_1, + }, + .m_custom_sampler_constraints = {}, + }, + { + .m_value = VERTEX_SHADER_MODEL_LIT, + .m_material_type = MTL_TYPE_MODEL_VERTCOL, + .m_vertex_const_constraints = { + CONST_SRC_CODE_WORLD_MATRIX, + CONST_SRC_CODE_GRID_LIGHTING_COORDS_AND_VIS, + CONST_SRC_CODE_GRID_LIGHTING_SH_0, + CONST_SRC_CODE_GRID_LIGHTING_SH_1, + CONST_SRC_CODE_GRID_LIGHTING_SH_2, + }, + .m_custom_sampler_constraints = { + CUSTOM_SAMPLER_REFLECTION_PROBE, + }, + }, + { + .m_value = VERTEX_SHADER_MODEL_LIT, + .m_material_type = MTL_TYPE_MODEL_VERTCOL, + .m_vertex_const_constraints = { + CONST_SRC_CODE_WORLD_MATRIX, + }, + .m_custom_sampler_constraints = { + CUSTOM_SAMPLER_REFLECTION_PROBE, + }, + }, + { + .m_value = VERTEX_SHADER_MODEL_LIT, + .m_material_type = MTL_TYPE_MODEL_VERTCOL, + .m_vertex_const_constraints = { + CONST_SRC_CODE_WORLD_MATRIX, + CONST_SRC_CODE_GRID_LIGHTING_SH_0, + CONST_SRC_CODE_GRID_LIGHTING_SH_1, + CONST_SRC_CODE_GRID_LIGHTING_SH_2, + }, + .m_custom_sampler_constraints = { + CUSTOM_SAMPLER_REFLECTION_PROBE, + }, + }, + { + .m_value = VERTEX_SHADER_MODEL_LIT_LIGHTMAP_VC, + .m_material_type = MTL_TYPE_MODEL_LIGHTMAP_VC, + .m_vertex_const_constraints = { + CONST_SRC_CODE_WORLD_MATRIX, + CONST_SRC_CODE_GRID_LIGHTING_SH_0, + CONST_SRC_CODE_GRID_LIGHTING_SH_1, + CONST_SRC_CODE_GRID_LIGHTING_SH_2, + }, + .m_custom_sampler_constraints = {}, + }, + { + .m_value = VERTEX_SHADER_MODEL_LIT_LIGHTMAP_VC, + .m_material_type = MTL_TYPE_MODEL_LIGHTMAP_VC, + .m_vertex_const_constraints = { + CONST_SRC_CODE_WORLD_MATRIX, + CONST_SRC_CODE_GRID_LIGHTING_COORDS_AND_VIS, + }, + .m_custom_sampler_constraints = {}, + }, + { + .m_value = VERTEX_SHADER_MODEL_LIT_LIGHTMAP_VC, + .m_material_type = MTL_TYPE_MODEL_LIGHTMAP_VC, + .m_vertex_const_constraints = { + CONST_SRC_CODE_WORLD_MATRIX, + CONST_SRC_CODE_GRID_LIGHTING_COORDS_AND_VIS, + CONST_SRC_CODE_GRID_LIGHTING_SH_0, + CONST_SRC_CODE_GRID_LIGHTING_SH_1, + CONST_SRC_CODE_GRID_LIGHTING_SH_2, + }, + .m_custom_sampler_constraints = {}, + }, + { + .m_value = VERTEX_SHADER_MODEL_LIT_LIGHTMAP_VC, + .m_material_type = MTL_TYPE_MODEL_LIGHTMAP_VC, + .m_vertex_const_constraints = { + CONST_SRC_CODE_WORLD_MATRIX, + CONST_SRC_CODE_GRID_LIGHTING_COORDS_AND_VIS, + CONST_SRC_CODE_GRID_LIGHTING_SH_0, + CONST_SRC_CODE_GRID_LIGHTING_SH_1, + }, + .m_custom_sampler_constraints = {}, + }, + { + .m_value = VERTEX_SHADER_MODEL_LIT_LIGHTMAP_VC, + .m_material_type = MTL_TYPE_MODEL_LIGHTMAP_VC, + .m_vertex_const_constraints = { + CONST_SRC_CODE_WORLD_MATRIX, + CONST_SRC_CODE_GRID_LIGHTING_COORDS_AND_VIS, + CONST_SRC_CODE_GRID_LIGHTING_SH_0, + CONST_SRC_CODE_GRID_LIGHTING_SH_1, + CONST_SRC_CODE_GRID_LIGHTING_SH_2, + }, + .m_custom_sampler_constraints = { + CUSTOM_SAMPLER_REFLECTION_PROBE, + }, + }, + { + .m_value = VERTEX_SHADER_MODEL_LIT_LIGHTMAP_VC, + .m_material_type = MTL_TYPE_MODEL_LIGHTMAP_VC, + .m_vertex_const_constraints = { + CONST_SRC_CODE_WORLD_MATRIX, + }, + .m_custom_sampler_constraints = { + CUSTOM_SAMPLER_REFLECTION_PROBE, + }, + }, + { + .m_value = VERTEX_SHADER_MODEL_LIT_LIGHTMAP_VC, + .m_material_type = MTL_TYPE_MODEL_LIGHTMAP_VC, + .m_vertex_const_constraints = { + CONST_SRC_CODE_WORLD_MATRIX, + CONST_SRC_CODE_GRID_LIGHTING_SH_0, + CONST_SRC_CODE_GRID_LIGHTING_SH_1, + CONST_SRC_CODE_GRID_LIGHTING_SH_2, + }, + .m_custom_sampler_constraints = { + CUSTOM_SAMPLER_REFLECTION_PROBE, + }, + }, + { + .m_value = VERTEX_SHADER_MODEL_UNLIT, + .m_material_type = std::nullopt, + .m_vertex_const_constraints = { + CONST_SRC_CODE_WORLD_MATRIX, + }, + .m_custom_sampler_constraints = {}, + }, + }; + // clang-format on + unsigned ConvertArgumentType(const techset::CommonShaderArgumentType& type) { if (type.m_shader_type == techset::CommonTechniqueShaderType::VERTEX) @@ -233,6 +439,41 @@ namespace } } + void ApplyPrecompiledIndex(MaterialPass& pass) + { + if (!pass.args) + return; + + std::vector codeConstants; + const auto argCount = static_cast(pass.perPrimArgCount); + for (auto argIndex = 0u; argIndex < argCount; argIndex++) + { + const auto& arg = pass.args[argIndex]; + if (arg.type != MTL_ARG_CODE_VERTEX_CONST) + continue; + + const auto codeConst = static_cast(arg.u.codeConst.index); + + // Make sure we are agnostic of the used transposed versions + const auto codeConstInfo = commonCodeSourceInfos.GetInfoForCodeConstSource(codeConst); + if (codeConstInfo && codeConstInfo->transposedMatrix) + codeConstants.emplace_back(std::min(codeConst, *codeConstInfo->transposedMatrix)); + else + codeConstants.emplace_back(codeConst); + } + + const auto end = std::end(precompiledIndexMappings); + const auto foundMapping = std::find_if(std::begin(precompiledIndexMappings), + end, + [&codeConstants, pass](const PrecompiledIndexMapping& mapping) -> bool + { + return mapping.Matches(pass.materialType, codeConstants, pass.customSamplerFlags); + }); + + if (foundMapping != end) + pass.precompiledIndex = foundMapping->m_value; + } + class TechniqueShaderLoaderT6 final : public techset::ITechniqueShaderLoader { public: @@ -314,6 +555,16 @@ namespace { ApplyTechFlagsFromMaterial(*materialAsset->Asset(), m_zone); } + + const auto techniques = context.PoolSubAssets(); + for (auto* techniqueSubAsset : techniques) + { + auto& technique = *techniqueSubAsset->Asset(); + for (auto passIndex = 0u; passIndex < technique.passCount; passIndex++) + { + ApplyPrecompiledIndex(technique.passArray[passIndex]); + } + } } private: diff --git a/src/ObjLoading/Asset/AssetCreationContext.h b/src/ObjLoading/Asset/AssetCreationContext.h index 0c349457..501da641 100644 --- a/src/ObjLoading/Asset/AssetCreationContext.h +++ b/src/ObjLoading/Asset/AssetCreationContext.h @@ -3,6 +3,7 @@ #include "Asset/IZoneAssetCreationState.h" #include "AssetRegistration.h" #include "Game/IAsset.h" +#include "Pool/AssetPool.h" #include "Pool/XAssetInfo.h" #include "Zone/AssetList/AssetList.h" #include "Zone/ZoneTypes.h" @@ -89,6 +90,11 @@ public: XAssetInfoGeneric* ForceLoadDependencyGeneric(asset_type_t assetType, const std::string& assetName); + template [[nodiscard]] AssetPoolIterators PoolSubAssets() const + { + return AssetPoolIterators(*m_sub_asset_pools[SubAsset_t::EnumEntry]); + } + private: [[nodiscard]] XAssetInfoGeneric* LoadDefaultAssetDependency(asset_type_t assetType, const std::string& assetName); diff --git a/src/ObjWriting/Game/T5/Techset/TechsetDumperT5.cpp b/src/ObjWriting/Game/T5/Techset/TechsetDumperT5.cpp index 6f37efe8..d7586677 100644 --- a/src/ObjWriting/Game/T5/Techset/TechsetDumperT5.cpp +++ b/src/ObjWriting/Game/T5/Techset/TechsetDumperT5.cpp @@ -193,7 +193,8 @@ namespace "passthrough", ConvertToCommonShader(pass.vertexShader), ConvertToCommonShader(pass.pixelShader), - ConvertToCommonVertexDeclaration(pass.vertexDecl)); + ConvertToCommonVertexDeclaration(pass.vertexDecl), + std::string()); if (pass.args) { diff --git a/src/ObjWriting/Game/T6/Techset/TechsetDumperT6.cpp b/src/ObjWriting/Game/T6/Techset/TechsetDumperT6.cpp index e905b8d9..63d2d4a0 100644 --- a/src/ObjWriting/Game/T6/Techset/TechsetDumperT6.cpp +++ b/src/ObjWriting/Game/T6/Techset/TechsetDumperT6.cpp @@ -232,19 +232,28 @@ namespace return result; } - techset::CommonTechnique ConvertToCommonTechnique(const MaterialTechnique& technique) + techset::CommonTechnique ConvertToCommonTechnique(const MaterialTechnique& technique, const bool debug) { 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]; + + std::string comment; + if (debug) + { + comment = std::format( + "MaterialType: {}; PrecompiledIndex: {}", static_cast(pass.materialType), static_cast(pass.precompiledIndex)); + } + techset::CommonPass commonPass(pass.customSamplerFlags, // No clue what the actual state map was "passthrough", ConvertToCommonShader(pass.vertexShader), ConvertToCommonShader(pass.pixelShader), - ConvertToCommonVertexDeclaration(pass.vertexDecl)); + ConvertToCommonVertexDeclaration(pass.vertexDecl), + std::move(comment)); if (pass.args) { @@ -268,7 +277,7 @@ namespace { if (technique && techniqueState->ShouldDumpTechnique(technique)) { - const auto commonTechnique = ConvertToCommonTechnique(*technique); + const auto commonTechnique = ConvertToCommonTechnique(*technique, debug); techset::DumpCommonTechnique( context, commonTechnique, techset::DxVersion::DX11, commonCodeSourceInfos, commonRoutingInfos, *materialConstantState, debug); diff --git a/src/ObjWriting/Techset/CommonTechniqueDumper.cpp b/src/ObjWriting/Techset/CommonTechniqueDumper.cpp index 8afb185c..e83bd777 100644 --- a/src/ObjWriting/Techset/CommonTechniqueDumper.cpp +++ b/src/ObjWriting/Techset/CommonTechniqueDumper.cpp @@ -67,6 +67,12 @@ namespace m_stream << std::format("// CUSTOM SAMPLER FLAGS: 0x{:x}\n", mask); } } + + if (!pass.m_comment.empty()) + { + Indent(); + m_stream << std::format("// {}\n", pass.m_comment); + } } DumpStateMap(); diff --git a/src/ZoneCommon/Pool/AssetPool.h b/src/ZoneCommon/Pool/AssetPool.h index 27cc7266..f06e0ea9 100644 --- a/src/ZoneCommon/Pool/AssetPool.h +++ b/src/ZoneCommon/Pool/AssetPool.h @@ -67,7 +67,7 @@ private: std::vector> m_assets; }; -template class AssetPoolIterator +template class AssetPoolIterator { public: explicit AssetPoolIterator(AssetPool::Iterator i) @@ -94,7 +94,7 @@ private: AssetPool::Iterator m_iterator; }; -template class AssetPoolIterators +template class AssetPoolIterators { public: explicit AssetPoolIterators(AssetPool& assetPool) diff --git a/test/ObjWritingTests/Game/T6/Techset/TechsetDumperT6Test.cpp b/test/ObjWritingTests/Game/T6/Techset/TechsetDumperT6Test.cpp index 972896c2..9c2c8c04 100644 --- a/test/ObjWritingTests/Game/T6/Techset/TechsetDumperT6Test.cpp +++ b/test/ObjWritingTests/Game/T6/Techset/TechsetDumperT6Test.cpp @@ -309,6 +309,7 @@ TEST_CASE("TechsetDumperT6", "[t6][techset][dumper]") // TECHNIQUE FLAGS: 0x4 // TECHNIQUE FLAGS: 0x80 { + // MaterialType: 2; PrecompiledIndex: 3 stateMap "passthrough"; // TODO vertexShader 4.0 "simple.hlsl" @@ -339,6 +340,7 @@ TEST_CASE("TechsetDumperT6", "[t6][techset][dumper]") { // CUSTOM SAMPLER FLAGS: 0x1 // CUSTOM SAMPLER FLAGS: 0x2 + // MaterialType: 0; PrecompiledIndex: 0 stateMap "passthrough"; // TODO vertexShader 4.0 "advanced.hlsl"