Shader: Turn every AstError into a proper compilation error (with source info)
This commit is contained in:
parent
ac9e7207ac
commit
16cf75440b
|
|
@ -7,6 +7,7 @@
|
||||||
#ifndef NAZARA_SHADER_AST_ASTTYPES_HPP
|
#ifndef NAZARA_SHADER_AST_ASTTYPES_HPP
|
||||||
#define NAZARA_SHADER_AST_ASTTYPES_HPP
|
#define NAZARA_SHADER_AST_ASTTYPES_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Shader/ShaderLangSourceLocation.hpp>
|
||||||
#include <Nazara/Shader/Ast/ConstantValue.hpp>
|
#include <Nazara/Shader/Ast/ConstantValue.hpp>
|
||||||
#include <Nazara/Shader/Ast/ExpressionType.hpp>
|
#include <Nazara/Shader/Ast/ExpressionType.hpp>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
@ -28,7 +29,7 @@ namespace Nz::ShaderAst
|
||||||
struct PartialType
|
struct PartialType
|
||||||
{
|
{
|
||||||
std::vector<TypeParameterCategory> parameters;
|
std::vector<TypeParameterCategory> parameters;
|
||||||
std::function<ExpressionType(const TypeParameter* parameters, std::size_t parameterCount)> buildFunc;
|
std::function<ExpressionType(const TypeParameter* parameters, std::size_t parameterCount, const ShaderLang::SourceLocation& sourceLocation)> buildFunc;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,6 @@ namespace Nz::ShaderAst
|
||||||
private:
|
private:
|
||||||
enum class IdentifierCategory;
|
enum class IdentifierCategory;
|
||||||
enum class ValidationResult;
|
enum class ValidationResult;
|
||||||
struct AstError;
|
|
||||||
struct CurrentFunctionData;
|
struct CurrentFunctionData;
|
||||||
struct Environment;
|
struct Environment;
|
||||||
struct FunctionData;
|
struct FunctionData;
|
||||||
|
|
@ -122,8 +121,8 @@ namespace Nz::ShaderAst
|
||||||
ExpressionPtr CacheResult(ExpressionPtr expression);
|
ExpressionPtr CacheResult(ExpressionPtr expression);
|
||||||
|
|
||||||
std::optional<ConstantValue> ComputeConstantValue(Expression& expr) const;
|
std::optional<ConstantValue> ComputeConstantValue(Expression& expr) const;
|
||||||
template<typename T> ValidationResult ComputeExprValue(ExpressionValue<T>& attribute) const;
|
template<typename T> ValidationResult ComputeExprValue(ExpressionValue<T>& attribute, const ShaderLang::SourceLocation& sourceLocation) const;
|
||||||
template<typename T> ValidationResult ComputeExprValue(const ExpressionValue<T>& attribute, ExpressionValue<T>& targetAttribute);
|
template<typename T> ValidationResult ComputeExprValue(const ExpressionValue<T>& attribute, ExpressionValue<T>& targetAttribute, const ShaderLang::SourceLocation& sourceLocation);
|
||||||
template<typename T> std::unique_ptr<T> PropagateConstants(T& node) const;
|
template<typename T> std::unique_ptr<T> PropagateConstants(T& node) const;
|
||||||
|
|
||||||
void PreregisterIndices(const Module& module);
|
void PreregisterIndices(const Module& module);
|
||||||
|
|
@ -144,11 +143,11 @@ namespace Nz::ShaderAst
|
||||||
|
|
||||||
const IdentifierData* ResolveAliasIdentifier(const IdentifierData* identifier, const ShaderLang::SourceLocation& sourceLocation) const;
|
const IdentifierData* ResolveAliasIdentifier(const IdentifierData* identifier, const ShaderLang::SourceLocation& sourceLocation) const;
|
||||||
void ResolveFunctions();
|
void ResolveFunctions();
|
||||||
std::size_t ResolveStruct(const AliasType& aliasType);
|
std::size_t ResolveStruct(const AliasType& aliasType, const ShaderLang::SourceLocation& sourceLocation);
|
||||||
std::size_t ResolveStruct(const ExpressionType& exprType);
|
std::size_t ResolveStruct(const ExpressionType& exprType, const ShaderLang::SourceLocation& sourceLocation);
|
||||||
std::size_t ResolveStruct(const IdentifierType& identifierType);
|
std::size_t ResolveStruct(const IdentifierType& identifierType, const ShaderLang::SourceLocation& sourceLocation);
|
||||||
std::size_t ResolveStruct(const StructType& structType);
|
std::size_t ResolveStruct(const StructType& structType, const ShaderLang::SourceLocation& sourceLocation);
|
||||||
std::size_t ResolveStruct(const UniformType& uniformType);
|
std::size_t ResolveStruct(const UniformType& uniformType, const ShaderLang::SourceLocation& sourceLocation);
|
||||||
ExpressionType ResolveType(const ExpressionType& exprType, bool resolveAlias, const ShaderLang::SourceLocation& sourceLocation);
|
ExpressionType ResolveType(const ExpressionType& exprType, bool resolveAlias, const ShaderLang::SourceLocation& sourceLocation);
|
||||||
std::optional<ExpressionType> ResolveTypeExpr(const ExpressionValue<ExpressionType>& exprTypeValue, bool resolveAlias, const ShaderLang::SourceLocation& sourceLocation);
|
std::optional<ExpressionType> ResolveTypeExpr(const ExpressionValue<ExpressionType>& exprTypeValue, bool resolveAlias, const ShaderLang::SourceLocation& sourceLocation);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -51,11 +51,18 @@ NAZARA_SHADERLANG_PARSER_ERROR(16, UnexpectedEndOfFile, "unexpected end of file"
|
||||||
NAZARA_SHADERLANG_PARSER_ERROR(17, UnexpectedToken, "unexpected token {}", ShaderLang::TokenType)
|
NAZARA_SHADERLANG_PARSER_ERROR(17, UnexpectedToken, "unexpected token {}", ShaderLang::TokenType)
|
||||||
|
|
||||||
// Compiler errors
|
// Compiler errors
|
||||||
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, AliasUnexpectedType, "for now, only aliases, functions and structs can be aliased")
|
||||||
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, ArrayLength, "array length must a strictly positive integer")
|
||||||
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, AssignTemporary, "temporary values cannot be assigned")
|
||||||
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, AttributeUnexpectedExpression, "unexpected expression for this type")
|
||||||
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, AttributeUnexpectedType, "unexpected attribute type")
|
||||||
NAZARA_SHADERLANG_COMPILER_ERROR(2, BinaryIncompatibleTypes, "incompatibles types (<TODO> and <TODO>)")
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, BinaryIncompatibleTypes, "incompatibles types (<TODO> and <TODO>)")
|
||||||
NAZARA_SHADERLANG_COMPILER_ERROR(2, BinaryUnsupported, "{} type (<TODO>) does not support this binary operation", std::string)
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, BinaryUnsupported, "{} type (<TODO>) does not support this binary operation", std::string)
|
||||||
NAZARA_SHADERLANG_COMPILER_ERROR(2, BranchOutsideOfFunction, "non-const branching statements can only exist inside a function")
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, BranchOutsideOfFunction, "non-const branching statements can only exist inside a function")
|
||||||
NAZARA_SHADERLANG_COMPILER_ERROR(2, CastIncompatibleTypes, "incompatibles types (<TODO> and <TODO>)")
|
|
||||||
NAZARA_SHADERLANG_COMPILER_ERROR(2, CastComponentMismatch, "component count doesn't match required component count")
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, CastComponentMismatch, "component count doesn't match required component count")
|
||||||
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, CastIncompatibleTypes, "incompatibles types (<TODO> and <TODO>)")
|
||||||
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, CastMatrixExpectedVector, "expected vector type, got <TODO>")
|
||||||
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, CastMatrixVectorComponentMismatch, "vector component count ({}) doesn't match target matrix row count ({})", UInt32, UInt32)
|
||||||
NAZARA_SHADERLANG_COMPILER_ERROR(2, CircularImport, "circular import detected on {}", std::string)
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, CircularImport, "circular import detected on {}", std::string)
|
||||||
NAZARA_SHADERLANG_COMPILER_ERROR(2, ConditionExpectedBool, "expected a boolean value")
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, ConditionExpectedBool, "expected a boolean value")
|
||||||
NAZARA_SHADERLANG_COMPILER_ERROR(2, ConstMissingExpression, "const variables must have an expression")
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, ConstMissingExpression, "const variables must have an expression")
|
||||||
|
|
@ -63,41 +70,69 @@ NAZARA_SHADERLANG_COMPILER_ERROR(2, ConstantExpectedValue, "expected a value")
|
||||||
NAZARA_SHADERLANG_COMPILER_ERROR(2, ConstantExpressionRequired, "a constant expression is required in this context")
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, ConstantExpressionRequired, "a constant expression is required in this context")
|
||||||
NAZARA_SHADERLANG_COMPILER_ERROR(2, DepthWriteAttribute, "only fragment entry-points can have the depth_write attribute")
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, DepthWriteAttribute, "only fragment entry-points can have the depth_write attribute")
|
||||||
NAZARA_SHADERLANG_COMPILER_ERROR(2, DiscardEarlyFragmentTests, "discard is not compatible with early fragment tests")
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, DiscardEarlyFragmentTests, "discard is not compatible with early fragment tests")
|
||||||
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, DiscardOutsideOfFragmentStage, "discard can only be used in the fragment stage (function gets called in the {} stage)", ShaderStageType)
|
||||||
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, DiscardOutsideOfFunction, "discard can only be used inside a function")
|
||||||
NAZARA_SHADERLANG_COMPILER_ERROR(2, EarlyFragmentTestsAttribute, "only functions with entry(frag) attribute can have the early_fragments_tests attribute")
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, EarlyFragmentTestsAttribute, "only functions with entry(frag) attribute can have the early_fragments_tests attribute")
|
||||||
NAZARA_SHADERLANG_COMPILER_ERROR(2, EntryFunctionParameter, "entry functions can either take one struct parameter or no parameter")
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, EntryFunctionParameter, "entry functions can either take one struct parameter or no parameter")
|
||||||
NAZARA_SHADERLANG_COMPILER_ERROR(2, EntryPointAlreadyDefined, "the same entry type has been defined multiple times")
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, EntryPointAlreadyDefined, "the same entry type has been defined multiple times")
|
||||||
NAZARA_SHADERLANG_COMPILER_ERROR(2, ExpectedFunction, "expected function expression")
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, ExpectedFunction, "expected function expression")
|
||||||
NAZARA_SHADERLANG_COMPILER_ERROR(2, ExpectedIntrinsicFunction, "expected intrinsic function expression")
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, ExpectedIntrinsicFunction, "expected intrinsic function expression")
|
||||||
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, ExpectedPartialType, "only partial types can be specialized, got <TODO>")
|
||||||
NAZARA_SHADERLANG_COMPILER_ERROR(2, ExtAlreadyDeclared, "external variable {} is already declared", std::string)
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, ExtAlreadyDeclared, "external variable {} is already declared", std::string)
|
||||||
NAZARA_SHADERLANG_COMPILER_ERROR(2, ExtTypeNotAllowed, "external variable {} is of wrong type: only uniform and sampler are allowed in external blocks", std::string)
|
|
||||||
NAZARA_SHADERLANG_COMPILER_ERROR(2, ExtBindingAlreadyUsed, "binding (set={}, binding={}) is already in use", UInt32, UInt32)
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, ExtBindingAlreadyUsed, "binding (set={}, binding={}) is already in use", UInt32, UInt32)
|
||||||
NAZARA_SHADERLANG_COMPILER_ERROR(2, ExtMissingBindingIndex, "external variable requires a binding index")
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, ExtMissingBindingIndex, "external variable requires a binding index")
|
||||||
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, ExtTypeNotAllowed, "external variable {} is of wrong type: only uniform and sampler are allowed in external blocks", std::string)
|
||||||
NAZARA_SHADERLANG_COMPILER_ERROR(2, ForEachUnsupportedType, "for-each statements can only be called on array types, got <TODO>")
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, ForEachUnsupportedType, "for-each statements can only be called on array types, got <TODO>")
|
||||||
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, ForFromTypeExpectIntegerType, "numerical for from expression must be an integer or unsigned integer, got <TODO>")
|
||||||
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, ForStepUnmatchingType, "numerical for step expression type (<TODO>) must match from expression type (<TODO>)")
|
||||||
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, ForToUnmatchingType, "numerical for to expression type (<TODO>) must match from expression type (<TODO>)")
|
||||||
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, FullTypeExpected, "expected a full type, got <TODO>")
|
||||||
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, FunctionCallExpectedFunction, "expected function expression")
|
||||||
NAZARA_SHADERLANG_COMPILER_ERROR(2, FunctionCallOutsideOfFunction, "function calls must happen inside a function")
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, FunctionCallOutsideOfFunction, "function calls must happen inside a function")
|
||||||
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, FunctionCallUnexpectedEntryFunction, "{} is an entry function which cannot be called by the program", std::string)
|
||||||
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, FunctionCallUnmatchingParameterCount, "function {} expects {} parameter(s), but got {}", std::string, UInt32, UInt32)
|
||||||
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, FunctionCallUnmatchingParameterType, "function {} parameter #{} type mismatch (expected <TODO>, got <TODO>)", std::string, UInt32)
|
||||||
NAZARA_SHADERLANG_COMPILER_ERROR(2, FunctionDeclarationInsideFunction, "a function cannot be defined inside another function")
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, FunctionDeclarationInsideFunction, "a function cannot be defined inside another function")
|
||||||
NAZARA_SHADERLANG_COMPILER_ERROR(2, IdentifierAlreadyUsed, "identifier {} is already used", std::string)
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, IdentifierAlreadyUsed, "identifier {} is already used", std::string)
|
||||||
NAZARA_SHADERLANG_COMPILER_ERROR(2, IntrinsicExpectedParameterCount, "expected {} parameter(s)", unsigned int)
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, IndexRequiresIntegerIndices, "index access requires integer indices (got <TODO>)")
|
||||||
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, IndexStructRequiresInt32Indices, "struct indexing requires constant i32 indices (got <TODO>)")
|
||||||
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, IndexUnexpectedType, "unexpected type: only arrays, structs, vectors and matrices can be indexed (got <TODO>)")
|
||||||
NAZARA_SHADERLANG_COMPILER_ERROR(2, IntrinsicExpectedFloat, "expected scalar or vector floating-points")
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, IntrinsicExpectedFloat, "expected scalar or vector floating-points")
|
||||||
NAZARA_SHADERLANG_COMPILER_ERROR(2, IntrinsicExpectedType, "expected type <TODO> for parameter #{}, got <TODO>", unsigned int)
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, IntrinsicExpectedParameterCount, "expected {} parameter(s)", UInt32)
|
||||||
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, IntrinsicExpectedType, "expected type <TODO> for parameter #{}, got <TODO>", UInt32)
|
||||||
NAZARA_SHADERLANG_COMPILER_ERROR(2, IntrinsicUnexpectedBoolean, "boolean parameters are not allowed")
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, IntrinsicUnexpectedBoolean, "boolean parameters are not allowed")
|
||||||
NAZARA_SHADERLANG_COMPILER_ERROR(2, IntrinsicUnmatchingParameterType, "all types must match")
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, IntrinsicUnmatchingParameterType, "all types must match")
|
||||||
NAZARA_SHADERLANG_COMPILER_ERROR(2, InvalidScalarSwizzle, "invalid swizzle for scalar")
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, InvalidScalarSwizzle, "invalid swizzle for scalar")
|
||||||
NAZARA_SHADERLANG_COMPILER_ERROR(2, InvalidSwizzle, "invalid swizzle {}", std::string)
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, InvalidSwizzle, "invalid swizzle {}", std::string)
|
||||||
NAZARA_SHADERLANG_COMPILER_ERROR(2, MissingOptionValue, "option {} requires a value (no default value set)", std::string)
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, MissingOptionValue, "option {} requires a value (no default value set)", std::string)
|
||||||
NAZARA_SHADERLANG_COMPILER_ERROR(2, PartialTypeExpect, "expected a {} type at #{}", std::string, unsigned int)
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, ModuleCompilationFailed, "module {} compilation failed: {}", std::string, std::string)
|
||||||
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, ModuleNotFound, "module {} not found", std::string)
|
||||||
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, NoModuleResolver, "import statement found but no module resolver has been set (and partial sanitization is not enabled)")
|
||||||
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, OptionDeclarationInsideFunction, "options must be declared outside of functions")
|
||||||
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, PartialTypeExpect, "expected a {} type at #{}", std::string, UInt32)
|
||||||
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, PartialTypeParameterCountMismatch, "parameter count mismatch (expected {}, got {})", UInt32, UInt32)
|
||||||
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, SamplerUnexpectedType, "for now only f32 samplers are supported (got <TODO>)")
|
||||||
NAZARA_SHADERLANG_COMPILER_ERROR(2, StructDeclarationInsideFunction, "structs must be declared outside of functions")
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, StructDeclarationInsideFunction, "structs must be declared outside of functions")
|
||||||
NAZARA_SHADERLANG_COMPILER_ERROR(2, VarDeclarationMissingTypeAndValue, "variable must either have a type or an initial value")
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, StructExpected, "struct type expected, got <TODO>")
|
||||||
NAZARA_SHADERLANG_COMPILER_ERROR(2, VarDeclarationTypeUnmatching, "initial expression type (<TODO>) doesn't match specified type (<TODO>)")
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, StructFieldBuiltinLocation, "a struct field cannot have both builtin and location attributes")
|
||||||
NAZARA_SHADERLANG_COMPILER_ERROR(2, UnexpectedAccessedType, "unexpected type (only struct and vectors can be indexed with identifiers)")
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, StructFieldMultiple, "multiple {} active struct field found, only one can be active at a time", std::string)
|
||||||
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, StructLayoutInnerMismatch, "inner struct layout mismatch, struct is declared with {} but field has layout {}", std::string, std::string)
|
||||||
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, StructLayoutTypeNotAllowed, "{} type is not allowed in {} layout", std::string, std::string)
|
||||||
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, SwizzleUnexpectedType, "expression type (<TODO>) does not support swizzling")
|
||||||
NAZARA_SHADERLANG_COMPILER_ERROR(2, UnaryUnsupported, "type (<TODO>) does not support this unary operation", std::string)
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, UnaryUnsupported, "type (<TODO>) does not support this unary operation", std::string)
|
||||||
NAZARA_SHADERLANG_COMPILER_ERROR(2, UnmatchingTypes, "left expression type (<TODO>) doesn't match right expression type (<TODO>)")
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, UnexpectedAccessedType, "unexpected type (only struct and vectors can be indexed with identifiers)")
|
||||||
NAZARA_SHADERLANG_COMPILER_ERROR(2, UnknownField, "unknown field {}", std::string)
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, UnknownField, "unknown field {}", std::string)
|
||||||
NAZARA_SHADERLANG_COMPILER_ERROR(2, UnknownMethod, "unknown method {}", std::string)
|
|
||||||
NAZARA_SHADERLANG_COMPILER_ERROR(2, UnknownIdentifier, "unknown identifier {}", std::string)
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, UnknownIdentifier, "unknown identifier {}", std::string)
|
||||||
NAZARA_SHADERLANG_COMPILER_ERROR(2, WhileUnrollNotSupported, "unroll(always) is not yet supported on while")
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, UnknownMethod, "unknown method {}", std::string)
|
||||||
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, UnmatchingTypes, "left expression type (<TODO>) doesn't match right expression type (<TODO>)")
|
||||||
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, VarDeclarationMissingTypeAndValue, "variable must either have a type or an initial value")
|
||||||
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, VarDeclarationOutsideOfFunction, "global variables outside of external blocks are forbidden")
|
||||||
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, VarDeclarationTypeUnmatching, "initial expression type (<TODO>) doesn't match specified type (<TODO>)")
|
||||||
|
NAZARA_SHADERLANG_COMPILER_ERROR(2, WhileUnrollNotSupported, "unroll(always) is not yet supported on while, use a for loop")
|
||||||
|
|
||||||
// AST errors
|
// AST errors
|
||||||
NAZARA_SHADERLANG_AST_ERROR(1, AlreadyUsedIndex, "index {} is already used", std::size_t)
|
NAZARA_SHADERLANG_AST_ERROR(1, AlreadyUsedIndex, "index {} is already used", std::size_t)
|
||||||
|
NAZARA_SHADERLANG_AST_ERROR(1, AttributeRequiresValue, "index {} is already used", std::size_t)
|
||||||
NAZARA_SHADERLANG_AST_ERROR(2, AlreadyUsedIndexPreregister, "cannot preregister used index {} as its already used", std::size_t)
|
NAZARA_SHADERLANG_AST_ERROR(2, AlreadyUsedIndexPreregister, "cannot preregister used index {} as its already used", std::size_t)
|
||||||
NAZARA_SHADERLANG_AST_ERROR(2, EmptyIdentifier, "identifier cannot be empty")
|
NAZARA_SHADERLANG_AST_ERROR(2, EmptyIdentifier, "identifier cannot be empty")
|
||||||
NAZARA_SHADERLANG_AST_ERROR(2, Internal, "internal error: {}", std::string)
|
NAZARA_SHADERLANG_AST_ERROR(2, Internal, "internal error: {}", std::string)
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ namespace Nz::ShaderLang
|
||||||
|
|
||||||
static inline SourceLocation BuildFromTo(const SourceLocation& leftSource, const SourceLocation& rightSource);
|
static inline SourceLocation BuildFromTo(const SourceLocation& leftSource, const SourceLocation& rightSource);
|
||||||
|
|
||||||
std::shared_ptr<const std::string> file; //< Since the same file will be used for every node, prevent holding X time the same path
|
std::shared_ptr<const std::string> file; //< Since the same file will be used for every node, prevent storing X time the same path
|
||||||
UInt32 endColumn;
|
UInt32 endColumn;
|
||||||
UInt32 endLine;
|
UInt32 endLine;
|
||||||
UInt32 startColumn;
|
UInt32 startColumn;
|
||||||
|
|
|
||||||
|
|
@ -26,11 +26,6 @@
|
||||||
|
|
||||||
namespace Nz::ShaderAst
|
namespace Nz::ShaderAst
|
||||||
{
|
{
|
||||||
struct SanitizeVisitor::AstError
|
|
||||||
{
|
|
||||||
std::string errMsg;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SanitizeVisitor::CurrentFunctionData
|
struct SanitizeVisitor::CurrentFunctionData
|
||||||
{
|
{
|
||||||
std::optional<ShaderStageType> stageType;
|
std::optional<ShaderStageType> stageType;
|
||||||
|
|
@ -317,7 +312,7 @@ namespace Nz::ShaderAst
|
||||||
}
|
}
|
||||||
else if (IsStructType(resolvedType))
|
else if (IsStructType(resolvedType))
|
||||||
{
|
{
|
||||||
std::size_t structIndex = ResolveStruct(resolvedType);
|
std::size_t structIndex = ResolveStruct(resolvedType, indexedExpr->sourceLocation);
|
||||||
const StructDescription* s = m_context->structs.Retrieve(structIndex, indexedExpr->sourceLocation);
|
const StructDescription* s = m_context->structs.Retrieve(structIndex, indexedExpr->sourceLocation);
|
||||||
|
|
||||||
// Retrieve member index (not counting disabled fields)
|
// Retrieve member index (not counting disabled fields)
|
||||||
|
|
@ -1025,7 +1020,7 @@ namespace Nz::ShaderAst
|
||||||
std::optional<UInt32> defaultBlockSet = 0;
|
std::optional<UInt32> defaultBlockSet = 0;
|
||||||
if (clone->bindingSet.HasValue())
|
if (clone->bindingSet.HasValue())
|
||||||
{
|
{
|
||||||
if (ComputeExprValue(clone->bindingSet) == ValidationResult::Validated)
|
if (ComputeExprValue(clone->bindingSet, node.sourceLocation) == ValidationResult::Validated)
|
||||||
defaultBlockSet = clone->bindingSet.GetResultingValue();
|
defaultBlockSet = clone->bindingSet.GetResultingValue();
|
||||||
else
|
else
|
||||||
defaultBlockSet.reset(); //< Unresolved value
|
defaultBlockSet.reset(); //< Unresolved value
|
||||||
|
|
@ -1037,11 +1032,11 @@ namespace Nz::ShaderAst
|
||||||
throw ShaderLang::CompilerExtMissingBindingIndexError{ extVar.sourceLocation };
|
throw ShaderLang::CompilerExtMissingBindingIndexError{ extVar.sourceLocation };
|
||||||
|
|
||||||
if (extVar.bindingSet.HasValue())
|
if (extVar.bindingSet.HasValue())
|
||||||
ComputeExprValue(extVar.bindingSet);
|
ComputeExprValue(extVar.bindingSet, node.sourceLocation);
|
||||||
else if (defaultBlockSet)
|
else if (defaultBlockSet)
|
||||||
extVar.bindingSet = *defaultBlockSet;
|
extVar.bindingSet = *defaultBlockSet;
|
||||||
|
|
||||||
ComputeExprValue(extVar.bindingIndex);
|
ComputeExprValue(extVar.bindingIndex, node.sourceLocation);
|
||||||
|
|
||||||
if (extVar.bindingSet.IsResultingValue() && extVar.bindingIndex.IsResultingValue())
|
if (extVar.bindingSet.IsResultingValue() && extVar.bindingIndex.IsResultingValue())
|
||||||
{
|
{
|
||||||
|
|
@ -1110,16 +1105,16 @@ namespace Nz::ShaderAst
|
||||||
clone->returnType = ExpressionType{ NoType{} };
|
clone->returnType = ExpressionType{ NoType{} };
|
||||||
|
|
||||||
if (node.depthWrite.HasValue())
|
if (node.depthWrite.HasValue())
|
||||||
ComputeExprValue(node.depthWrite, clone->depthWrite);
|
ComputeExprValue(node.depthWrite, clone->depthWrite, node.sourceLocation);
|
||||||
|
|
||||||
if (node.earlyFragmentTests.HasValue())
|
if (node.earlyFragmentTests.HasValue())
|
||||||
ComputeExprValue(node.earlyFragmentTests, clone->earlyFragmentTests);
|
ComputeExprValue(node.earlyFragmentTests, clone->earlyFragmentTests, node.sourceLocation);
|
||||||
|
|
||||||
if (node.entryStage.HasValue())
|
if (node.entryStage.HasValue())
|
||||||
ComputeExprValue(node.entryStage, clone->entryStage);
|
ComputeExprValue(node.entryStage, clone->entryStage, node.sourceLocation);
|
||||||
|
|
||||||
if (node.isExported.HasValue())
|
if (node.isExported.HasValue())
|
||||||
ComputeExprValue(node.isExported, clone->isExported);
|
ComputeExprValue(node.isExported, clone->isExported, node.sourceLocation);
|
||||||
|
|
||||||
if (clone->entryStage.IsResultingValue())
|
if (clone->entryStage.IsResultingValue())
|
||||||
{
|
{
|
||||||
|
|
@ -1181,7 +1176,7 @@ namespace Nz::ShaderAst
|
||||||
StatementPtr SanitizeVisitor::Clone(DeclareOptionStatement& node)
|
StatementPtr SanitizeVisitor::Clone(DeclareOptionStatement& node)
|
||||||
{
|
{
|
||||||
if (m_context->currentFunction)
|
if (m_context->currentFunction)
|
||||||
throw AstError{ "options must be declared outside of functions" };
|
throw ShaderLang::CompilerOptionDeclarationInsideFunctionError{ node.sourceLocation };
|
||||||
|
|
||||||
auto clone = StaticUniquePointerCast<DeclareOptionStatement>(AstCloner::Clone(node));
|
auto clone = StaticUniquePointerCast<DeclareOptionStatement>(AstCloner::Clone(node));
|
||||||
if (clone->optName.empty())
|
if (clone->optName.empty())
|
||||||
|
|
@ -1246,34 +1241,34 @@ namespace Nz::ShaderAst
|
||||||
auto clone = StaticUniquePointerCast<DeclareStructStatement>(AstCloner::Clone(node));
|
auto clone = StaticUniquePointerCast<DeclareStructStatement>(AstCloner::Clone(node));
|
||||||
|
|
||||||
if (clone->isExported.HasValue())
|
if (clone->isExported.HasValue())
|
||||||
ComputeExprValue(clone->isExported);
|
ComputeExprValue(clone->isExported, node.sourceLocation);
|
||||||
|
|
||||||
if (clone->description.layout.HasValue())
|
if (clone->description.layout.HasValue())
|
||||||
ComputeExprValue(clone->description.layout);
|
ComputeExprValue(clone->description.layout, node.sourceLocation);
|
||||||
|
|
||||||
std::unordered_set<std::string> declaredMembers;
|
std::unordered_set<std::string> declaredMembers;
|
||||||
for (auto& member : clone->description.members)
|
for (auto& member : clone->description.members)
|
||||||
{
|
{
|
||||||
if (member.cond.HasValue())
|
if (member.cond.HasValue())
|
||||||
{
|
{
|
||||||
ComputeExprValue(member.cond);
|
ComputeExprValue(member.cond, node.sourceLocation);
|
||||||
if (member.cond.IsResultingValue() && !member.cond.GetResultingValue())
|
if (member.cond.IsResultingValue() && !member.cond.GetResultingValue())
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (member.builtin.HasValue())
|
if (member.builtin.HasValue())
|
||||||
ComputeExprValue(member.builtin);
|
ComputeExprValue(member.builtin, node.sourceLocation);
|
||||||
|
|
||||||
if (member.locationIndex.HasValue())
|
if (member.locationIndex.HasValue())
|
||||||
ComputeExprValue(member.locationIndex);
|
ComputeExprValue(member.locationIndex, node.sourceLocation);
|
||||||
|
|
||||||
if (member.builtin.HasValue() && member.locationIndex.HasValue())
|
if (member.builtin.HasValue() && member.locationIndex.HasValue())
|
||||||
throw AstError{ "A struct field cannot have both builtin and location attributes" };
|
throw ShaderLang::CompilerStructFieldBuiltinLocationError{ member.sourceLocation };
|
||||||
|
|
||||||
if (declaredMembers.find(member.name) != declaredMembers.end())
|
if (declaredMembers.find(member.name) != declaredMembers.end())
|
||||||
{
|
{
|
||||||
if ((!member.cond.HasValue() || !member.cond.IsResultingValue()) && !m_context->options.allowPartialSanitization)
|
if ((!member.cond.HasValue() || !member.cond.IsResultingValue()) && !m_context->options.allowPartialSanitization)
|
||||||
throw AstError{ "struct member " + member.name + " found multiple time" };
|
throw ShaderLang::CompilerStructFieldMultipleError{ member.sourceLocation, member.name };
|
||||||
}
|
}
|
||||||
|
|
||||||
declaredMembers.insert(member.name);
|
declaredMembers.insert(member.name);
|
||||||
|
|
@ -1290,13 +1285,13 @@ namespace Nz::ShaderAst
|
||||||
const ExpressionType& targetType = ResolveAlias(member.type.GetResultingValue());
|
const ExpressionType& targetType = ResolveAlias(member.type.GetResultingValue());
|
||||||
|
|
||||||
if (IsPrimitiveType(targetType) && std::get<PrimitiveType>(targetType) == PrimitiveType::Boolean)
|
if (IsPrimitiveType(targetType) && std::get<PrimitiveType>(targetType) == PrimitiveType::Boolean)
|
||||||
throw AstError{ "boolean type is not allowed in std140 layout" };
|
throw ShaderLang::CompilerStructLayoutTypeNotAllowedError{ member.sourceLocation, "bool", "std140" };
|
||||||
else if (IsStructType(targetType))
|
else if (IsStructType(targetType))
|
||||||
{
|
{
|
||||||
std::size_t structIndex = std::get<StructType>(targetType).structIndex;
|
std::size_t structIndex = std::get<StructType>(targetType).structIndex;
|
||||||
const StructDescription* desc = m_context->structs.Retrieve(structIndex, member.sourceLocation);
|
const StructDescription* desc = m_context->structs.Retrieve(structIndex, member.sourceLocation);
|
||||||
if (!desc->layout.HasValue() || desc->layout.GetResultingValue() != clone->description.layout.GetResultingValue())
|
if (!desc->layout.HasValue() || desc->layout.GetResultingValue() != clone->description.layout.GetResultingValue())
|
||||||
throw AstError{ "inner struct layout mismatch" };
|
throw ShaderLang::CompilerStructLayoutInnerMismatchError{ member.sourceLocation, "std140", "<TODO>" };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1311,7 +1306,7 @@ namespace Nz::ShaderAst
|
||||||
StatementPtr SanitizeVisitor::Clone(DeclareVariableStatement& node)
|
StatementPtr SanitizeVisitor::Clone(DeclareVariableStatement& node)
|
||||||
{
|
{
|
||||||
if (!m_context->currentFunction)
|
if (!m_context->currentFunction)
|
||||||
throw AstError{ "global variables outside of external blocks are forbidden" };
|
throw ShaderLang::CompilerVarDeclarationOutsideOfFunctionError{ node.sourceLocation };
|
||||||
|
|
||||||
auto clone = StaticUniquePointerCast<DeclareVariableStatement>(AstCloner::Clone(node));
|
auto clone = StaticUniquePointerCast<DeclareVariableStatement>(AstCloner::Clone(node));
|
||||||
Validate(*clone);
|
Validate(*clone);
|
||||||
|
|
@ -1322,7 +1317,7 @@ namespace Nz::ShaderAst
|
||||||
StatementPtr SanitizeVisitor::Clone(DiscardStatement& node)
|
StatementPtr SanitizeVisitor::Clone(DiscardStatement& node)
|
||||||
{
|
{
|
||||||
if (!m_context->currentFunction)
|
if (!m_context->currentFunction)
|
||||||
throw AstError{ "discard can only be used inside a function" };
|
throw ShaderLang::CompilerDiscardOutsideOfFunctionError{ node.sourceLocation };
|
||||||
|
|
||||||
m_context->currentFunction->flags |= FunctionFlag::DoesDiscard;
|
m_context->currentFunction->flags |= FunctionFlag::DoesDiscard;
|
||||||
|
|
||||||
|
|
@ -1339,7 +1334,7 @@ namespace Nz::ShaderAst
|
||||||
StatementPtr SanitizeVisitor::Clone(ForStatement& node)
|
StatementPtr SanitizeVisitor::Clone(ForStatement& node)
|
||||||
{
|
{
|
||||||
if (node.varName.empty())
|
if (node.varName.empty())
|
||||||
throw AstError{ "numerical for variable name cannot be empty" };
|
throw ShaderLang::AstEmptyIdentifierError{ node.sourceLocation };
|
||||||
|
|
||||||
auto fromExpr = CloneExpression(MandatoryExpr(node.fromExpr, node.sourceLocation));
|
auto fromExpr = CloneExpression(MandatoryExpr(node.fromExpr, node.sourceLocation));
|
||||||
auto stepExpr = CloneExpression(node.stepExpr);
|
auto stepExpr = CloneExpression(node.stepExpr);
|
||||||
|
|
@ -1378,7 +1373,7 @@ namespace Nz::ShaderAst
|
||||||
return clone;
|
return clone;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (node.unroll.HasValue() && ComputeExprValue(node.unroll, unrollValue) == ValidationResult::Unresolved)
|
if (node.unroll.HasValue() && ComputeExprValue(node.unroll, unrollValue, node.sourceLocation) == ValidationResult::Unresolved)
|
||||||
return CloneFor(); //< unresolved unroll
|
return CloneFor(); //< unresolved unroll
|
||||||
|
|
||||||
if (!fromExprType || !toExprType)
|
if (!fromExprType || !toExprType)
|
||||||
|
|
@ -1386,15 +1381,15 @@ namespace Nz::ShaderAst
|
||||||
|
|
||||||
const ExpressionType& resolvedFromExprType = ResolveAlias(*fromExprType);
|
const ExpressionType& resolvedFromExprType = ResolveAlias(*fromExprType);
|
||||||
if (!IsPrimitiveType(resolvedFromExprType))
|
if (!IsPrimitiveType(resolvedFromExprType))
|
||||||
throw AstError{ "numerical for from expression must be an integer or unsigned integer" };
|
throw ShaderLang::CompilerForFromTypeExpectIntegerTypeError{ fromExpr->sourceLocation };
|
||||||
|
|
||||||
PrimitiveType counterType = std::get<PrimitiveType>(resolvedFromExprType);
|
PrimitiveType counterType = std::get<PrimitiveType>(resolvedFromExprType);
|
||||||
if (counterType != PrimitiveType::Int32 && counterType != PrimitiveType::UInt32)
|
if (counterType != PrimitiveType::Int32 && counterType != PrimitiveType::UInt32)
|
||||||
throw AstError{ "numerical for from expression must be an integer or unsigned integer" };
|
throw ShaderLang::CompilerForFromTypeExpectIntegerTypeError{ fromExpr->sourceLocation };
|
||||||
|
|
||||||
const ExpressionType& resolvedToExprType = ResolveAlias(*toExprType);
|
const ExpressionType& resolvedToExprType = ResolveAlias(*toExprType);
|
||||||
if (resolvedToExprType != resolvedFromExprType)
|
if (resolvedToExprType != resolvedFromExprType)
|
||||||
throw AstError{ "numerical for to expression type must match from expression type" };
|
throw ShaderLang::CompilerForToUnmatchingTypeError{ toExpr->sourceLocation };
|
||||||
|
|
||||||
if (stepExpr)
|
if (stepExpr)
|
||||||
{
|
{
|
||||||
|
|
@ -1404,7 +1399,7 @@ namespace Nz::ShaderAst
|
||||||
|
|
||||||
const ExpressionType& resolvedStepExprType = ResolveAlias(*stepExprType);
|
const ExpressionType& resolvedStepExprType = ResolveAlias(*stepExprType);
|
||||||
if (resolvedStepExprType != resolvedFromExprType)
|
if (resolvedStepExprType != resolvedFromExprType)
|
||||||
throw AstError{ "numerical for step expression type must match from expression type" };
|
throw ShaderLang::CompilerForStepUnmatchingTypeError{ stepExpr->sourceLocation };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unrollValue.HasValue())
|
if (unrollValue.HasValue())
|
||||||
|
|
@ -1463,7 +1458,7 @@ namespace Nz::ShaderAst
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw AstError{ "internal error" };
|
throw ShaderLang::AstInternalError{ node.sourceLocation, "unexpected counter type <TODO>" };
|
||||||
}
|
}
|
||||||
|
|
||||||
PopScope();
|
PopScope();
|
||||||
|
|
@ -1580,7 +1575,7 @@ namespace Nz::ShaderAst
|
||||||
ExpressionValue<LoopUnroll> unrollValue;
|
ExpressionValue<LoopUnroll> unrollValue;
|
||||||
if (node.unroll.HasValue())
|
if (node.unroll.HasValue())
|
||||||
{
|
{
|
||||||
if (ComputeExprValue(node.unroll, unrollValue) == ValidationResult::Unresolved)
|
if (ComputeExprValue(node.unroll, unrollValue, node.sourceLocation) == ValidationResult::Unresolved)
|
||||||
return AstCloner::Clone(node); //< unresolved unroll type
|
return AstCloner::Clone(node); //< unresolved unroll type
|
||||||
|
|
||||||
if (unrollValue.GetResultingValue() == LoopUnroll::Always)
|
if (unrollValue.GetResultingValue() == LoopUnroll::Always)
|
||||||
|
|
@ -1696,7 +1691,7 @@ namespace Nz::ShaderAst
|
||||||
if (!m_context->options.moduleResolver)
|
if (!m_context->options.moduleResolver)
|
||||||
{
|
{
|
||||||
if (!m_context->options.allowPartialSanitization)
|
if (!m_context->options.allowPartialSanitization)
|
||||||
throw AstError{ "module " + node.moduleName + " not found" };
|
throw ShaderLang::CompilerNoModuleResolverError{ node.sourceLocation };
|
||||||
|
|
||||||
// when partially sanitizing, importing a whole module could register any identifier, so at this point we can't see unknown identifiers as errors
|
// when partially sanitizing, importing a whole module could register any identifier, so at this point we can't see unknown identifiers as errors
|
||||||
m_context->allowUnknownIdentifiers = true;
|
m_context->allowUnknownIdentifiers = true;
|
||||||
|
|
@ -1706,7 +1701,7 @@ namespace Nz::ShaderAst
|
||||||
|
|
||||||
ModulePtr targetModule = m_context->options.moduleResolver->Resolve(node.moduleName);
|
ModulePtr targetModule = m_context->options.moduleResolver->Resolve(node.moduleName);
|
||||||
if (!targetModule)
|
if (!targetModule)
|
||||||
throw AstError{ "module " + node.moduleName + " not found" };
|
throw ShaderLang::CompilerModuleNotFoundError{ node.sourceLocation, node.moduleName };
|
||||||
|
|
||||||
std::size_t moduleIndex;
|
std::size_t moduleIndex;
|
||||||
|
|
||||||
|
|
@ -1738,7 +1733,7 @@ namespace Nz::ShaderAst
|
||||||
std::string error;
|
std::string error;
|
||||||
sanitizedModule->rootNode = SanitizeInternal(*targetModule->rootNode, &error);
|
sanitizedModule->rootNode = SanitizeInternal(*targetModule->rootNode, &error);
|
||||||
if (!sanitizedModule->rootNode)
|
if (!sanitizedModule->rootNode)
|
||||||
throw AstError{ "module " + node.moduleName + " compilation failed: " + error };
|
throw ShaderLang::CompilerModuleCompilationFailedError{ node.sourceLocation, node.moduleName, error };
|
||||||
|
|
||||||
moduleIndex = m_context->modules.size();
|
moduleIndex = m_context->modules.size();
|
||||||
|
|
||||||
|
|
@ -1872,7 +1867,7 @@ namespace Nz::ShaderAst
|
||||||
|
|
||||||
if (clone->unroll.HasValue())
|
if (clone->unroll.HasValue())
|
||||||
{
|
{
|
||||||
if (ComputeExprValue(clone->unroll) == ValidationResult::Validated && clone->unroll.GetResultingValue() == LoopUnroll::Always)
|
if (ComputeExprValue(clone->unroll, node.sourceLocation) == ValidationResult::Validated && clone->unroll.GetResultingValue() == LoopUnroll::Always)
|
||||||
throw ShaderLang::CompilerWhileUnrollNotSupportedError{ node.sourceLocation };
|
throw ShaderLang::CompilerWhileUnrollNotSupportedError{ node.sourceLocation };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2088,10 +2083,10 @@ namespace Nz::ShaderAst
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
auto SanitizeVisitor::ComputeExprValue(ExpressionValue<T>& attribute) const -> ValidationResult
|
auto SanitizeVisitor::ComputeExprValue(ExpressionValue<T>& attribute, const ShaderLang::SourceLocation& sourceLocation) const -> ValidationResult
|
||||||
{
|
{
|
||||||
if (!attribute.HasValue())
|
if (!attribute.HasValue())
|
||||||
throw AstError{ "attribute expected a value" };
|
throw ShaderLang::AstAttributeRequiresValueError{ sourceLocation };
|
||||||
|
|
||||||
if (attribute.IsExpression())
|
if (attribute.IsExpression())
|
||||||
{
|
{
|
||||||
|
|
@ -2107,23 +2102,23 @@ namespace Nz::ShaderAst
|
||||||
if (std::holds_alternative<Int32>(*value) && std::is_same_v<T, UInt32>)
|
if (std::holds_alternative<Int32>(*value) && std::is_same_v<T, UInt32>)
|
||||||
attribute = static_cast<UInt32>(std::get<Int32>(*value));
|
attribute = static_cast<UInt32>(std::get<Int32>(*value));
|
||||||
else
|
else
|
||||||
throw AstError{ "unexpected attribute type" };
|
throw ShaderLang::CompilerAttributeUnexpectedTypeError{ sourceLocation };
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
attribute = std::get<T>(*value);
|
attribute = std::get<T>(*value);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw AstError{ "unexpected expression for this type" };
|
throw ShaderLang::CompilerAttributeUnexpectedExpressionError{ sourceLocation };
|
||||||
}
|
}
|
||||||
|
|
||||||
return ValidationResult::Validated;
|
return ValidationResult::Validated;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
auto SanitizeVisitor::ComputeExprValue(const ExpressionValue<T>& attribute, ExpressionValue<T>& targetAttribute) -> ValidationResult
|
auto SanitizeVisitor::ComputeExprValue(const ExpressionValue<T>& attribute, ExpressionValue<T>& targetAttribute, const ShaderLang::SourceLocation& sourceLocation) -> ValidationResult
|
||||||
{
|
{
|
||||||
if (!attribute.HasValue())
|
if (!attribute.HasValue())
|
||||||
throw AstError{ "attribute expected a value" };
|
throw ShaderLang::AstAttributeRequiresValueError{ sourceLocation };
|
||||||
|
|
||||||
if (attribute.IsExpression())
|
if (attribute.IsExpression())
|
||||||
{
|
{
|
||||||
|
|
@ -2142,13 +2137,13 @@ namespace Nz::ShaderAst
|
||||||
if (std::holds_alternative<Int32>(*value) && std::is_same_v<T, UInt32>)
|
if (std::holds_alternative<Int32>(*value) && std::is_same_v<T, UInt32>)
|
||||||
targetAttribute = static_cast<UInt32>(std::get<Int32>(*value));
|
targetAttribute = static_cast<UInt32>(std::get<Int32>(*value));
|
||||||
else
|
else
|
||||||
throw AstError{ "unexpected attribute type" };
|
throw ShaderLang::CompilerAttributeUnexpectedTypeError{ sourceLocation };
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
targetAttribute = std::get<T>(*value);
|
targetAttribute = std::get<T>(*value);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw AstError{ "unexpected expression for this type" };
|
throw ShaderLang::CompilerAttributeUnexpectedExpressionError{ sourceLocation };
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -2167,7 +2162,7 @@ namespace Nz::ShaderAst
|
||||||
{
|
{
|
||||||
const ConstantValue* value = m_context->constantValues.TryRetrieve(constantId, node.sourceLocation);
|
const ConstantValue* value = m_context->constantValues.TryRetrieve(constantId, node.sourceLocation);
|
||||||
if (!value && !m_context->options.allowPartialSanitization)
|
if (!value && !m_context->options.allowPartialSanitization)
|
||||||
throw AstError{ "invalid constant index #" + std::to_string(constantId) };
|
throw ShaderLang::AstInvalidConstantIndexError{ node.sourceLocation, constantId };
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
};
|
};
|
||||||
|
|
@ -2219,7 +2214,7 @@ namespace Nz::ShaderAst
|
||||||
// Array
|
// Array
|
||||||
RegisterType("array", PartialType {
|
RegisterType("array", PartialType {
|
||||||
{ TypeParameterCategory::FullType, TypeParameterCategory::ConstantValue },
|
{ TypeParameterCategory::FullType, TypeParameterCategory::ConstantValue },
|
||||||
[=](const TypeParameter* parameters, std::size_t parameterCount) -> ExpressionType
|
[=](const TypeParameter* parameters, std::size_t parameterCount, const ShaderLang::SourceLocation& sourceLocation) -> ExpressionType
|
||||||
{
|
{
|
||||||
assert(parameterCount == 2);
|
assert(parameterCount == 2);
|
||||||
assert(std::holds_alternative<ExpressionType>(parameters[0]));
|
assert(std::holds_alternative<ExpressionType>(parameters[0]));
|
||||||
|
|
@ -2233,7 +2228,7 @@ namespace Nz::ShaderAst
|
||||||
{
|
{
|
||||||
Int32 value = std::get<Int32>(length);
|
Int32 value = std::get<Int32>(length);
|
||||||
if (value <= 0)
|
if (value <= 0)
|
||||||
throw AstError{ "array length must a positive integer" };
|
throw ShaderLang::CompilerArrayLengthError{ sourceLocation };
|
||||||
|
|
||||||
lengthValue = SafeCast<UInt32>(value);
|
lengthValue = SafeCast<UInt32>(value);
|
||||||
}
|
}
|
||||||
|
|
@ -2241,10 +2236,10 @@ namespace Nz::ShaderAst
|
||||||
{
|
{
|
||||||
lengthValue = std::get<UInt32>(length);
|
lengthValue = std::get<UInt32>(length);
|
||||||
if (lengthValue == 0)
|
if (lengthValue == 0)
|
||||||
throw AstError{ "array length must a positive integer" };
|
throw ShaderLang::CompilerArrayLengthError{ sourceLocation };
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw AstError{ "array length must a positive integer" };
|
throw ShaderLang::CompilerArrayLengthError{ sourceLocation };
|
||||||
|
|
||||||
ArrayType arrayType;
|
ArrayType arrayType;
|
||||||
arrayType.containedType = std::make_unique<ContainedType>();
|
arrayType.containedType = std::make_unique<ContainedType>();
|
||||||
|
|
@ -2260,7 +2255,7 @@ namespace Nz::ShaderAst
|
||||||
{
|
{
|
||||||
RegisterType("mat" + std::to_string(componentCount), PartialType {
|
RegisterType("mat" + std::to_string(componentCount), PartialType {
|
||||||
{ TypeParameterCategory::PrimitiveType },
|
{ TypeParameterCategory::PrimitiveType },
|
||||||
[=](const TypeParameter* parameters, std::size_t parameterCount) -> ExpressionType
|
[=](const TypeParameter* parameters, std::size_t parameterCount, const ShaderLang::SourceLocation& /*sourceLocation*/) -> ExpressionType
|
||||||
{
|
{
|
||||||
assert(parameterCount == 1);
|
assert(parameterCount == 1);
|
||||||
assert(std::holds_alternative<ExpressionType>(*parameters));
|
assert(std::holds_alternative<ExpressionType>(*parameters));
|
||||||
|
|
@ -2280,7 +2275,7 @@ namespace Nz::ShaderAst
|
||||||
{
|
{
|
||||||
RegisterType("vec" + std::to_string(componentCount), PartialType {
|
RegisterType("vec" + std::to_string(componentCount), PartialType {
|
||||||
{ TypeParameterCategory::PrimitiveType },
|
{ TypeParameterCategory::PrimitiveType },
|
||||||
[=](const TypeParameter* parameters, std::size_t parameterCount) -> ExpressionType
|
[=](const TypeParameter* parameters, std::size_t parameterCount, const ShaderLang::SourceLocation& /*sourceLocation*/) -> ExpressionType
|
||||||
{
|
{
|
||||||
assert(parameterCount == 1);
|
assert(parameterCount == 1);
|
||||||
assert(std::holds_alternative<ExpressionType>(*parameters));
|
assert(std::holds_alternative<ExpressionType>(*parameters));
|
||||||
|
|
@ -2319,7 +2314,7 @@ namespace Nz::ShaderAst
|
||||||
{
|
{
|
||||||
RegisterType(std::move(sampler.typeName), PartialType {
|
RegisterType(std::move(sampler.typeName), PartialType {
|
||||||
{ TypeParameterCategory::PrimitiveType },
|
{ TypeParameterCategory::PrimitiveType },
|
||||||
[=](const TypeParameter* parameters, std::size_t parameterCount) -> ExpressionType
|
[=](const TypeParameter* parameters, std::size_t parameterCount, const ShaderLang::SourceLocation& sourceLocation) -> ExpressionType
|
||||||
{
|
{
|
||||||
assert(parameterCount == 1);
|
assert(parameterCount == 1);
|
||||||
assert(std::holds_alternative<ExpressionType>(*parameters));
|
assert(std::holds_alternative<ExpressionType>(*parameters));
|
||||||
|
|
@ -2331,7 +2326,7 @@ namespace Nz::ShaderAst
|
||||||
|
|
||||||
// TODO: Add support for integer samplers
|
// TODO: Add support for integer samplers
|
||||||
if (primitiveType != PrimitiveType::Float32)
|
if (primitiveType != PrimitiveType::Float32)
|
||||||
throw AstError{ "for now only f32 samplers are supported" };
|
throw ShaderLang::CompilerSamplerUnexpectedTypeError{ sourceLocation };
|
||||||
|
|
||||||
return SamplerType {
|
return SamplerType {
|
||||||
sampler.imageType, primitiveType
|
sampler.imageType, primitiveType
|
||||||
|
|
@ -2343,7 +2338,7 @@ namespace Nz::ShaderAst
|
||||||
// uniform
|
// uniform
|
||||||
RegisterType("uniform", PartialType {
|
RegisterType("uniform", PartialType {
|
||||||
{ TypeParameterCategory::StructType },
|
{ TypeParameterCategory::StructType },
|
||||||
[=](const TypeParameter* parameters, std::size_t parameterCount) -> ExpressionType
|
[=](const TypeParameter* parameters, std::size_t parameterCount, const ShaderLang::SourceLocation& /*sourceLocation*/) -> ExpressionType
|
||||||
{
|
{
|
||||||
assert(parameterCount == 1);
|
assert(parameterCount == 1);
|
||||||
assert(std::holds_alternative<ExpressionType>(*parameters));
|
assert(std::holds_alternative<ExpressionType>(*parameters));
|
||||||
|
|
@ -2672,23 +2667,23 @@ namespace Nz::ShaderAst
|
||||||
for (const auto& [funcIndex, funcData] : m_context->functions.values)
|
for (const auto& [funcIndex, funcData] : m_context->functions.values)
|
||||||
{
|
{
|
||||||
if (funcData.flags.Test(FunctionFlag::DoesDiscard) && funcData.node->entryStage.HasValue() && funcData.node->entryStage.GetResultingValue() != ShaderStageType::Fragment)
|
if (funcData.flags.Test(FunctionFlag::DoesDiscard) && funcData.node->entryStage.HasValue() && funcData.node->entryStage.GetResultingValue() != ShaderStageType::Fragment)
|
||||||
throw AstError{ "discard can only be used in the fragment stage" };
|
throw ShaderLang::CompilerDiscardOutsideOfFragmentStageError{ funcData.node->sourceLocation, funcData.node->entryStage.GetResultingValue() };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t SanitizeVisitor::ResolveStruct(const AliasType& aliasType)
|
std::size_t SanitizeVisitor::ResolveStruct(const AliasType& aliasType, const ShaderLang::SourceLocation& sourceLocation)
|
||||||
{
|
{
|
||||||
return ResolveStruct(aliasType.targetType->type);
|
return ResolveStruct(aliasType.targetType->type, sourceLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t SanitizeVisitor::ResolveStruct(const ExpressionType& exprType)
|
std::size_t SanitizeVisitor::ResolveStruct(const ExpressionType& exprType, const ShaderLang::SourceLocation& sourceLocation)
|
||||||
{
|
{
|
||||||
return std::visit([&](auto&& arg) -> std::size_t
|
return std::visit([&](auto&& arg) -> std::size_t
|
||||||
{
|
{
|
||||||
using T = std::decay_t<decltype(arg)>;
|
using T = std::decay_t<decltype(arg)>;
|
||||||
|
|
||||||
if constexpr (std::is_same_v<T, IdentifierType> || std::is_same_v<T, StructType> || std::is_same_v<T, UniformType> || std::is_same_v<T, AliasType>)
|
if constexpr (std::is_same_v<T, IdentifierType> || std::is_same_v<T, StructType> || std::is_same_v<T, UniformType> || std::is_same_v<T, AliasType>)
|
||||||
return ResolveStruct(arg);
|
return ResolveStruct(arg, sourceLocation);
|
||||||
else if constexpr (std::is_same_v<T, NoType> ||
|
else if constexpr (std::is_same_v<T, NoType> ||
|
||||||
std::is_same_v<T, ArrayType> ||
|
std::is_same_v<T, ArrayType> ||
|
||||||
std::is_same_v<T, FunctionType> ||
|
std::is_same_v<T, FunctionType> ||
|
||||||
|
|
@ -2700,31 +2695,31 @@ namespace Nz::ShaderAst
|
||||||
std::is_same_v<T, Type> ||
|
std::is_same_v<T, Type> ||
|
||||||
std::is_same_v<T, VectorType>)
|
std::is_same_v<T, VectorType>)
|
||||||
{
|
{
|
||||||
throw AstError{ "expression is not a structure" };
|
throw ShaderLang::CompilerStructExpectedError{ sourceLocation };
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
static_assert(AlwaysFalse<T>::value, "non-exhaustive visitor");
|
static_assert(AlwaysFalse<T>::value, "non-exhaustive visitor");
|
||||||
}, exprType);
|
}, exprType);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t SanitizeVisitor::ResolveStruct(const IdentifierType& identifierType)
|
std::size_t SanitizeVisitor::ResolveStruct(const IdentifierType& identifierType, const ShaderLang::SourceLocation& sourceLocation)
|
||||||
{
|
{
|
||||||
const IdentifierData* identifierData = FindIdentifier(identifierType.name);
|
const IdentifierData* identifierData = FindIdentifier(identifierType.name);
|
||||||
if (!identifierData)
|
if (!identifierData)
|
||||||
throw AstError{ "unknown identifier " + identifierType.name };
|
throw ShaderLang::CompilerUnknownIdentifierError{ sourceLocation, identifierType.name };
|
||||||
|
|
||||||
if (identifierData->category != IdentifierCategory::Struct)
|
if (identifierData->category != IdentifierCategory::Struct)
|
||||||
throw AstError{ identifierType.name + " is not a struct" };
|
throw ShaderLang::CompilerStructExpectedError{ sourceLocation };
|
||||||
|
|
||||||
return identifierData->index;
|
return identifierData->index;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t SanitizeVisitor::ResolveStruct(const StructType& structType)
|
std::size_t SanitizeVisitor::ResolveStruct(const StructType& structType, const ShaderLang::SourceLocation& /*sourceLocation*/)
|
||||||
{
|
{
|
||||||
return structType.structIndex;
|
return structType.structIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t SanitizeVisitor::ResolveStruct(const UniformType& uniformType)
|
std::size_t SanitizeVisitor::ResolveStruct(const UniformType& uniformType, const ShaderLang::SourceLocation& /*sourceLocation*/)
|
||||||
{
|
{
|
||||||
return uniformType.containedType.structIndex;
|
return uniformType.containedType.structIndex;
|
||||||
}
|
}
|
||||||
|
|
@ -2743,7 +2738,7 @@ namespace Nz::ShaderAst
|
||||||
|
|
||||||
const auto& type = m_context->types.Retrieve(typeIndex, sourceLocation);
|
const auto& type = m_context->types.Retrieve(typeIndex, sourceLocation);
|
||||||
if (std::holds_alternative<PartialType>(type))
|
if (std::holds_alternative<PartialType>(type))
|
||||||
throw AstError{ "full type expected" };
|
throw ShaderLang::CompilerFullTypeExpectedError{ sourceLocation };
|
||||||
|
|
||||||
return std::get<ExpressionType>(type);
|
return std::get<ExpressionType>(type);
|
||||||
}
|
}
|
||||||
|
|
@ -2790,13 +2785,6 @@ namespace Nz::ShaderAst
|
||||||
{
|
{
|
||||||
output = StaticUniquePointerCast<MultiStatement>(AstCloner::Clone(rootNode));
|
output = StaticUniquePointerCast<MultiStatement>(AstCloner::Clone(rootNode));
|
||||||
}
|
}
|
||||||
catch (const AstError& err)
|
|
||||||
{
|
|
||||||
if (!error)
|
|
||||||
throw std::runtime_error(err.errMsg);
|
|
||||||
|
|
||||||
*error = err.errMsg;
|
|
||||||
}
|
|
||||||
catch (const std::runtime_error& err)
|
catch (const std::runtime_error& err)
|
||||||
{
|
{
|
||||||
if (!error)
|
if (!error)
|
||||||
|
|
@ -2825,7 +2813,7 @@ namespace Nz::ShaderAst
|
||||||
auto SanitizeVisitor::Validate(DeclareAliasStatement& node) -> ValidationResult
|
auto SanitizeVisitor::Validate(DeclareAliasStatement& node) -> ValidationResult
|
||||||
{
|
{
|
||||||
if (node.name.empty())
|
if (node.name.empty())
|
||||||
throw std::runtime_error("invalid alias name");
|
throw ShaderLang::AstEmptyIdentifierError{ node.sourceLocation };
|
||||||
|
|
||||||
const ExpressionType* exprType = GetExpressionType(*node.expression);
|
const ExpressionType* exprType = GetExpressionType(*node.expression);
|
||||||
if (!exprType)
|
if (!exprType)
|
||||||
|
|
@ -2836,7 +2824,7 @@ namespace Nz::ShaderAst
|
||||||
IdentifierData targetIdentifier;
|
IdentifierData targetIdentifier;
|
||||||
if (IsStructType(resolvedType))
|
if (IsStructType(resolvedType))
|
||||||
{
|
{
|
||||||
std::size_t structIndex = ResolveStruct(resolvedType);
|
std::size_t structIndex = ResolveStruct(resolvedType, node.expression->sourceLocation);
|
||||||
targetIdentifier = { structIndex, IdentifierCategory::Struct };
|
targetIdentifier = { structIndex, IdentifierCategory::Struct };
|
||||||
}
|
}
|
||||||
else if (IsFunctionType(resolvedType))
|
else if (IsFunctionType(resolvedType))
|
||||||
|
|
@ -2850,7 +2838,7 @@ namespace Nz::ShaderAst
|
||||||
targetIdentifier = { alias.aliasIndex, IdentifierCategory::Alias };
|
targetIdentifier = { alias.aliasIndex, IdentifierCategory::Alias };
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw AstError{ "for now, only aliases, functions and structs can be aliased" };
|
throw ShaderLang::CompilerAliasUnexpectedTypeError{ node.sourceLocation };
|
||||||
|
|
||||||
node.aliasIndex = RegisterAlias(node.name, targetIdentifier, node.aliasIndex, node.sourceLocation);
|
node.aliasIndex = RegisterAlias(node.name, targetIdentifier, node.aliasIndex, node.sourceLocation);
|
||||||
return ValidationResult::Validated;
|
return ValidationResult::Validated;
|
||||||
|
|
@ -2884,11 +2872,11 @@ namespace Nz::ShaderAst
|
||||||
const auto& type = m_context->types.Retrieve(typeIndex, node.sourceLocation);
|
const auto& type = m_context->types.Retrieve(typeIndex, node.sourceLocation);
|
||||||
|
|
||||||
if (!std::holds_alternative<PartialType>(type))
|
if (!std::holds_alternative<PartialType>(type))
|
||||||
throw std::runtime_error("only partial types can be specialized");
|
throw ShaderLang::CompilerExpectedPartialTypeError{ node.sourceLocation };
|
||||||
|
|
||||||
const PartialType& partialType = std::get<PartialType>(type);
|
const PartialType& partialType = std::get<PartialType>(type);
|
||||||
if (partialType.parameters.size() != node.indices.size())
|
if (partialType.parameters.size() != node.indices.size())
|
||||||
throw std::runtime_error("parameter count mismatch");
|
throw ShaderLang::CompilerPartialTypeParameterCountMismatchError{ node.sourceLocation, SafeCast<UInt32>(partialType.parameters.size()), SafeCast<UInt32>(node.indices.size()) };
|
||||||
|
|
||||||
StackVector<TypeParameter> parameters = NazaraStackVector(TypeParameter, partialType.parameters.size());
|
StackVector<TypeParameter> parameters = NazaraStackVector(TypeParameter, partialType.parameters.size());
|
||||||
for (std::size_t i = 0; i < partialType.parameters.size(); ++i)
|
for (std::size_t i = 0; i < partialType.parameters.size(); ++i)
|
||||||
|
|
@ -2921,7 +2909,7 @@ namespace Nz::ShaderAst
|
||||||
case TypeParameterCategory::PrimitiveType:
|
case TypeParameterCategory::PrimitiveType:
|
||||||
{
|
{
|
||||||
if (!IsPrimitiveType(resolvedType))
|
if (!IsPrimitiveType(resolvedType))
|
||||||
throw ShaderLang::CompilerPartialTypeExpectError{ indexExpr->sourceLocation, "primitive", SafeCast<unsigned int>(i) };
|
throw ShaderLang::CompilerPartialTypeExpectError{ indexExpr->sourceLocation, "primitive", SafeCast<UInt32>(i) };
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -2929,7 +2917,7 @@ namespace Nz::ShaderAst
|
||||||
case TypeParameterCategory::StructType:
|
case TypeParameterCategory::StructType:
|
||||||
{
|
{
|
||||||
if (!IsStructType(resolvedType))
|
if (!IsStructType(resolvedType))
|
||||||
throw ShaderLang::CompilerPartialTypeExpectError{ indexExpr->sourceLocation, "struct", SafeCast<unsigned int>(i) };
|
throw ShaderLang::CompilerPartialTypeExpectError{ indexExpr->sourceLocation, "struct", SafeCast<UInt32>(i) };
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -2945,7 +2933,7 @@ namespace Nz::ShaderAst
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(parameters.size() == partialType.parameters.size());
|
assert(parameters.size() == partialType.parameters.size());
|
||||||
node.cachedExpressionType = partialType.buildFunc(parameters.data(), parameters.size());
|
node.cachedExpressionType = partialType.buildFunc(parameters.data(), parameters.size(), node.sourceLocation);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -2959,11 +2947,11 @@ namespace Nz::ShaderAst
|
||||||
return ValidationResult::Unresolved;
|
return ValidationResult::Unresolved;
|
||||||
|
|
||||||
if (!IsPrimitiveType(*indexType))
|
if (!IsPrimitiveType(*indexType))
|
||||||
throw AstError{ "AccessIndex expects integer indices" };
|
throw ShaderLang::CompilerIndexRequiresIntegerIndicesError{ node.sourceLocation };
|
||||||
|
|
||||||
PrimitiveType primitiveIndexType = std::get<PrimitiveType>(*indexType);
|
PrimitiveType primitiveIndexType = std::get<PrimitiveType>(*indexType);
|
||||||
if (primitiveIndexType != PrimitiveType::Int32 && primitiveIndexType != PrimitiveType::UInt32)
|
if (primitiveIndexType != PrimitiveType::Int32 && primitiveIndexType != PrimitiveType::UInt32)
|
||||||
throw AstError{ "AccessIndex expects integer indices" };
|
throw ShaderLang::CompilerIndexRequiresIntegerIndicesError{ node.sourceLocation };
|
||||||
|
|
||||||
if (IsArrayType(resolvedExprType))
|
if (IsArrayType(resolvedExprType))
|
||||||
{
|
{
|
||||||
|
|
@ -2974,13 +2962,13 @@ namespace Nz::ShaderAst
|
||||||
else if (IsStructType(resolvedExprType))
|
else if (IsStructType(resolvedExprType))
|
||||||
{
|
{
|
||||||
if (primitiveIndexType != PrimitiveType::Int32)
|
if (primitiveIndexType != PrimitiveType::Int32)
|
||||||
throw AstError{ "struct can only be accessed with constant i32 indices" };
|
throw ShaderLang::CompilerIndexStructRequiresInt32IndicesError{ node.sourceLocation };
|
||||||
|
|
||||||
ConstantValueExpression& constantExpr = static_cast<ConstantValueExpression&>(*indexExpr);
|
ConstantValueExpression& constantExpr = static_cast<ConstantValueExpression&>(*indexExpr);
|
||||||
|
|
||||||
Int32 index = std::get<Int32>(constantExpr.value);
|
Int32 index = std::get<Int32>(constantExpr.value);
|
||||||
|
|
||||||
std::size_t structIndex = ResolveStruct(resolvedExprType);
|
std::size_t structIndex = ResolveStruct(resolvedExprType, indexExpr->sourceLocation);
|
||||||
const StructDescription* s = m_context->structs.Retrieve(structIndex, indexExpr->sourceLocation);
|
const StructDescription* s = m_context->structs.Retrieve(structIndex, indexExpr->sourceLocation);
|
||||||
|
|
||||||
std::optional<ExpressionType> resolvedExprTypeOpt = ResolveTypeExpr(s->members[index].type, true, indexExpr->sourceLocation);
|
std::optional<ExpressionType> resolvedExprTypeOpt = ResolveTypeExpr(s->members[index].type, true, indexExpr->sourceLocation);
|
||||||
|
|
@ -3005,7 +2993,7 @@ namespace Nz::ShaderAst
|
||||||
resolvedExprType = swizzledVec.type;
|
resolvedExprType = swizzledVec.type;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw AstError{ "unexpected type (only struct, vectors and matrices can be indexed)" };
|
throw ShaderLang::CompilerIndexUnexpectedTypeError{ node.sourceLocation };
|
||||||
}
|
}
|
||||||
|
|
||||||
node.cachedExpressionType = std::move(resolvedExprType);
|
node.cachedExpressionType = std::move(resolvedExprType);
|
||||||
|
|
@ -3025,7 +3013,7 @@ namespace Nz::ShaderAst
|
||||||
return ValidationResult::Unresolved;
|
return ValidationResult::Unresolved;
|
||||||
|
|
||||||
if (GetExpressionCategory(*node.left) != ExpressionCategory::LValue)
|
if (GetExpressionCategory(*node.left) != ExpressionCategory::LValue)
|
||||||
throw AstError{ "Assignation is only possible with a l-value" };
|
throw ShaderLang::CompilerAssignTemporaryError{ node.sourceLocation };
|
||||||
|
|
||||||
std::optional<BinaryType> binaryType;
|
std::optional<BinaryType> binaryType;
|
||||||
switch (node.op)
|
switch (node.op)
|
||||||
|
|
@ -3086,19 +3074,19 @@ namespace Nz::ShaderAst
|
||||||
|
|
||||||
const IdentifierData* targetIdentifier = ResolveAliasIdentifier(&m_context->aliases.Retrieve(alias.aliasId, node.sourceLocation), node.sourceLocation);
|
const IdentifierData* targetIdentifier = ResolveAliasIdentifier(&m_context->aliases.Retrieve(alias.aliasId, node.sourceLocation), node.sourceLocation);
|
||||||
if (targetIdentifier->category != IdentifierCategory::Function)
|
if (targetIdentifier->category != IdentifierCategory::Function)
|
||||||
throw AstError{ "expected function expression" };
|
throw ShaderLang::CompilerFunctionCallExpectedFunctionError{ node.sourceLocation };
|
||||||
|
|
||||||
targetFuncIndex = targetIdentifier->index;
|
targetFuncIndex = targetIdentifier->index;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw AstError{ "expected function expression" };
|
throw ShaderLang::CompilerFunctionCallExpectedFunctionError{ node.sourceLocation };
|
||||||
|
|
||||||
auto& funcData = m_context->functions.Retrieve(targetFuncIndex, node.sourceLocation);
|
auto& funcData = m_context->functions.Retrieve(targetFuncIndex, node.sourceLocation);
|
||||||
|
|
||||||
const DeclareFunctionStatement* referenceDeclaration = funcData.node;
|
const DeclareFunctionStatement* referenceDeclaration = funcData.node;
|
||||||
|
|
||||||
if (referenceDeclaration->entryStage.HasValue())
|
if (referenceDeclaration->entryStage.HasValue())
|
||||||
throw AstError{ referenceDeclaration->name + " is an entry function which cannot be called by the program" };
|
throw ShaderLang::CompilerFunctionCallUnexpectedEntryFunctionError{ node.sourceLocation, referenceDeclaration->name };
|
||||||
|
|
||||||
for (std::size_t i = 0; i < node.parameters.size(); ++i)
|
for (std::size_t i = 0; i < node.parameters.size(); ++i)
|
||||||
{
|
{
|
||||||
|
|
@ -3107,11 +3095,11 @@ namespace Nz::ShaderAst
|
||||||
return ValidationResult::Unresolved;
|
return ValidationResult::Unresolved;
|
||||||
|
|
||||||
if (ResolveAlias(*parameterType) != ResolveAlias(referenceDeclaration->parameters[i].type.GetResultingValue()))
|
if (ResolveAlias(*parameterType) != ResolveAlias(referenceDeclaration->parameters[i].type.GetResultingValue()))
|
||||||
throw AstError{ "function " + referenceDeclaration->name + " parameter " + std::to_string(i) + " type mismatch" };
|
throw ShaderLang::CompilerFunctionCallUnmatchingParameterTypeError{ node.sourceLocation, referenceDeclaration->name, SafeCast<UInt32>(i) };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node.parameters.size() != referenceDeclaration->parameters.size())
|
if (node.parameters.size() != referenceDeclaration->parameters.size())
|
||||||
throw AstError{ "function " + referenceDeclaration->name + " expected " + std::to_string(referenceDeclaration->parameters.size()) + " parameters, got " + std::to_string(node.parameters.size()) };
|
throw ShaderLang::CompilerFunctionCallUnmatchingParameterCountError{ node.sourceLocation, referenceDeclaration->name, SafeCast<UInt32>(referenceDeclaration->parameters.size()), SafeCast<UInt32>(node.parameters.size()) };
|
||||||
|
|
||||||
node.cachedExpressionType = referenceDeclaration->returnType.GetResultingValue();
|
node.cachedExpressionType = referenceDeclaration->returnType.GetResultingValue();
|
||||||
return ValidationResult::Validated;
|
return ValidationResult::Validated;
|
||||||
|
|
@ -3138,7 +3126,7 @@ namespace Nz::ShaderAst
|
||||||
if (IsMatrixType(ResolveAlias(*firstExprType)))
|
if (IsMatrixType(ResolveAlias(*firstExprType)))
|
||||||
{
|
{
|
||||||
if (node.expressions[1])
|
if (node.expressions[1])
|
||||||
throw AstError{ "too many expressions" };
|
throw ShaderLang::CompilerCastComponentMismatchError{ node.expressions[1]->sourceLocation };
|
||||||
|
|
||||||
// Matrix to matrix cast: always valid
|
// Matrix to matrix cast: always valid
|
||||||
}
|
}
|
||||||
|
|
@ -3149,7 +3137,7 @@ namespace Nz::ShaderAst
|
||||||
{
|
{
|
||||||
const auto& exprPtr = node.expressions[i];
|
const auto& exprPtr = node.expressions[i];
|
||||||
if (!exprPtr)
|
if (!exprPtr)
|
||||||
throw AstError{ "component count doesn't match required component count" };
|
throw ShaderLang::CompilerCastComponentMismatchError{ node.sourceLocation };
|
||||||
|
|
||||||
const ExpressionType* exprType = GetExpressionType(*exprPtr);
|
const ExpressionType* exprType = GetExpressionType(*exprPtr);
|
||||||
if (!exprType)
|
if (!exprType)
|
||||||
|
|
@ -3157,11 +3145,11 @@ namespace Nz::ShaderAst
|
||||||
|
|
||||||
const ExpressionType& resolvedExprType = ResolveAlias(*exprType);
|
const ExpressionType& resolvedExprType = ResolveAlias(*exprType);
|
||||||
if (!IsVectorType(resolvedExprType))
|
if (!IsVectorType(resolvedExprType))
|
||||||
throw AstError{ "expected vector type" };
|
throw ShaderLang::CompilerCastMatrixExpectedVectorError{ node.sourceLocation };
|
||||||
|
|
||||||
const VectorType& vecType = std::get<VectorType>(resolvedExprType);
|
const VectorType& vecType = std::get<VectorType>(resolvedExprType);
|
||||||
if (vecType.componentCount != targetMatrixType.rowCount)
|
if (vecType.componentCount != targetMatrixType.rowCount)
|
||||||
throw AstError{ "vector component count must match target matrix row count" };
|
throw ShaderLang::CompilerCastMatrixVectorComponentMismatchError{ node.expressions[i]->sourceLocation, SafeCast<UInt32>(vecType.componentCount), SafeCast<UInt32>(targetMatrixType.rowCount) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3435,7 +3423,7 @@ namespace Nz::ShaderAst
|
||||||
const ExpressionType& resolvedExprType = ResolveAlias(*exprType);
|
const ExpressionType& resolvedExprType = ResolveAlias(*exprType);
|
||||||
|
|
||||||
if (!IsPrimitiveType(resolvedExprType) && !IsVectorType(resolvedExprType))
|
if (!IsPrimitiveType(resolvedExprType) && !IsVectorType(resolvedExprType))
|
||||||
throw AstError{ "Cannot swizzle this type" };
|
throw ShaderLang::CompilerSwizzleUnexpectedTypeError{ node.sourceLocation };
|
||||||
|
|
||||||
PrimitiveType baseType;
|
PrimitiveType baseType;
|
||||||
std::size_t componentCount;
|
std::size_t componentCount;
|
||||||
|
|
@ -3706,7 +3694,7 @@ namespace Nz::ShaderAst
|
||||||
auto SanitizeVisitor::ValidateIntrinsicParamCount(IntrinsicExpression& node) -> ValidationResult
|
auto SanitizeVisitor::ValidateIntrinsicParamCount(IntrinsicExpression& node) -> ValidationResult
|
||||||
{
|
{
|
||||||
if (node.parameters.size() != N)
|
if (node.parameters.size() != N)
|
||||||
throw ShaderLang::CompilerIntrinsicExpectedParameterCountError{ node.sourceLocation, SafeCast<unsigned int>(N) };
|
throw ShaderLang::CompilerIntrinsicExpectedParameterCountError{ node.sourceLocation, SafeCast<UInt32>(N) };
|
||||||
|
|
||||||
for (auto& param : node.parameters)
|
for (auto& param : node.parameters)
|
||||||
MandatoryExpr(param, node.sourceLocation);
|
MandatoryExpr(param, node.sourceLocation);
|
||||||
|
|
@ -3760,7 +3748,7 @@ namespace Nz::ShaderAst
|
||||||
|
|
||||||
const ExpressionType& resolvedType = ResolveAlias(*type);
|
const ExpressionType& resolvedType = ResolveAlias(*type);
|
||||||
if (!func(resolvedType))
|
if (!func(resolvedType))
|
||||||
throw ShaderLang::CompilerIntrinsicExpectedTypeError{ parameter.sourceLocation, SafeCast<unsigned int>(N) };
|
throw ShaderLang::CompilerIntrinsicExpectedTypeError{ parameter.sourceLocation, SafeCast<UInt32>(N) };
|
||||||
|
|
||||||
return ValidationResult::Validated;
|
return ValidationResult::Validated;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,24 @@ struct fmt::formatter<Nz::ShaderLang::ErrorCategory> : formatter<string_view>
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct fmt::formatter<Nz::ShaderStageType> : formatter<string_view>
|
||||||
|
{
|
||||||
|
template <typename FormatContext>
|
||||||
|
auto format(const Nz::ShaderStageType& p, FormatContext& ctx) -> decltype(ctx.out())
|
||||||
|
{
|
||||||
|
// TODO: Add ToString
|
||||||
|
std::string_view name = "<unhandled shader stage>";
|
||||||
|
switch (p)
|
||||||
|
{
|
||||||
|
case Nz::ShaderStageType::Fragment: name = "fragment"; break;
|
||||||
|
case Nz::ShaderStageType::Vertex: name = "vertex"; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return formatter<string_view>::format(name, ctx);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct fmt::formatter<Nz::ShaderLang::TokenType> : formatter<string_view>
|
struct fmt::formatter<Nz::ShaderLang::TokenType> : formatter<string_view>
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue