Skip to content

Commit 5f1ba7b

Browse files
authored
Various documentation improvements. (#5017)
1 parent 3136771 commit 5f1ba7b

11 files changed

+168
-87
lines changed

docs/proposals/001-where-clauses.md

+61-83
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,12 @@ We propose to allow generic declarations in Slang to move the constraints on gen
66
Status
77
------
88

9-
Unimplemented.
9+
Status: Partially implemented. The only unimplemented case is the canonicalization of generic constraints.
10+
11+
Implementation: [PR 4986](https://github.com/shader-slang/slang/pull/4986)
12+
13+
Reviewed by: Theresa Foley, Yong He
14+
1015

1116
Background
1217
----------
@@ -24,18 +29,17 @@ Introducing `where` clauses allows a programmer to state the constraints *after*
2429

2530
void resolve<T, U, V>(ResolutionContext<U> context, List<T> stuffToResolve, out V destination)
2631
where T : IResolvable,
27-
U : IResolver<T>,
28-
V : IResolveDestination<T>
32+
where U : IResolver<T>,
33+
where V : IResolveDestination<T>
2934
{ ... }
3035

3136
This latter form makes it easier to quickly glean the overall shape of the function signature.
3237

33-
A second important benefit of `where` clauses is that they open the door to expressing more complicated constraints on and between type parameters.
34-
While this document does not propose to allow any new forms of constraints right away, we can imagine things like allowing constraints on *associated types*, e.g.:
38+
A second important benefit of `where` clauses is that they open the door to expressing more complicated constraints on and between type parameters, such as allowing constraints on *associated types*, e.g.:
3539

3640
void writePackedData<T, U>(T src, out U dst)
3741
where T : IPackable,
38-
T.Packed : IWritable<U>
42+
where T.Packed : IWritable<U>
3943
{ .. }
4044

4145
Related Work
@@ -92,46 +96,63 @@ Proposed Approach
9296

9397
For any kind of declaration that Slang allows to have generic parameters, we will allow a `where` clause to appear after the *header* of that declaration.
9498
A `where` clause consists of the (contextual) keyword `where`, following by a comma-separated list of *constraints*:
95-
96-
struct MyStuff<T> : Base, IFoo
97-
where T : IFoo,
98-
T : IBar
99+
```csharp
100+
struct MyStuff<T, U> : IFoo
101+
where T : IFoo, IBar
102+
where T : IBaz
103+
where U : IArray<T>
99104
{ ... }
100-
105+
```
101106
A `where` clause is only allowed after the header of a declaration that has one or more generic parameters.
102107

103108
Each constraint must take the form of one of the type parameters from the immediately enclosing generic parameter list, followed by a colon (`:`), and then followed by a type expression that names an interface or a conjunction of interfaces.
104109
Multiple constraints can be defined for the same parameter.
105110

106111
We haven't previously defined what the header of a declaration is, so we briefly illustrate what we mean by showing where the split between the header and the *body* of a declaration is for each of the major kinds of declarations that are supported. In each case a comment `/****/` is placed between the header and body:
107112

108-
// variables:
109-
let v : Int /****/ = 99;
110-
var v : Int /****/ = 99;
111-
Int v /****/ = 99;
112-
113-
// simple type declarations:
114-
typealias X : IFoo /****/ = Y;
115-
associatedtype X : IFoo /****/;
116-
117-
// functions and other callables:
118-
Int f(Float y) /****/ { ... }
119-
func f(Float y) -> Int /****/ { ... }
120-
init(Float y) /****/ { ... }
121-
subscript(Int idx) -> Float /****/ { ... }
122-
123-
// properties
124-
property p : Int /****/ { ... }
125-
126-
// aggregates
127-
extension Int : IFoo /****/ { ... }
128-
struct Thing : Base /****/ { ... }
129-
class Thing : Base /****/ { ... }
130-
interface IThing : IBase /****/ { ... }
131-
enum Stuff : Int /****/ { ... }
132-
113+
```csharp
114+
// variables:
115+
let v : Int /****/ = 99;
116+
var v : Int /****/ = 99;
117+
Int v /****/ = 99;
118+
119+
// simple type declarations:
120+
typealias X : IFoo /****/ = Y;
121+
associatedtype X : IFoo /****/;
122+
123+
// functions and other callables:
124+
Int f(Float y) /****/ { ... }
125+
func f(Float y) -> Int /****/ { ... }
126+
init(Float y) /****/ { ... }
127+
subscript(Int idx) -> Float /****/ { ... }
128+
129+
// properties
130+
property p : Int /****/ { ... }
131+
132+
// aggregates
133+
extension Int : IFoo /****/ { ... }
134+
struct Thing : Base /****/ { ... }
135+
class Thing : Base /****/ { ... }
136+
interface IThing : IBase /****/ { ... }
137+
enum Stuff : Int /****/ { ... }
138+
```
133139
In practice, the body of a declaration starts at the `=` for declarations with an initial-value expression, at the opening `{` for declarations with a `{}`-enclosed body, or at the closing `;` for any other declarations.
134140

141+
With introduction of `where` clauses, we can extend type system to allow more kinds of type constraints. In this proposal,
142+
we allow type constraints followed by `where` to be one of:
143+
- Type conformance constraint, in the form of `T : IBase`
144+
- Type equality constraint, in the form of `T == X`
145+
146+
In both cases, the left hand side of a constraint can be a simple generic type parameter, or any types that are dependent on some
147+
generic type parameter. For example, the following is allowed:
148+
```csharp
149+
interface IFoo { associatedtype A; }
150+
struct S<T, U>
151+
where T : IFoo
152+
where T.A == U
153+
{}
154+
```
155+
135156
Detailed Explanation
136157
--------------------
137158

@@ -241,37 +262,18 @@ Alternatives Considered
241262
There really aren't any compelling alternatives to `where` clauses among the languages that Slang takes design influence from.
242263
We could try to design something to solve the same problems from first principles, but the hypothetical benefits of doing so are unclear.
243264

244-
When it comes to the syntactic details, we could consider allowing for *multiple* `where` clauses (matching the C# syntax) as an alternative to the comma-separated list:
265+
When it comes to the syntactic details, we could consider disallow type lists in the right hand side of a conformance constraint, and return allow multiple constraints to be separated with comma and sharing with one `where` keyword:
245266

246267
struct MyStuff<T> : Base, IFoo
247-
where T : IFoo
248-
where T : IBar
268+
where T : IFoo,
269+
T : IBar
249270
{ ... }
250271

251-
This alternative form may result in more compact and tidy diffs when editing the constraints on declarations, at the cost of repeating the `where` keyword many times.
272+
This alternative form may result in more compact code without needing duplicated `where` clause, but may be harder to achieve tidy diffs when editing the constraints on declarations.
252273

253274
Future Directions
254275
-----------------
255276

256-
### Allow more general types on the left-hand side of `:`
257-
258-
There are many cases where it would be helpful to be able to introduce constraints on associated types.
259-
As a contrived example:
260-
261-
interface IPrintable { ... }
262-
interface ISequence
263-
{
264-
associatedtype Element;
265-
...
266-
}
267-
extention<T> T : IPrintable
268-
where T : ISequence,
269-
T.Element : IPrintable
270-
{ ... }
271-
272-
In this example, an `extension` is used to declare that sequences are printable if their elements are printable.
273-
274-
275277
### Allow more general types on the right-hand side of `:`
276278

277279
Currently, the only constraints allowed using `:` have a concrete (non-`interface`) type on the left-hand side, and an `interface` (or conjunction of interfaces) on the right-hand side.
@@ -284,30 +286,6 @@ In the context of `class`-based hierarchies, we can also consider having constra
284286
where T : Base
285287
{ ... }
286288

287-
### Equality Constraints
288-
289-
One future direction that we already intend to pursue is allowing exact equality constraints.
290-
The primary use case envisioned for equality constraints is to express restrictions on associated types of type parameters.
291-
As a contrived example:
292-
293-
interface IProducer
294-
{
295-
associatedtype Element;
296-
// ...
297-
}
298-
interface IConsumer
299-
{
300-
associatedtype Element;
301-
// ...
302-
}
303-
void runPipeline<P, C>(P producer, C consumer)
304-
where P : IProducer,
305-
C : IConsumer,
306-
P.Element == C.Element
307-
{ ... }
308-
309-
An equality constraint could either constrain an associated type to be equal to some concrete type, or to some other associated type.
310-
311289
### Allow `where` clauses on non-generic declarations
312290

313291
We could consider allowing `where` clauses to appear on any declaration nested under a generic, such that those declarations are only usable when certain additinal constraints are met.
File renamed without changes.
File renamed without changes.
File renamed without changes.

docs/user-guide/06-interfaces-generics.md

+71
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,22 @@ Generic value parameters can also be defined using the traditional C-style synta
104104
void g1<typename T, int n>() { ... }
105105
```
106106

107+
Slang allows multiple `where` clauses, and multiple interface types in a single `where` clause:
108+
```csharp
109+
struct MyType<T, U>
110+
where T: IFoo, IBar
111+
where U : IBaz<T>
112+
{
113+
}
114+
// equivalent to:
115+
struct MyType<T, U>
116+
where T: IFoo
117+
where T : IBar
118+
where U : IBaz<T>
119+
{
120+
}
121+
```
122+
107123
Supported Constructs in Interface Definitions
108124
-----------------------------------------------------
109125

@@ -793,6 +809,61 @@ void main()
793809
See [if-let syntax](convenience-features.html#if_let-syntax) for more details.
794810

795811

812+
Generic Interfaces
813+
------------------
814+
815+
Slang allows interfaces themselves to be generic. A common use of generic interfaces is to define the `IEnumerable` type:
816+
```csharp
817+
interface IEnumerator<T>
818+
{
819+
This moveNext();
820+
bool isEnd();
821+
T getValue();
822+
}
823+
824+
interface IEnumerable<T>
825+
{
826+
assoicatedtype Enumerator : IEnumerator<T>;
827+
Enumerator getEnumerator();
828+
}
829+
```
830+
831+
You can constrain a generic type parameter to conform to a generic interface:
832+
```csharp
833+
void traverse<TElement, TCollection>(TCollection c)
834+
where TCollection : IEnumerable<TElement>
835+
{
836+
...
837+
}
838+
```
839+
840+
841+
Generic Extensions
842+
----------------------
843+
You can use generic extensions to extend a generic type. For example,
844+
```csharp
845+
interface IFoo { void foo(); }
846+
interface IBar { void bar(); }
847+
848+
struct MyType<T : IFoo>
849+
{
850+
void foo() { ... }
851+
}
852+
853+
// Extend `MyType<T>` so it conforms to `IBar`.
854+
extension<T:IFoo> MyType<T> : IBar
855+
{
856+
void bar() { ... }
857+
}
858+
// Equivalent to:
859+
__generic<T:IFoo>
860+
extension MyType<T> : IBar
861+
{
862+
void bar() { ... }
863+
}
864+
```
865+
866+
796867
Extensions to Interfaces
797868
-----------------------------
798869

docs/user-guide/09-targets.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -302,14 +302,14 @@ Metal
302302
> #### Note ####
303303
> Slang support for Metal is a work in progress.
304304
305-
Metal is a shading language exclusive on Apple slicons. The functionality from Metal is similar to DX12 or Vulkan with more or less features.
305+
Metal is a shading language exclusive on Apple platforms. The functionality from Metal is similar to DX12 or Vulkan with more or less features.
306306

307307
### Pipelines
308308

309-
Metal includes rasterization, compute, and ray tracing pipelines with the same set of stages as described for D3D12 above.
309+
Metal includes vertex, fragment, task, mesh and tessellation stages for rasterization, as well as compute, and ray tracing stages.
310310

311311
> #### Note ####
312-
> Ray-tracing and Mesh support for Metal is a work in progress.
312+
> Ray-tracing support for Metal is a work in progress.
313313
314314
### Parameter Passing
315315

docs/user-guide/a2-01-spirv-target-specific.md

+29-1
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ SPIR-V 1.5 with [SPV_EXT_shader_atomic_float16_add](https://github.com/KhronosGr
134134
ConstantBuffer, (RW/RasterizerOrdered)StructuredBuffer, (RW/RasterizerOrdered)ByteAddressBuffer
135135
-----------------------------------------------------------------------------------------------
136136

137-
Each member in a `ConstantBuffer` will be emitted as `uniform` parameter.
137+
Each member in a `ConstantBuffer` will be emitted as `uniform` parameter in a uniform block.
138138
StructuredBuffer and ByteAddressBuffer are translated to a shader storage buffer with `readonly` layout.
139139
RWStructuredBuffer and RWByteAddressBuffer are translated to a shader storage buffer with `read-write` layout.
140140
RasterizerOrderedStructuredBuffer and RasterizerOrderedByteAddressBuffer will use an extension, `SPV_EXT_fragment_shader_interlock`.
@@ -156,6 +156,34 @@ It is similar to `ConstantBuffer` in HLSL, and `ParameterBlock` can include not
156156
When both ordinary data fields and resource typed fields exist in a parameter block, all ordinary data fields will be grouped together into a uniform buffer and appear as a binding 0 of the resulting descriptor set.
157157

158158

159+
Push Constants
160+
---------------------
161+
162+
By default, a `uniform` parameter defined in the parameter list of an entrypoint function is translated to a push constant in SPIRV, if the type of the parameter is ordinary data type (no resources/textures).
163+
All `uniform` parameter defined in global scope are grouped together and placed in a default constant bbuffer. You can make a global uniform parameter laid out as a push constant by using the `[vk::push_constant]` attribute
164+
on the uniform parameter.
165+
166+
Specialization Constants
167+
------------------------
168+
169+
You can specify a global constant to translate into a SPIRV specialization constant with the `[SpecializationConstant]` attribute.
170+
For example:
171+
```csharp
172+
[SpecializationConstant]
173+
const int myConst = 1; // Maps to a SPIRV specialization constant
174+
```
175+
176+
By default, Slang will automatically assign `constant_id` number for specialization constants. If you wish to explicitly specify them, use `[vk::constant_id]` attribute:
177+
```csharp
178+
[vk::constant_id(1)]
179+
const int myConst = 1;
180+
```
181+
182+
Alternatively, the GLSL `layout` syntax is also supported by Slang:
183+
```glsl
184+
layout(constant_id = 1) const int MyConst = 1;
185+
```
186+
159187
SPIR-V specific Compiler options
160188
--------------------------------
161189

docs/user-guide/toc.html

+4
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@
8383
<li data-link="interfaces-generics#interface-typed-values"><span>Interface-typed Values</span></li>
8484
<li data-link="interfaces-generics#extending-a-type-with-additional-interface-conformances"><span>Extending a Type with Additional Interface Conformances</span></li>
8585
<li data-link="interfaces-generics#is-and-as-operator"><span>`is` and `as` Operator</span></li>
86+
<li data-link="interfaces-generics#generic-interfaces"><span>Generic Interfaces</span></li>
87+
<li data-link="interfaces-generics#generic-extensions"><span>Generic Extensions</span></li>
8688
<li data-link="interfaces-generics#extensions-to-interfaces"><span>Extensions to Interfaces</span></li>
8789
<li data-link="interfaces-generics#variadic-generics"><span>Variadic Generics</span></li>
8890
<li data-link="interfaces-generics#builtin-interfaces"><span>Builtin Interfaces</span></li>
@@ -207,6 +209,8 @@
207209
<li data-link="spirv-target-specific#supported-atomic-types-for-each-target"><span>Supported atomic types for each target</span></li>
208210
<li data-link="spirv-target-specific#constantbuffer-rwrasterizerorderedstructuredbuffer-rwrasterizerorderedbyteaddressbuffer"><span>ConstantBuffer, (RW/RasterizerOrdered)StructuredBuffer, (RW/RasterizerOrdered)ByteAddressBuffer</span></li>
209211
<li data-link="spirv-target-specific#parameterblock-for-spir-v-target"><span>ParameterBlock for SPIR-V target</span></li>
212+
<li data-link="spirv-target-specific#push-constants"><span>Push Constants</span></li>
213+
<li data-link="spirv-target-specific#specialization-constants"><span>Specialization Constants</span></li>
210214
<li data-link="spirv-target-specific#spir-v-specific-compiler-options"><span>SPIR-V specific Compiler options</span></li>
211215
<li data-link="spirv-target-specific#spir-v-specific-attributes"><span>SPIR-V specific Attributes </span></li>
212216
<li data-link="spirv-target-specific#multiple-entry-points-support"><span>Multiple entry points support</span></li>

0 commit comments

Comments
 (0)