<feed xmlns='http://www.w3.org/2005/Atom'>
<title>slang.git/source/slang/slang-hlsl-intrinsic-set.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>2023-02-17T00:44:04+00:00</updated>
<entry>
<title>Remove `SharedIRBuilder`. (#2657)</title>
<updated>2023-02-17T00:44:04+00:00</updated>
<author>
<name>Yong He</name>
<email>yonghe@outlook.com</email>
</author>
<published>2023-02-17T00:44:04+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=245466d89cfe54b78da486f06d470bc6daaf4625'/>
<id>urn:sha1:245466d89cfe54b78da486f06d470bc6daaf4625</id>
<content type='text'>
Co-authored-by: Yong He &lt;yhe@nvidia.com&gt;</content>
</entry>
<entry>
<title>Overhaul global inst deduplication and cpp/cuda backend. (#2654)</title>
<updated>2023-02-16T21:55:32+00:00</updated>
<author>
<name>Yong He</name>
<email>yonghe@outlook.com</email>
</author>
<published>2023-02-16T21:55:32+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=4c4826d47eeef4675daae4ae53ff76f4d5ebd84a'/>
<id>urn:sha1:4c4826d47eeef4675daae4ae53ff76f4d5ebd84a</id>
<content type='text'>
* Overhaul global inst deduplication and cpp/cuda backend.

* Update IR documentation.

---------

Co-authored-by: Yong He &lt;yhe@nvidia.com&gt;</content>
</entry>
<entry>
<title>Rename IR opcodes to unify style. (#2556)</title>
<updated>2022-12-07T21:42:48+00:00</updated>
<author>
<name>Yong He</name>
<email>yonghe@outlook.com</email>
</author>
<published>2022-12-07T21:42:48+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=53e891eb28ceac5f956399c65f2ae27d37f3d724'/>
<id>urn:sha1:53e891eb28ceac5f956399c65f2ae27d37f3d724</id>
<content type='text'>
Co-authored-by: Yong He &lt;yhe@nvidia.com&gt;</content>
</entry>
<entry>
<title>Remove `construct` IR op. (#2555)</title>
<updated>2022-12-07T20:52:20+00:00</updated>
<author>
<name>Yong He</name>
<email>yonghe@outlook.com</email>
</author>
<published>2022-12-07T20:52:20+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=70714705747f3491c55e14b74f87641010351d6c'/>
<id>urn:sha1:70714705747f3491c55e14b74f87641010351d6c</id>
<content type='text'>
Co-authored-by: Yong He &lt;yhe@nvidia.com&gt;</content>
</entry>
<entry>
<title>Lower-to-ir no longer produce `Construct` inst. (#2553)</title>
<updated>2022-12-07T20:02:30+00:00</updated>
<author>
<name>Yong He</name>
<email>yonghe@outlook.com</email>
</author>
<published>2022-12-07T20:02:30+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=3a3a8b5f7701109fc413f42692c4de5769870489'/>
<id>urn:sha1:3a3a8b5f7701109fc413f42692c4de5769870489</id>
<content type='text'>
Co-authored-by: Yong He &lt;yhe@nvidia.com&gt;</content>
</entry>
<entry>
<title>Clean up void returns. (#2260)</title>
<updated>2022-06-02T05:29:10+00:00</updated>
<author>
<name>Yong He</name>
<email>yonghe@outlook.com</email>
</author>
<published>2022-06-02T05:29:10+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=bc6bc56db51d06b92dc63ef9c9e0def6c9760c9e'/>
<id>urn:sha1:bc6bc56db51d06b92dc63ef9c9e0def6c9760c9e</id>
<content type='text'>
* Clean up `IRReturnVoid`.

* Update gitignore.

Co-authored-by: Yong He &lt;yhe@nvidia.com&gt;</content>
</entry>
<entry>
<title>Add an accessor for IRInst opcode (#1707)</title>
<updated>2021-02-16T19:48:21+00:00</updated>
<author>
<name>Tim Foley</name>
<email>tfoleyNV@users.noreply.github.com</email>
</author>
<published>2021-02-16T19:48:21+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=e474c4e3aadc22a1b9f9b006104409f10936244f'/>
<id>urn:sha1:e474c4e3aadc22a1b9f9b006104409f10936244f</id>
<content type='text'>
* Add an accessor for IRInst opcode

This main changing is renaming `IRInst::op` over to `IRInst::m_op` and then adds an accessor `IRInst::getOp()` to read it. The rest of the changes are just changing use sites to `getOp` (or to `m_op` in the limited cases where we write to it).

This work is in anticipation of a future change that might need to store an extra bit in the same field as the opcode. It seemed better to do this massive refactoring as a separate PR.

* fixup</content>
</entry>
<entry>
<title>Add first steps toward a "capability" system (#1636)</title>
<updated>2020-12-11T16:50:43+00:00</updated>
<author>
<name>Tim Foley</name>
<email>tfoleyNV@users.noreply.github.com</email>
</author>
<published>2020-12-11T16:50:43+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=992778e25c444932921ce92fe7934893b2aca35f'/>
<id>urn:sha1:992778e25c444932921ce92fe7934893b2aca35f</id>
<content type='text'>
* Add first steps toward a "capability" system

We already have cases in the stdlib where we mark declarations as being specific to certain targets, e.g.:

```
// My ordinary function to add two numbers.
// Works everywhere.
//
void myFunc(int a, int b) { return a + b; }

// On the "coolgpu" target, we can use a secret intrinsic
// that adds numbers even faster!
//
__specialized_for_target(coolgpu)
void myFunc(int a, int b) { return __secretIntrinsic(a, b); }
```

The existing logic for dealing with these modifiers (`__specialized_for_target` and `__target_intrinsic`) was almost entirely string-based. We would turn the chosen compilation target into a string, and then use that to try and search for the "best" definition of a function at a few steps:

* During IR linking, we always pick one definition of an `[import]`ed function, and that definition will be the one with the "best" target-specialization modifier (if any)

* During final code generation, we always look up the "best" target-intrinsic modifier, and use it as the template for the code we output.

This change preserves the basic flow there, but replaces the ad hoc string-based logic with something a bit more principled, in terms of a new `CapabilitySet` type.

A `CapabilitySet` represents a set of zero or more atomic features (here represented as `CapabilityAtom`s). What a `CapabilitySet` means depends on how and where it is used:

* A compilation target implies a `CapabilitySet` where the contents of the set are the features the target *supports*.

* A `CapabilitySet` attached to a declaration (or a modifier on that declaration) describes a set of feature that declaration *requires*.

The current implementation of `CapabilitySet` is wasteful and inefficient, but that is something we can iterate on over time.

In practice, most of the current code only ever uses capability sets that are either empty (because they represent a function with no specific requirements) or singleton (because they represent asingle atomic capability like "is a GLSL target," "is an HLSL target," etc.).

The main goal here was to put in the skeleton of a new system, including some of the features it might need down the line, and then to leave changes that eventually use the greater flexibility for later. Eventually, the capability system should encompass:

* Differences between shader model versions, GLSL versions, SPIR-V versions, etc. (currently tracked with other modifiers)

* Optional extensions, and functions that are made available only with certain extensions (currently tracked with other modifiers)

* Front-end checking that the call graph of a program doesn't violate any capability-requirements (e.g., having a GLSL+HLSL portable function call a GLSL-only subroutine)

* Hypothetically we can also try to fold stage-specific (vertex-only, fragment-only, etc.) functions into this system, but doing so would require more linker cleverness if we allow overloading on stages (since we might have to clone a caller if it calls through to a callee with multiple stage-specific versions)

One important complication that the system has to deal with just because of the "do what I mean" nature of the current compiler is that somethings a current Slang user might compile for target X and specify version N, but then use a function that actually requires version N+1 of that target. Currently the Slang compiler silently "upgrades" the version(s) used by user code in these cases, because it is often what users want in cross-compilation scenarios.

Dealing with the "silent upgrade" situation requires us to be a little careful and sometimes pick a "best" capability set that doesn't appear to be supported on our target. Refining that system and potentially getting rid of the "do what I mean" behavior over time could be a goal for future changes.

* fixup: handle case where value is incompatible during linking</content>
</entry>
<entry>
<title>Avoid nondeterministic ordering of output (#1522)</title>
<updated>2020-08-28T18:21:40+00:00</updated>
<author>
<name>Tim Foley</name>
<email>tfoleyNV@users.noreply.github.com</email>
</author>
<published>2020-08-28T18:21:40+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=9a2a35f9282570ed075ebc2313f4aa9ed7a643ce'/>
<id>urn:sha1:9a2a35f9282570ed075ebc2313f4aa9ed7a643ce</id>
<content type='text'>
Most people agree that it is a Good Thing when compilers are deterministic: the exact same input bits produce the exact same output bits every time the compiler is run. Bonus points are awarded if the results are independent of the platform the compiler was compiled for and run on.

One of the easiest kinds of nondeterminism to have sneak into a compiler is for it to produce the "same" code inside functions, but sometimes emits functions or other global symbols in a different order from run to run. Right now, the Slang compiler has some of this kind of nondeterminism.

The main way (but not necessarily the only way) that a compiler ends up producing output with a different ordering across runs is by iterating over the contents of a hash-based container (in our codebase, a `Dictionary` or `HashSet`), where the keys make use of pointers. Most operating systems intentionally try to randomize the address space of processes across runs (as a security feature), so that exact pointer values are not stable across runs, and thus hash value are not stable across runs, and thus the ordering of entries is not stable across runs.

This change identifies a few cases of iterating over dictionaries or sets that could have produced output non-determinism:

* The `HLSLIntrinsicSet` was using a `Dictionary` to store intrinsics that had been referenced, and would later produce a linear list of those intrinsics based on their order in the dictionary.

* The `WitnessTable`s produced by the front-end stored a `Dictionary` or requirements, and lowering from AST-&gt;IR was iterating over that dictionary to ensure that everythign got emitted.

* The `SharedSemanticsContext` was tracking a `HashSet` of modules that were imported into scope (so that their `extension`s should be visible), and an iteration over that list was used when producing candidate extensions during lookup. This case is unlikely to cause any nondeterminism in final output, but could lead to nondeterministic ordering in diagnostic messages for ambiguous reference/overload cases.

* The IR linker maintains a `Dictionary` of symbols based on their mangled names, and iterates over it in code that clones all witness tables into the linked IR whether or not they are referenced.

For most of these cases the fix is simple:

* Keep both a `Dictionary`/`HashSet` and a `List` of the appropriate type
* Whenever adding to the hash-based container also add to the list
* Whenever iterating, iterate over the list

In the final case of the IR linker, the relevant code was marked with a `TODO` comment noting that it shouldn't actually be needed, so I simply dropped it and the change doesn't seem to break any of our tests. I've been fairly confident that code wasn't needed for a while.

This change isn't exactly elegant, and a better long term solution might be to introduce two new types, `OrderedDictionary` and `OrderedSet`, which are similar to `Dictionary` and `HashSet` except that they guarantee a deterministic order of enumeration of their contents, based on insertion order.

(Note that a `SortedDictionary` and/or `SortedSet` that use something like a binary tree to produce a "determinsitc" sorted order wouldn't actually help here, because sorting entries by pointer values wouldn't solve the underlying problem that the pointer values aren't stable across runs)

I've chosen to avoid adding new types to `core` in the interest of making the change as small as possible. If we all agree that new types are warranted, it should be easy to clean up these use cases.

Testing this change is difficult, because we can't produce a reliable test to rule out nondeterminism. I have done best-effort testing by hand by crafting shaders that show output nondeterminism, and then compiling them both with and without these changes.</content>
</entry>
<entry>
<title>Clean-ups related to expanded standard library coverage (#1269)</title>
<updated>2020-03-11T15:50:38+00:00</updated>
<author>
<name>Tim Foley</name>
<email>tfoleyNV@users.noreply.github.com</email>
</author>
<published>2020-03-11T15:50:38+00:00</published>
<link rel='alternate' type='text/html' href='https://git.yummers.dev/slang.git/commit/?id=935768c6a00c258bf5122a2d04b84064a1eee67d'/>
<id>urn:sha1:935768c6a00c258bf5122a2d04b84064a1eee67d</id>
<content type='text'>
This change continues the work already started in moving the definitions of many built-in functions to the standard library.

The main focus in this change was reducing the number of operations that had to be special-cased on the CPU and CUDA targets by making sure that the scalar cases of built-in functions map to the proper names in the prelude (e.g., `F32_sin()`) via the ordinary `__target_intrinsic` mechanism. In some cases this cleanup meant that special-case logic that was constructing definitions for those functions using C++ code could be scrapped.

Additional changes made along the way:

* A few scalar functions that were missing in the CPU/CUDA preludes got added: `round`, hyperbolic trigonometric functions, `frexp`, `modf`, and `fma`

* The floating-point `min()` and `max()` definitions in the preludes were changed to use intrinsic operations on the target (which are likely to follow IEEE semantics, while our definitions did not)

* For the CUDA target, many of the functions had their names translated during code emit from, e.g., `sin` to `sinf`. This change makes the CUDA target more closely match the C++/CPU target in using names like `F32_sin` consistently.

* For the CUDA target, a few additional functions have intrinsics that don't exist (portably) on CPU: `sincos()` and `rsqrt()`.

* For the Slang stdlib definitions to work, a new `$P` replacement was defined for `__targert_intrinsic` that expands to a type based on the first operand of the function (e.g., `F32` for `float`).

* I removed the dedicated opcodes for matrix-matrix, matrix-vector, and vector-matrix multiplication, and instead turned them into ordinary functions with definitions and `__target_intrinsic` modifiers to map them appropriately for HLSL and GLSL. This is realistically how we would have implemented these if we'd had `__target_intrinsic` from the start.

Notes about possible follow-on work:

* The `ldexp` function is still left in the Slang stdlib because it has to account for a floating-point exponent and the `math.h` version only handles integers for the exponent. It is possible that we can/should define another overload for `ldexp` (and `frexp`) that uses an integer for exponent, and then have that one be a built-in on CPU/CUDA, with the HLSL `frexp` being defined in the stdlib to delegate to the correct `frexp` for those targets.

* The `firstbithigh` and related functions are missing for our CPU and CUDA targets, and will need to be added. It is worth nothing that `firstbithigh` apparently has some very odd functionality around signed integer arguments (which are supported, despite MSDN being unclear on that point). General cleanup will be required for those functions.

* Maxing the various matrix and vector products no longer be intrinsic ops might affect how we emit code for them as sub-expressions (both whether we fold them into use sites and how we parenthize them). This doesn't seem to affect any of our existing tests, but we could consider marking these functions with `[__readNone]` to ensure they can be folded, and then also adding whatever modifier(s) we might invent to control precdence and parentheses insertion during emit.</content>
</entry>
</feed>
