From f4ed3e6c93a38edc64d82b5b97da1ff6539d9a8d Mon Sep 17 00:00:00 2001 From: Jan Laupetin Date: Sun, 15 Mar 2026 12:56:13 +0100 Subject: [PATCH] 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));