yum-mirror/slang

Making it easier to work with shaders

git clone https://git.yummers.dev/yum-mirror/slang

davli-nvImplement SV_VulkanSamplePosition (#8236)05f0f5603

master
11.0 KiB305 linesraw

layout: user-guide permalink: /user-guide/metal-target-specific

Metal-Specific Functionalities

This chapter provides information for Metal-specific functionalities and behaviors in Slang.

Entry Point Parameter Handling

Slang performs several transformations on entry point parameters when targeting Metal:

  • Struct parameters are flattened to eliminate nested structures
  • Input parameters with varying inputs are packed into a single struct
  • System value semantics are translated to Metal attributes
  • Parameters without semantics are given automatic attribute indices

System-Value semantics

The system-value semantics are translated to the following Metal attributes:

SV semantic nameMetal attribute
SV_Position[[position]]
SV_Coverage[[sample_mask]]
SV_Depth[[depth(any)]]
SV_DepthGreaterEqual[[depth(greater)]]
SV_DepthLessEqual[[depth(less)]]
SV_DispatchThreadID[[thread_position_in_grid]]
SV_FragInvocationCount(Not supported)
SV_FragSize(Not supported)
SV_GroupID[[threadgroup_position_in_grid]]
SV_GroupThreadID[[thread_position_in_threadgroup]]
SV_GroupIndexCalculated from SV_GroupThreadID and group extents
SV_InstanceID[[instance_id]]
SV_IsFrontFace[[front_facing]]
SV_PointSize[[point_size]]
SV_PointCoord[[point_coord]]
SV_PrimitiveID[[primitive_id]]
SV_RenderTargetArrayIndex[[render_target_array_index]]
SV_SampleIndex[[sample_id]]
SV_Target<N>[[color(N)]]
SV_VertexID[[vertex_id]]
SV_ViewportArrayIndex[[viewport_array_index]]
SV_StartVertexLocation[[base_vertex]]
SV_StartInstanceLocation[[base_instance]]
SV_VulkanInstanceID[[instance_id]]
SV_VulkanSamplePosition(Not supported)
SV_VulkanVertexID[[vertex_id]]

Custom semantics are mapped to user attributes:

  • [[user(SEMANTIC_NAME)]] For non-system value semantics
  • [[user(SEMANTIC_NAME_INDEX)]] When semantic has an index

Interpolation Modifiers

Slang maps interpolation modifiers to Metal's interpolation attributes:

Slang InterpolationMetal Attribute
nointerpolation[[flat]]
noperspective[[center_no_perspective]]
linear[[sample_no_perspective]]
sample[[sample_perspective]]
centroid[[center_perspective]]

Resource Types

Resource types are translated with appropriate Metal qualifiers:

Slang TypeMetal Translation
Texture2Dtexture2d
RWTexture2Dtexture2d
ByteAddressBufferuint32_t device*
StructuredBuffer<T>device* T
ConstantBuffer<T>constant* T
Slang TypeMetal Translation
Texture1Dtexture1d
Texture1DArraytexture1d_array
RWTexture1Dtexture1d
RWTexture1DArraytexture1d_array
Texture2Dtexture2d
Texture2DArraytexture2d_array
RWTexture2Dtexture2d
RWTexture2DArraytexture2d_array
Texture3Dtexture3d
RWTexture3Dtexture3d
TextureCubetexturecube
TextureCubeArraytexturecube_array
Buffer<T>device* T
RWBuffer<T>device* T
ByteAddressBufferdevice* uint32_t
RWByteAddressBufferdevice* uint32_t
StructuredBuffer<T>device* T
RWStructuredBuffer<T>device* T
AppendStructuredBuffer<T>device* T
ConsumeStructuredBuffer<T>device* T
ConstantBuffer<T>constant* T
SamplerStatesampler
SamplerComparisonStatesampler
RaytracingAccelerationStructure(Not supported)
RasterizerOrderedTexture2Dtexture2d [[raster_order_group(0)]]
RasterizerOrderedBuffer<T>device* T [[raster_order_group(0)]]

Raster-ordered access resources receive the [[raster_order_group(0)]] attribute, for example texture2d<float, access::read_write> tex [[raster_order_group(0)]].

Array Types

Array types in Metal are declared using the array template:

Slang TypeMetal Translation
ElementType[Size]array<ElementType, Size>

Matrix Layout

Metal exclusively uses column-major matrix layout. Slang automatically handles the translation of matrix operations to maintain correct semantics:

  • Matrix multiplication is transformed to account for layout differences
  • Matrix types are declared as matrix<T, Columns, Rows>, for example float3x4 is represented as matrix<float, 3, 4>

Mesh Shader Support

Mesh shaders can be targeted using the following types and syntax. The same as task/mesh shaders generally in Slang.

[outputtopology("triangle")]
[numthreads(12, 1, 1)]
void meshMain(
    in uint tig: SV_GroupIndex,
    in payload MeshPayload meshPayload,
    OutputVertices<Vertex, MAX_VERTS> verts,
    OutputIndices<uint3, MAX_PRIMS> triangles,
    OutputPrimitives<Primitive, MAX_PRIMS> primitives
    )

Header Inclusions and Namespace

When targeting Metal, Slang automatically includes the following headers, these are available to any intrinsic code.

#include <metal_stdlib>
#include <metal_math>
#include <metal_texture>
using namespace metal;

Parameter blocks and Argument Buffers

ParameterBlock values are translated into Argument Buffers potentially containing nested resources. For example, this Slang code...

struct MyParameters
{
    int x;
    int y;
    StructuredBuffer<float> buffer1;
    RWStructuredBuffer<uint3> buffer2;
}

ParameterBlock<MyParameters> gObj;

void main(){ ... gObj ... }

... results in this Metal output:

struct MyParameters
{
    int x;
    int y;
    float device* buffer1;
    uint3 device* buffer2;
};

[[kernel]] void main(MyParameters constant* gObj [[buffer(1)]])

Struct Parameter Flattening

When targeting Metal, top-level nested struct parameters are automatically flattened. For example:

struct NestedStruct
{
    float2 uv;
};
struct InputStruct
{
    float4 position;
    float3 normal;
    NestedStruct nested;
};

Will be flattened to:

struct InputStruct
{
    float4 position;
    float3 normal;
    float2 uv;
};

Return Value Handling

Non-struct return values from entry points are automatically wrapped in a struct with appropriate semantics. For example:

float4 main() : SV_Target
{
    return float4(1,2,3,4);
}

becomes:

struct FragmentOutput
{
    float4 value : SV_Target;
};
FragmentOutput main()
{
    return { float4(1,2,3,4) };
}

Value Type Conversion

Metal enforces strict type requirements for certain operations. Slang automatically performs the following conversions:

  • Vector size expansion (e.g., float2 to float4), for example when the user specified float2 but the semantic type in Metal is float4.
  • Image store value expansion to 4-components

For example:

RWTexture2D<float2> tex;
tex[coord] = float2(1,2);  // Automatically expanded to float4(1,2,0,0)

Conservative Rasterization

Since Metal doesn't support conservative rasterization, SV_InnerCoverage is always false.

Address Space Assignment

Metal requires explicit address space qualifiers. Slang automatically assigns appropriate address spaces:

Variable TypeMetal Address Space
Local Variablesthread
Global Variablesdevice
Uniform Buffersconstant
RW/Structured Buffersdevice
Group Sharedthreadgroup
Parameter Blocksconstant

Explicit Parameter Binding

The HLSL :register() semantic is respected when emitting Metal code.

Since Metal does not differentiate between a constant buffer, a shader resource (read-only) buffer and an unordered access buffer, Slang will map register(tN), register(uN) and register(bN) to [[buffer(N)]] when such register semantic is declared on a buffer-typed parameter.

spaceN specifiers inside register semantics are ignored.

The [vk::location(N)] attributes on stage input/output parameters are respected.

Specialization Constants

Specialization constants declared with the [SpecializationConstant] or [vk::constant_id] attribute will be translated into a function_constant when generating Metal source. For example:

[vk::constant_id(7)]
const int a = 2;

Translates to:

constant int fc_a_0 [[function_constant(7)]];
constant int a_0 = is_function_constant_defined(fc_a_0) ? fc_a_0 : 2;
1---
2layout: user-guide
3permalink: /user-guide/metal-target-specific
4---
5
6# Metal-Specific Functionalities
7
8This chapter provides information for Metal-specific functionalities and
9behaviors in Slang.
10
11## Entry Point Parameter Handling
12
13Slang performs several transformations on entry point parameters when targeting Metal:
14
15- Struct parameters are flattened to eliminate nested structures
16- Input parameters with varying inputs are packed into a single struct
17- System value semantics are translated to Metal attributes
18- Parameters without semantics are given automatic attribute indices
19
20## System-Value semantics
21
22The system-value semantics are translated to the following Metal attributes:
23
24| SV semantic name            | Metal attribute                                      |
25| --------------------------- | ---------------------------------------------------- |
26| `SV_Position`               | `[[position]]`                                       |
27| `SV_Coverage`               | `[[sample_mask]]`                                    |
28| `SV_Depth`                  | `[[depth(any)]]`                                     |
29| `SV_DepthGreaterEqual`      | `[[depth(greater)]]`                                 |
30| `SV_DepthLessEqual`         | `[[depth(less)]]`                                    |
31| `SV_DispatchThreadID`       | `[[thread_position_in_grid]]`                        |
32| `SV_FragInvocationCount`    | `(Not supported)`                                    |
33| `SV_FragSize`               | `(Not supported)`                                    |
34| `SV_GroupID`                | `[[threadgroup_position_in_grid]]`                   |
35| `SV_GroupThreadID`          | `[[thread_position_in_threadgroup]]`                 |
36| `SV_GroupIndex`             | Calculated from `SV_GroupThreadID` and group extents |
37| `SV_InstanceID`             | `[[instance_id]]`                                    |
38| `SV_IsFrontFace`            | `[[front_facing]]`                                   |
39| `SV_PointSize`              | `[[point_size]]`                                     |
40| `SV_PointCoord`             | `[[point_coord]]`                                    |
41| `SV_PrimitiveID`            | `[[primitive_id]]`                                   |
42| `SV_RenderTargetArrayIndex` | `[[render_target_array_index]]`                      |
43| `SV_SampleIndex`            | `[[sample_id]]`                                      |
44| `SV_Target<N>`              | `[[color(N)]]`                                       |
45| `SV_VertexID`               | `[[vertex_id]]`                                      |
46| `SV_ViewportArrayIndex`     | `[[viewport_array_index]]`                           |
47| `SV_StartVertexLocation`    | `[[base_vertex]]`                                    |
48| `SV_StartInstanceLocation`  | `[[base_instance]]`                                  |
49| `SV_VulkanInstanceID`       | `[[instance_id]]`                                    |
50| `SV_VulkanSamplePosition`   | `(Not supported)`                                    |
51| `SV_VulkanVertexID`         | `[[vertex_id]]`                                      |
52
53Custom semantics are mapped to user attributes:
54
55- `[[user(SEMANTIC_NAME)]]` For non-system value semantics
56- `[[user(SEMANTIC_NAME_INDEX)]]` When semantic has an index
57
58## Interpolation Modifiers
59
60Slang maps interpolation modifiers to Metal's interpolation attributes:
61
62| Slang Interpolation | Metal Attribute             |
63| ------------------- | --------------------------- |
64| `nointerpolation`   | `[[flat]]`                  |
65| `noperspective`     | `[[center_no_perspective]]` |
66| `linear`            | `[[sample_no_perspective]]` |
67| `sample`            | `[[sample_perspective]]`    |
68| `centroid`          | `[[center_perspective]]`    |
69
70## Resource Types
71
72Resource types are translated with appropriate Metal qualifiers:
73
74| Slang Type            | Metal Translation  |
75| --------------------- | ------------------ |
76| `Texture2D`           | `texture2d`        |
77| `RWTexture2D`         | `texture2d`        |
78| `ByteAddressBuffer`   | `uint32_t device*` |
79| `StructuredBuffer<T>` | `device* T`        |
80| `ConstantBuffer<T>`   | `constant* T`      |
81
82| Slang Type                        | Metal Translation                     |
83| --------------------------------- | ------------------------------------- |
84| `Texture1D`                       | `texture1d`                           |
85| `Texture1DArray`                  | `texture1d_array`                     |
86| `RWTexture1D`                     | `texture1d`                           |
87| `RWTexture1DArray`                | `texture1d_array`                     |
88| `Texture2D`                       | `texture2d`                           |
89| `Texture2DArray`                  | `texture2d_array`                     |
90| `RWTexture2D`                     | `texture2d`                           |
91| `RWTexture2DArray`                | `texture2d_array`                     |
92| `Texture3D`                       | `texture3d`                           |
93| `RWTexture3D`                     | `texture3d`                           |
94| `TextureCube`                     | `texturecube`                         |
95| `TextureCubeArray`                | `texturecube_array`                   |
96| `Buffer<T>`                       | `device* T`                           |
97| `RWBuffer<T>`                     | `device* T`                           |
98| `ByteAddressBuffer`               | `device* uint32_t`                    |
99| `RWByteAddressBuffer`             | `device* uint32_t`                    |
100| `StructuredBuffer<T>`             | `device* T`                           |
101| `RWStructuredBuffer<T>`           | `device* T`                           |
102| `AppendStructuredBuffer<T>`       | `device* T`                           |
103| `ConsumeStructuredBuffer<T>`      | `device* T`                           |
104| `ConstantBuffer<T>`               | `constant* T`                         |
105| `SamplerState`                    | `sampler`                             |
106| `SamplerComparisonState`          | `sampler`                             |
107| `RaytracingAccelerationStructure` | `(Not supported)`                     |
108| `RasterizerOrderedTexture2D`      | `texture2d [[raster_order_group(0)]]` |
109| `RasterizerOrderedBuffer<T>`      | `device* T [[raster_order_group(0)]]` |
110
111Raster-ordered access resources receive the `[[raster_order_group(0)]]`
112attribute, for example `texture2d<float, access::read_write> tex
113[[raster_order_group(0)]]`.
114
115## Array Types
116
117Array types in Metal are declared using the array template:
118
119| Slang Type          | Metal Translation          |
120| ------------------- | -------------------------- |
121| `ElementType[Size]` | `array<ElementType, Size>` |
122
123## Matrix Layout
124
125Metal exclusively uses column-major matrix layout. Slang automatically handles
126the translation of matrix operations to maintain correct semantics:
127
128- Matrix multiplication is transformed to account for layout differences
129- Matrix types are declared as `matrix<T, Columns, Rows>`, for example
130  `float3x4` is represented as `matrix<float, 3, 4>`
131
132## Mesh Shader Support
133
134Mesh shaders can be targeted using the following types and syntax. The same as task/mesh shaders generally in Slang.
135
136```slang
137[outputtopology("triangle")]
138[numthreads(12, 1, 1)]
139void meshMain(
140    in uint tig: SV_GroupIndex,
141    in payload MeshPayload meshPayload,
142    OutputVertices<Vertex, MAX_VERTS> verts,
143    OutputIndices<uint3, MAX_PRIMS> triangles,
144    OutputPrimitives<Primitive, MAX_PRIMS> primitives
145    )
146```
147
148## Header Inclusions and Namespace
149
150When targeting Metal, Slang automatically includes the following headers, these
151are available to any intrinsic code.
152
153```cpp
154#include <metal_stdlib>
155#include <metal_math>
156#include <metal_texture>
157using namespace metal;
158```
159
160## Parameter blocks and Argument Buffers
161
162`ParameterBlock` values are translated into _Argument Buffers_ potentially
163containing nested resources. For example, this Slang code...
164
165```slang
166struct MyParameters
167{
168    int x;
169    int y;
170    StructuredBuffer<float> buffer1;
171    RWStructuredBuffer<uint3> buffer2;
172}
173
174ParameterBlock<MyParameters> gObj;
175
176void main(){ ... gObj ... }
177```
178
179... results in this Metal output:
180
181```cpp
182struct MyParameters
183{
184    int x;
185    int y;
186    float device* buffer1;
187    uint3 device* buffer2;
188};
189
190[[kernel]] void main(MyParameters constant* gObj [[buffer(1)]])
191```
192
193## Struct Parameter Flattening
194
195When targeting Metal, top-level nested struct parameters are automatically
196flattened. For example:
197
198```slang
199struct NestedStruct
200{
201    float2 uv;
202};
203struct InputStruct
204{
205    float4 position;
206    float3 normal;
207    NestedStruct nested;
208};
209```
210
211Will be flattened to:
212
213```cpp
214struct InputStruct
215{
216    float4 position;
217    float3 normal;
218    float2 uv;
219};
220```
221
222## Return Value Handling
223
224Non-struct return values from entry points are automatically wrapped in a
225struct with appropriate semantics. For example:
226
227```slang
228float4 main() : SV_Target
229{
230    return float4(1,2,3,4);
231}
232```
233
234becomes:
235
236```c++
237struct FragmentOutput
238{
239    float4 value : SV_Target;
240};
241FragmentOutput main()
242{
243    return { float4(1,2,3,4) };
244}
245```
246
247## Value Type Conversion
248
249Metal enforces strict type requirements for certain operations. Slang
250automatically performs the following conversions:
251
252- Vector size expansion (e.g., `float2` to `float4`), for example when the user
253  specified `float2` but the semantic type in Metal is `float4`.
254- Image store value expansion to 4-components
255
256For example:
257
258```slang
259RWTexture2D<float2> tex;
260tex[coord] = float2(1,2);  // Automatically expanded to float4(1,2,0,0)
261```
262
263## Conservative Rasterization
264
265Since Metal doesn't support conservative rasterization, SV_InnerCoverage is always false.
266
267## Address Space Assignment
268
269Metal requires explicit address space qualifiers. Slang automatically assigns appropriate address spaces:
270
271| Variable Type         | Metal Address Space |
272| --------------------- | ------------------- |
273| Local Variables       | `thread`            |
274| Global Variables      | `device`            |
275| Uniform Buffers       | `constant`          |
276| RW/Structured Buffers | `device`            |
277| Group Shared          | `threadgroup`       |
278| Parameter Blocks      | `constant`          |
279
280## Explicit Parameter Binding
281
282The HLSL `:register()` semantic is respected when emitting Metal code.
283
284Since Metal does not differentiate between a constant buffer, a shader resource (read-only) buffer and an unordered access buffer, Slang will map `register(tN)`, `register(uN)` and `register(bN)` to `[[buffer(N)]]` when such `register` semantic is declared on a buffer-typed parameter.
285
286`spaceN` specifiers inside `register` semantics are ignored.
287
288The `[vk::location(N)]` attributes on stage input/output parameters are respected.
289
290## Specialization Constants
291
292Specialization constants declared with the `[SpecializationConstant]` or `[vk::constant_id]` attribute will be translated into a `function_constant` when generating Metal source.
293For example:
294
295```csharp
296[vk::constant_id(7)]
297const int a = 2;
298```
299
300Translates to:
301
302```metal
303constant int fc_a_0 [[function_constant(7)]];
304constant int a_0 = is_function_constant_defined(fc_a_0) ? fc_a_0 : 2;
305```