Only accept sampler arguments for sampler shader arguments and constant argument for constant shader arguments

This commit is contained in:
Jan 2022-04-10 13:58:08 +02:00
parent 7a2fe6dc4f
commit 516878698d
3 changed files with 74 additions and 25 deletions

View File

@ -1,6 +1,7 @@
#include "AssetLoaderTechniqueSet.h" #include "AssetLoaderTechniqueSet.h"
#include <cstring> #include <cstring>
#include <iostream>
#include <memory> #include <memory>
#include <unordered_map> #include <unordered_map>
#include <sstream> #include <sstream>
@ -159,7 +160,7 @@ namespace IW4
return true; return true;
} }
static bool IsSamplerConstant(const d3d9::ShaderConstant& constant) static bool IsSamplerArgument(const d3d9::ShaderConstant& constant)
{ {
return constant.m_type == d3d9::ParameterType::SAMPLER return constant.m_type == d3d9::ParameterType::SAMPLER
|| constant.m_type == d3d9::ParameterType::SAMPLER_1D || constant.m_type == d3d9::ParameterType::SAMPLER_1D
@ -222,7 +223,7 @@ namespace IW4
return foundSource; 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()); assert(!m_passes.empty());
auto& pass = m_passes.at(m_passes.size() - 1); auto& pass = m_passes.at(m_passes.size() - 1);
@ -245,10 +246,10 @@ namespace IW4
return false; return false;
} }
const auto constantIsSampler = IsSamplerConstant(*matchingShaderConstant); const auto argumentIsSampler = IsSamplerArgument(*matchingShaderConstant);
if (constantIsSampler) if (argumentIsSampler)
{ {
errorMessage = "Vertex sampler are unsupported"; errorMessage = "Vertex shader argument expected sampler but got constant";
return false; return false;
} }
@ -299,7 +300,7 @@ namespace IW4
return true; 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()); assert(!m_passes.empty());
auto& pass = m_passes.at(m_passes.size() - 1); auto& pass = m_passes.at(m_passes.size() - 1);
@ -323,13 +324,24 @@ namespace IW4
return false; 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{}; 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<uint16_t>(matchingShaderConstant->m_register_index); argument.dest = static_cast<uint16_t>(matchingShaderConstant->m_register_index);
unsigned sourceIndex, arrayCount; unsigned sourceIndex, arrayCount;
if (constantIsSampler) if (isSampler)
{ {
const CodeSamplerSource* samplerSource = FindCodeSamplerSource(source.m_accessors, s_codeSamplers); const CodeSamplerSource* samplerSource = FindCodeSamplerSource(source.m_accessors, s_codeSamplers);
if (!samplerSource) if (!samplerSource)
@ -393,14 +405,27 @@ namespace IW4
return true; return true;
} }
bool AcceptShaderCodeArgument(const techset::ShaderSelector shader, const techset::ShaderArgument shaderArgument, const techset::ShaderArgumentCodeSource source, bool AcceptShaderConstantArgument(const techset::ShaderSelector shader, const techset::ShaderArgument shaderArgument, const techset::ShaderArgumentCodeSource source,
std::string& errorMessage) override std::string& errorMessage) override
{ {
if (shader == techset::ShaderSelector::VERTEX_SHADER) if (shader == techset::ShaderSelector::VERTEX_SHADER)
return AcceptVertexShaderCodeArgument(shaderArgument, source, errorMessage); return AcceptVertexShaderConstantArgument(shaderArgument, source, errorMessage);
assert(shader == techset::ShaderSelector::PIXEL_SHADER); 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 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; 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<uint16_t>(matchingShaderConstant->m_register_index); argument.dest = static_cast<uint16_t>(matchingShaderConstant->m_register_index);
argument.u.literalConst = m_zone_state->GetAllocatedLiteral(m_memory, source); argument.u.literalConst = m_zone_state->GetAllocatedLiteral(m_memory, source);
pass.m_arguments.push_back(argument); pass.m_arguments.push_back(argument);

View File

@ -30,9 +30,10 @@ namespace techset
class SequenceShaderArgument final : public TechniqueParser::sequence_t class SequenceShaderArgument final : public TechniqueParser::sequence_t
{ {
static constexpr auto TAG_CODE = 1; static constexpr auto TAG_CONSTANT = 1;
static constexpr auto TAG_LITERAL = 2; static constexpr auto TAG_SAMPLER = 2;
static constexpr auto TAG_MATERIAL = 3; static constexpr auto TAG_LITERAL = 3;
static constexpr auto TAG_MATERIAL = 4;
static constexpr auto CAPTURE_FIRST_TOKEN = 1; static constexpr auto CAPTURE_FIRST_TOKEN = 1;
static constexpr auto CAPTURE_SHADER_ARGUMENT = 2; static constexpr auto CAPTURE_SHADER_ARGUMENT = 2;
@ -46,7 +47,10 @@ namespace techset
static std::unique_ptr<matcher_t> CodeMatchers(const SimpleMatcherFactory& create) static std::unique_ptr<matcher_t> CodeMatchers(const SimpleMatcherFactory& create)
{ {
return create.And({ return create.And({
create.Keyword("code"), create.Or({
create.Keyword("constant").Tag(TAG_CONSTANT),
create.Keyword("sampler").Tag(TAG_SAMPLER)
}),
create.Char('.'), create.Char('.'),
create.Identifier().Capture(CAPTURE_CODE_ACCESSOR), create.Identifier().Capture(CAPTURE_CODE_ACCESSOR),
create.OptionalLoop(create.And({ create.OptionalLoop(create.And({
@ -58,7 +62,7 @@ namespace techset
create.Integer().Capture(CAPTURE_CODE_INDEX), create.Integer().Capture(CAPTURE_CODE_INDEX),
create.Char(']') create.Char(']')
})) }))
}).Tag(TAG_CODE); });
} }
static std::unique_ptr<matcher_t> LiteralValueMatchers(const SimpleMatcherFactory& create) static std::unique_ptr<matcher_t> LiteralValueMatchers(const SimpleMatcherFactory& create)
@ -124,7 +128,7 @@ namespace techset
}); });
} }
static void ProcessCodeArgument(const TechniqueParserState* state, SequenceResult<SimpleParserValue>& result, ShaderArgument arg) static void ProcessCodeArgument(const TechniqueParserState* state, SequenceResult<SimpleParserValue>& result, ShaderArgument arg, const bool isSampler)
{ {
std::vector<std::string> accessors; std::vector<std::string> accessors;
while (result.HasNextCapture(CAPTURE_CODE_ACCESSOR)) while (result.HasNextCapture(CAPTURE_CODE_ACCESSOR))
@ -142,9 +146,17 @@ namespace techset
source = ShaderArgumentCodeSource(std::move(accessors)); source = ShaderArgumentCodeSource(std::move(accessors));
std::string errorMessage; std::string errorMessage;
if (!state->m_acceptor->AcceptShaderCodeArgument(state->m_current_shader, std::move(arg), std::move(source), 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)); 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<SimpleParserValue>& result, ShaderArgument arg) static void ProcessLiteralArgument(const TechniqueParserState* state, SequenceResult<SimpleParserValue>& result, ShaderArgument arg)
{ {
@ -202,9 +214,9 @@ namespace techset
arg = ShaderArgument(shaderArgumentNameToken.IdentifierValue()); arg = ShaderArgument(shaderArgumentNameToken.IdentifierValue());
const auto typeTag = result.NextTag(); const auto typeTag = result.NextTag();
assert(typeTag == TAG_CODE || typeTag == TAG_LITERAL || typeTag == TAG_MATERIAL); assert(typeTag == TAG_CONSTANT || typeTag == TAG_SAMPLER || typeTag == TAG_LITERAL || typeTag == TAG_MATERIAL);
if (typeTag == TAG_CODE) if (typeTag == TAG_CONSTANT || typeTag == TAG_SAMPLER)
ProcessCodeArgument(state, result, std::move(arg)); ProcessCodeArgument(state, result, std::move(arg), typeTag == TAG_SAMPLER);
else if (typeTag == TAG_LITERAL) else if (typeTag == TAG_LITERAL)
ProcessLiteralArgument(state, result, std::move(arg)); ProcessLiteralArgument(state, result, std::move(arg));
else else

View File

@ -80,7 +80,8 @@ namespace techset
virtual bool AcceptVertexShader(const std::string& vertexShaderName, std::string& errorMessage) = 0; virtual bool AcceptVertexShader(const std::string& vertexShaderName, std::string& errorMessage) = 0;
virtual bool AcceptPixelShader(const std::string& pixelShaderName, 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 AcceptShaderLiteralArgument(ShaderSelector shader, ShaderArgument shaderArgument, ShaderArgumentLiteralSource source, std::string& errorMessage) = 0;
virtual bool AcceptShaderMaterialArgument(ShaderSelector shader, ShaderArgument shaderArgument, ShaderArgumentMaterialSource source, std::string& errorMessage) = 0; virtual bool AcceptShaderMaterialArgument(ShaderSelector shader, ShaderArgument shaderArgument, ShaderArgumentMaterialSource source, std::string& errorMessage) = 0;