diff options
| author | Tim Foley <tfoleyNV@users.noreply.github.com> | 2018-03-19 12:45:23 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-03-19 12:45:23 -0700 |
| commit | 72562144254145612c68534c6b7457764c28acf5 (patch) | |
| tree | 1d33abbe3ccf6321b80e2870544b852395a4633c /source/slang/slang.cpp | |
| parent | 04c9476622cc22daa0994c8141f686405858c8a7 (diff) | |
Entry point attribute (#447)
* Typo
* Add [shader(...)] and clean up some literal handling
* Add supporting for validating the `[shader(...)]` attribute, by checking that its argument is a string literal that names a known shader stage.
* Split the `ConstantExpr` class into distinct subclasses rooted at `LiteralExpr`, so we have `BoolLiteralExpr`, `IntegerLiteralExpr`, `FloatingPointLiteralExpr`, and `StringLiteralExpr`
* Add a `String` type to the stdlib, to be used as the type of a string literal.
This change allows code using `[shader(...)]` to be accepted by the front-end again, but it does nothing about emitting it in final HLSL.
* Allow entry points to be specified via [shader(...)]
Before this change, the compiler would track a list of `EntryPointRequest` objects, based on what the suer specified via API and/or command-line options. Each entry point request would get matched up with an AST `FuncDecl` as part of semantic checking, and then the back end steps (layout, codegen, etc.) would work from that information.
This change makes the compiler modal, in that it can *either* continue to use an explicit list of entry point requests (this is the mode when the list is non-empty), or it can rely on user-supplied attributes on entry point functions to drive codegen (this is the mode when the list is empty).
User-specified `[shader(...)]` attributes are processed at the same place where the association from `EntryPointRequest`s to `FuncDecl`s would otherwise be made, and basically does the same thing in the opposite direction: looks for `FuncDecl`s with the appropriate attribute and synthesizes an `EntryPointRequest` for them.
Subsequent processing should ideally not know where a given `EntryPointRequest` came from, and should handle both methods of specifying the entry points equivalently.
One design choice that might not make immediate sense is that we do *not* process a function as an entry point (applying further validation, etc.) just because it has a `[shader(...)]` modifier, unless we are in the appropriate mode (which in this case is the mode where the user didn't specify their own entry points via API or command line). This is to handle cases where the user wants to explicitly compile only one entry point, so that they (1) don't want us to spend time validating code they don't care about, (2) don't want do get output they don't expect, and (3) might actually be presenting us with code that violates the language rules due to a combination of `#define`s in effect (e.g., they might have a `[shader("vertex")]` function that transitively executes a `discard` because of how the preprocessor was configured, but they don't care because they are compiling a fragment entry point). This decision might be something we revisit over time.
As part of this work, I had to add some logic to pick a "profile version" to use for a combination of a target and stage (because when you specify `[shader("vertex")]` the compiler can't tell if you want `vs_5_0`, `vs_5_1`, etc.). This isn't really complete right now, because something like `-target dxbc` *also* doesn't determine a profile, so there is a bit of a kludge at present. We need to figure out a good long-term plan here, which might involve keeping target format, feature level/version, and pipeline stage as truly orthogonal concepts, rather than conflating them. That would involve more work in the API and command-line layers to de-compose things when the user specifies, e.g., `vs_5_1`, but might make downstream logic easier to manage.
* Emit [shader(...)] attribute on entry point for SM 6.1 and later
This should help ensure that the output from Slang can be compiled with dxc `lib_*` profiles.
* Fix warning
Diffstat (limited to 'source/slang/slang.cpp')
| -rw-r--r-- | source/slang/slang.cpp | 53 |
1 files changed, 35 insertions, 18 deletions
diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp index 1d888dcb5..4fa6f5130 100644 --- a/source/slang/slang.cpp +++ b/source/slang/slang.cpp @@ -112,6 +112,38 @@ struct IncludeHandlerImpl : IncludeHandler } }; +// + + +Profile getEffectiveProfile(EntryPointRequest* entryPoint, TargetRequest* target) +{ + auto entryPointProfile = entryPoint->profile; + auto targetProfile = target->targetProfile; + + auto entryPointProfileVersion = entryPointProfile.GetVersion(); + auto targetProfileVersion = targetProfile.GetVersion(); + + // Default to the entry point profile, since we know that has the right stage. + Profile effectiveProfile = entryPointProfile; + + // Ignore the input from the target profile if it is missing. + if( targetProfile.getFamily() != ProfileFamily::Unknown ) + { + // If the target comes from a different profile family, *or* it is from + // the same family but has a greater version number, then use the target's version. + if( targetProfile.getFamily() != entryPointProfile.getFamily() + || (targetProfileVersion > entryPointProfileVersion) ) + { + effectiveProfile.setVersion(targetProfileVersion); + } + } + + return effectiveProfile; +} + + +// + CompileRequest::CompileRequest(Session* session) : mSession(session) { @@ -224,7 +256,7 @@ void CompileRequest::parseTranslationUnit( } } -void validateEntryPoint(EntryPointRequest*); +void validateEntryPoints(CompileRequest*); void CompileRequest::checkAllTranslationUnits() { @@ -235,23 +267,8 @@ void CompileRequest::checkAllTranslationUnits() checkTranslationUnit(translationUnit.Ptr()); } - for (auto& translationUnit : translationUnits) - { - // Next, do follow-up validation on any entry - // points that the user declared via API or - // command line, to ensure that they meet - // requirements. - // - // Note: We may eventually have syntax to - // identify entry points via a modifier on - // declarations, and in this case they should - // probably get validated as part of orindary - // checking above. - for (auto entryPoint : translationUnit->entryPoints) - { - validateEntryPoint(entryPoint); - } - } + // Next, do follow-up validation on any entry points. + validateEntryPoints(this); } void CompileRequest::generateIR() |
