Skip to content

Commit eadf7e3

Browse files
authored
[SPIR-V] Add proposal for vk::push_constant (#360)
Adds proposal to implement VK push constant support in Clang. E2E implementation draft: llvm/llvm-project#166793
1 parent eda52c9 commit eadf7e3

File tree

1 file changed

+90
-0
lines changed

1 file changed

+90
-0
lines changed
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
---
2+
title: "[NNNN] - SPIR-V Push constants"
3+
params:
4+
status: Design In Progress
5+
authors:
6+
- Keenuts: Nathan Gauër
7+
---
8+
9+
## Introduction
10+
11+
Push Constants are a Vulkan mechanism to pass a small amount of data to the
12+
shaders without creating buffers or modifying bindings.
13+
14+
Usage is as follows:
15+
16+
```hlsl
17+
struct S {
18+
float3 light_color;
19+
};
20+
21+
[[vk::push_constant]]
22+
S data;
23+
24+
void main() {
25+
[...]
26+
do_something(data.light_color)
27+
}
28+
```
29+
## Motivation
30+
31+
This is a core feature of HLSL+Vulkan.
32+
33+
## Proposed Solution
34+
35+
### HLSL - Parsing
36+
37+
``[[vk::push_constant]]`` is a normal attribute in the `vk` namespace, with
38+
no custom parsing.
39+
This attribute is only allowed on global variables. Additional checks like
40+
storage class compatibility is done in sema.
41+
42+
At this stage, we know the attribute can only be attached to a global
43+
variable.
44+
45+
### HLSL - Sema
46+
47+
During sema, compatibility checks between the global variable definition
48+
and the attribute are checked, and the global variable definition is created.
49+
50+
Additional checks are:
51+
- The attribute is only allowed on a global variable with a struct type.
52+
- There can only be one ``[[vk::push_constant]]`` attribute in the shader.
53+
- There can be no VLA in the struct type (or a nested struct type).
54+
55+
DXC allows any storage class to be attached to a push constant. I believe
56+
this is an oversight and we should probably refuse this. As result, the
57+
following rules will apply:
58+
59+
- The variable storage class must be either `auto` or `uniform`.
60+
- The variable can be marked `const`, but is always considered `const`.
61+
62+
### DXIL
63+
64+
This being a Vulkan specific feature, the attribute is ignored when targeting
65+
DXIL. This means the push constant global becomes part of the cbuffer when
66+
building for DXIL.
67+
68+
The attribute being ignored, the variable belong to the cbuffer, meaning no
69+
additional handling is required.
70+
71+
### SPIR-V
72+
73+
The created global variable after parsing has the following characteristics:
74+
- the global variable will be marked as `const`.
75+
- the variable address space will be `hlsl_push_constant`.
76+
77+
Codegen will be left almost as-is as we simply load a variable in a different
78+
address space. The layout rule for those struct follows the same rules as
79+
[RW]StructuredBuffers.
80+
What we need to fixup is the cbuffer logic as a global variable with the
81+
HLSLVkPushConstant attribute should not be added to the constant buffer.
82+
83+
The backend will then lower variables into the `hlsl_push_constant` address
84+
space into a `PushConstant` storage class. The rest is similar to any variable
85+
in another address space and should already be handled.
86+
87+
## Draft PR
88+
89+
There is also a draft PR implementing this end-to-end:
90+
- https://github.com/llvm/llvm-project/pull/166793

0 commit comments

Comments
 (0)