summaryrefslogtreecommitdiffstats
path: root/source/slang
diff options
context:
space:
mode:
Diffstat (limited to 'source/slang')
-rw-r--r--source/slang/compiler.cpp26
-rw-r--r--source/slang/emit.cpp16
-rw-r--r--source/slang/lower.cpp43
-rw-r--r--source/slang/reflection.cpp142
-rw-r--r--source/slang/type-layout.h6
5 files changed, 220 insertions, 13 deletions
diff --git a/source/slang/compiler.cpp b/source/slang/compiler.cpp
index 3155bb75a..7df978707 100644
--- a/source/slang/compiler.cpp
+++ b/source/slang/compiler.cpp
@@ -565,13 +565,31 @@ namespace Slang
void generateOutput(
CompileRequest* compileRequest)
{
- // Allow for an "extra" target to verride things first.
+ // Start of with per-translation-unit and per-entry-point lowering
+ for( auto translationUnit : compileRequest->translationUnits )
+ {
+ CompileResult translationUnitResult = emitTranslationUnit(translationUnit.Ptr());
+ translationUnit->result = translationUnitResult;
+ }
+
+
+ // Allow for an "extra" target to verride things before we finish.
switch (compileRequest->extraTarget)
{
case CodeGenTarget::ReflectionJSON:
{
String reflectionJSON = emitReflectionJSON(compileRequest->layout.Ptr());
+ // Clobber existing output so we don't have to deal with it
+ for( auto translationUnit : compileRequest->translationUnits )
+ {
+ translationUnit->result = CompileResult();
+ }
+ for( auto entryPoint : compileRequest->entryPoints )
+ {
+ entryPoint->result = CompileResult();
+ }
+
// HACK(tfoley): just print it out since that is what people probably expect.
// TODO: need a way to control where output gets routed across all possible targets.
fprintf(stdout, "%s", reflectionJSON.begin());
@@ -584,12 +602,6 @@ namespace Slang
break;
}
- // For most targets, we will do things per-translation-unit
- for( auto translationUnit : compileRequest->translationUnits )
- {
- CompileResult translationUnitResult = emitTranslationUnit(translationUnit.Ptr());
- translationUnit->result = translationUnitResult;
- }
}
}
diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp
index 0c39a98bd..03cc7d8aa 100644
--- a/source/slang/emit.cpp
+++ b/source/slang/emit.cpp
@@ -2833,7 +2833,10 @@ struct EmitVisitor
// Emit a single `regsiter` semantic, as appropriate for a given resource-type-specific layout info
void emitHLSLRegisterSemantic(
- VarLayout::ResourceInfo const& info)
+ VarLayout::ResourceInfo const& info,
+
+ // Keyword to use in the uniform case (`register` for globals, `packoffset` inside a `cbuffer`)
+ char const* uniformSemanticSpelling = "register")
{
if( info.kind == LayoutResourceKind::Uniform )
{
@@ -2845,7 +2848,9 @@ struct EmitVisitor
// units, and then a "component" within that register, based on 4-byte
// offsets from there. We cannot support more fine-grained offsets than that.
- Emit(": packoffset(c");
+ Emit(": ");
+ Emit(uniformSemanticSpelling);
+ Emit("(c");
// Size of a logical `c` register in bytes
auto registerSize = 16;
@@ -2907,7 +2912,8 @@ struct EmitVisitor
// Emit all the `register` semantics that are appropriate for a particular variable layout
void emitHLSLRegisterSemantics(
- RefPtr<VarLayout> layout)
+ RefPtr<VarLayout> layout,
+ char const* uniformSemanticSpelling = "register")
{
if (!layout) return;
@@ -2922,7 +2928,7 @@ struct EmitVisitor
for( auto rr : layout->resourceInfos )
{
- emitHLSLRegisterSemantic(rr);
+ emitHLSLRegisterSemantic(rr, uniformSemanticSpelling);
}
}
@@ -3026,7 +3032,7 @@ struct EmitVisitor
offsetResource.space += cbufferResource->space;
}
- emitHLSLRegisterSemantic(offsetResource);
+ emitHLSLRegisterSemantic(offsetResource, "packoffset");
}
Emit(";\n");
diff --git a/source/slang/lower.cpp b/source/slang/lower.cpp
index ecf23d9ed..02da47ccb 100644
--- a/source/slang/lower.cpp
+++ b/source/slang/lower.cpp
@@ -210,7 +210,8 @@ struct SharedLoweringContext
{
CompileRequest* compileRequest;
- ProgramLayout* programLayout;
+ ProgramLayout* programLayout;
+ EntryPointLayout* entryPointLayout;
// The target we are going to generate code for.
//
@@ -607,6 +608,8 @@ struct LoweringVisitor
RefPtr<ExpressionSyntaxNode> visitVarExpressionSyntaxNode(
VarExpressionSyntaxNode* expr)
{
+ doSampleRateInputCheck(expr->name);
+
// If the expression didn't get resolved, we can leave it as-is
if (!expr->declRef)
return expr;
@@ -1019,6 +1022,12 @@ struct LoweringVisitor
RefPtr<UnparsedStmt> loweredStmt = new UnparsedStmt();
lowerStmtFields(loweredStmt, stmt);
+ for (auto token : stmt->tokens)
+ {
+ if (token.Type == TokenType::Identifier)
+ doSampleRateInputCheck(token.Content);
+ }
+
loweredStmt->tokens = stmt->tokens;
addStmt(loweredStmt);
@@ -2052,9 +2061,39 @@ struct LoweringVisitor
return SourceLanguage::Unknown;
}
+ void setSampleRateFlag()
+ {
+ shared->entryPointLayout->flags |= EntryPointLayout::Flag::usesAnySampleRateInput;
+ }
+
+ void doSampleRateInputCheck(VarDeclBase* decl)
+ {
+ if (decl->HasModifier<HLSLSampleModifier>())
+ {
+ setSampleRateFlag();
+ }
+ }
+
+ void doSampleRateInputCheck(String const& name)
+ {
+ if (name == "gl_SampleIndex")
+ {
+ setSampleRateFlag();
+ }
+ }
+
RefPtr<VarDeclBase> visitVariable(
Variable* decl)
{
+ // Global variable? Check if it is a sample-rate input.
+ if (dynamic_cast<ProgramSyntaxNode*>(decl->ParentDecl))
+ {
+ if (decl->HasModifier<InModifier>())
+ {
+ doSampleRateInputCheck(decl);
+ }
+ }
+
auto loweredDecl = lowerVarDeclCommon(decl, getClass<Variable>());
if(!loweredDecl)
return nullptr;
@@ -2905,6 +2944,8 @@ LoweredEntryPoint lowerEntryPoint(
bool isRewrite = isRewriteRequest(translationUnit->sourceLanguage, target);
sharedContext.isRewrite = isRewrite;
+ sharedContext.entryPointLayout = visitor.findEntryPointLayout(entryPoint);
+
LoweredEntryPoint result;
if (isRewrite)
{
diff --git a/source/slang/reflection.cpp b/source/slang/reflection.cpp
index 08621d9a3..1beacc21b 100644
--- a/source/slang/reflection.cpp
+++ b/source/slang/reflection.cpp
@@ -651,8 +651,71 @@ SLANG_API unsigned spReflectionParameter_GetBindingSpace(SlangReflectionParamete
return 0;
}
+// Helpers for getting parameter count
+
+namespace Slang
+{
+ static unsigned getParameterCount(RefPtr<TypeLayout> typeLayout)
+ {
+ if(auto parameterBlockLayout = typeLayout.As<ParameterBlockTypeLayout>())
+ {
+ typeLayout = parameterBlockLayout->elementTypeLayout;
+ }
+
+ if(auto structLayout = typeLayout.As<StructTypeLayout>())
+ {
+ return (unsigned) structLayout->fields.Count();
+ }
+
+ return 0;
+ }
+
+ static VarLayout* getParameterByIndex(RefPtr<TypeLayout> typeLayout, unsigned index)
+ {
+ if(auto parameterBlockLayout = typeLayout.As<ParameterBlockTypeLayout>())
+ {
+ typeLayout = parameterBlockLayout->elementTypeLayout;
+ }
+
+ if(auto structLayout = typeLayout.As<StructTypeLayout>())
+ {
+ return structLayout->fields[index];
+ }
+
+ return 0;
+ }
+}
+
// Entry Point Reflection
+SLANG_API char const* spReflectionEntryPoint_getName(
+ SlangReflectionEntryPoint* inEntryPoint)
+{
+ auto entryPointLayout = convert(inEntryPoint);
+ if(!entryPointLayout) return 0;
+
+ return entryPointLayout->entryPoint->getName().begin();
+}
+
+SLANG_API unsigned spReflectionEntryPoint_getParameterCount(
+ SlangReflectionEntryPoint* inEntryPoint)
+{
+ auto entryPointLayout = convert(inEntryPoint);
+ if(!entryPointLayout) return 0;
+
+ return getParameterCount(entryPointLayout);
+}
+
+SLANG_API SlangReflectionVariableLayout* spReflectionEntryPoint_getParameterByIndex(
+ SlangReflectionEntryPoint* inEntryPoint,
+ unsigned index)
+{
+ auto entryPointLayout = convert(inEntryPoint);
+ if(!entryPointLayout) return 0;
+
+ return convert(getParameterByIndex(entryPointLayout, index));
+}
+
SLANG_API SlangStage spReflectionEntryPoint_getStage(SlangReflectionEntryPoint* inEntryPoint)
{
auto entryPointLayout = convert(inEntryPoint);
@@ -688,6 +751,18 @@ SLANG_API void spReflectionEntryPoint_getComputeThreadGroupSize(
}
}
+SLANG_API int spReflectionEntryPoint_usesAnySampleRateInput(
+ SlangReflectionEntryPoint* inEntryPoint)
+{
+ auto entryPointLayout = convert(inEntryPoint);
+ if(!entryPointLayout)
+ return 0;
+
+ if (entryPointLayout->profile.GetStage() != Stage::Fragment)
+ return 0;
+
+ return (entryPointLayout->flags & EntryPointLayout::Flag::usesAnySampleRateInput) != 0;
+}
// Shader Reflection
@@ -1395,6 +1470,54 @@ Range<T> range(T end)
return Range<T>(T(0), end);
}
+static void emitReflectionEntryPointJSON(
+ PrettyWriter& writer,
+ slang::EntryPointReflection* entryPoint)
+{
+ write(writer, "{\n");
+ indent(writer);
+
+ emitReflectionNameInfoJSON(writer, entryPoint->getName());
+
+ switch (entryPoint->getStage())
+ {
+ case SLANG_STAGE_VERTEX: write(writer, ",\n\"stage:\": \"vertex\""); break;
+ case SLANG_STAGE_HULL: write(writer, ",\n\"stage:\": \"hull\""); break;
+ case SLANG_STAGE_DOMAIN: write(writer, ",\n\"stage:\": \"domain\""); break;
+ case SLANG_STAGE_GEOMETRY: write(writer, ",\n\"stage:\": \"geometry\""); break;
+ case SLANG_STAGE_FRAGMENT: write(writer, ",\n\"stage:\": \"fragment\""); break;
+ case SLANG_STAGE_COMPUTE: write(writer, ",\n\"stage:\": \"compute\""); break;
+ default:
+ break;
+ }
+
+ auto parameterCount = entryPoint->getParameterCount();
+ if (parameterCount)
+ {
+ write(writer, ",\n\"parameters\": [\n");
+ indent(writer);
+
+ for( auto pp : range(parameterCount) )
+ {
+ if(pp != 0) write(writer, ",\n");
+
+ auto parameter = entryPoint->getParameterByIndex(pp);
+ emitReflectionParamJSON(writer, parameter);
+ }
+
+ dedent(writer);
+ write(writer, "\n]");
+ }
+
+ if (entryPoint->usesAnySampleRateInput())
+ {
+ write(writer, ",\n\"usesAnySampleRateInput\": true");
+ }
+
+ dedent(writer);
+ write(writer, "\n}");
+}
+
static void emitReflectionJSON(
PrettyWriter& writer,
slang::ShaderReflection* programReflection)
@@ -1415,6 +1538,25 @@ static void emitReflectionJSON(
dedent(writer);
write(writer, "\n]");
+
+ auto entryPointCount = programReflection->getEntryPointCount();
+ if (entryPointCount)
+ {
+ write(writer, ",\n\"entryPoints\": [\n");
+ indent(writer);
+
+ for (auto ee : range(entryPointCount))
+ {
+ if (ee != 0) write(writer, ",\n");
+
+ auto entryPoint = programReflection->getEntryPointByIndex(ee);
+ emitReflectionEntryPointJSON(writer, entryPoint);
+ }
+
+ dedent(writer);
+ write(writer, "\n]");
+ }
+
dedent(writer);
write(writer, "\n}\n");
}
diff --git a/source/slang/type-layout.h b/source/slang/type-layout.h
index 1a63a4883..add9930ae 100644
--- a/source/slang/type-layout.h
+++ b/source/slang/type-layout.h
@@ -352,6 +352,12 @@ public:
// Layout for any results of the entry point
RefPtr<VarLayout> resultLayout;
+
+ enum Flag : unsigned
+ {
+ usesAnySampleRateInput = 0x1,
+ };
+ unsigned flags = 0;
};
// Layout information for the global scope of a program