summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--source/slang-glslang/slang-glslang.vcxproj8
-rw-r--r--source/slang/emit.cpp44
-rw-r--r--source/slang/emit.h5
-rw-r--r--source/slang/lower.cpp508
-rw-r--r--source/slang/lower.h9
-rw-r--r--source/slang/parameter-binding.cpp3
-rw-r--r--tests/nv-extensions/multi-view-per-view-attributes.slang17
-rw-r--r--tests/nv-extensions/multi-view-per-view-attributes.slang.glsl44
8 files changed, 561 insertions, 77 deletions
diff --git a/source/slang-glslang/slang-glslang.vcxproj b/source/slang-glslang/slang-glslang.vcxproj
index 7f6761c4a..be617f363 100644
--- a/source/slang-glslang/slang-glslang.vcxproj
+++ b/source/slang-glslang/slang-glslang.vcxproj
@@ -96,7 +96,7 @@
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
- <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;GLSLANG_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NV_EXTENSIONS;AMD_EXTENSIONS;WIN32;_DEBUG;_WINDOWS;_USRDLL;GLSLANG_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -109,7 +109,7 @@
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
- <PreprocessorDefinitions>_DEBUG;_WINDOWS;_USRDLL;GLSLANG_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NV_EXTENSIONS;AMD_EXTENSIONS;_DEBUG;_WINDOWS;_USRDLL;GLSLANG_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -124,7 +124,7 @@
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
- <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;GLSLANG_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NV_EXTENSIONS;AMD_EXTENSIONS;WIN32;NDEBUG;_WINDOWS;_USRDLL;GLSLANG_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -141,7 +141,7 @@
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
- <PreprocessorDefinitions>NDEBUG;_WINDOWS;_USRDLL;GLSLANG_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>NV_EXTENSIONS;AMD_EXTENSIONS;NDEBUG;_WINDOWS;_USRDLL;GLSLANG_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp
index 4754578b3..ee90510a9 100644
--- a/source/slang/emit.cpp
+++ b/source/slang/emit.cpp
@@ -15,6 +15,31 @@
namespace Slang {
+struct ExtensionUsageTracker
+{
+ // Record the GLSL extnsions we have already emitted a `#extension` for
+ HashSet<String> glslExtensionsRequired;
+ StringBuilder glslExtensionRequireLines;
+};
+
+void requireGLSLExtension(
+ ExtensionUsageTracker* tracker,
+ String const& name)
+{
+ if (tracker->glslExtensionsRequired.Contains(name))
+ return;
+
+ StringBuilder& sb = tracker->glslExtensionRequireLines;
+
+ sb.append("#extension ");
+ sb.append(name);
+ sb.append(" : require\n");
+
+ tracker->glslExtensionsRequired.Add(name);
+}
+
+
+
// Shared state for an entire emit session
struct SharedEmitContext
{
@@ -61,9 +86,7 @@ struct SharedEmitContext
bool needHackSamplerForTexelFetch = false;
- // Record the GLSL extnsions we have already emitted a `#extension` for
- HashSet<String> glslExtensionsRequired;
- StringBuilder glslExtensionRequireLines;
+ ExtensionUsageTracker extensionUsageTracker;
};
struct EmitContext
@@ -1668,16 +1691,7 @@ struct EmitVisitor
void requireGLSLExtension(String const& name)
{
- if (context->shared->glslExtensionsRequired.Contains(name))
- return;
-
- StringBuilder& sb = context->shared->glslExtensionRequireLines;
-
- sb.append("#extension ");
- sb.append(name);
- sb.append(" : require\n");
-
- context->shared->glslExtensionsRequired.Add(name);
+ Slang::requireGLSLExtension(&context->shared->extensionUsageTracker, name);
}
void requireGLSLVersion(ProfileVersion version)
@@ -3774,7 +3788,7 @@ String emitEntryPoint(
// because the lowering process might change how we emit some
// boilerplate at the start of the ouput for GLSL (e.g., what
// version we require).
- auto lowered = lowerEntryPoint(entryPoint, programLayout, target);
+ auto lowered = lowerEntryPoint(entryPoint, programLayout, target, &sharedContext.extensionUsageTracker);
sharedContext.program = lowered.program;
// Note that we emit the main body code of the program *before*
@@ -3797,7 +3811,7 @@ String emitEntryPoint(
StringBuilder finalResultBuilder;
finalResultBuilder << prefix;
- finalResultBuilder << sharedContext.glslExtensionRequireLines.ProduceString();
+ finalResultBuilder << sharedContext.extensionUsageTracker.glslExtensionRequireLines.ProduceString();
if (sharedContext.needHackSamplerForTexelFetch)
{
diff --git a/source/slang/emit.h b/source/slang/emit.h
index da1ac9f08..5d546bdf4 100644
--- a/source/slang/emit.h
+++ b/source/slang/emit.h
@@ -12,6 +12,11 @@ namespace Slang
class ProgramLayout;
class TranslationUnitRequest;
+ struct ExtensionUsageTracker;
+ void requireGLSLExtension(
+ ExtensionUsageTracker* tracker,
+ String const& name);
+
// Emit code for a single entry point, based on
// the input translation unit.
String emitEntryPoint(
diff --git a/source/slang/lower.cpp b/source/slang/lower.cpp
index 52b865ba3..54afc283c 100644
--- a/source/slang/lower.cpp
+++ b/source/slang/lower.cpp
@@ -1,6 +1,7 @@
// lower.cpp
#include "lower.h"
+#include "emit.h"
#include "type-layout.h"
#include "visitor.h"
@@ -253,6 +254,8 @@ struct SharedLoweringContext
CompileRequest* compileRequest;
EntryPointRequest* entryPointRequest;
+ ExtensionUsageTracker* extensionUsageTracker;
+
ProgramLayout* programLayout;
EntryPointLayout* entryPointLayout;
@@ -278,7 +281,8 @@ struct SharedLoweringContext
// Counter used for generating unique temporary names
int nameCounter = 0;
- bool isRewrite;
+ bool isRewrite = false;
+ bool requiresCopyGLPositionToPositionPerView = false;
};
static void attachLayout(
@@ -786,10 +790,243 @@ struct LoweringVisitor
return expr;
}
- RefPtr<ExpressionSyntaxNode> createAssignExpr(
+ // When constructing assignment syntax, we can either
+ // just leave things alone, or create code that will
+ // try to coerce types to "fix up" differences in
+ // the apparent type of things.
+ enum class AssignMode
+ {
+ Default,
+ WithFixups,
+ };
+
+ RefPtr<ExpressionSyntaxNode> createSimpleAssignExpr(
+ RefPtr<ExpressionSyntaxNode> leftExpr,
+ RefPtr<ExpressionSyntaxNode> rightExpr)
+ {
+ RefPtr<AssignExpr> loweredExpr = new AssignExpr();
+ loweredExpr->Type = leftExpr->Type;
+ loweredExpr->left = leftExpr;
+ loweredExpr->right = rightExpr;
+ return loweredExpr;
+ }
+
+ RefPtr<ExpressionSyntaxNode> convertExprForAssignmentWithFixups(
+ RefPtr<ExpressionType> leftType,
+ RefPtr<ExpressionSyntaxNode> rightExpr)
+ {
+ auto rightType = rightExpr->Type.type;
+ if (auto leftArrayType = leftType->As<ArrayExpressionType>())
+ {
+ // LHS type was an array
+
+ if (auto rightVecType = rightType->As<VectorExpressionType>())
+ {
+ // RHS type was a vector
+ if (auto leftElemVecType = leftArrayType->BaseType->As<VectorExpressionType>())
+ {
+ // LHS element type was also a vector, so this is a "scalar splat
+ // to array" case.
+ }
+ else
+ {
+ // LHS is an array of non-vectors, while RHS is a vector,
+ // so in this case we want to splat out the vector elements
+ // to create an array and use that.
+ rightExpr = maybeMoveTemp(rightExpr);
+
+ RefPtr<AggTypeCtorExpr> ctorExpr = new AggTypeCtorExpr();
+ ctorExpr->Position = rightExpr->Position;
+ ctorExpr->Type.type = leftType;
+ ctorExpr->base.type = leftType;
+
+ int elementCount = (int) GetIntVal(rightVecType->elementCount);
+ for (int ee = 0; ee < elementCount; ++ee)
+ {
+ RefPtr<SwizzleExpr> swizzleExpr = new SwizzleExpr();
+ swizzleExpr->Position = rightExpr->Position;
+ swizzleExpr->Type.type = rightVecType->elementType;
+ swizzleExpr->base = rightExpr;
+ swizzleExpr->elementCount = 1;
+ swizzleExpr->elementIndices[0] = ee;
+
+ auto convertedArgExpr = convertExprForAssignmentWithFixups(
+ leftArrayType->BaseType,
+ swizzleExpr);
+
+ ctorExpr->Arguments.Add(convertedArgExpr);
+ }
+
+ return ctorExpr;
+ }
+ }
+ }
+
+ // Default case: if the types didn't match, try to insert
+ // an explicit cast to deal with the issue.
+ return createCastExpr(leftType, rightExpr);
+
+ }
+
+ RefPtr<ExpressionSyntaxNode> createConstIntExpr(IntegerLiteralValue value)
+ {
+ RefPtr<ConstantExpressionSyntaxNode> expr = new ConstantExpressionSyntaxNode();
+ expr->Type.type = getIntType();
+ expr->ConstType = ConstantExpressionSyntaxNode::ConstantType::Int;
+ expr->integerValue = value;
+ return expr;
+ }
+
+ struct SeqExprBuilder
+ {
+ RefPtr<ExpressionSyntaxNode> expr;
+ RefPtr<ExpressionSyntaxNode>* link = nullptr;
+ };
+
+ RefPtr<ExpressionSyntaxNode> createSimpleVarExpr(char const* name)
+ {
+ RefPtr<VarExpressionSyntaxNode> varExpr = new VarExpressionSyntaxNode();
+ varExpr->name = name;
+ return varExpr;
+ }
+
+ RefPtr<InvokeExpressionSyntaxNode> createSeqExpr(
+ RefPtr<ExpressionSyntaxNode> left,
+ RefPtr<ExpressionSyntaxNode> right)
+ {
+ RefPtr<InfixExpr> seqExpr = new InfixExpr();
+ seqExpr->Position = left->Position;
+ seqExpr->Type = right->Type;
+ seqExpr->FunctionExpr = createSimpleVarExpr(",");
+ seqExpr->Arguments.Add(left);
+ seqExpr->Arguments.Add(right);
+ return seqExpr;
+ }
+
+ void addExpr(SeqExprBuilder* builder, RefPtr<ExpressionSyntaxNode> expr)
+ {
+ // No expression to add? Do nothing.
+ if (!expr) return;
+
+ if (!builder->expr)
+ {
+ // No expression so far?
+ // Set up a single-expression result.
+
+ builder->expr = expr;
+ builder->link = &builder->expr;
+ return;
+ }
+
+ // There is an existing expression, so we need to append
+ // to the sequence of expressions. The invariant is
+ // that `link` points to the last expression in the
+ // sequence.
+
+ // We will extract the old last element, and construct
+ // a new sequence expression ("operator comma") that
+ // concatenates with with our new last expression.
+ auto oldLastExpr = *builder->link;
+ auto seqExpr = createSeqExpr(oldLastExpr, expr);
+
+ // Now we need to overwrite the old last expression,
+ // wherever it occured in the AST (which we handily
+ // stored in `link`) and set our `link` to track
+ // the new last expression (which will be the second
+ // argument to our sequence expression).
+ *builder->link = seqExpr;
+ builder->link = &seqExpr->Arguments[1];
+ }
+
+ RefPtr<ExpressionSyntaxNode> createSimpleAssignExprWithFixups(
RefPtr<ExpressionSyntaxNode> leftExpr,
RefPtr<ExpressionSyntaxNode> rightExpr)
{
+ auto leftType = leftExpr->Type.type;
+ auto rightType = rightExpr->Type.type;
+
+ // If types are unknown, or match, then just do
+ // things the ordinary way.
+ if (!leftType
+ || !rightType
+ || leftType->As<ErrorType>()
+ || rightType->As<ErrorType>()
+ || leftType->Equals(rightType))
+ {
+ return createSimpleAssignExpr(leftExpr, rightExpr);
+ }
+
+ // Otherwise, start to look at the types involved,
+ // and see if we can do something.
+
+ if (auto leftArrayType = leftType->As<ArrayExpressionType>())
+ {
+ // LHS type was an array
+
+ if (auto rightVecType = rightType->As<VectorExpressionType>())
+ {
+ // RHS type was a vector
+ if (auto leftElemVecType = leftArrayType->BaseType->As<VectorExpressionType>())
+ {
+ // LHS element type was also a vector, so this is a "scalar splat
+ // to array" case.
+ }
+ else
+ {
+ // LHS is an array of non-vectors, while RHS is a vector,
+ // so in this case we want to splat out the vector elements
+ // to create an array and use that.
+ leftExpr = maybeMoveTemp(leftExpr);
+ rightExpr = maybeMoveTemp(rightExpr);
+
+ SeqExprBuilder builder;
+
+ int elementCount = (int) GetIntVal(rightVecType->elementCount);
+ for (int ee = 0; ee < elementCount; ++ee)
+ {
+ // LHS array element
+ RefPtr<IndexExpressionSyntaxNode> arrayElemExpr = new IndexExpressionSyntaxNode();
+ arrayElemExpr->Position = leftExpr->Position;
+ arrayElemExpr->Type.type = leftArrayType->BaseType;
+ arrayElemExpr->BaseExpression = leftExpr;
+ arrayElemExpr->IndexExpression = createConstIntExpr(ee);
+
+ // RHS swizzle
+ RefPtr<SwizzleExpr> swizzleExpr = new SwizzleExpr();
+ swizzleExpr->Position = rightExpr->Position;
+ swizzleExpr->Type.type = rightVecType->elementType;
+ swizzleExpr->base = rightExpr;
+ swizzleExpr->elementCount = 1;
+ swizzleExpr->elementIndices[0] = ee;
+
+ auto elemAssignExpr = createSimpleAssignExprWithFixups(
+ arrayElemExpr,
+ swizzleExpr);
+
+ addExpr(&builder, elemAssignExpr);
+ }
+
+ return builder.expr;
+ }
+ }
+ }
+
+
+
+
+ // TODO: are there any cases we can't solve with a cast?
+
+ // Try to convert the right-hand-side expression to have the type
+ // we expect on the left-hand side
+ auto convertedRightExpr = convertExprForAssignmentWithFixups(leftType, rightExpr);
+ return createSimpleAssignExpr(leftExpr, convertedRightExpr);
+ }
+
+ RefPtr<ExpressionSyntaxNode> createAssignExpr(
+ RefPtr<ExpressionSyntaxNode> leftExpr,
+ RefPtr<ExpressionSyntaxNode> rightExpr,
+ AssignMode mode = AssignMode::Default)
+ {
auto leftTuple = leftExpr.As<TupleExpr>();
auto rightTuple = rightExpr.As<TupleExpr>();
if (leftTuple && rightTuple)
@@ -803,7 +1040,8 @@ struct LoweringVisitor
resultTuple->primaryExpr = createAssignExpr(
leftTuple->primaryExpr,
- rightTuple->primaryExpr);
+ rightTuple->primaryExpr,
+ mode);
}
auto elementCount = leftTuple->tupleElements.Count();
@@ -818,7 +1056,8 @@ struct LoweringVisitor
resultElement.tupleFieldDeclRef = leftElement.tupleFieldDeclRef;
resultElement.expr = createAssignExpr(
leftElement.expr,
- rightElement.expr);
+ rightElement.expr,
+ mode);
resultTuple->tupleElements.Add(resultElement);
}
@@ -852,7 +1091,8 @@ struct LoweringVisitor
elem.originalFieldDeclRef = leftElem.originalFieldDeclRef;
elem.expr = createAssignExpr(
leftElem.expr,
- rightElem.expr);
+ rightElem.expr,
+ mode);
}
}
else if (leftVaryingTuple)
@@ -888,14 +1128,15 @@ struct LoweringVisitor
RefPtr<MemberExpressionSyntaxNode> rightElemExpr = new MemberExpressionSyntaxNode();
rightElemExpr->Position = rightExpr->Position;
- rightElemExpr->Type = leftElem.expr->Type;
+ rightElemExpr->Type.type = GetType(leftElem.originalFieldDeclRef);
rightElemExpr->declRef = leftElem.originalFieldDeclRef;
rightElemExpr->name = leftElem.originalFieldDeclRef.GetName();
rightElemExpr->BaseExpression = rightExpr;
auto subExpr = createAssignExpr(
leftElem.expr,
- rightElemExpr);
+ rightElemExpr,
+ mode);
RefPtr<InfixExpr> seqExpr = new InfixExpr();
seqExpr->FunctionExpr = createUncheckedVarRef(",");
@@ -942,7 +1183,8 @@ struct LoweringVisitor
auto subExpr = createAssignExpr(
leftElemExpr,
- rightElem.expr);
+ rightElem.expr,
+ mode);
RefPtr<InfixExpr> seqExpr = new InfixExpr();
seqExpr->FunctionExpr = createUncheckedVarRef(",");
@@ -957,12 +1199,14 @@ struct LoweringVisitor
// Default case: no tuples of any kind...
+ switch (mode)
+ {
+ default:
+ return createSimpleAssignExpr(leftExpr, rightExpr);
- RefPtr<AssignExpr> loweredExpr = new AssignExpr();
- loweredExpr->Type = leftExpr->Type;
- loweredExpr->left = leftExpr;
- loweredExpr->right = rightExpr;
- return loweredExpr;
+ case AssignMode::WithFixups:
+ return createSimpleAssignExprWithFixups(leftExpr, rightExpr);
+ }
}
RefPtr<ExpressionSyntaxNode> visitAssignExpr(
@@ -1462,6 +1706,11 @@ struct LoweringVisitor
}
}
}
+ else if (auto varExpr = expr.As<VarExpressionSyntaxNode>())
+ {
+ // Skip an expression that is just a reference to a single variable
+ return;
+ }
RefPtr<ExpressionStatementSyntaxNode> stmt = new ExpressionStatementSyntaxNode();
stmt->Expression = expr;
@@ -1710,9 +1959,10 @@ struct LoweringVisitor
void assign(
RefPtr<ExpressionSyntaxNode> destExpr,
- RefPtr<ExpressionSyntaxNode> srcExpr)
+ RefPtr<ExpressionSyntaxNode> srcExpr,
+ AssignMode mode = AssignMode::Default)
{
- auto assignExpr = createAssignExpr(destExpr, srcExpr);
+ auto assignExpr = createAssignExpr(destExpr, srcExpr, mode);
addExprStmt(assignExpr);
}
@@ -1726,6 +1976,38 @@ struct LoweringVisitor
assign(expr, createVarRef(expr->Position, varDecl));
}
+ RefPtr<ExpressionSyntaxNode> createCastExpr(
+ RefPtr<ExpressionType> type,
+ RefPtr<ExpressionSyntaxNode> expr)
+ {
+ RefPtr<ExplicitCastExpr> castExpr = new ExplicitCastExpr();
+ castExpr->Position = expr->Position;
+ castExpr->Type.type = type;
+ castExpr->TargetType.type = type;
+ castExpr->Expression = expr;
+ return castExpr;
+ }
+
+ // Like `assign`, but with some extra logic to handle cases
+ // where the types don't actually line up, because of
+ // differences in how something is declared in HLSL vs. GLSL
+ void assignWithFixups(
+ RefPtr<ExpressionSyntaxNode> destExpr,
+ RefPtr<ExpressionSyntaxNode> srcExpr)
+ {
+ assign(destExpr, srcExpr, AssignMode::WithFixups);
+ }
+
+ void assignWithFixups(VarDeclBase* varDecl, RefPtr<ExpressionSyntaxNode> expr)
+ {
+ assignWithFixups(createVarRef(expr->Position, varDecl), expr);
+ }
+
+ void assignWithFixups(RefPtr<ExpressionSyntaxNode> expr, VarDeclBase* varDecl)
+ {
+ assignWithFixups(expr, createVarRef(expr->Position, varDecl));
+ }
+
void visitReturnStatementSyntaxNode(ReturnStatementSyntaxNode* stmt)
{
auto loweredStmt = new ReturnStatementSyntaxNode();
@@ -2926,10 +3208,12 @@ struct LoweringVisitor
};
RefPtr<ExpressionSyntaxNode> createGLSLBuiltinRef(
- char const* name)
+ char const* name,
+ RefPtr<ExpressionType> type)
{
RefPtr<VarExpressionSyntaxNode> globalVarRef = new VarExpressionSyntaxNode();
globalVarRef->name = name;
+ globalVarRef->Type.type = type;
return globalVarRef;
}
@@ -2970,6 +3254,82 @@ struct LoweringVisitor
Slang::requireGLSLVersion(entryPoint, version);
}
+ RefPtr<ExpressionType> getFloatType()
+ {
+ return ExpressionType::GetFloat();
+ }
+
+ RefPtr<ExpressionType> getIntType()
+ {
+ return ExpressionType::GetInt();
+ }
+
+ RefPtr<ExpressionType> getUIntType()
+ {
+ return ExpressionType::GetUInt();
+ }
+
+ RefPtr<ExpressionType> getBoolType()
+ {
+ return ExpressionType::GetBool();
+ }
+
+ RefPtr<VectorExpressionType> getVectorType(
+ RefPtr<ExpressionType> elementType,
+ RefPtr<IntVal> elementCount)
+ {
+ auto vectorGenericDecl = findMagicDecl("Vector").As<GenericDecl>();
+ auto vectorTypeDecl = vectorGenericDecl->inner;
+
+ auto substitutions = new Substitutions();
+ substitutions->genericDecl = vectorGenericDecl.Ptr();
+ substitutions->args.Add(elementType);
+ substitutions->args.Add(elementCount);
+
+ auto declRef = DeclRef<Decl>(vectorTypeDecl.Ptr(), substitutions);
+
+ return DeclRefType::Create(declRef)->As<VectorExpressionType>();
+ }
+
+ RefPtr<IntVal> getConstantIntVal(IntegerLiteralValue value)
+ {
+ RefPtr<ConstantIntVal> intVal = new ConstantIntVal();
+ intVal->value = value;
+ return intVal;
+ }
+
+ RefPtr<VectorExpressionType> getVectorType(
+ RefPtr<ExpressionType> elementType,
+ int elementCount)
+ {
+ return getVectorType(elementType, getConstantIntVal(elementCount));
+ }
+
+ RefPtr<ArrayExpressionType> getUnsizedArrayType(
+ RefPtr<ExpressionType> elementType)
+ {
+ RefPtr<ArrayExpressionType> arrayType = new ArrayExpressionType();
+ arrayType->BaseType = elementType;
+ return arrayType;
+ }
+
+ RefPtr<ArrayExpressionType> getArrayType(
+ RefPtr<ExpressionType> elementType,
+ RefPtr<IntVal> elementCount)
+ {
+ RefPtr<ArrayExpressionType> arrayType = new ArrayExpressionType();
+ arrayType->BaseType = elementType;
+ arrayType->ArrayLength = elementCount;
+ return arrayType;
+ }
+
+ RefPtr<ArrayExpressionType> getArrayType(
+ RefPtr<ExpressionType> elementType,
+ IntegerLiteralValue elementCount)
+ {
+ return getArrayType(elementType, getConstantIntVal(elementCount));
+ }
+
RefPtr<ExpressionSyntaxNode> lowerSimpleShaderParameterToGLSLGlobal(
VaryingParameterInfo const& info,
RefPtr<ExpressionType> varType,
@@ -2986,6 +3346,8 @@ struct LoweringVisitor
type = arrayType;
}
+ assert(type);
+
// We need to create a reference to the global-scope declaration
// of the proper GLSL input/output variable. This might
// be a user-defined input/output, or a system-defined `gl_` one.
@@ -3009,94 +3371,90 @@ struct LoweringVisitor
{
if (info.direction == VaryingParameterDirection::Input)
{
- globalVarExpr = createGLSLBuiltinRef("gl_FragCoord");
+ globalVarExpr = createGLSLBuiltinRef("gl_FragCoord", getVectorType(getFloatType(), 4));
}
else
{
- globalVarExpr = createGLSLBuiltinRef("gl_Position");
+ globalVarExpr = createGLSLBuiltinRef("gl_Position", getVectorType(getFloatType(), 4));
}
}
else if (ns == "sv_clipdistance")
{
- globalVarExpr = createGLSLBuiltinRef("gl_ClipDistance");
+ globalVarExpr = createGLSLBuiltinRef("gl_ClipDistance", getUnsizedArrayType(getFloatType()));
}
else if (ns == "sv_culldistance")
{
- // TODO: ARB_cull_distance
- globalVarExpr = createGLSLBuiltinRef("gl_CullDistance");
+ requireGLSLExtension(shared->extensionUsageTracker, "ARB_cull_distance");
+ globalVarExpr = createGLSLBuiltinRef("gl_CullDistance", getUnsizedArrayType(getFloatType()));
}
else if (ns == "sv_coverage")
{
if (info.direction == VaryingParameterDirection::Input)
{
- globalVarExpr = createGLSLBuiltinRef("gl_SampleMaskIn");
+ globalVarExpr = createGLSLBuiltinRef("gl_SampleMaskIn", getUnsizedArrayType(getIntType()));
}
else
{
- globalVarExpr = createGLSLBuiltinRef("gl_SampleMask");
+ globalVarExpr = createGLSLBuiltinRef("gl_SampleMask", getUnsizedArrayType(getIntType()));
}
}
else if (ns == "sv_depth")
{
- globalVarExpr = createGLSLBuiltinRef("gl_FragDepth");
+ globalVarExpr = createGLSLBuiltinRef("gl_FragDepth", getFloatType());
}
else if (ns == "sv_depthgreaterequal")
{
// TODO: layout(depth_greater) out float gl_FragDepth;
- globalVarExpr = createGLSLBuiltinRef("gl_FragDepth");
+ globalVarExpr = createGLSLBuiltinRef("gl_FragDepth", getFloatType());
}
else if (ns == "sv_depthlessequal")
{
// TODO: layout(depth_less) out float gl_FragDepth;
- globalVarExpr = createGLSLBuiltinRef("gl_FragDepth");
+ globalVarExpr = createGLSLBuiltinRef("gl_FragDepth", getFloatType());
}
else if (ns == "sv_dispatchthreadid")
{
- globalVarExpr = createGLSLBuiltinRef("gl_GlobalInvocationID");
+ globalVarExpr = createGLSLBuiltinRef("gl_GlobalInvocationID", getVectorType(getUIntType(), 3));
}
else if (ns == "sv_domainlocation")
{
- globalVarExpr = createGLSLBuiltinRef("gl_TessCoord");
+ globalVarExpr = createGLSLBuiltinRef("gl_TessCoord", getVectorType(getFloatType(), 3));
}
else if (ns == "sv_groupid")
{
- globalVarExpr = createGLSLBuiltinRef("gl_WorkGroupID");
+ globalVarExpr = createGLSLBuiltinRef("gl_WorkGroupID", getVectorType(getUIntType(), 3));
}
else if (ns == "sv_groupindex")
{
- globalVarExpr = createGLSLBuiltinRef("gl_LocationInvocationIndex");
+ globalVarExpr = createGLSLBuiltinRef("gl_LocalInvocationIndex", getUIntType());
}
else if (ns == "sv_groupthreadid")
{
- globalVarExpr = createGLSLBuiltinRef("gl_LocalInvocationID");
+ globalVarExpr = createGLSLBuiltinRef("gl_LocalInvocationID", getVectorType(getUIntType(), 3));
}
else if (ns == "sv_gsinstanceid")
{
- globalVarExpr = createGLSLBuiltinRef("gl_InvocationID");
+ globalVarExpr = createGLSLBuiltinRef("gl_InvocationID", getIntType());
}
else if (ns == "sv_insidetessfactor")
{
- globalVarExpr = createGLSLBuiltinRef("gl_TessLevelInner");
+ globalVarExpr = createGLSLBuiltinRef("gl_TessLevelInner", getArrayType(getFloatType(), 2));
}
else if (ns == "sv_instanceid")
{
- globalVarExpr = createGLSLBuiltinRef("gl_InstanceIndex");
+ globalVarExpr = createGLSLBuiltinRef("gl_InstanceIndex", getIntType());
}
else if (ns == "sv_isfrontface")
{
- globalVarExpr = createGLSLBuiltinRef("gl_FrontFacing");
- }
- else if (ns == "sv_outputcontrolpointid")
- {
- globalVarExpr = createGLSLBuiltinRef("gl_InvocationID");
+ globalVarExpr = createGLSLBuiltinRef("gl_FrontFacing", getBoolType());
}
else if (ns == "sv_outputcontrolpointid")
{
- globalVarExpr = createGLSLBuiltinRef("gl_InvocationID");
+ globalVarExpr = createGLSLBuiltinRef("gl_InvocationID", getIntType());
}
else if (ns == "sv_primitiveid")
{
- globalVarExpr = createGLSLBuiltinRef("gl_PrimitiveID");
+ globalVarExpr = createGLSLBuiltinRef("gl_PrimitiveID", getIntType());
}
else if (ns == "sv_rendertargetarrayindex")
{
@@ -3104,28 +3462,61 @@ struct LoweringVisitor
{
requireGLSLVersion(ProfileVersion::GLSL_430);
}
- globalVarExpr = createGLSLBuiltinRef("gl_Layer");
+ globalVarExpr = createGLSLBuiltinRef("gl_Layer", getIntType());
}
else if (ns == "sv_sampleindex")
{
- globalVarExpr = createGLSLBuiltinRef("gl_SampleID");
+ setSampleRateFlag();
+ globalVarExpr = createGLSLBuiltinRef("gl_SampleID", getIntType());
}
else if (ns == "sv_stencilref")
{
- // TODO: ARB_shader_stencil_export
- globalVarExpr = createGLSLBuiltinRef("gl_SampleID");
+ requireGLSLExtension(shared->extensionUsageTracker, "ARB_shader_stencil_export");
+ globalVarExpr = createGLSLBuiltinRef("gl_FragStencilRef", getIntType());
}
else if (ns == "sv_tessfactor")
{
- globalVarExpr = createGLSLBuiltinRef("gl_TessLevelOuter");
+ globalVarExpr = createGLSLBuiltinRef("gl_TessLevelOuter", getArrayType(getFloatType(), 4));
}
else if (ns == "sv_vertexid")
{
- globalVarExpr = createGLSLBuiltinRef("gl_VertexIndex");
+ globalVarExpr = createGLSLBuiltinRef("gl_VertexIndex", getIntType());
}
else if (ns == "sv_viewportarrayindex")
{
- globalVarExpr = createGLSLBuiltinRef("gl_ViewportIndex");
+ globalVarExpr = createGLSLBuiltinRef("gl_ViewportIndex", getIntType());
+ }
+ else if (ns == "nv_x_right")
+ {
+ requireGLSLVersion(ProfileVersion::GLSL_450);
+ requireGLSLExtension(shared->extensionUsageTracker, "GL_NVX_multiview_per_view_attributes");
+
+ // The actual output in GLSL is:
+ //
+ // vec4 gl_PositionPerViewNV[];
+ //
+ // and is meant to support an arbitrary number of views,
+ // while the HLSL case just defines a second position
+ // output.
+ //
+ // For now we will hack this by:
+ // 1. Mapping an `NV_X_Right` output to `gl_PositionPerViewNV[1]`
+ // (that is, just one element of the output array)
+ // 2. Adding logic to copy the traditional `gl_Position` output
+ // over to `gl_PositionPerViewNV[0]`
+ //
+
+ globalVarExpr = createGLSLBuiltinRef("gl_PositionPerViewNV[1]",
+ getVectorType(getFloatType(), 4));
+
+ shared->requiresCopyGLPositionToPositionPerView = true;
+ }
+ else if (ns == "nv_viewport_mask")
+ {
+ requireGLSLVersion(ProfileVersion::GLSL_450);
+ requireGLSLExtension(shared->extensionUsageTracker, "GL_NVX_multiview_per_view_attributes");
+ globalVarExpr = createGLSLBuiltinRef("gl_ViewportMaskPerViewNV",
+ getUnsizedArrayType(getIntType()));
}
else
{
@@ -3193,6 +3584,7 @@ struct LoweringVisitor
RefPtr<VarExpressionSyntaxNode> globalVarRef = new VarExpressionSyntaxNode();
globalVarRef->Position = globalVarDecl->Position;
+ globalVarRef->Type.type = globalVarDecl->Type.type;
globalVarRef->declRef = makeDeclRef(globalVarDecl.Ptr());
globalVarRef->name = globalVarDecl->getName();
@@ -3451,7 +3843,7 @@ struct LoweringVisitor
paramPair.layout,
VaryingParameterDirection::Input);
- subVisitor.assign(paramPair.lowered, loweredExpr);
+ subVisitor.assignWithFixups(paramPair.lowered, loweredExpr);
}
}
@@ -3521,7 +3913,7 @@ struct LoweringVisitor
paramPair.layout,
VaryingParameterDirection::Output);
- subVisitor.assign(loweredExpr, paramPair.lowered);
+ subVisitor.assignWithFixups(loweredExpr, paramPair.lowered);
}
}
if (resultVarDecl)
@@ -3536,7 +3928,13 @@ struct LoweringVisitor
resultVarDecl->Type.type,
entryPointLayout->resultLayout);
- subVisitor.assign(loweredExpr, resultVarDecl);
+ subVisitor.assignWithFixups(loweredExpr, resultVarDecl);
+ }
+ if (shared->requiresCopyGLPositionToPositionPerView)
+ {
+ subVisitor.assign(
+ createSimpleVarExpr("gl_PositionPerViewNV[0]"),
+ createSimpleVarExpr("gl_Position"));
}
bodyStmt->body = subVisitor.stmtBeingBuilt;
@@ -3701,15 +4099,17 @@ bool isRewriteRequest(
LoweredEntryPoint lowerEntryPoint(
- EntryPointRequest* entryPoint,
- ProgramLayout* programLayout,
- CodeGenTarget target)
+ EntryPointRequest* entryPoint,
+ ProgramLayout* programLayout,
+ CodeGenTarget target,
+ ExtensionUsageTracker* extensionUsageTracker)
{
SharedLoweringContext sharedContext;
sharedContext.compileRequest = entryPoint->compileRequest;
sharedContext.entryPointRequest = entryPoint;
sharedContext.programLayout = programLayout;
sharedContext.target = target;
+ sharedContext.extensionUsageTracker = extensionUsageTracker;
auto translationUnit = entryPoint->getTranslationUnit();
diff --git a/source/slang/lower.h b/source/slang/lower.h
index c690ea025..688c1df8f 100644
--- a/source/slang/lower.h
+++ b/source/slang/lower.h
@@ -17,6 +17,8 @@ namespace Slang
class ProgramLayout;
class TranslationUnitRequest;
+ struct ExtensionUsageTracker;
+
struct LoweredEntryPoint
{
// The actual lowered entry point
@@ -31,8 +33,9 @@ namespace Slang
// Emit code for a single entry point, based on
// the input translation unit.
LoweredEntryPoint lowerEntryPoint(
- EntryPointRequest* entryPoint,
- ProgramLayout* programLayout,
- CodeGenTarget target);
+ EntryPointRequest* entryPoint,
+ ProgramLayout* programLayout,
+ CodeGenTarget target,
+ ExtensionUsageTracker* extensionUsageTracker);
}
#endif
diff --git a/source/slang/parameter-binding.cpp b/source/slang/parameter-binding.cpp
index 17c2bb193..2f2bbec05 100644
--- a/source/slang/parameter-binding.cpp
+++ b/source/slang/parameter-binding.cpp
@@ -1081,7 +1081,8 @@ static RefPtr<TypeLayout> processSimpleEntryPointParameter(
String sn = semanticName.ToLower();
RefPtr<TypeLayout> typeLayout = new TypeLayout();
- if (sn.StartsWith("sv_"))
+ if (sn.StartsWith("sv_")
+ || sn.StartsWith("nv_"))
{
// System-value semantic.
diff --git a/tests/nv-extensions/multi-view-per-view-attributes.slang b/tests/nv-extensions/multi-view-per-view-attributes.slang
new file mode 100644
index 000000000..ca398ba16
--- /dev/null
+++ b/tests/nv-extensions/multi-view-per-view-attributes.slang
@@ -0,0 +1,17 @@
+//TEST:CROSS_COMPILE: -profile vs_5_0 -entry main -target spirv-assembly
+
+struct VS_OUT
+{
+ float4 left : SV_Position;
+ float4 right : NV_X_RIGHT;
+ uint4 mask : NV_VIEWPORT_MASK;
+};
+
+VS_OUT main(float4 ll, float4 rr)
+{
+ VS_OUT res;
+ res.left = ll;
+ res.right = rr;
+ res.mask = 0x1;
+ return res;
+} \ No newline at end of file
diff --git a/tests/nv-extensions/multi-view-per-view-attributes.slang.glsl b/tests/nv-extensions/multi-view-per-view-attributes.slang.glsl
new file mode 100644
index 000000000..4e2609834
--- /dev/null
+++ b/tests/nv-extensions/multi-view-per-view-attributes.slang.glsl
@@ -0,0 +1,44 @@
+#version 450
+//TEST_IGNORE_FILE:
+
+#extension GL_NVX_multiview_per_view_attributes : require
+
+struct VS_OUT
+{
+ vec4 left;
+ vec4 right;
+ uvec4 mask;
+};
+
+VS_OUT main_(vec4 ll, vec4 rr)
+{
+ VS_OUT res;
+ res.left = ll;
+ res.right = rr;
+ res.mask = uvec4(0x1);
+ return res;
+}
+
+layout(location = 0)
+in vec4 SLANG_in_ll;
+
+layout(location = 1)
+in vec4 SLANG_in_rr;
+
+void main()
+{
+ vec4 ll = SLANG_in_ll;
+ vec4 rr = SLANG_in_rr;
+
+ VS_OUT main_result = main_(ll, rr);
+
+ uvec4 SLANG_tmp_0 = main_result.mask;
+
+ gl_Position = main_result.left;
+ gl_PositionPerViewNV[1] = main_result.right;
+ gl_ViewportMaskPerViewNV[0] = int(SLANG_tmp_0.x);
+ gl_ViewportMaskPerViewNV[1] = int(SLANG_tmp_0.y);
+ gl_ViewportMaskPerViewNV[2] = int(SLANG_tmp_0.z);
+ gl_ViewportMaskPerViewNV[3] = int(SLANG_tmp_0.w);
+ gl_PositionPerViewNV[0] = gl_Position;
+}