Skip to content

Commit 24ea9e8

Browse files
authored
Treat matrix load/stores as column major in raw buffers (#4526)
Assume that matrices are stored in the column major order in raw buffers, e.g., `ByteAddressBuffer` and `RWByteAddressBuffer`. Add a new flag,`-fspv-use-legacy-buffer-matrix-order`, so that shaders that depend on the previous matrix order (row major) can opt-out of this change. Fixes: #3370
1 parent 0ef9b70 commit 24ea9e8

9 files changed

Lines changed: 215 additions & 27 deletions

File tree

docs/SPIR-V.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4012,6 +4012,8 @@ codegen for Vulkan:
40124012
the resource arrays must be marked with ``[unroll]``.
40134013
- ``-fspv-entrypoint-name=<name>``: Specify the SPIR-V entry point name. Defaults
40144014
to the HLSL entry point name.
4015+
- ``-fspv-use-legacy-buffer-matrix-order``: Assumes the legacy matrix order (row
4016+
major) when accessing raw buffers (e.g., ByteAdddressBuffer).
40154017
- ``-Wno-vk-ignored-features``: Does not emit warnings on ignored features
40164018
resulting from no Vulkan support, e.g., cbuffer member initializer.
40174019

include/dxc/Support/HLSLOptions.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,8 @@ def fvk_use_dx_layout: Flag<["-"], "fvk-use-dx-layout">, Group<spirv_Group>, Fla
345345
HelpText<"Use DirectX memory layout for Vulkan resources">;
346346
def fvk_use_scalar_layout: Flag<["-"], "fvk-use-scalar-layout">, Group<spirv_Group>, Flags<[CoreOption, DriverOption]>,
347347
HelpText<"Use scalar memory layout for Vulkan resources">;
348+
def fspv_use_legacy_buffer_matrix_order: Flag<["-"], "fspv-use-legacy-buffer-matrix-order">, Group<spirv_Group>, Flags<[CoreOption, DriverOption]>,
349+
HelpText<"Assume the legacy matrix order (row major) when accessing raw buffers (e.g., ByteAdddressBuffer)">;
348350
def fspv_reflect: Flag<["-"], "fspv-reflect">, Group<spirv_Group>, Flags<[CoreOption, DriverOption]>,
349351
HelpText<"Emit additional SPIR-V instructions to aid reflection">;
350352
def fspv_debug_EQ : Joined<["-"], "fspv-debug=">, Group<spirv_Group>, Flags<[CoreOption, DriverOption]>,

include/dxc/Support/SPIRVOptions.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ struct SpirvCodeGenOptions {
5656
bool noWarnIgnoredFeatures;
5757
bool useDxLayout;
5858
bool useGlLayout;
59+
bool useLegacyBufferMatrixOrder;
5960
bool useScalarLayout;
6061
bool flattenResourceArrays;
6162
bool reduceLoadSize;

lib/DxcSupport/HLSLOptions.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -976,6 +976,7 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude,
976976
opts.SpirvOptions.useGlLayout = Args.hasFlag(OPT_fvk_use_gl_layout, OPT_INVALID, false);
977977
opts.SpirvOptions.useDxLayout = Args.hasFlag(OPT_fvk_use_dx_layout, OPT_INVALID, false);
978978
opts.SpirvOptions.useScalarLayout = Args.hasFlag(OPT_fvk_use_scalar_layout, OPT_INVALID, false);
979+
opts.SpirvOptions.useLegacyBufferMatrixOrder = Args.hasFlag(OPT_fspv_use_legacy_buffer_matrix_order, OPT_INVALID, false);
979980
opts.SpirvOptions.enableReflect = Args.hasFlag(OPT_fspv_reflect, OPT_INVALID, false);
980981
opts.SpirvOptions.noWarnIgnoredFeatures = Args.hasFlag(OPT_Wno_vk_ignored_features, OPT_INVALID, false);
981982
opts.SpirvOptions.noWarnEmulatedFeatures = Args.hasFlag(OPT_Wno_vk_emulated_features, OPT_INVALID, false);
@@ -1104,6 +1105,7 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude,
11041105
Args.hasFlag(OPT_fvk_use_gl_layout, OPT_INVALID, false) ||
11051106
Args.hasFlag(OPT_fvk_use_dx_layout, OPT_INVALID, false) ||
11061107
Args.hasFlag(OPT_fvk_use_scalar_layout, OPT_INVALID, false) ||
1108+
Args.hasFlag(OPT_fspv_use_legacy_buffer_matrix_order, OPT_INVALID, false) ||
11071109
Args.hasFlag(OPT_fspv_flatten_resource_arrays, OPT_INVALID, false) ||
11081110
Args.hasFlag(OPT_fspv_reduce_load_size, OPT_INVALID, false) ||
11091111
Args.hasFlag(OPT_fspv_reflect, OPT_INVALID, false) ||

tools/clang/lib/SPIRV/RawBufferMethods.cpp

Lines changed: 52 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@
1111
#include "clang/AST/ASTContext.h"
1212
#include "clang/AST/CharUnits.h"
1313
#include "clang/AST/RecordLayout.h"
14+
#include "clang/AST/Type.h"
1415
#include "clang/SPIRV/AstTypeProbe.h"
1516
#include "clang/SPIRV/SpirvBuilder.h"
1617
#include "clang/SPIRV/SpirvInstruction.h"
18+
#include <cstdint>
1719

1820
namespace {
1921
/// Rounds the given value up to the given power of 2.
@@ -290,22 +292,43 @@ SpirvInstruction *RawBufferHandler::processTemplatedLoadFromBuffer(
290292
// Matrix types
291293
{
292294
QualType elemType = {};
293-
uint32_t numRows = 0, numCols = 0;
295+
uint32_t numRows = 0;
296+
uint32_t numCols = 0;
294297
if (isMxNMatrix(targetType, &elemType, &numRows, &numCols)) {
295-
llvm::SmallVector<SpirvInstruction *, 4> loadedElems;
298+
// In DX, the default matrix orientation in ByteAddressBuffer is column
299+
// major. If HLSL/DXIL support the `column_major` and `row_major`
300+
// attributes in the future, we will have to check for them here and
301+
// override the behavior.
302+
//
303+
// The assume buffer matrix order is controlled by the
304+
// `-fspv-use-legacy-buffer-matrix-order` flag:
305+
// (a) false --> assume the matrix is stored column major
306+
// (b) true --> assume the matrix is stored row major
307+
//
308+
// We provide (b) for compatibility with legacy shaders that depend on
309+
// the previous, incorrect, raw buffer matrix order assumed by the SPIR-V
310+
// codegen.
311+
const bool isBufferColumnMajor =
312+
!theEmitter.getSpirvOptions().useLegacyBufferMatrixOrder;
313+
const uint32_t numElements = numRows * numCols;
314+
llvm::SmallVector<SpirvInstruction *, 16> loadedElems(numElements);
315+
for (uint32_t i = 0; i != numElements; ++i)
316+
loadedElems[i] = processTemplatedLoadFromBuffer(buffer, index, elemType,
317+
bitOffset, range);
318+
296319
llvm::SmallVector<SpirvInstruction *, 4> loadedRows;
297320
for (uint32_t i = 0; i < numRows; ++i) {
321+
llvm::SmallVector<SpirvInstruction *, 4> loadedColumn;
298322
for (uint32_t j = 0; j < numCols; ++j) {
299-
// TODO: This is currently doing a row_major matrix load. We must
300-
// investigate whether we also need to implement it for column_major.
301-
loadedElems.push_back(processTemplatedLoadFromBuffer(
302-
buffer, index, elemType, bitOffset, range));
323+
const uint32_t elementIndex =
324+
isBufferColumnMajor ? (j * numRows + i) : (i * numCols + j);
325+
loadedColumn.push_back(loadedElems[elementIndex]);
303326
}
304327
const auto rowType = astContext.getExtVectorType(elemType, numCols);
305328
loadedRows.push_back(spvBuilder.createCompositeConstruct(
306-
rowType, loadedElems, loc, range));
307-
loadedElems.clear();
329+
rowType, loadedColumn, loc, range));
308330
}
331+
309332
result = spvBuilder.createCompositeConstruct(targetType, loadedRows, loc,
310333
range);
311334
result->setRValue();
@@ -593,14 +616,28 @@ QualType RawBufferHandler::serializeToScalarsOrStruct(
593616
QualType elemType = {};
594617
uint32_t numRows = 0, numCols = 0;
595618
if (isMxNMatrix(valueType, &elemType, &numRows, &numCols)) {
619+
// Check if the destination buffer expects matrices in column major or row
620+
// major order. In the future, we may also need to consider the
621+
// `row_major` and `column_major` attribures. This is not handled by
622+
// HLSL/DXIL at the moment, so we ignore them too.
623+
const bool isBufferColumnMajor =
624+
!theEmitter.getSpirvOptions().useLegacyBufferMatrixOrder;
596625
for (uint32_t i = 0; i < size; ++i) {
597-
for (uint32_t j = 0; j < numRows; ++j) {
598-
for (uint32_t k = 0; k < numCols; ++k) {
599-
// TODO: This is currently doing a row_major matrix store. We must
600-
// investigate whether we also need to implement it for
601-
// column_major.
602-
values->push_back(spvBuilder.createCompositeExtract(
603-
elemType, values->front(), {j, k}, loc, range));
626+
if (isBufferColumnMajor) {
627+
// Access the matrix in the column major order.
628+
for (uint32_t j = 0; j != numCols; ++j) {
629+
for (uint32_t k = 0; k != numRows; ++k) {
630+
values->push_back(spvBuilder.createCompositeExtract(
631+
elemType, values->front(), {k, j}, loc, range));
632+
}
633+
}
634+
} else {
635+
// Access the matrix in the row major order.
636+
for (uint32_t j = 0; j != numRows; ++j) {
637+
for (uint32_t k = 0; k != numCols; ++k) {
638+
values->push_back(spvBuilder.createCompositeExtract(
639+
elemType, values->front(), {j, k}, loc, range));
640+
}
604641
}
605642
}
606643
values->pop_front();

tools/clang/test/CodeGenSPIRV/method.byte-address-buffer.templated-load.matrix.hlsl

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ void main(uint3 tid : SV_DispatchThreadId)
2020
// CHECK: [[ptr:%\d+]] = OpAccessChain %_ptr_Uniform_uint %buf %uint_0 [[index_1]]
2121
// CHECK: [[word1:%\d+]] = OpLoad %uint [[ptr]]
2222
// CHECK: [[val2:%\d+]] = OpUConvert %ushort [[word1]]
23-
// CHECK: [[row0:%\d+]] = OpCompositeConstruct %v3ushort [[val0]] [[val1]] [[val2]]
2423
// CHECK: [[ptr:%\d+]] = OpAccessChain %_ptr_Uniform_uint %buf %uint_0 [[index_1]]
2524
// CHECK: [[word1:%\d+]] = OpLoad %uint [[ptr]]
2625
// CHECK: [[shifted_word1:%\d+]] = OpShiftRightLogical %uint [[word1]] %uint_16
@@ -33,7 +32,8 @@ void main(uint3 tid : SV_DispatchThreadId)
3332
// CHECK: [[word2:%\d+]] = OpLoad %uint [[ptr]]
3433
// CHECK: [[shifted_word2:%\d+]] = OpShiftRightLogical %uint [[word2]] %uint_16
3534
// CHECK: [[val5:%\d+]] = OpUConvert %ushort [[shifted_word2:%\d+]]
36-
// CHECK: [[row1:%\d+]] = OpCompositeConstruct %v3ushort [[val3]] [[val4]] [[val5]]
35+
// CHECK: [[row0:%\d+]] = OpCompositeConstruct %v3ushort [[val0]] [[val2]] [[val4]]
36+
// CHECK: [[row1:%\d+]] = OpCompositeConstruct %v3ushort [[val1]] [[val3]] [[val5]]
3737
// CHECK: [[matrix:%\d+]] = OpCompositeConstruct %_arr_v3ushort_uint_2 [[row0]] [[row1]]
3838
// CHECK: OpStore %u16 [[matrix]]
3939
uint16_t2x3 u16 = buf.Load<uint16_t2x3>(tid.x);
@@ -48,18 +48,27 @@ void main(uint3 tid : SV_DispatchThreadId)
4848
// CHECK: [[word1:%\d+]] = OpLoad %uint [[ptr]]
4949
// CHECK: [[val1:%\d+]] = OpBitcast %int [[word1:%\d+]]
5050
// CHECK:[[index_2:%\d+]] = OpIAdd %uint [[index_1]] %uint_1
51-
// CHECK: [[row0:%\d+]] = OpCompositeConstruct %v2int [[val0]] [[val1]]
5251
// CHECK: [[ptr:%\d+]] = OpAccessChain %_ptr_Uniform_uint %buf %uint_0 [[index_2]]
5352
// CHECK: [[word2:%\d+]] = OpLoad %uint [[ptr]]
5453
// CHECK: [[val2:%\d+]] = OpBitcast %int [[word2]]
5554
// CHECK:[[index_3:%\d+]] = OpIAdd %uint [[index_2]] %uint_1
5655
// CHECK: [[ptr:%\d+]] = OpAccessChain %_ptr_Uniform_uint %buf %uint_0 [[index_3]]
5756
// CHECK: [[word3:%\d+]] = OpLoad %uint [[ptr]]
5857
// CHECK: [[val3:%\d+]] = OpBitcast %int [[word3]]
59-
// CHECK: [[row1:%\d+]] = OpCompositeConstruct %v2int [[val2]] [[val3]]
60-
// CHECK: [[matrix:%\d+]] = OpCompositeConstruct %_arr_v2int_uint_2 [[row0]] [[row1]]
61-
// CHECK: OpStore %i [[matrix]]
62-
int2x2 i = buf.Load<int2x2>(tid.x);
58+
// CHECK:[[index_4:%\d+]] = OpIAdd %uint [[index_3]] %uint_1
59+
// CHECK: [[ptr:%\d+]] = OpAccessChain %_ptr_Uniform_uint %buf %uint_0 [[index_4]]
60+
// CHECK: [[word4:%\d+]] = OpLoad %uint [[ptr]]
61+
// CHECK: [[val4:%\d+]] = OpBitcast %int [[word4]]
62+
// CHECK:[[index_5:%\d+]] = OpIAdd %uint [[index_4]] %uint_1
63+
// CHECK: [[ptr:%\d+]] = OpAccessChain %_ptr_Uniform_uint %buf %uint_0 [[index_5]]
64+
// CHECK: [[word5:%\d+]] = OpLoad %uint [[ptr]]
65+
// CHECK: [[val5:%\d+]] = OpBitcast %int [[word5]]
66+
// CHECK: [[row0:%\d+]] = OpCompositeConstruct %v2int [[val0]] [[val3]]
67+
// CHECK: [[row1:%\d+]] = OpCompositeConstruct %v2int [[val1]] [[val4]]
68+
// CHECK: [[row2:%\d+]] = OpCompositeConstruct %v2int [[val2]] [[val5]]
69+
// CHECK: [[matrix:%\d+]] = OpCompositeConstruct %_arr_v2int_uint_3 [[row0]] [[row1]] [[row2]]
70+
// CHECK: OpStore %j [[matrix]]
71+
int3x2 j = buf.Load<int3x2>(tid.x);
6372

6473
// ********* 64-bit matrix ********************
6574

@@ -85,7 +94,6 @@ void main(uint3 tid : SV_DispatchThreadId)
8594
// CHECK: [[val1_ulong:%\d+]] = OpBitwiseOr %ulong [[word2_ulong]] [[word3_ulong_shifted]]
8695
// CHECK: [[val1:%\d+]] = OpBitcast %double [[val1_ulong]]
8796
// CHECK: [[index_4:%\d+]] = OpIAdd %uint [[index_3]] %uint_1
88-
// CHECK: [[row0:%\d+]] = OpCompositeConstruct %v2double [[val0]] [[val1]]
8997
// CHECK: [[ptr:%\d+]] = OpAccessChain %_ptr_Uniform_uint %buf %uint_0 [[index_4]]
9098
// CHECK: [[word4:%\d+]] = OpLoad %uint [[ptr]]
9199
// CHECK: [[index_5:%\d+]] = OpIAdd %uint [[index_4]] %uint_1
@@ -107,7 +115,8 @@ void main(uint3 tid : SV_DispatchThreadId)
107115
// CHECK: [[word7_ulong_shifted:%\d+]] = OpShiftLeftLogical %ulong [[word7_ulong]] %uint_32
108116
// CHECK: [[val3_ulong:%\d+]] = OpBitwiseOr %ulong [[word6_ulong]] [[word7_ulong_shifted]]
109117
// CHECK: [[val3:%\d+]] = OpBitcast %double [[val3_ulong]]
110-
// CHECK: [[row1:%\d+]] = OpCompositeConstruct %v2double [[val2]] [[val3]]
118+
// CHECK: [[row0:%\d+]] = OpCompositeConstruct %v2double [[val0]] [[val2]]
119+
// CHECK: [[row1:%\d+]] = OpCompositeConstruct %v2double [[val1]] [[val3]]
111120
// CHECK: [[matrix:%\d+]] = OpCompositeConstruct %mat2v2double [[row0]] [[row1]]
112121
// CHECK: OpStore %f64 [[matrix]]
113122
float64_t2x2 f64 = buf.Load<float64_t2x2>(tid.x);
@@ -118,35 +127,35 @@ void main(uint3 tid : SV_DispatchThreadId)
118127
// CHECK: [[ptr:%\d+]] = OpAccessChain %_ptr_Uniform_uint %buf %uint_0 [[index_0]]
119128
// CHECK: [[index_1:%\d+]] = OpIAdd %uint [[index_0]] %uint_1
120129
// CHECK: [[ptr:%\d+]] = OpAccessChain %_ptr_Uniform_uint %buf %uint_0 [[index_1]]
121-
// CHECK: [[row1:%\d+]] = OpCompositeConstruct %v3half
122130
// CHECK: [[ptr:%\d+]] = OpAccessChain %_ptr_Uniform_uint %buf %uint_0 [[index_1]]
123131
// CHECK: [[index_2:%\d+]] = OpIAdd %uint [[index_1]] %uint_1
124132
// CHECK: [[ptr:%\d+]] = OpAccessChain %_ptr_Uniform_uint %buf %uint_0 [[index_2]]
125133
// CHECK: [[ptr:%\d+]] = OpAccessChain %_ptr_Uniform_uint %buf %uint_0 [[index_2]]
126134
// CHECK: [[index_3:%\d+]] = OpIAdd %uint [[index_2]] %uint_1
135+
// CHECK: [[row1:%\d+]] = OpCompositeConstruct %v3half
127136
// CHECK: [[row2:%\d+]] = OpCompositeConstruct %v3half
128137
// CHECK: [[matrix_1:%\d+]] = OpCompositeConstruct %mat2v3half [[row1]] [[row2]]
129138
// CHECK: [[ptr:%\d+]] = OpAccessChain %_ptr_Uniform_uint %buf %uint_0 [[index_3]]
130139
// CHECK: [[ptr:%\d+]] = OpAccessChain %_ptr_Uniform_uint %buf %uint_0 [[index_3]]
131140
// CHECK: [[index_4:%\d+]] = OpIAdd %uint [[index_3]] %uint_1
132141
// CHECK: [[ptr:%\d+]] = OpAccessChain %_ptr_Uniform_uint %buf %uint_0 [[index_4]]
133-
// CHECK: [[row1:%\d+]] = OpCompositeConstruct %v3half
134142
// CHECK: [[ptr:%\d+]] = OpAccessChain %_ptr_Uniform_uint %buf %uint_0 [[index_4]]
135143
// CHECK: [[index_5:%\d+]] = OpIAdd %uint [[index_4]] %uint_1
136144
// CHECK: [[ptr:%\d+]] = OpAccessChain %_ptr_Uniform_uint %buf %uint_0 [[index_5]]
137145
// CHECK: [[ptr:%\d+]] = OpAccessChain %_ptr_Uniform_uint %buf %uint_0 [[index_5]]
138146
// CHECK: [[index_6:%\d+]] = OpIAdd %uint [[index_5]] %uint_1
147+
// CHECK: [[row1:%\d+]] = OpCompositeConstruct %v3half
139148
// CHECK: [[row2:%\d+]] = OpCompositeConstruct %v3half
140149
// CHECK: [[matrix_2:%\d+]] = OpCompositeConstruct %mat2v3half [[row1]] [[row2]]
141150
// CHECK: [[ptr:%\d+]] = OpAccessChain %_ptr_Uniform_uint %buf %uint_0 [[index_6]]
142151
// CHECK: [[ptr:%\d+]] = OpAccessChain %_ptr_Uniform_uint %buf %uint_0 [[index_6]]
143152
// CHECK: [[index_7:%\d+]] = OpIAdd %uint [[index_6]] %uint_1
144153
// CHECK: [[ptr:%\d+]] = OpAccessChain %_ptr_Uniform_uint %buf %uint_0 [[index_7]]
145-
// CHECK: [[row1:%\d+]] = OpCompositeConstruct %v3half
146154
// CHECK: [[ptr:%\d+]] = OpAccessChain %_ptr_Uniform_uint %buf %uint_0 [[index_7]]
147155
// CHECK: [[index_8:%\d+]] = OpIAdd %uint [[index_7]] %uint_1
148156
// CHECK: [[ptr:%\d+]] = OpAccessChain %_ptr_Uniform_uint %buf %uint_0 [[index_8]]
149157
// CHECK: [[ptr:%\d+]] = OpAccessChain %_ptr_Uniform_uint %buf %uint_0 [[index_8]]
158+
// CHECK: [[row1:%\d+]] = OpCompositeConstruct %v3half
150159
// CHECK: [[row2:%\d+]] = OpCompositeConstruct %v3half
151160
// CHECK: [[matrix_3:%\d+]] = OpCompositeConstruct %mat2v3half [[row1]] [[row2]]
152161
// CHECK: [[matrix_array:%\d+]] = OpCompositeConstruct %_arr_mat2v3half_uint_3 [[matrix_1]] [[matrix_2]] [[matrix_3]]
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// RUN: %dxc -T cs_6_2 -E main
2+
//
3+
// In this test, check that matrix order is preserved on a templated store.
4+
5+
ByteAddressBuffer buf;
6+
RWByteAddressBuffer buf2;
7+
8+
[numthreads(64, 1, 1)]
9+
void main(uint3 tid : SV_DispatchThreadId)
10+
{
11+
// CHECK: [[ptr:%\d+]] = OpAccessChain %_ptr_Uniform_uint %buf %uint_0 [[index_0:%\d+]]
12+
// CHECK: [[word0:%\d+]] = OpLoad %uint [[ptr]]
13+
// CHECK: [[val0:%\d+]] = OpBitcast %int [[word0]]
14+
// CHECK:[[index_1:%\d+]] = OpIAdd %uint [[index_0]] %uint_1
15+
// CHECK: [[ptr:%\d+]] = OpAccessChain %_ptr_Uniform_uint %buf %uint_0 [[index_1]]
16+
// CHECK: [[word1:%\d+]] = OpLoad %uint [[ptr]]
17+
// CHECK: [[val1:%\d+]] = OpBitcast %int [[word1:%\d+]]
18+
// CHECK:[[index_2:%\d+]] = OpIAdd %uint [[index_1]] %uint_1
19+
// CHECK: [[ptr:%\d+]] = OpAccessChain %_ptr_Uniform_uint %buf %uint_0 [[index_2]]
20+
// CHECK: [[word2:%\d+]] = OpLoad %uint [[ptr]]
21+
// CHECK: [[val2:%\d+]] = OpBitcast %int [[word2]]
22+
// CHECK:[[index_3:%\d+]] = OpIAdd %uint [[index_2]] %uint_1
23+
// CHECK: [[ptr:%\d+]] = OpAccessChain %_ptr_Uniform_uint %buf %uint_0 [[index_3]]
24+
// CHECK: [[word3:%\d+]] = OpLoad %uint [[ptr]]
25+
// CHECK: [[val3:%\d+]] = OpBitcast %int [[word3]]
26+
// CHECK: [[row0:%\d+]] = OpCompositeConstruct %v2int [[val0]] [[val2]]
27+
// CHECK: [[row1:%\d+]] = OpCompositeConstruct %v2int [[val1]] [[val3]]
28+
// CHECK: [[mat0:%\d+]] = OpCompositeConstruct %_arr_v2int_uint_2 [[row0]] [[row1]]
29+
// CHECK: OpStore [[temp:%\w+]] [[mat0]]
30+
// CHECK: [[mat1:%\d+]] = OpLoad %_arr_v2int_uint_2 [[temp]]
31+
// CHECK: [[elem0:%\d+]] = OpCompositeExtract %int [[mat1]] 0 0
32+
// CHECK: [[elem1:%\d+]] = OpCompositeExtract %int [[mat1]] 1 0
33+
// CHECK: [[elem2:%\d+]] = OpCompositeExtract %int [[mat1]] 0 1
34+
// CHECK: [[elem3:%\d+]] = OpCompositeExtract %int [[mat1]] 1 1
35+
// CHECK: [[ptr:%\d+]] = OpAccessChain %_ptr_Uniform_uint %buf2 %uint_0 [[idx0:%\d+]]
36+
// CHECK: [[val:%\d+]] = OpBitcast %uint [[elem0]]
37+
// CHECK: OpStore [[ptr]] [[val]]
38+
// CHECK: [[idx1:%\d+]] = OpIAdd %uint [[idx0]] %uint_1
39+
// CHECK: [[ptr:%\d+]] = OpAccessChain %_ptr_Uniform_uint %buf2 %uint_0 [[idx1]]
40+
// CHECK: [[val:%\d+]] = OpBitcast %uint [[elem1]]
41+
// CHECK: OpStore [[ptr]] [[val]]
42+
// CHECK: [[idx2:%\d+]] = OpIAdd %uint [[idx1]] %uint_1
43+
// CHECK: [[ptr:%\d+]] = OpAccessChain %_ptr_Uniform_uint %buf2 %uint_0 [[idx2]]
44+
// CHECK: [[val:%\d+]] = OpBitcast %uint [[elem2]]
45+
// CHECK: OpStore [[ptr]] [[val]]
46+
// CHECK: [[idx3:%\d+]] = OpIAdd %uint [[idx2]] %uint_1
47+
// CHECK: [[ptr:%\d+]] = OpAccessChain %_ptr_Uniform_uint %buf2 %uint_0 [[idx3]]
48+
// CHECK: [[val:%\d+]] = OpBitcast %uint [[elem3]]
49+
// CHECK: OpStore [[ptr]] [[val]]
50+
51+
int2x2 i = buf.Load<int2x2>(tid.x);
52+
buf2.Store<int2x2>(tid.x, i);
53+
}

0 commit comments

Comments
 (0)