summaryrefslogtreecommitdiffstats
path: root/source/slang/emit.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/slang/emit.cpp')
-rw-r--r--source/slang/emit.cpp183
1 files changed, 160 insertions, 23 deletions
diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp
index 71ee31e5e..c8f3f06cb 100644
--- a/source/slang/emit.cpp
+++ b/source/slang/emit.cpp
@@ -2,6 +2,7 @@
#include "emit.h"
#include "lower.h"
+#include "lower-to-ir.h"
#include "name.h"
#include "syntax.h"
#include "type-layout.h"
@@ -47,6 +48,9 @@ struct SharedEmitContext
// The entry point we are being asked to compile
EntryPointRequest* entryPoint;
+ // The layout for the entry point
+ EntryPointLayout* entryPointLayout;
+
// The target language we want to generate code for
CodeGenTarget target;
@@ -519,7 +523,7 @@ struct EmitVisitor
emitRawText("\n#line ");
char buffer[16];
- sprintf(buffer, "%d", sourceLocation.line);
+ sprintf(buffer, "%llu", (unsigned long long)sourceLocation.line);
emitRawText(buffer);
emitRawText(" ");
@@ -679,7 +683,7 @@ struct EmitVisitor
// and how we do.
if(sourceLocation.column > context->shared->loc.column)
{
- int delta = sourceLocation.column - context->shared->loc.column;
+ Slang::Int delta = sourceLocation.column - context->shared->loc.column;
for( int ii = 0; ii < delta; ++ii )
{
emitRawText(" ");
@@ -2282,8 +2286,32 @@ struct EmitVisitor
emitName(expr->lookupResult2.getName());
}
+ void setSampleRateFlag()
+ {
+ context->shared->entryPointLayout->flags |= EntryPointLayout::Flag::usesAnySampleRateInput;
+ }
+
+ void doSampleRateInputCheck(VarDeclBase* decl)
+ {
+ if (decl->HasModifier<HLSLSampleModifier>())
+ {
+ setSampleRateFlag();
+ }
+ }
+
+ void doSampleRateInputCheck(Name* name)
+ {
+ auto text = getText(name);
+ if (text == "gl_SampleID")
+ {
+ setSampleRateFlag();
+ }
+ }
+
void visitVarExpr(VarExpr* varExpr, ExprEmitArg const& arg)
{
+ doSampleRateInputCheck(varExpr->name);
+
auto prec = kEOp_Atomic;
auto outerPrec = arg.outerPrec;
bool needClose = MaybeEmitParens(outerPrec, kEOp_Atomic);
@@ -2484,6 +2512,11 @@ struct EmitVisitor
Emit("{\n");
for( auto& token : stmt->tokens )
{
+ if (token.type == TokenType::Identifier)
+ {
+ doSampleRateInputCheck(token.getName());
+ }
+
emitTokenWithLocation(token);
}
Emit("}\n");
@@ -3559,6 +3592,15 @@ struct EmitVisitor
void visitVarDeclBase(RefPtr<VarDeclBase> decl, DeclEmitArg const& arg)
{
+ // Global variable? Check if it is a sample-rate input.
+ if (dynamic_cast<ModuleDecl*>(decl->ParentDecl))
+ {
+ if (decl->HasModifier<InModifier>())
+ {
+ doSampleRateInputCheck(decl);
+ }
+ }
+
// Skip fields that have been tuple-ified and don't contribute
// any fields of "ordinary" type.
if (auto tupleFieldMod = decl->FindModifier<TupleFieldModifier>())
@@ -3756,7 +3798,7 @@ struct EmitVisitor
void EmitDecl(RefPtr<Decl> decl)
{
- emitDeclImpl(decl, nullptr);
+emitDeclImpl(decl, nullptr);
}
void EmitDeclUsingLayout(RefPtr<Decl> decl, RefPtr<VarLayout> layout)
@@ -3770,9 +3812,9 @@ struct EmitVisitor
{
EmitDecl(decl);
}
- else if(auto declGroup = declBase.As<DeclGroup>())
+ else if( auto declGroup = declBase.As<DeclGroup>() )
{
- for(auto d : declGroup->decls)
+ for( auto d : declGroup->decls )
EmitDecl(d);
}
else
@@ -3782,6 +3824,29 @@ struct EmitVisitor
}
};
+
+EntryPointLayout* findEntryPointLayout(
+ ProgramLayout* programLayout,
+ EntryPointRequest* entryPointRequest)
+{
+ for( auto entryPointLayout : programLayout->entryPoints )
+ {
+ if(entryPointLayout->entryPoint->getName() != entryPointRequest->name)
+ continue;
+
+ if(entryPointLayout->profile != entryPointRequest->profile)
+ continue;
+
+ // TODO: can't easily filter on translation unit here...
+ // Ideally the `EntryPointRequest` should get filled in with a pointer
+ // the specific function declaration that represents the entry point.
+
+ return entryPointLayout.Ptr();
+ }
+
+ return nullptr;
+}
+
String emitEntryPoint(
EntryPointRequest* entryPoint,
ProgramLayout* programLayout,
@@ -3794,6 +3859,13 @@ String emitEntryPoint(
sharedContext.finalTarget = entryPoint->compileRequest->Target;
sharedContext.entryPoint = entryPoint;
+ if (entryPoint)
+ {
+ sharedContext.entryPointLayout = findEntryPointLayout(
+ programLayout,
+ entryPoint);
+ }
+
sharedContext.programLayout = programLayout;
// Layout information for the global scope is either an ordinary
@@ -3805,7 +3877,7 @@ String emitEntryPoint(
{
globalStructLayout = gs.Ptr();
}
- else if(auto globalConstantBufferLayout = globalScopeLayout.As<ParameterBlockTypeLayout>())
+ else if( auto globalConstantBufferLayout = globalScopeLayout.As<ParameterBlockTypeLayout>() )
{
// TODO: the `cbuffer` case really needs to be emitted very
// carefully, but that is beyond the scope of what a simple rewriter
@@ -3837,32 +3909,97 @@ String emitEntryPoint(
}
sharedContext.globalStructLayout = globalStructLayout;
+ auto translationUnitSyntax = translationUnit->SyntaxNode.Ptr();
+
EmitContext context;
context.shared = &sharedContext;
EmitVisitor visitor(&context);
- auto translationUnitSyntax = translationUnit->SyntaxNode.Ptr();
-
- // We perform lowering of the program before emitting *anything*,
- // 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, &sharedContext.extensionUsageTracker);
- sharedContext.program = lowered.program;
-
- // Note that we emit the main body code of the program *before*
- // we emit any leading preprocessor directives for GLSL.
- // This is to give the emit logic a change to make last-minute
- // adjustments like changing the required GLSL version.
+ // Depending on how the compiler was invoked, we may need to perform
+ // some amount of preocessing on the code before we can emit it.
+ //
+ // For our purposes, there are basically three different "modes" we
+ // care about:
+ //
+ // 1. "Full rewriter" mode, where the user provides HLSL/GLSL, and
+ // doesn't make use of any Slang code via `import`.
//
- // TODO: All such adjustments would be better handled during
- // lowering, but that requires having a semantic rather than
- // textual format for the HLSL->GLSL mapping.
- visitor.EmitDeclsInContainer(lowered.program.Ptr());
+ // 2. "Partial rewriter" mode, where the user starts with HLSL/GLSL,
+ // but also imports some Slang code, and may need us to rewrite
+ // their HLSL/GLSL function bodies to make things work.
+ //
+ // 3. "Full" mode, where all of the input code is in Slang (and/or
+ // the subset of HLSL we can fully type-check).
+ //
+ // We'll try to detect the cases here:
+ //
+#if 0
+ if(!(translationUnit->compileFlags & SLANG_COMPILE_FLAG_NO_CHECKING ))
+ {
+ // This seems to be case (3), because the user is asking for full
+ // checking, and so we can assume we understand the code fully.
+ //
+ // In this case we want to translate to our intermediate representation
+ // and do optimizations/transformations there before we emit final code.
+ //
+
+ auto lowered = lowerEntryPointToIR(entryPoint, programLayout, target);
+
+ dumpIR(lowered);
+
+ throw 99;
+
+ }
+ else if(translationUnit->compileRequest->loadedModulesList.Count() != 0)
+#else
+ if(!(translationUnit->compileFlags & SLANG_COMPILE_FLAG_NO_CHECKING )
+ || translationUnit->compileRequest->loadedModulesList.Count() != 0)
+#endif
+ {
+ // The user has `import`ed some Slang modules, and so we are in case (2)
+ //
+ // We need to apply a "rewriting" pass to the code the user wrote,
+ // and then emit the result.
+
+ // We perform lowering of the program before emitting *anything*,
+ // 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, &sharedContext.extensionUsageTracker);
+ sharedContext.program = lowered.program;
+
+ // Note that we emit the main body code of the program *before*
+ // we emit any leading preprocessor directives for GLSL.
+ // This is to give the emit logic a change to make last-minute
+ // adjustments like changing the required GLSL version.
+ //
+ // TODO: All such adjustments would be better handled during
+ // lowering, but that requires having a semantic rather than
+ // textual format for the HLSL->GLSL mapping.
+ visitor.EmitDeclsInContainer(lowered.program.Ptr());
+ }
+ else
+ {
+ // We are in case (1).
+ //
+ // We should be able to just emit the AST we parsed right back out,
+ // along with whatever annotations we added along the way.
+
+ sharedContext.program = translationUnitSyntax;
+ visitor.EmitDeclsInContainerUsingLayout(
+ translationUnitSyntax,
+ globalStructLayout);
+ }
+
String code = sharedContext.sb.ProduceString();
sharedContext.sb.Clear();
+ // Now that we've emitted the code for all the declaratiosn in the file,
+ // it is time to stich together the final output.
+
+
+
// There may be global-scope modifiers that we should emit now
visitor.emitGLSLPreprocessorDirectives(translationUnitSyntax);
String prefix = sharedContext.sb.ProduceString();