From 516878698d6bbcd5a249851a12df500eb4e847e7 Mon Sep 17 00:00:00 2001 From: Jan Date: Sun, 10 Apr 2022 13:58:08 +0200 Subject: [PATCH] Only accept sampler arguments for sampler shader arguments and constant argument for constant shader arguments --- .../AssetLoaders/AssetLoaderTechniqueSet.cpp | 62 +++++++++++++++---- .../TechniqueShaderScopeSequences.cpp | 34 ++++++---- .../Techset/TechniqueDefinitionAcceptor.h | 3 +- 3 files changed, 74 insertions(+), 25 deletions(-) diff --git a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.cpp b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.cpp index f4e21721..5a24e391 100644 --- a/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.cpp +++ b/src/ObjLoading/Game/IW4/AssetLoaders/AssetLoaderTechniqueSet.cpp @@ -1,6 +1,7 @@ #include "AssetLoaderTechniqueSet.h" #include +#include #include #include #include @@ -159,7 +160,7 @@ namespace IW4 return true; } - static bool IsSamplerConstant(const d3d9::ShaderConstant& constant) + static bool IsSamplerArgument(const d3d9::ShaderConstant& constant) { return constant.m_type == d3d9::ParameterType::SAMPLER || constant.m_type == d3d9::ParameterType::SAMPLER_1D @@ -222,7 +223,7 @@ namespace IW4 return foundSource; } - bool AcceptVertexShaderCodeArgument(techset::ShaderArgument shaderArgument, const techset::ShaderArgumentCodeSource& source, std::string& errorMessage) + bool AcceptVertexShaderConstantArgument(techset::ShaderArgument shaderArgument, const techset::ShaderArgumentCodeSource& source, std::string& errorMessage) { assert(!m_passes.empty()); auto& pass = m_passes.at(m_passes.size() - 1); @@ -245,10 +246,10 @@ namespace IW4 return false; } - const auto constantIsSampler = IsSamplerConstant(*matchingShaderConstant); - if (constantIsSampler) + const auto argumentIsSampler = IsSamplerArgument(*matchingShaderConstant); + if (argumentIsSampler) { - errorMessage = "Vertex sampler are unsupported"; + errorMessage = "Vertex shader argument expected sampler but got constant"; return false; } @@ -299,7 +300,7 @@ namespace IW4 return true; } - bool AcceptPixelShaderCodeArgument(techset::ShaderArgument shaderArgument, const techset::ShaderArgumentCodeSource& source, std::string& errorMessage) + bool AcceptPixelShaderCodeArgument(techset::ShaderArgument shaderArgument, const techset::ShaderArgumentCodeSource& source, std::string& errorMessage, const bool isSampler) { assert(!m_passes.empty()); auto& pass = m_passes.at(m_passes.size() - 1); @@ -323,13 +324,24 @@ namespace IW4 return false; } - const auto constantIsSampler = IsSamplerConstant(*matchingShaderConstant); + const auto argumentIsSampler = IsSamplerArgument(*matchingShaderConstant); + if (argumentIsSampler && !isSampler) + { + errorMessage = "Pixel shader argument expects sampler but got constant"; + return false; + } + else if (!argumentIsSampler && isSampler) + { + errorMessage = "Pixel shader argument expects constant but got sampler"; + return false; + } + MaterialShaderArgument argument{}; - argument.type = constantIsSampler ? MTL_ARG_CODE_PIXEL_SAMPLER : MTL_ARG_CODE_PIXEL_CONST; + argument.type = isSampler ? MTL_ARG_CODE_PIXEL_SAMPLER : MTL_ARG_CODE_PIXEL_CONST; argument.dest = static_cast(matchingShaderConstant->m_register_index); unsigned sourceIndex, arrayCount; - if (constantIsSampler) + if (isSampler) { const CodeSamplerSource* samplerSource = FindCodeSamplerSource(source.m_accessors, s_codeSamplers); if (!samplerSource) @@ -393,14 +405,27 @@ namespace IW4 return true; } - bool AcceptShaderCodeArgument(const techset::ShaderSelector shader, const techset::ShaderArgument shaderArgument, const techset::ShaderArgumentCodeSource source, - std::string& errorMessage) override + bool AcceptShaderConstantArgument(const techset::ShaderSelector shader, const techset::ShaderArgument shaderArgument, const techset::ShaderArgumentCodeSource source, + std::string& errorMessage) override { if (shader == techset::ShaderSelector::VERTEX_SHADER) - return AcceptVertexShaderCodeArgument(shaderArgument, source, errorMessage); + return AcceptVertexShaderConstantArgument(shaderArgument, source, errorMessage); assert(shader == techset::ShaderSelector::PIXEL_SHADER); - return AcceptPixelShaderCodeArgument(shaderArgument, source, errorMessage); + return AcceptPixelShaderCodeArgument(shaderArgument, source, errorMessage, false); + } + + bool AcceptShaderSamplerArgument(const techset::ShaderSelector shader, const techset::ShaderArgument shaderArgument, const techset::ShaderArgumentCodeSource source, + std::string& errorMessage) override + { + if (shader == techset::ShaderSelector::VERTEX_SHADER) + { + errorMessage = "Vertex sampler are unsupported"; + return false; + } + + assert(shader == techset::ShaderSelector::PIXEL_SHADER); + return AcceptPixelShaderCodeArgument(shaderArgument, source, errorMessage, true); } bool AcceptShaderLiteralArgument(const techset::ShaderSelector shader, techset::ShaderArgument shaderArgument, techset::ShaderArgumentLiteralSource source, std::string& errorMessage) override @@ -434,6 +459,17 @@ namespace IW4 return constant.m_name == shaderArgument.m_argument_name; }); + const auto argumentIsSampler = IsSamplerArgument(*matchingShaderConstant); + if(argumentIsSampler) + { + if(shader == techset::ShaderSelector::VERTEX_SHADER) + errorMessage = "Vertex shader argument expects sampler but got constant"; + else + errorMessage = "Pixel shader argument expects sampler but got constant"; + + return false; + } + argument.dest = static_cast(matchingShaderConstant->m_register_index); argument.u.literalConst = m_zone_state->GetAllocatedLiteral(m_memory, source); pass.m_arguments.push_back(argument); diff --git a/src/ObjLoading/Techset/Parsing/Sequence/TechniqueShaderScopeSequences.cpp b/src/ObjLoading/Techset/Parsing/Sequence/TechniqueShaderScopeSequences.cpp index 55a63abb..eea462f4 100644 --- a/src/ObjLoading/Techset/Parsing/Sequence/TechniqueShaderScopeSequences.cpp +++ b/src/ObjLoading/Techset/Parsing/Sequence/TechniqueShaderScopeSequences.cpp @@ -30,9 +30,10 @@ namespace techset class SequenceShaderArgument final : public TechniqueParser::sequence_t { - static constexpr auto TAG_CODE = 1; - static constexpr auto TAG_LITERAL = 2; - static constexpr auto TAG_MATERIAL = 3; + static constexpr auto TAG_CONSTANT = 1; + static constexpr auto TAG_SAMPLER = 2; + static constexpr auto TAG_LITERAL = 3; + static constexpr auto TAG_MATERIAL = 4; static constexpr auto CAPTURE_FIRST_TOKEN = 1; static constexpr auto CAPTURE_SHADER_ARGUMENT = 2; @@ -46,7 +47,10 @@ namespace techset static std::unique_ptr CodeMatchers(const SimpleMatcherFactory& create) { return create.And({ - create.Keyword("code"), + create.Or({ + create.Keyword("constant").Tag(TAG_CONSTANT), + create.Keyword("sampler").Tag(TAG_SAMPLER) + }), create.Char('.'), create.Identifier().Capture(CAPTURE_CODE_ACCESSOR), create.OptionalLoop(create.And({ @@ -58,7 +62,7 @@ namespace techset create.Integer().Capture(CAPTURE_CODE_INDEX), create.Char(']') })) - }).Tag(TAG_CODE); + }); } static std::unique_ptr LiteralValueMatchers(const SimpleMatcherFactory& create) @@ -124,7 +128,7 @@ namespace techset }); } - static void ProcessCodeArgument(const TechniqueParserState* state, SequenceResult& result, ShaderArgument arg) + static void ProcessCodeArgument(const TechniqueParserState* state, SequenceResult& result, ShaderArgument arg, const bool isSampler) { std::vector accessors; while (result.HasNextCapture(CAPTURE_CODE_ACCESSOR)) @@ -142,8 +146,16 @@ namespace techset source = ShaderArgumentCodeSource(std::move(accessors)); std::string errorMessage; - if (!state->m_acceptor->AcceptShaderCodeArgument(state->m_current_shader, std::move(arg), std::move(source), errorMessage)) - throw ParsingException(result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos(), std::move(errorMessage)); + if(!isSampler) + { + if (!state->m_acceptor->AcceptShaderConstantArgument(state->m_current_shader, std::move(arg), std::move(source), errorMessage)) + throw ParsingException(result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos(), std::move(errorMessage)); + } + else + { + if (!state->m_acceptor->AcceptShaderSamplerArgument(state->m_current_shader, std::move(arg), std::move(source), errorMessage)) + throw ParsingException(result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos(), std::move(errorMessage)); + } } static void ProcessLiteralArgument(const TechniqueParserState* state, SequenceResult& result, ShaderArgument arg) @@ -202,9 +214,9 @@ namespace techset arg = ShaderArgument(shaderArgumentNameToken.IdentifierValue()); const auto typeTag = result.NextTag(); - assert(typeTag == TAG_CODE || typeTag == TAG_LITERAL || typeTag == TAG_MATERIAL); - if (typeTag == TAG_CODE) - ProcessCodeArgument(state, result, std::move(arg)); + assert(typeTag == TAG_CONSTANT || typeTag == TAG_SAMPLER || typeTag == TAG_LITERAL || typeTag == TAG_MATERIAL); + if (typeTag == TAG_CONSTANT || typeTag == TAG_SAMPLER) + ProcessCodeArgument(state, result, std::move(arg), typeTag == TAG_SAMPLER); else if (typeTag == TAG_LITERAL) ProcessLiteralArgument(state, result, std::move(arg)); else diff --git a/src/ObjLoading/Techset/TechniqueDefinitionAcceptor.h b/src/ObjLoading/Techset/TechniqueDefinitionAcceptor.h index 3cb4a2ee..c0938859 100644 --- a/src/ObjLoading/Techset/TechniqueDefinitionAcceptor.h +++ b/src/ObjLoading/Techset/TechniqueDefinitionAcceptor.h @@ -80,7 +80,8 @@ namespace techset virtual bool AcceptVertexShader(const std::string& vertexShaderName, std::string& errorMessage) = 0; virtual bool AcceptPixelShader(const std::string& pixelShaderName, std::string& errorMessage) = 0; - virtual bool AcceptShaderCodeArgument(ShaderSelector shader, ShaderArgument shaderArgument, ShaderArgumentCodeSource source, std::string& errorMessage) = 0; + virtual bool AcceptShaderConstantArgument(ShaderSelector shader, ShaderArgument shaderArgument, ShaderArgumentCodeSource source, std::string& errorMessage) = 0; + virtual bool AcceptShaderSamplerArgument(ShaderSelector shader, ShaderArgument shaderArgument, ShaderArgumentCodeSource source, std::string& errorMessage) = 0; virtual bool AcceptShaderLiteralArgument(ShaderSelector shader, ShaderArgument shaderArgument, ShaderArgumentLiteralSource source, std::string& errorMessage) = 0; virtual bool AcceptShaderMaterialArgument(ShaderSelector shader, ShaderArgument shaderArgument, ShaderArgumentMaterialSource source, std::string& errorMessage) = 0;