Shader: Add support for max/min intrinsic
This commit is contained in:
parent
0339ea346f
commit
a7235ab02d
|
|
@ -57,6 +57,8 @@ namespace Nz::ShaderAst
|
|||
CrossProduct = 0,
|
||||
DotProduct = 1,
|
||||
Length = 3,
|
||||
Max = 4,
|
||||
Min = 5,
|
||||
SampleTexture = 2,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -448,6 +448,8 @@ namespace Nz::ShaderAst
|
|||
{
|
||||
case IntrinsicType::CrossProduct:
|
||||
case IntrinsicType::DotProduct:
|
||||
case IntrinsicType::Max:
|
||||
case IntrinsicType::Min:
|
||||
{
|
||||
if (clone->parameters.size() != 2)
|
||||
throw AstError { "Expected two parameters" };
|
||||
|
|
@ -523,6 +525,21 @@ namespace Nz::ShaderAst
|
|||
break;
|
||||
}
|
||||
|
||||
case IntrinsicType::Max:
|
||||
case IntrinsicType::Min:
|
||||
{
|
||||
const ExpressionType& type = GetExpressionType(*clone->parameters.front());
|
||||
if (!IsPrimitiveType(type) && !IsVectorType(type))
|
||||
throw AstError{ "max and min only work with primitive and vector types" };
|
||||
|
||||
if ((IsPrimitiveType(type) && std::get<PrimitiveType>(type) == PrimitiveType::Boolean) ||
|
||||
(IsVectorType(type) && std::get<VectorType>(type).type == PrimitiveType::Boolean))
|
||||
throw AstError{ "max and min do not work with booleans" };
|
||||
|
||||
clone->cachedExpressionType = type;
|
||||
break;
|
||||
}
|
||||
|
||||
case IntrinsicType::SampleTexture:
|
||||
{
|
||||
clone->cachedExpressionType = VectorType{ 4, std::get<SamplerType>(GetExpressionType(*clone->parameters.front())).sampledType };
|
||||
|
|
|
|||
|
|
@ -822,6 +822,14 @@ namespace Nz
|
|||
Append("length");
|
||||
break;
|
||||
|
||||
case ShaderAst::IntrinsicType::Max:
|
||||
Append("max");
|
||||
break;
|
||||
|
||||
case ShaderAst::IntrinsicType::Min:
|
||||
Append("min");
|
||||
break;
|
||||
|
||||
case ShaderAst::IntrinsicType::SampleTexture:
|
||||
Append("texture");
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -658,6 +658,14 @@ namespace Nz
|
|||
Append("length");
|
||||
break;
|
||||
|
||||
case ShaderAst::IntrinsicType::Max:
|
||||
Append("max");
|
||||
break;
|
||||
|
||||
case ShaderAst::IntrinsicType::Min:
|
||||
Append("min");
|
||||
break;
|
||||
|
||||
case ShaderAst::IntrinsicType::SampleTexture:
|
||||
Append("texture");
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ namespace Nz::ShaderLang
|
|||
std::unordered_map<std::string, ShaderAst::IntrinsicType> s_identifierToIntrinsic = {
|
||||
{ "cross", ShaderAst::IntrinsicType::CrossProduct },
|
||||
{ "dot", ShaderAst::IntrinsicType::DotProduct },
|
||||
{ "max", ShaderAst::IntrinsicType::Max },
|
||||
{ "min", ShaderAst::IntrinsicType::Min },
|
||||
{ "length", ShaderAst::IntrinsicType::Length },
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -710,6 +710,51 @@ namespace Nz
|
|||
break;
|
||||
}
|
||||
|
||||
case ShaderAst::IntrinsicType::Max:
|
||||
case ShaderAst::IntrinsicType::Min:
|
||||
{
|
||||
UInt32 glslInstructionSet = m_writer.GetExtendedInstructionSet("GLSL.std.450");
|
||||
|
||||
const ShaderAst::ExpressionType& parameterType = GetExpressionType(*node.parameters[0]);
|
||||
assert(IsPrimitiveType(parameterType) || IsVectorType(parameterType));
|
||||
UInt32 typeId = m_writer.GetTypeId(parameterType);
|
||||
|
||||
ShaderAst::PrimitiveType basicType;
|
||||
if (IsPrimitiveType(parameterType))
|
||||
basicType = std::get<ShaderAst::PrimitiveType>(parameterType);
|
||||
else if (IsVectorType(parameterType))
|
||||
basicType = std::get<ShaderAst::VectorType>(parameterType).type;
|
||||
else
|
||||
throw std::runtime_error("unexpected expression type");
|
||||
|
||||
GLSLstd450 op;
|
||||
switch (basicType)
|
||||
{
|
||||
case ShaderAst::PrimitiveType::Boolean:
|
||||
throw std::runtime_error("unexpected boolean for max/min intrinsic");
|
||||
|
||||
case ShaderAst::PrimitiveType::Float32:
|
||||
op = (node.intrinsic == ShaderAst::IntrinsicType::Max) ? GLSLstd450FMax : GLSLstd450FMin;
|
||||
break;
|
||||
|
||||
case ShaderAst::PrimitiveType::Int32:
|
||||
op = (node.intrinsic == ShaderAst::IntrinsicType::Max) ? GLSLstd450SMax : GLSLstd450SMin;
|
||||
break;
|
||||
|
||||
case ShaderAst::PrimitiveType::UInt32:
|
||||
op = (node.intrinsic == ShaderAst::IntrinsicType::Max) ? GLSLstd450UMax : GLSLstd450UMin;
|
||||
break;
|
||||
}
|
||||
|
||||
UInt32 firstParam = EvaluateExpression(node.parameters[0]);
|
||||
UInt32 secondParam = EvaluateExpression(node.parameters[1]);
|
||||
UInt32 resultId = m_writer.AllocateResultId();
|
||||
|
||||
m_currentBlock->Append(SpirvOp::OpExtInst, typeId, resultId, glslInstructionSet, op, firstParam, secondParam);
|
||||
PushResultId(resultId);
|
||||
break;
|
||||
}
|
||||
|
||||
case ShaderAst::IntrinsicType::SampleTexture:
|
||||
{
|
||||
UInt32 typeId = m_writer.GetTypeId(ShaderAst::VectorType{4, ShaderAst::PrimitiveType::Float32});
|
||||
|
|
|
|||
|
|
@ -283,6 +283,8 @@ namespace Nz
|
|||
// Require GLSL.std.450
|
||||
case ShaderAst::IntrinsicType::CrossProduct:
|
||||
case ShaderAst::IntrinsicType::Length:
|
||||
case ShaderAst::IntrinsicType::Max:
|
||||
case ShaderAst::IntrinsicType::Min:
|
||||
extInsts.emplace("GLSL.std.450");
|
||||
break;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue