| Commit message (Collapse) | Author | Age |
| |
|
|
|
|
| |
- The old code was just doing `exit(1)` if glslang or `D3DCompile` failed, which is obviously unacceptable
- The new approach adds the output to the diagnostic buffer (or invokes the callback), and tracks the error count just like any other errors
|
| |
|
|
|
|
| |
- When assigning tuples `(a0, ...) = (b0, ...)` generate a tuple of assignments `(a0 = b0, ...)`
- Given an expression statement on a tuple `(a0, ...);` generate a sequence of statements `a0; ...`
|
| |
|
|
|
|
|
|
|
|
|
|
| |
- This really just checks two basic things:
1. Was there any global variable declared with `in` and `sample`?
2. Did any code encountered during lowering referenece `gl_SampleIndex`?
- This doesn't cover what HLSL could need, nor what we would need for cross-compilation. Consider it GLSL-specific for now.
- In order to generate the information with even a reasonable chance of being accurate (not giving a ton of false positives) I tried to integrate the checks into the lowering process (so they only see code that is referenced, one hopes).
- For this to work with my testing setup, I needed to make sure that lowering is always performed, prior to emitting reflection info
- This change broke several reflection tests, because they had been using code that wouldn't actually pass the downstream compiler. I checked in fixes for those.
|
| |
|
|
|
|
| |
- This also adds reflection API for querying:
- Entry point name
- Entry point parameter list
|
| |
|
|
|
|
| |
Fixes #75
In order to avoid cascaded errors, I went ahead and made the parser refuse to skip past a `}` in recovery mode. The problem with this is that we fail to make forward progress if we are stuck on a `}` (this happens if you have an extra `}` at the global scope.
|
| | |
|
| | |
|
| |
|
|
| |
- Don't try to extract the body layout for a field without a layout
|
| |\
| |
| | |
Improve reporting of GLSL `image*` types
|
| | |
| |
| |
| |
| |
| |
| | |
- Update stdlib so taht `image*` types have read-write access encoded in their type
- TODO: this isn't 100% right, since there are GLSL qualifiers that might override this
- Add a test case to verify that the reflection API reports `image*` parameters
|
| | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
- The basic idea is that during the "lowering" pass, some types (notably: aggregate types that contain resource variables) will get turned into "tuple" types, which are pseduo-types that aren't meant to survive lowering.
- An attempt to declare a variable with a tuple type expands into a tuple of declarations
- An attempt to reference such a tuple-ified variable leads to a tuple of expressions
- An attempt to extract a member from such a tuple expression will pick the appropriate sub-element
- Dereference a tuple by dereferencing the primary expression
- Expand a tuple in the argument list to a call into N arguments (by recursively flattening the tuple)
- Don't create tuple types when not generating GLSL
- Make sure to preserve the specialized type of a call expression through lowering, since emission of unchecked calls relies on that info.
- TODO: maybe the infix/prefix/postifx/select information should come in as a side-band? Should we have modifiers on expressions?
- Make sure to offset the layout for a nested field based on teh base offset of its parent variable, when generating declarations for nested fields
|
| |/
|
|
|
|
| |
Actually output SPIR-V/DXBC assembly as text, instead of binary.
This fixes a bunch of tests that were passing on accident, because nothing was producing output.
|
| |
|
|
| |
I haven't tried to be 100% exhaustie, but this should cover the main cases we are likely to encounter in library code.
|
| |
|
|
| |
This helps avoid the problem where we emit a function that does a `discard` and thus get a GLSL compilation failure in a vertex shader (that doesn't even call the function).
|
| |
|
|
| |
EntryPointResult/TranslationUnitResult, added helper functionality; Ensure null termination when printing raw data
|
| | |
|
| |
|
|
| |
The emit logic was checking for a missing decl, and then asking that same (missing) declaration for its name.
|
| |
|
|
| |
I forgot to include a trailing space.
|
| |
|
|
|
| |
This was mostly just a missing `typedef` in the Slang standard library code.
This should also cover `textureBuffer` and `samplerBuffer`.
|
| |
|
|
|
|
|
|
| |
- Try to handle `ErrorType` gracefully when computing type layouts
- When outputting a `TypeExp`, if the type part is errorneous (or missing), try to use the expression part
- Make sure to lower the expressions side of a `TypeExp` during lowering
|
| |
|
|
|
|
|
| |
I hadn't been lowering `SV_Position` outputs to `gl_Position`, and had somehow been relying on hidden driver behavior that I guess made things Just Work.
This change adds some infrastructure to handle `SV_` semantics during lowering of an entry point (currently only covering `SV_Position` and `SV_Target`, FWIW).
As a byproduct, this also means that a `VarLayout` stores semantic info, which could conceivably be exposed through reflection data now.
|
| |
|
|
|
|
| |
- Allow a code-generation target of `NONE` in order to suppress ordinary output in test cases where we don't care about the actual output (just pass/fail result)
- Add explicit `location` layout qualifiers to intermediate vertex-to-fragment variables in GLSL test cases for rendering, to work around apparent Intel driver bugs.
|
| |
|
|
|
|
|
|
|
| |
- Add GLSL mappings for more `Texture*` methods
- The annoying one here is `Texture*.Load()` because it doesn't take a sampler, but the GLSL equivalent needs one (while the SPIR-V does *not*). I've hacked this pretty seriously for now.
- Try to ensure that we add `uniform` to global declarations that need it in GLSL
- When outputting an `in` or `out` variable that might have been created from an `inout` shader parameter, filter the layout qualifiers that we output to only cover the appropriate resource kind.
|
| |
|
|
|
|
|
| |
If the user had a shader entry point with an `inout` parameter, we would end up lowering it to two GLSL global variables with the same name.
This change adds a `SLANG_in_` or `SLANG_out_` prefix to the two declarations.
Note: I haven't dealt with the issue that we end up printing two different `layout` qualifiers on such a variable...
|
| |
|
|
| |
The earier changes to add sequence statements and change how the `isBuildingStmt` logic in lowering works doesn't work for this logic, which assumes it can just set `isBuildingStmt` and be sure that decls will go into the right place.
|
| |
|
|
| |
The tricky bit here was that the `reflection-json` output format isn't really a code generation target like the others, and we need to be able to have multiple "targets" active to make sense of it. This needs cleaning-up.
|
| |
|
|
|
|
| |
- Expand most queries that handle `TextureType` to handle `TextureTypeBase`, in hopes that this covers most uses of `image*` types in Vulkan GLSL
- Adopt the quick fix from Falcor to return read-write access for shader-storage-block types. Something more comprehensive is probably needed if people want to do queries on these, since constant buffers should really be included, then.
|
| |
|
|
| |
Adding an explicit AST node for `(expr)` was a good change, but it broke constant folding because I forgot to handle it.
|
| |
|
|
|
|
|
|
|
|
|
|
| |
Code in Slang that is cross-compiled *might* introduce declarations that collide with language keywords that are reserved in the target.
This was previously being dealth with during final code emission, but the challenge there is that we want to allow user code that is being "rewritten" to use whatever identifiers it wants (they know better than us what is an error), and only apply renaming to our own code.
The approach here is to apply renaming during lowering - we validate each declaration to make sure its name is valid. Any expressions/types that refer to those declarations will automatically get emitted with the new name (while unchecked expressions will continue to be emitted with their existing name).
This isn't quite perfect, since we could in theory still rename a declaration in user code.
A more robust version down the line would try to determine if a declaration was nested inside code for the "rewriter."
Also note that this does *not* deal with any issues of name conflicts that might arise between modules. That would require a more complete and robust renaming pass, which seems tricky for me to pull off.
|
| |
|
|
|
|
|
| |
If the user doesn't use any `import` declarations, there is no reason to parse their code at all, so having the option of falling back to `UnparsedStmt` can potentially save us some headaches down the road.
The new rule now is that if you have the "no checking" flag on, *and* the parser hasn't yet seen any `import` declarations, then it still used `UnparsedStmt` to avoid touching function bodies.
Otherwise, I go ahead and parse function bodies, and assume I can rewrite any code I can semantically understand.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
HLSL has the bad scoping behavior for `for` loops, and we need to respect that.
But, we need to have correct scoping for GLSL, and we'd like it for Slang.
We also need to ensure that `for` loops written in a "correct" language get the correct behavior when emitted as HLSL.
There was already code to handle this in the emit pass, but it was unfortunately using an `isRewrite` flag to try to tell if the HLSL behavior was wanted.
This doesn't work when the code being emitted might come from a mix of languages.
This change adds a distinct `UnscopedForStmt` syntax node type, and uses that when parsing HLSL input (bot not for other languages).
We make sure to preserve this node type through lowering, and then specialize our emit logic on this case.
With this, there are no more remaining uses of `isRewrite` in the emit logic, which is good because it didn't mean what I needed it to mean any more (since we now emit only a single module, that was merged during lowering).
|
| |
|
|
|
|
| |
The old approach used an `isRewriter` flag in the emit logic, but I kind of need that flag to go away.
Instead, I now how the semantic checking pass detect whether an implicitly-generated type cast is in rewriter code, and if so it uses the new `HiddenImplicitCastExpr` AST node.
The emit logic then looks for that specific node and eliminates it.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
When emitting code it is easy to be overly defensive and emit tons of extra parentheses.
In some cases these are just annoying, and make the output more cluttered than it needs to be.
In other cases, though, being over-aggressive here can actually break things when a downstream compiler has more stringent requirements (e.g., doesn't allow a general expression for the function in a call expression, but only a particular set of atomic/postfix expressions).
This wasn't as bad when we weren't parsing function bodies in user code, but now that we *are* it becomes important to not emit bad parentheses and screw up their code. At the same time, though, we don't want to fail to output them and silently break code. A nice property today is that we preserve parentheses in the input code, so hopefully we don't ever break operator precedence.
The code already had an approach to avoid *some* parens, by tracking an "outer precedence" and only emitting parens for an expression if they were needed relative to this outer precedence. That approach doesn't handle associativity, and so it doesn't work for things like chains of postfix operators.
The new approach basically tracks *two* outer precedence levels: one on the left, and one on the right. When recursing into a sub-expression of an op (e.g., the `A` in `A + B`) on of the precdence levels for the recursive call will come from the outer environment, and the other from the operation itself (e.g., `A` has `(X, +)` as its left/right precdence, where `X` is whatever was to the left of `A + B`, while `B` gets `(+,Y)`).
One more piece of the puzzle is that an operator like `+` actually exposes *two* precedence levels: one for the left-hand side and one for the right-hand, so that if both `A` and `B` are themselves uses of `+`, `A` won't get parens, but `B` will.
Finally, when we have an un-checked application of an operator (which our AST stores as something like a function-call node), we do a little lookup step to find the corresponding operator and its precedence (while for things that actually got resolved we *know* the precedence.
|
| |
|
|
|
|
|
|
|
|
|
| |
This is in anticipation of needing to have more complete knowledge to be able to handle user code that `import`s library functionality.
The big picture of this change is just to remove the `UnparsedStmt` class that was used to hold the bodies of user functions as opaque token streams, and thus to let the full parser and compiler loose on that code. That is the easy part, of course, and the hard part is all the fixes that this requires in the rest of the compielr to make this even remotely work.
Subsequent commit address a lot of other issues, so this particular commit mostly represents work-in-progress.
One detail is that this change puts a conditional around nearly every diagnostic message in `check.cpp` to suppress thing when in rewriter mode.
I have yet to check how that works out if there are errors in anything we actually need to understand for the purposes of generating reflection data.
|
| |
|
|
| |
- Also fix a bug in `emit.cpp` where I wasn't detecting `__intrinsic` remaps that don't include `$` (this is a byproduct of changing the string index type to be unsigned; other bugs like this may be lurking)
|
| |
|
|
|
|
| |
- I really ought to make these semantically understood attributes, which might make this logic easier
- Long-term if we start emitting SPIR-V directly, we should translte these, of course
|
| |
|
|
|
|
|
|
|
|
|
| |
- Map HLSL `atan2(y,x)` to GLSL `atan(y,x)`
- Add support for `$p` escape in `__intrinsic` modifier, which allows generating GLSL texture-sampler pairs more easily
- Also added a `$o` escape to represent the base object in an OOP-style call (`obj.F(...)`)
- This isn't used in the texture functions right now, because getting the right GLSL texture type in this context is a bit thorny (the prefix depends on the generic parameter being used)
- Used the `$p` capability to add mappings for `SampleBias` and `SampleLevel`
|
| |
|
|
|
|
|
| |
- This is in preparation for splitting out HLSL vs. GLSL emit as different cases.
- Along the way, I added more cases to the visitor implementation, to handle visitors with arguments
- This is getting a bit busy, though, and we might be reaching the breaking point where a more general bit of meta-magic is needed to clean things up (either going further down the ugly template route, or plugging in a more real code generation strategy)
|
| |
|
|
|
|
|
|
|
|
| |
GLSL doesn't support `static` at all, while HLSL uses it for multiple things:
- To mark global variables that are "thread local" rather than shader parameters
- In the C/C++ style to mark `static` allocation for variables inside a function or type
The latter case needs to be handled during lowering (but isn't handled right now).
The former case can be solved just by dropping the `static` keyword.
|
| |
|
|
|
|
|
| |
GLSL doesn't support `typedef` declarations.
The lowering code already lowered any named types (references to `typedef`s) to their underlying definition when targetting GLSL.
This changes makes sure that we also don't generate any lowered output for `typedef` declarations in the source program.
|
| |
|
|
|
|
|
|
|
|
|
| |
The existing code used a catch-all `visit()` method, and then relied on overloading to find the right version (allowing fallback to a `visit()` method taking a base-class parameter).
This approach works, but has some big down-sides:
- When browsing the code, you have a bunch of identically-named methods, and it can be hard to find the one you want.
- It is impossible to use inheritance to implement fallback for `visit()` methods, because *any* method in the derived class with that name hides *all* methods with the same name in a base class
This change makes the `visit()` methods use the name of the corresponding syntax class, and then has visitors inherit the fallback methods they need from the base visitor template class.
|
| |
|
|
|
|
| |
Fixes #57
There were a bunch of issues in how `std430` was being implemented, largely due to just stubbing it in without any test cases. This commit adds a reasonably good test case to ensure that we've got things basically working.
|
| |
|
|
| |
These are mostly copy-pasted from the existing `cbuffer` support, so there might be details I'm missing.
|
| |
|
|
|
|
| |
Fixes #55
I was incorrectly computing alignment as `elementSize * elementAlignment`, rounded up to a power of two (which works out to be `elementSize` squared), when I should have been using `elementSize * elementCount`, rounded up to a power of two.
|
| |
|
|
| |
This logic hadn't been updated for Vulkan GLSL.
|
| | |
|
| |
|
|
| |
These were accidentally calling the version of `String::append()` that takes an `int` and prints its decimal value, rather than the version that takes a `char` and appends the corresponding ASCII character.
|
| |
|
|
|
|
| |
- Handle all statement cases explicitly (rather than falling back to the "structural recursion" mess)
- Handle back-references from child statements to their parents
|
| |
|
|
| |
Most of these are cases we don't expect to encounter, but the big missing one was `TypeDefDecl`.
|
| |
|
|
|
| |
The code should now compile cleanly with warnings as errors for VS2015 with `W3`.
Most of the changes had to do with propagating a real pointer-sized integer type through code that had been using `int`.
|