<feed xmlns='http://www.w3.org/2005/Atom'>
<title>slang.git/source/slang/lower.cpp, branch master</title>
<subtitle>Making it easier to work with shaders</subtitle>
<id>https://git.yummers.dev/slang.git/atom?h=master</id>
<link rel='self' href='https://git.yummers.dev/slang.git/atom?h=master'/>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/'/>
<updated>2017-11-28T00:33:28+00:00</updated>
<entry>
<title>Cleanups (#298)</title>
<updated>2017-11-28T00:33:28+00:00</updated>
<author>
<name>Tim Foley</name>
<email>tfoleyNV@users.noreply.github.com</email>
</author>
<published>2017-11-28T00:33:28+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=31993854b164fb6e19e449b7be550b1e48297ef5'/>
<id>urn:sha1:31993854b164fb6e19e449b7be550b1e48297ef5</id>
<content type='text'>
* Rename `lower.{h,cpp}` to `ast-legalize.{h,cpp}`

This pass isn't really performing lowering akin to `lower-to-ir.{h,cpp}` so the file name is misleading.
By renaming this pass we emphasize its role as an AST-related pass.

Also update the comment at the top of `ast-legalize.h` to reflect the intended purpose of this pass in a world where we have the IR up and running.

* Allow `import` as an alias for `__import`

The use of double underscores to mark our new syntax has so far had two purposes:

1. It helps identify syntax that isn't meant to be exposed to users in its current form (e.g., `__generic` gets a double underscore because we want users to have a more pleasant surface syntax for generics that they write). This rationale doesn't apply to `__import`, which is a major language feature that users need to interact with.

2. It helps avoid the problem where the compiler treats something as a keyword that isn't supposed to be reserved in HLSL/GLSL and so causes existing user code to fail to parse (e.g., when the user tries to write a function called `import`). This no longer matters because we look up almost all of our keywords using the existing lexical scoping in the language (so the user can shadow almost any keyword with a local declaration).

So, neither of the original two reasons applies to `__import`, and it makes sense to expose it as `import`.
Doing so is a one-line change.
</content>
</entry>
<entry>
<title>Add support for global generic parameters (#285)</title>
<updated>2017-11-18T02:26:21+00:00</updated>
<author>
<name>Yong He</name>
<email>yonghe@outlook.com</email>
</author>
<published>2017-11-18T02:26:21+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=54bf54bd0dda378f8400860b25855558f39cb52b'/>
<id>urn:sha1:54bf54bd0dda378f8400860b25855558f39cb52b</id>
<content type='text'>
* Add support for global generic parameters
(In-progress work)

This commit include:
1.  Update Slang API to allow specification of generic type arguments in an `EntryPointRequest`
2. Add parsing of `__generic_param` construct, which becomes a GlobalGenericParamDecl, contains members of `GenericTypeConstraintDecl`.
3. Semantics checking will check whether the provided type arguments conform to the interfaces as defined by the generic parameter, and store SubtypeWitness values in the EntryPointRequest, which will be used by `specializeIRForEntryPoint` when generating final IR.
4. Add a new type of substitution - `GlobalGenericParamSubstitution` for subsittuting references to `__generic_param` decls or to its member `GenericTypeConsraintDecl` with the actual type argument or witness tables.
5. Update `IRSpecContext` to apply `GlobalGenericParamSubstitution` when specializing the IR for an EntryPointRequest.
6. Update `render-test` to take additional `type` inputs, which specifies the type arguments to substitute into the global `__generic_param` types.

This commit does not include ProgramLayout specialization.

* IR: pass through `[unroll]` attribute (#284)

The initial lowering was adding an `IRLoopControlDecoration` to the instruction at the head of a loop, but this was getting dropped when the IR gets cloned for a particular entry point.
The fix was simply to add a case for loop-control decorations to `cloneDecoration`.

* fix warnings

* IR: support `CompileTimeForStmt` (#286)

This statement type is a bit of a hack, to support loops that *must* be unrolled.
The AST-to-AST pass handles them by cloning the AST for the loop body N times, and it was easy enough to do the same thing for the IR: emit the instructions for the body N times.
The only thing that requires a bit of care is that now we might see the same variable declarations multiple times, so we need to play it safe and overwrite existing entries in our map from declarations to their IR values.

Of course a better answer long-term would be to do the actual unrolling in the IR. This is especially true because we might some day want to support compile-time/must-unroll loops in functions, where the loop counter comes in as a parameter (but must still be compile-time-constant at every call site).

* Add support for global generic parameters
(In-progress work)

This commit include:
1.  Update Slang API to allow specification of generic type arguments in an `EntryPointRequest`
2. Add parsing of `__generic_param` construct, which becomes a GlobalGenericParamDecl, contains members of `GenericTypeConstraintDecl`.
3. Semantics checking will check whether the provided type arguments conform to the interfaces as defined by the generic parameter, and store SubtypeWitness values in the EntryPointRequest, which will be used by `specializeIRForEntryPoint` when generating final IR.
4. Add a new type of substitution - `GlobalGenericParamSubstitution` for subsittuting references to `__generic_param` decls or to its member `GenericTypeConsraintDecl` with the actual type argument or witness tables.
5. Update `IRSpecContext` to apply `GlobalGenericParamSubstitution` when specializing the IR for an EntryPointRequest.
6. Update `render-test` to take additional `type` inputs, which specifies the type arguments to substitute into the global `__generic_param` types.

progress on parameter binding

* Add a more contrived test case for specializing parameter bindings

* update render-test to align buffers to 256 bytes (to get rid of D3D complains on minimal buffer size).

* adding one more test case for parameter binding specialization.

* Cleanup according to @tfoleyNV 's suggestions.

* fix a bug introduced in the cleanup
</content>
</entry>
<entry>
<title>Revise type legalization so it can handle constant buffers (#282)</title>
<updated>2017-11-16T22:01:16+00:00</updated>
<author>
<name>Tim Foley</name>
<email>tfoleyNV@users.noreply.github.com</email>
</author>
<published>2017-11-16T22:01:16+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=871fbeec58caaa02ec990a676f10fa7014391a58'/>
<id>urn:sha1:871fbeec58caaa02ec990a676f10fa7014391a58</id>
<content type='text'>
* Revise type legalization so it can handle constant buffers

The existing legalization approach with "tuples" can handle scalarizing a `struct` type with resource-type fields in it, but it had several big gaps. The most notable is that given a type that mixes uniform and resource fields, we can't just blindly scalarize things:

```
struct P {
    float4 a;
    float4 b;
    Texture2D t;
};

cbuffer C
{
    P gParam[8];
};
```

The existing code was completely ignoring the declaration of `gParam` inside `C`, but even if we fixed that issue, we'd get something like:

```
cbuffer C
{
    float4 gParam_a[8];
    float4 gParam_b[8];
};
Texture2D gParam_t[8];
```

In this case we've completely changed the layout of the uniform buffer, by switching from AOS to SOA.
Even if we could get the type layout logic and the IR to agree on this, it would be a surprise to users, and "principle of least surprise" should be a big deal on a project with as many moving parts as ours.

The right thing to do is to have legalization create a "stripped" version of the original type `P` and use that:

```
struct P_stripped {
    float4 a;
    float4 b;
};
cbuffer C
{
    P_stripped gParam[8];
};
Texture2D gParam_t[8];
```

Then at a call site, this:

```
foo(gParam);
```

becomes:

```
foo(gParam, gParam_t);
```

This is exactly how the current AST-to-AST legalization handles mixed uniform and resource types, but the way it does it involves some annoying kludges:

- That pass has a notion of a "tuple" similar to our legalization, but every tuple has an optional "primary" entry for all the uniform data, plus tuple elements for the resources, and a given field may be represented on one side, the other, or both. It makes the code for handling tuples very messy.

- That pass does the "stripping" of types by actually marking up the AST declarations (this is okay because it is constructing a new AST as it goes), so that when they get emitted certain fields don't actually show up. That is, we fix the problem with type `P` by actually *modifying* the user's declaration of `P`. That seems out of bounds for the IR.

This change fixes the problem in our IR type legalization while trying to avoid the problems of the AST-to-AST pass by using two new ideas:

1. We add a new case for `LegalType` (and `LegalVal`) that is a "pair" type, where a pair consists of both an "ordinary" type (for uniform data) and a "special" type (for resource data). E.g., after legalization, the type for `C` (which can be over-simplified to `ConstantBuffer&lt;P&gt;` for our purposes), will be a `LegalType::pair` where the ordinary side is `ConstantBuffer&lt;P_stripped&gt;` and the special side is a tuple containing the `Texture2D` field.

2. We add a new (and annoyingly hacky) AST-level type called `FilteredTupleType` which is semantically a sort of tuple type (it holds a list of elements, and the elements have their own types), but which remembers an "original type" that it was created from, and for each element remembers the field of the original type that it corresponds to. This is used to construct a type like `P_stripped` as an actual AST-level structural type.

The core logic for legalizing an aggregate type had to get more complicated just because of the new pair case, so there is now a `TupleTypeBuilder` that asists with taking an aggregate type, processing its fields, and then picking the right `LegalType` representation for the result.

Other smaller changes:

- Made the legalization logic actually legalize `PtrType&lt;T&gt;`. E.g., if `T` legalizes to a tuple, we need to construct a tuple of pointer types. The same exact thing needs to be applied to arrays, and any other generic type that should "distribute over" pairs/tuples.

- Made the legalization logic actually legalize `ConstantBuffer&lt;T&gt;` and similar. The basic idea there is if `T` maps to a pair, we wrap `ConstantBuffer&lt;...&gt;` around the ordinary side, and `implicitDeref` around the special side.

- Removed a bunch of `#ifdef`ed-out code from the end of `ir-legalize-types.cpp`. That was code from my first attempt at legalization that failed miserably (trying to do it via local changes and a work list instead of a global rewrite pass), but it had some code I wanted to reference when writing the version that actually got checked in (should have deleted the code earlier, though).

- Added a bunch of cases for `LegalType::none` (and the `LegalVal` equivalent) that helped simplify the logic fo the `pair` case by allowing me to *always* dispatch to both the "ordinary" and "special" sides, even if they might not actually be present.

- Renamed `TupleType` and `TupleVal` over to `TuplePseudoType` and `TuplePseudoval` to recognize the fact that we might actually need/want *real* tuples in the type system, to go along with these fake ones (that need to be optimized away).

The biggest doubt I have about this change is the whole `FilteredTupleType` thing; it seems like an obviously contrived type to add to the front-end type system that really only solves IR-level problems. A cleaner approach might have been to just add a plain old `TupleType` to the front-end type system (and initially I started with that), and then have yet another `LegalType`/`LegalVal` case that handles mapping from the fields of the original type to the numbered tuple elements.

I expect we'll actually want to make that change in the future (especially if we ever add true tuples to the front-end), but for right now I let myself be swayed by the desire to have these stripped/filtered types get names that explain their provenance ("where they came from") to make our output code more debuggable. The way I've done it is probably overkill, though, and we need a much more complete effort on the readability and debuggability of our output before anything like that is worth worrying about.

* Fixup: typo

* Fixup: fix output of "non-mangled" names for test cases

- Make sure to attach high-level decls to variables created as part of type legalization
  - Also, try to share more of the code between the different cases of variables

- Fix up `parameter-blocks` test case that was passing `-no-mangle` but expecting mangled names in the output

- Fix up `multiple-parameter-blocks` to not rely on `-no-mangle` for now, because it would lead to two global variables with the same name (need to fix that underlying issue eventually).

- Also fix name generation logic so that we only use "original" names (from high-level decls) specifically when the `-no-mangle` flag is on, and otherwise use IR-level names.

* Fix: handle constant buffers better in render-test

- Don't request both CB and SRV usage for buffers, since that is illegal

- Also, don't try to create an SRV when user requested a CB (since the required usage flag won't be there)

- Record the input buffer type on the `D3DBinding` for a buffer, and use that to tell us when to bind a CB instead of SRV/UAV

- Fix expected output for `cbuffer-legalize` test now that we are actually feeding it correct cbuffer dta.
</content>
</entry>
<entry>
<title>Parameter block work (#276)</title>
<updated>2017-11-13T22:17:09+00:00</updated>
<author>
<name>Tim Foley</name>
<email>tfoleyNV@users.noreply.github.com</email>
</author>
<published>2017-11-13T22:17:09+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=c9d94248dc73fe41c344b0a23230e597f7b94a2c'/>
<id>urn:sha1:c9d94248dc73fe41c344b0a23230e597f7b94a2c</id>
<content type='text'>
* Don't auto-enable IR use for compute tests

The `COMPARE_COMPUTE` and `COMPARE_RENDER_COMPUTE` test fixtures were set up to always enable the `-use-ir` flag on Slang, which precludes having any tests that confirm functionality on the old non-IR path (which is still required by our main customer).

This change adds the `-xslang -use-ir` flags explicitly to any compute test cases that left them out, and makes the fixture no longer add it by default.

* Continue building out parameter block support

The initial front-end logic for parameter blocks was already added, but they are still missing a bunch of functionality. This change addresses some of the known issues:

- Bug fix: don't try to emit HLSL `register` bindings for variables that consume whole register spaces/sets

- Overhaul type layout logic so that it can make decisions based on a given code generation target (currently passed in as a `TargetRequest`), which allows us to decide whether or not a parameter block should get its own register set on a per-target basis.
  - Always use a register space/set for Vulkan
  - Never use a register space/set for HLSL SM 5.0 and lower
  - By default, don't use register spaces/sets for HLSL output
  - Add a command-line flag and some "target flags" to enable register-space usage for D3D targets

- Hackily add initial support for parameter blocks in the AST-to-AST path
  - This just blindly lowers `ParameterBlock&lt;T&gt;` to `T`, which shouldn't quite work
  - A more complete overhaul will probably need to wait until the AST-to-AST legalization is changed to use the `LegalType`s from the IR legalization pass.

- Add a compute-based test case to actually run code using parameter blocks
  - This file runs test cases both with and without the IR
</content>
</entry>
<entry>
<title>Parameter blocks (#245)</title>
<updated>2017-11-06T18:37:27+00:00</updated>
<author>
<name>Tim Foley</name>
<email>tfoleyNV@users.noreply.github.com</email>
</author>
<published>2017-11-06T18:37:27+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=9919c823938ae929b16efac9d507f6d5eb122bf4'/>
<id>urn:sha1:9919c823938ae929b16efac9d507f6d5eb122bf4</id>
<content type='text'>
* Rename existing ParameterBlock to ParameterGroup

We are planning to add a new `ParameterBlock&lt;T&gt;` type, which maps to the notion of a "parameter block" as used in the Spire research work.
Unfortunately, the compiler codebase already uses the term `ParameterBlock` as catch-all to encompass all of HLSL `cbuffer`/`tbuffer` and GLSL `uniform`/`buffer`/`in`/`out` blocks (all of which are lexical `{}`-enclosed blocks that define parameters...).

This change instead renames all of the existing concepts over to `ParameterGroup`, which isn't an ideal name, but at least doesn't directly overlap the new terminology or any existing terminology.

The new `ParameterBlockType` case will probably be a subclass of `ParameterGroupType`, since it is a logical extension of the underlying concept.

* Add Shader Model 5.1 profiles

The HLSL `register(..., space0)` syntax is only allowed on "SM5.1" and later profiles (which is supported by the newer version of `d3dcompiler_47.dll` that comes with the Win10 SDK, but not the older version of `d3dcompiler_47.dll` - good luck figuring out which you have!).

This change adds those profiles to our master list of profiles, and nothing else.

* First pass at support for `ParameterBlock&lt;T&gt;`

- Add the type declaration in stdlib

- Add a special case of `ParameterGroupType` for parameter blocks

- Handle parameter blocks in type layout (currently handling them identically to constant buffers for now, which isn't going to be right in the long term)

- Add an IR pass that basically replaces `ParameterBlock&lt;T&gt;` with `T`
  - Eventually this should replace it with either `T` or `ConstantBuffer&lt;T&gt;`, depending on whether the layout that was computed required a constant buffer to hold any "free" uniforms

- Add first stab at an IR pass to "scalarize" global variables using aggregate types with resources inside.
  - This currently only applies to global variables, so it won't handle things passed through functions, or used as local variables
  - It also only supports cases where the references to the original variable are always references to its fields, and not the whole value itself

- Add a single test case that technically passes with this level of support, but probably isn't very representative of what we need from the feature

* Fold parameter-block desugaring into a more complete "type legalization" pass

The basic problem that was arising is that once you desugar `ParameterBlock&lt;T&gt;` into `T`, you then need todeal with splitting `T` into its constituent fields if it contains any resource types.
Handling those transformations by following the usual use-def chains wasn't really helping, because you might need systematic rewriting that can really only be handled bottom-up.

This change adds a new pass that is intended to perform multiple kinds of type "legalization" at once:

- It will turn `ParameterBlock&lt;T&gt;` into `T`
  - It may at some point also convert `ConstantBuffer&lt;T&gt;` into `T` as well
- It will turn an value of an aggregate type that contains resources into N different values (one per field)
  - As a result of this, it will also deal with AOS-to-SOA conversion of these types

Legalization is applied to *every* function/instruction/value, so that it can make large-scale changes that would be tough to manage with a work list.

This pass needs to be run *after* generics have been fully specialized, so that we know we are always dealing with fully concrete types, so that their legalization for a given target is completely known.

This is still work in progress; there's more to be done to get this working with all our test cases, and finish the remaining `ParameterBlock&lt;T&gt;` work.

* Improve binding/layout information when using parameter blocks

- When doing type layout for a parameter block, don't include the resources consumed by the element type in the resource usage for the parameter block
  - Note that this is pretty much identical to how a `ConstantBuffer&lt;T&gt;` does not report any `LayoutResourceKind::Uniform` usage, except that `ParameterBlock&lt;T&gt;` is *also* going to hide underlying texture/sampler reigster usage
  - The one exception here is that any nested items that use up entire `space`s or `set`s those need to be exposed in the resource usage of the parent (I don't have a test for this)

- When type legalization needs to scalarize things, it must propagate layout information down to the new leaf variables. In general, the register/index for a new leaf parameter should be the sum of the offsets for all of the parent variables along the "chain" from the original variable down to the leaf (we aren't dealing with arrays here just yet).

- When type legalization decides to eliminate a pointer(-like) type (e.g., desugar `ParameterBlock&lt;T&gt;` over to `T`), actually deal with that in terms of the `LegalVal`s created, so that we can know to turn a `load` into a no-op when applied to a value that got indirection removed.

- Hack up the "complex" parameter-block test so that it actually passes (the big hack here is that the HLSL baseline is using names that are generated by the IR, and are unlikely to be stable as we add/remove transformations).
  - Note: I can't make these be compute tests right now, because regsiter spaces/sets are a feature of D3D12/Vulkan, and our test runner isn't using those APIs.
</content>
</entry>
<entry>
<title>cleanup useless code</title>
<updated>2017-11-04T23:19:23+00:00</updated>
<author>
<name>Yong He</name>
<email>yonghe@outlook.com</email>
</author>
<published>2017-11-04T23:19:23+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=33d9f07d6c86e80c44af4de0693532cee6635135'/>
<id>urn:sha1:33d9f07d6c86e80c44af4de0693532cee6635135</id>
<content type='text'>
</content>
</entry>
<entry>
<title>fix warnings</title>
<updated>2017-11-04T22:45:42+00:00</updated>
<author>
<name>Yong He</name>
<email>yonghe@outlook.com</email>
</author>
<published>2017-11-04T22:45:42+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=8c0a429c292ea6735ce1ac14c22125266e8fb6c5'/>
<id>urn:sha1:8c0a429c292ea6735ce1ac14c22125266e8fb6c5</id>
<content type='text'>
</content>
</entry>
<entry>
<title>merge</title>
<updated>2017-11-04T22:07:26+00:00</updated>
<author>
<name>Yong He</name>
<email>yonghe@outlook.com</email>
</author>
<published>2017-11-04T22:07:26+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=00e03825d80c4997fa35461d82ff267f721ae8a6'/>
<id>urn:sha1:00e03825d80c4997fa35461d82ff267f721ae8a6</id>
<content type='text'>
</content>
</entry>
<entry>
<title>merge with fixWarnings branch</title>
<updated>2017-11-04T22:07:09+00:00</updated>
<author>
<name>Yong He</name>
<email>yonghe@outlook.com</email>
</author>
<published>2017-11-04T22:07:09+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=d1009d1a5ac7463dc74169ed7c6e1e692b3541d7'/>
<id>urn:sha1:d1009d1a5ac7463dc74169ed7c6e1e692b3541d7</id>
<content type='text'>
</content>
</entry>
<entry>
<title>bug fix</title>
<updated>2017-11-04T20:54:44+00:00</updated>
<author>
<name>Yong He</name>
<email>yonghe@outlook.com</email>
</author>
<published>2017-11-04T20:54:44+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=cb0a5773cd3b3564c4a19b85aaddd3d9cc63a3c7'/>
<id>urn:sha1:cb0a5773cd3b3564c4a19b85aaddd3d9cc63a3c7</id>
<content type='text'>
</content>
</entry>
</feed>
