summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--source/slang/lower.cpp93
-rw-r--r--source/slang/parameter-binding.cpp53
-rw-r--r--source/slang/type-layout.h4
3 files changed, 113 insertions, 37 deletions
diff --git a/source/slang/lower.cpp b/source/slang/lower.cpp
index 023c63591..165812fae 100644
--- a/source/slang/lower.cpp
+++ b/source/slang/lower.cpp
@@ -1545,38 +1545,93 @@ struct LoweringVisitor
type = arrayType;
}
- // TODO: if we are declaring an SOA-ized array,
- // this is where those array dimensions would need
- // to be tacked on.
+ // 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.
+ RefPtr<ExpressionSyntaxNode> globalVarExpr;
+
+ // Handle system-value inputs/outputs
+ assert(varLayout);
+ auto systemValueSemantic = varLayout->systemValueSemantic;
+ if (systemValueSemantic.Length() != 0)
+ {
+ auto ns = systemValueSemantic.ToLower();
- RefPtr<Variable> globalVarDecl = new Variable();
- globalVarDecl->Name.Content = info.name;
- globalVarDecl->Type.type = type;
+ if (ns == "sv_target")
+ {
+ // Note: we do *not* need to generate some kind of `gl_`
+ // builtin for fragment-shader outputs: they are just
+ // ordinary `out` variables, with ordinary `location`s,
+ // as far as GLSL is concerned.
+ }
+ else if (ns == "sv_position")
+ {
+ RefPtr<VarExpressionSyntaxNode> globalVarRef = new VarExpressionSyntaxNode();
+ globalVarRef->name = "gl_Position";
+ globalVarExpr = globalVarRef;
+ }
+ else
+ {
+ assert(!"unhandled");
+ }
+ }
- ensureDeclHasAValidName(globalVarDecl);
+ // If we didn't match some kind of builtin input/output,
+ // then declare a user input/output variable instead
+ if (!globalVarExpr)
+ {
+ RefPtr<Variable> globalVarDecl = new Variable();
+ globalVarDecl->Name.Content = info.name;
+ globalVarDecl->Type.type = type;
- addMember(shared->loweredProgram, globalVarDecl);
+ ensureDeclHasAValidName(globalVarDecl);
- // Add the layout information
- RefPtr<ComputedLayoutModifier> modifier = new ComputedLayoutModifier();
- modifier->layout = varLayout;
- addModifier(globalVarDecl, modifier);
+ addMember(shared->loweredProgram, globalVarDecl);
- // Need to generate an assignment in the right direction.
+ // Add the layout information
+ RefPtr<ComputedLayoutModifier> modifier = new ComputedLayoutModifier();
+ modifier->layout = varLayout;
+ addModifier(globalVarDecl, modifier);
+
+ // Add appropriate in/out modifier
+ switch (info.direction)
+ {
+ case VaryingParameterDirection::Input:
+ addModifier(globalVarDecl, new InModifier());
+ break;
+
+ case VaryingParameterDirection::Output:
+ addModifier(globalVarDecl, new OutModifier());
+ break;
+ }
+
+
+ RefPtr<VarExpressionSyntaxNode> globalVarRef = new VarExpressionSyntaxNode();
+ globalVarRef->Position = globalVarDecl->Position;
+ globalVarRef->declRef = makeDeclRef(globalVarDecl.Ptr());
+ globalVarRef->name = globalVarDecl->getName();
+
+ globalVarExpr = globalVarRef;
+ }
+
+ // TODO: if we are declaring an SOA-ized array,
+ // this is where those array dimensions would need
+ // to be tacked on.
//
- // TODO: for now I am just dealing with input:
+ // That is, this logic should be getting collected into a loop,
+ // and so we need to have a loop variable we can use to
+ // index into the two different expressions.
+
+ // Need to generate an assignment in the right direction.
switch (info.direction)
{
case VaryingParameterDirection::Input:
- addModifier(globalVarDecl, new InModifier());
- assign(varExpr, globalVarDecl);
+ assign(varExpr, globalVarExpr);
break;
case VaryingParameterDirection::Output:
- addModifier(globalVarDecl, new OutModifier());
-
- assign(globalVarDecl, varExpr);
+ assign(globalVarExpr, varExpr);
break;
}
}
diff --git a/source/slang/parameter-binding.cpp b/source/slang/parameter-binding.cpp
index ec611f8b1..0683c7f8c 100644
--- a/source/slang/parameter-binding.cpp
+++ b/source/slang/parameter-binding.cpp
@@ -788,6 +788,7 @@ static RefPtr<TypeLayout> processSimpleEntryPointParameter(
ParameterBindingContext* context,
RefPtr<ExpressionType> type,
EntryPointParameterState const& inState,
+ RefPtr<VarLayout> varLayout,
int semanticSlotCount = 1)
{
EntryPointParameterState state = inState;
@@ -817,6 +818,13 @@ static RefPtr<TypeLayout> processSimpleEntryPointParameter(
}
}
+ // Remember the system-value semantic so that we can query it later
+ if (varLayout)
+ {
+ varLayout->systemValueSemantic = semanticName;
+ varLayout->systemValueSemanticIndex = semanticIndex;
+ }
+
// TODO: add some kind of usage information for system input/output
}
else
@@ -847,13 +855,15 @@ static RefPtr<TypeLayout> processSimpleEntryPointParameter(
static RefPtr<TypeLayout> processEntryPointParameter(
ParameterBindingContext* context,
RefPtr<ExpressionType> type,
- EntryPointParameterState const& state);
+ EntryPointParameterState const& state,
+ RefPtr<VarLayout> varLayout);
static RefPtr<TypeLayout> processEntryPointParameterWithPossibleSemantic(
ParameterBindingContext* context,
Decl* declForSemantic,
RefPtr<ExpressionType> type,
- EntryPointParameterState const& state)
+ EntryPointParameterState const& state,
+ RefPtr<VarLayout> varLayout)
{
// If there is no explicit semantic already in effect, *and* we find an explicit
// semantic on the associated declaration, then we'll use it.
@@ -868,7 +878,7 @@ static RefPtr<TypeLayout> processEntryPointParameterWithPossibleSemantic(
subState.optSemanticName = &semanticInfo.name;
subState.ioSemanticIndex = &semanticIndex;
- processEntryPointParameter(context, type, subState);
+ processEntryPointParameter(context, type, subState, varLayout);
}
}
@@ -876,29 +886,30 @@ static RefPtr<TypeLayout> processEntryPointParameterWithPossibleSemantic(
// *or* we couldn't find an explicit semantic to apply on the given
// declaration, so we will just recursive with whatever we have at
// the moment.
- return processEntryPointParameter(context, type, state);
+ return processEntryPointParameter(context, type, state, varLayout);
}
static RefPtr<TypeLayout> processEntryPointParameter(
ParameterBindingContext* context,
RefPtr<ExpressionType> type,
- EntryPointParameterState const& state)
+ EntryPointParameterState const& state,
+ RefPtr<VarLayout> varLayout)
{
// Scalar and vector types are treated as outputs directly
if(auto basicType = type->As<BasicExpressionType>())
{
- return processSimpleEntryPointParameter(context, basicType, state);
+ return processSimpleEntryPointParameter(context, basicType, state, varLayout);
}
else if(auto vectorType = type->As<VectorExpressionType>())
{
- return processSimpleEntryPointParameter(context, vectorType, state);
+ return processSimpleEntryPointParameter(context, vectorType, state, varLayout);
}
// A matrix is processed as if it was an array of rows
else if( auto matrixType = type->As<MatrixExpressionType>() )
{
auto rowCount = GetIntVal(matrixType->getRowCount());
- return processSimpleEntryPointParameter(context, matrixType, state, (int) rowCount);
+ return processSimpleEntryPointParameter(context, matrixType, state, varLayout, (int) rowCount);
}
else if( auto arrayType = type->As<ArrayExpressionType>() )
{
@@ -908,13 +919,13 @@ static RefPtr<TypeLayout> processEntryPointParameter(
auto elementCount = (UInt) GetIntVal(arrayType->ArrayLength);
// We use the first element to derive the layout for the element type
- auto elementTypeLayout = processEntryPointParameter(context, arrayType->BaseType, state);
+ auto elementTypeLayout = processEntryPointParameter(context, arrayType->BaseType, state, varLayout);
// We still walk over subsequent elements to make sure they consume resources
// as needed
for( UInt ii = 1; ii < elementCount; ++ii )
{
- processEntryPointParameter(context, arrayType->BaseType, state);
+ processEntryPointParameter(context, arrayType->BaseType, state, nullptr);
}
RefPtr<ArrayTypeLayout> arrayTypeLayout = new ArrayTypeLayout();
@@ -946,14 +957,16 @@ static RefPtr<TypeLayout> processEntryPointParameter(
// Need to recursively walk the fields of the structure now...
for( auto field : GetFields(structDeclRef) )
{
+ RefPtr<VarLayout> fieldVarLayout = new VarLayout();
+ fieldVarLayout->varDecl = field;
+
auto fieldTypeLayout = processEntryPointParameterWithPossibleSemantic(
context,
field.getDecl(),
GetType(field),
- state);
+ state,
+ fieldVarLayout);
- RefPtr<VarLayout> fieldVarLayout = new VarLayout();
- fieldVarLayout->varDecl = field;
fieldVarLayout->typeLayout = fieldTypeLayout;
for (auto rr : fieldTypeLayout->resourceInfos)
@@ -1062,14 +1075,16 @@ static void collectEntryPointParameters(
state.directionMask |= kEntryPointParameterDirection_Output;
}
+ RefPtr<VarLayout> paramVarLayout = new VarLayout();
+ paramVarLayout->varDecl = makeDeclRef(paramDecl.Ptr());
+
auto paramTypeLayout = processEntryPointParameterWithPossibleSemantic(
context,
paramDecl.Ptr(),
paramDecl->Type.type,
- state);
+ state,
+ paramVarLayout);
- RefPtr<VarLayout> paramVarLayout = new VarLayout();
- paramVarLayout->varDecl = makeDeclRef(paramDecl.Ptr());
paramVarLayout->typeLayout = paramTypeLayout;
for (auto rr : paramTypeLayout->resourceInfos)
@@ -1089,13 +1104,15 @@ static void collectEntryPointParameters(
{
state.directionMask = kEntryPointParameterDirection_Output;
+ RefPtr<VarLayout> resultLayout = new VarLayout();
+
auto resultTypeLayout = processEntryPointParameterWithPossibleSemantic(
context,
entryPointFuncDecl,
resultType,
- state);
+ state,
+ resultLayout);
- RefPtr<VarLayout> resultLayout = new VarLayout();
resultLayout->typeLayout = resultTypeLayout;
for (auto rr : resultTypeLayout->resourceInfos)
diff --git a/source/slang/type-layout.h b/source/slang/type-layout.h
index 3ee12656c..262a8c3b1 100644
--- a/source/slang/type-layout.h
+++ b/source/slang/type-layout.h
@@ -237,6 +237,10 @@ public:
// Additional flags
VarLayoutFlags flags = 0;
+ // System-value semantic (and index) if this is a system value
+ String systemValueSemantic;
+ int systemValueSemanticIndex;
+
// The start register(s) for any resources
struct ResourceInfo
{