Skip to content

Commit 93ad5b3

Browse files
[SPIR-V] Implement rasterizer ordered views (microsoft#5820)
Adds support for - `RasterizerOrderedBuffer` - `RasterizerOrderedByteAddressBuffer` - `RasterizerOrderedStructuredBuffer` - `RasterizerOrderedTexture1D` - `RasterizerOrderedTexture1DArray` - `RasterizerOrderedTexture2D` - `RasterizerOrderedTexture2DArray` - `RasterizerOrderedTexture3D` Each of these types is treated and lowered as their corresponding `RW` type, with the addition that loads and stores to values are wrapped with `OpBeginInvocationInterlockEXT` and `OpEndInvocationInterlockEXT`. If loads or stores to an ROV type are present, one of the - `SampleInterlockOrderedEXT` - `PixelInterlockOrderedEXT` - `ShadingRateInterlockOrderedEXT` execution modes are added to the entry function, based on semantics inputted to the function.
1 parent d6e7e37 commit 93ad5b3

34 files changed

+732
-201
lines changed

docs/SPIR-V.rst

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ more than one shader_record_nv block statically used per shader entry point
252252
otherwise results are undefined."
253253

254254
The official Khronos ray tracing extension also comes with a SPIR-V storage class
255-
that has the same functionality. The ``[[vk::shader_record_ext]]`` annotation can
255+
that has the same functionality. The ``[[vk::shader_record_ext]]`` annotation can
256256
be used when targeting the SPV_KHR_ray_tracing extension.
257257

258258
Builtin variables
@@ -1279,6 +1279,39 @@ will be translated into
12791279
%myBuffer1 = OpVariable %_ptr_Uniform_type_ByteAddressBuffer Uniform
12801280
%myBuffer2 = OpVariable %_ptr_Uniform_type_RWByteAddressBuffer Uniform
12811281
1282+
Rasterizer Ordered Views
1283+
------------------------
1284+
1285+
The following types are rasterizer ordered views:
1286+
1287+
* ``RasterizerOrderedBuffer``
1288+
* ``RasterizerOrderedByteAddressBuffer``
1289+
* ``RasterizerOrderedStructuredBuffer``
1290+
* ``RasterizerOrderedTexture1D``
1291+
* ``RasterizerOrderedTexture1DArray``
1292+
* ``RasterizerOrderedTexture2D``
1293+
* ``RasterizerOrderedTexture2DArray``
1294+
* ``RasterizerOrderedTexture3D``
1295+
1296+
These are translated to the same types as their equivalent RW* types - for
1297+
example, a ``RasterizerOrderedBuffer`` is translated to the same SPIR-V type as
1298+
an ``RWBuffer``. The sole difference lies in how loads and stores to these
1299+
values are treated.
1300+
1301+
The access order guarantee made by ROVs is implemented in SPIR-V using the
1302+
`SPV_EXT_fragment_shader_interlock <https://github.com/KhronosGroup/SPIRV-Registry/blob/main/extensions/EXT/SPV_EXT_fragment_shader_interlock.asciidoc>`_.
1303+
When you load or store a value from or to a rasterizer ordered view, using
1304+
either the ``Load*()`` or ``Store*()`` methods or the indexing operator,
1305+
``OpBeginInvocationInterlockEXT`` will be inserted before the first access and
1306+
``OpEndInvocationInterlockEXT`` will be inserted after the last access.
1307+
1308+
An execution mode will be added to the entry point, depending on the sample
1309+
frequency, which will be deduced based on the semantics inputted by the entry
1310+
point. ``PixelInterlockOrderedEXT`` will be selected by default,
1311+
``SampleInterlockOrderedEXT`` will be selected if the ``SV_SampleIndex``
1312+
semantic is input, and ``ShadingRateInterlockOrderedEXT`` will be selected if
1313+
the ``SV_ShadingRate`` semantic is input.
1314+
12821315
HLSL Variables and Resources
12831316
============================
12841317

@@ -3858,14 +3891,14 @@ implicit ``vk`` namepsace.
38583891
38593892
// Implicitly defined when compiling to SPIR-V.
38603893
namespace vk {
3861-
3894+
38623895
const uint CrossDeviceScope = 0;
38633896
const uint DeviceScope = 1;
38643897
const uint WorkgroupScope = 2;
38653898
const uint SubgroupScope = 3;
38663899
const uint InvocationScope = 4;
38673900
const uint QueueFamilyScope = 5;
3868-
3901+
38693902
uint64_t ReadClock(in uint scope);
38703903
T RawBufferLoad<T = uint>(in uint64_t deviceAddress,
38713904
in uint alignment = 4);
@@ -3918,20 +3951,20 @@ functionality to HLSL:
39183951

39193952
.. code:: hlsl
39203953
3921-
// RawBufferLoad and RawBufferStore use 'uint' for the default template argument.
3954+
// RawBufferLoad and RawBufferStore use 'uint' for the default template argument.
39223955
// The default alignment is 4. Note that 'alignment' must be a constant integer.
39233956
T RawBufferLoad<T = uint>(in uint64_t deviceAddress, in uint alignment = 4);
39243957
void RawBufferStore<T = uint>(in uint64_t deviceAddress, in T value, in uint alignment = 4);
39253958
39263959
3927-
These intrinsics allow the shader program to load and store a single value with type T (int, float2, struct, etc...)
3960+
These intrinsics allow the shader program to load and store a single value with type T (int, float2, struct, etc...)
39283961
from GPU accessible memory at given address, similar to ``ByteAddressBuffer.Load()``.
3929-
Additionally, these intrinsics allow users to set the memory alignment for the underlying data.
3930-
We assume a 'uint' type when the template argument is missing, and we use a value of '4' for the default alignment.
3962+
Additionally, these intrinsics allow users to set the memory alignment for the underlying data.
3963+
We assume a 'uint' type when the template argument is missing, and we use a value of '4' for the default alignment.
39313964
Note that the alignment argument must be a constant integer if it is given.
39323965

3933-
Though we do support setting the `alignment` of the data load and store, we do not currently
3934-
support setting the memory layout for the data. Since these intrinsics are supposed to load
3966+
Though we do support setting the `alignment` of the data load and store, we do not currently
3967+
support setting the memory layout for the data. Since these intrinsics are supposed to load
39353968
"arbitrary" data to or from a random device address, we assume that the program loads/stores some "bytes of data",
39363969
but that its format or layout is unknown. Therefore, keep in mind that these intrinsics
39373970
load or store ``sizeof(T)`` bytes of data, and that loading/storing data with a struct

tools/clang/include/clang/Basic/Attr.td

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -943,7 +943,7 @@ def CounterStructuredBuffer : SubsetSubject<
943943
S->getType()->getAs<RecordType>()->getDecl()->getName() == "AppendStructuredBuffer" ||
944944
S->getType()->getAs<RecordType>()->getDecl()->getName() == "ConsumeStructuredBuffer")}]>;
945945

946-
// Array of StructuredBuffer types that can have associated counters
946+
// Array of StructuredBuffer types that can have associated counters
947947
def ArrayOfCounterStructuredBuffer
948948
: SubsetSubject<
949949
Var, [{S->hasGlobalStorage() && S->getType()->getAsArrayTypeUnsafe() &&
@@ -974,7 +974,7 @@ def ConstantTextureBuffer
974974
S->getType()->getAs<RecordType>()->getDecl()->getName() ==
975975
"TextureBuffer")}]>;
976976

977-
// Global variable with "RWTexture" type
977+
// Global variable with "(RW|RasterizerOrdered)Texture" type
978978
def RWTexture
979979
: SubsetSubject<
980980
Var, [{S->hasGlobalStorage() && S->getType()->getAs<RecordType>() &&
@@ -988,9 +988,19 @@ def RWTexture
988988
S->getType()->getAs<RecordType>()->getDecl()->getName() ==
989989
"RWTexture2DArray" ||
990990
S->getType()->getAs<RecordType>()->getDecl()->getName() ==
991-
"RWTexture3D")}]>;
991+
"RWTexture3D" ||
992+
S->getType()->getAs<RecordType>()->getDecl()->getName() ==
993+
"RasterizerOrderedTexture1D" ||
994+
S->getType()->getAs<RecordType>()->getDecl()->getName() ==
995+
"RasterizerOrderedTexture1DArray" ||
996+
S->getType()->getAs<RecordType>()->getDecl()->getName() ==
997+
"RasterizerOrderedTexture2D" ||
998+
S->getType()->getAs<RecordType>()->getDecl()->getName() ==
999+
"RasterizerOrderedTexture2DArray" ||
1000+
S->getType()->getAs<RecordType>()->getDecl()->getName() ==
1001+
"RasterizerOrderedTexture3D")}]>;
9921002

993-
// Global variable of array of "RWTexture" type
1003+
// Global variable of array of "(RW|RasterizerOrdered)Texture" type
9941004
def ArrayOfRWTexture
9951005
: SubsetSubject<
9961006
Var, [{S->hasGlobalStorage() && S->getType()->getAsArrayTypeUnsafe() &&
@@ -1005,19 +1015,31 @@ def ArrayOfRWTexture
10051015
S->getType()->getAsArrayTypeUnsafe()->getElementType()->getAs<RecordType>()->getDecl()->getName() ==
10061016
"RWTexture2DArray" ||
10071017
S->getType()->getAsArrayTypeUnsafe()->getElementType()->getAs<RecordType>()->getDecl()->getName() ==
1008-
"RWTexture3D")}]>;
1018+
"RWTexture3D" ||
1019+
S->getType()->getAsArrayTypeUnsafe()->getElementType()->getAs<RecordType>()->getDecl()->getName() ==
1020+
"RasterizerOrderedTexture1D" ||
1021+
S->getType()->getAsArrayTypeUnsafe()->getElementType()->getAs<RecordType>()->getDecl()->getName() ==
1022+
"RasterizerOrderedTexture1DArray" ||
1023+
S->getType()->getAsArrayTypeUnsafe()->getElementType()->getAs<RecordType>()->getDecl()->getName() ==
1024+
"RasterizerOrderedTexture2D" ||
1025+
S->getType()->getAsArrayTypeUnsafe()->getElementType()->getAs<RecordType>()->getDecl()->getName() ==
1026+
"RasterizerOrderedTexture2DArray" ||
1027+
S->getType()->getAsArrayTypeUnsafe()->getElementType()->getAs<RecordType>()->getDecl()->getName() ==
1028+
"RasterizerOrderedTexture3D")}]>;
10091029

1010-
// Global variable with "[RW]Buffer" type
1030+
// Global variable with "[RW|RasterizerOrdered]Buffer" type
10111031
def Buffer
10121032
: SubsetSubject<
10131033
Var, [{S->hasGlobalStorage() && S->getType()->getAs<RecordType>() &&
10141034
S->getType()->getAs<RecordType>()->getDecl() &&
10151035
(S->getType()->getAs<RecordType>()->getDecl()->getName() ==
10161036
"Buffer" ||
10171037
S->getType()->getAs<RecordType>()->getDecl()->getName() ==
1018-
"RWBuffer")}]>;
1038+
"RWBuffer" ||
1039+
S->getType()->getAs<RecordType>()->getDecl()->getName() ==
1040+
"RasterizerOrderedBuffer")}]>;
10191041

1020-
// Global variable or array of "[RW]Buffer" type
1042+
// Global variable or array of "[RW|RasterizerOrdered]Buffer" type
10211043
def ArrayOfBuffer
10221044
: SubsetSubject<
10231045
Var, [{S->hasGlobalStorage() && S->getType()->getAsArrayTypeUnsafe() &&
@@ -1026,7 +1048,9 @@ def ArrayOfBuffer
10261048
(S->getType()->getAsArrayTypeUnsafe()->getElementType()->getAs<RecordType>()->getDecl()->getName() ==
10271049
"Buffer" ||
10281050
S->getType()->getAsArrayTypeUnsafe()->getElementType()->getAs<RecordType>()->getDecl()->getName() ==
1029-
"RWBuffer")}]>;
1051+
"RWBuffer" ||
1052+
S->getType()->getAsArrayTypeUnsafe()->getElementType()->getAs<RecordType>()->getDecl()->getName() ==
1053+
"RasterizerOrderedBuffer")}]>;
10301054

10311055
// Global variable with "Texture" or "SamplerState" type
10321056
def TextureOrSampler

0 commit comments

Comments
 (0)