From 3aac05a516ec4c6d0eb778cf5af4d53170c5ed65 Mon Sep 17 00:00:00 2001 From: Jan Laupetin Date: Sat, 7 Mar 2026 00:33:27 +0100 Subject: [PATCH] fix: make sure matrix shader args with less than 4 rows are properly dumped and loaded --- .../Techset/CommonShaderArgCreator.cpp | 20 +++++++++++++------ .../Techset/CommonTechniqueDumper.cpp | 20 ++++++++++++------- .../Techset/TechsetDumper.cpp.template | 19 ++++++++++++++++++ 3 files changed, 46 insertions(+), 13 deletions(-) diff --git a/src/ObjCompiling/Techset/CommonShaderArgCreator.cpp b/src/ObjCompiling/Techset/CommonShaderArgCreator.cpp index 9f0c5c10..5e1497fd 100644 --- a/src/ObjCompiling/Techset/CommonShaderArgCreator.cpp +++ b/src/ObjCompiling/Techset/CommonShaderArgCreator.cpp @@ -58,8 +58,9 @@ namespace { techset::CommonShaderArgDestination commonDestination{}; bool isTransposed; + unsigned rowCount; std::string errorMessage; - if (!FindDestinationForConstant(commonDestination, isTransposed, errorMessage, destination)) + if (!FindDestinationForConstant(commonDestination, isTransposed, rowCount, errorMessage, destination)) { if (!errorMessage.empty()) return result::Unexpected(std::move(errorMessage)); @@ -67,7 +68,7 @@ namespace return result::Unexpected(std::format("Could not find constant shader input with name {}", destination.m_argument_name)); } - return AcceptShaderConstantArgument(commonDestination, isTransposed, codeConstSource, sourceIndex); + return AcceptShaderConstantArgument(commonDestination, isTransposed, rowCount, codeConstSource, sourceIndex); } result::Expected AcceptShaderSamplerArgument(const techset::CommonShaderArgCreatorDestination& destination, @@ -91,8 +92,9 @@ namespace { techset::CommonShaderArgDestination commonDestination{}; bool isTransposed; + unsigned rowCount; std::string errorMessage; - if (!FindDestinationForConstant(commonDestination, isTransposed, errorMessage, destination)) + if (!FindDestinationForConstant(commonDestination, isTransposed, rowCount, errorMessage, destination)) { if (!errorMessage.empty()) return result::Unexpected(std::move(errorMessage)); @@ -121,8 +123,9 @@ namespace techset::CommonShaderArgDestination commonDestination{}; bool isTransposed; + unsigned rowCount; std::string errorMessage; - if (!FindDestinationForConstant(commonDestination, isTransposed, errorMessage, destination)) + if (!FindDestinationForConstant(commonDestination, isTransposed, rowCount, errorMessage, destination)) { if (!errorMessage.empty()) return result::Unexpected(std::move(errorMessage)); @@ -191,6 +194,7 @@ namespace protected: result::Expected AcceptShaderConstantArgument(const techset::CommonShaderArgDestination& commonDestination, const bool isTransposed, + const unsigned rowCount, const techset::CommonCodeConstSource codeConstSource, const unsigned sourceIndex) { @@ -207,7 +211,7 @@ namespace techset::CommonShaderArgCodeConstValue value{ .m_index = 0, .m_first_row = 0, - .m_row_count = isMatrix ? 4u : 1u, + .m_row_count = isMatrix ? rowCount : 1u, }; if (isMatrix) @@ -260,6 +264,7 @@ namespace [[nodiscard]] virtual bool FindDestinationForConstant(techset::CommonShaderArgDestination& commonDestination, bool& isTransposed, + unsigned& rowCount, std::string& errorMessage, const techset::CommonShaderArgCreatorDestination& input) = 0; [[nodiscard]] virtual bool FindDestinationForSampler(techset::CommonShaderArgDestination& commonDestination, @@ -316,6 +321,7 @@ namespace [[nodiscard]] bool FindDestinationForConstant(techset::CommonShaderArgDestination& commonDestination, bool& isTransposed, + unsigned& rowCount, std::string& errorMessage, const techset::CommonShaderArgCreatorDestination& input) override { @@ -402,6 +408,7 @@ namespace [[nodiscard]] bool FindDestinationForConstant(techset::CommonShaderArgDestination& commonDestination, bool& isTransposed, + unsigned& rowCount, std::string& errorMessage, const techset::CommonShaderArgCreatorDestination& input) override { @@ -448,6 +455,7 @@ namespace commonDestination.dx11.m_size = variableElementSize; commonDestination.dx11.m_buffer = bufferBinding->m_bind_point; isTransposed = variableIterator->m_variable_class == d3d11::VariableClass::MATRIX_COLUMNS; + rowCount = variableIterator->m_row_count; m_const_arg_added[usedConstantIndex] = true; @@ -632,7 +640,7 @@ namespace for (auto elementIndex = 0u; elementIndex < variableElementCount; elementIndex++) { commonDestination.dx11.m_location.constant_buffer_offset = variable.m_offset + variableElementSize * elementIndex; - auto result = AcceptShaderConstantArgument(commonDestination, isTransposed, *maybeCodeConst, elementIndex); + auto result = AcceptShaderConstantArgument(commonDestination, isTransposed, variable.m_row_count, *maybeCodeConst, elementIndex); if (!result) return std::move(result); } diff --git a/src/ObjWriting/Techset/CommonTechniqueDumper.cpp b/src/ObjWriting/Techset/CommonTechniqueDumper.cpp index 16283d2c..0be6f401 100644 --- a/src/ObjWriting/Techset/CommonTechniqueDumper.cpp +++ b/src/ObjWriting/Techset/CommonTechniqueDumper.cpp @@ -202,7 +202,7 @@ namespace codeDestAccessor = targetShaderArg->m_name; const auto isTransposed = targetShaderArg->m_class == d3d9::ParameterClass::MATRIX_COLUMNS; - DumpShaderArg(technique, arg, codeDestAccessor, isTransposed); + DumpShaderArg(technique, arg, codeDestAccessor, isTransposed, targetShaderArg->m_register_count); } void DumpShaderArgDx11(const CommonTechnique& technique, const CommonShaderArg& arg, const d3d11::ShaderInfo& shaderInfo) const @@ -284,7 +284,8 @@ namespace } const auto isTransposed = variable->m_variable_class == d3d11::VariableClass::MATRIX_COLUMNS; - DumpShaderArg(technique, arg, codeDestAccessor, isTransposed); + + DumpShaderArg(technique, arg, codeDestAccessor, isTransposed, variable->m_row_count); } else { @@ -315,11 +316,15 @@ namespace static_cast(arg.m_type.m_value_type)); return; } - DumpShaderArg(technique, arg, boundTextureResource->m_name, false); + DumpShaderArg(technique, arg, boundTextureResource->m_name, false, 0); } } - void DumpShaderArg(const CommonTechnique& technique, const CommonShaderArg& arg, std::string codeDestAccessor, const bool isTransposed) const + void DumpShaderArg(const CommonTechnique& technique, + const CommonShaderArg& arg, + std::string codeDestAccessor, + const bool isTransposed, + const size_t shaderRowCount) const { if (arg.m_type.m_value_type == CommonShaderValueType::CODE_CONST) { @@ -341,9 +346,10 @@ namespace else codeAccessor = std::format("{}[{}]", constSourceInfo->accessor, arg.m_value.code_const_source.m_index - constSourceInfo->value); - // Assert that the value uses 4 rows when matrix and 1 otherwise. - // If this is untrue, there must be more code handling the selected rows - assert((isMatrix && arg.m_value.code_const_source.m_row_count == 4) || arg.m_value.code_const_source.m_row_count == 1); + // Assert that when a code const is not a matrix, the game uses one row of it per arg + // If it is a matrix, the game uses as many rows as can be seen in the shader + assert(isMatrix || arg.m_value.code_const_source.m_row_count == 1); + assert(!isMatrix || arg.m_value.code_const_source.m_row_count == shaderRowCount); if (codeDestAccessor != codeAccessor) { diff --git a/src/ObjWriting/Techset/TechsetDumper.cpp.template b/src/ObjWriting/Techset/TechsetDumper.cpp.template index fd017b9f..c11f36bc 100644 --- a/src/ObjWriting/Techset/TechsetDumper.cpp.template +++ b/src/ObjWriting/Techset/TechsetDumper.cpp.template @@ -33,6 +33,7 @@ #include MATERIAL_CONSTANT_ZONE_STATE_HEADER #include TECHSET_CONSTANTS_HEADER +#include "Pool/GlobalAssetPool.h" #include "Techset/CommonTechniqueDumper.h" #include "Techset/CommonTechsetDumper.h" #include "Techset/CommonVertexDeclCreator.h" @@ -267,6 +268,15 @@ namespace techset::CommonTechniqueShader ConvertToCommonShader(const MaterialVertexShader* vertexShader) { +#if defined(FEATURE_IW4) + if (vertexShader && vertexShader->name && vertexShader->name[0] == ',') + { + auto* globalAsset = GameGlobalAssetPools::GetGlobalPoolsForGame(GameId::IW4)->GetAsset(&vertexShader->name[1]); + if (globalAsset) + vertexShader = globalAsset->Asset(); + } +#endif + techset::CommonTechniqueShader result(techset::CommonTechniqueShaderType::VERTEX, std::string()); if (!vertexShader) return result; @@ -291,6 +301,15 @@ namespace techset::CommonTechniqueShader ConvertToCommonShader(const MaterialPixelShader* pixelShader) { +#if defined(FEATURE_IW4) + if (pixelShader && pixelShader->name && pixelShader->name[0] == ',') + { + auto* globalAsset = GameGlobalAssetPools::GetGlobalPoolsForGame(GameId::IW4)->GetAsset(&pixelShader->name[1]); + if (globalAsset) + pixelShader = globalAsset->Asset(); + } +#endif + techset::CommonTechniqueShader result(techset::CommonTechniqueShaderType::PIXEL, std::string()); if (!pixelShader) return result;