diff options
Diffstat (limited to 'source/slang')
| -rw-r--r-- | source/slang/compiler.cpp | 26 | ||||
| -rw-r--r-- | source/slang/emit.cpp | 16 | ||||
| -rw-r--r-- | source/slang/lower.cpp | 43 | ||||
| -rw-r--r-- | source/slang/reflection.cpp | 142 | ||||
| -rw-r--r-- | source/slang/type-layout.h | 6 |
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 |
