Generalize WGSL polyfilling logic to include arrays.
We now support polyfilling arrays, matrices and arrays of matrices
when native WGSL alignment mismatches std140 alignment.
Change-Id: I06721bb8f9c2e89acc772dd1baaa0861be827033
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/741116
Commit-Queue: John Stiles <johnstiles@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
diff --git a/gn/sksl_tests.gni b/gn/sksl_tests.gni
index 622fc83..a3d08bf 100644
--- a/gn/sksl_tests.gni
+++ b/gn/sksl_tests.gni
@@ -408,6 +408,7 @@
"wgsl/OutParams.sksl",
"wgsl/Sample.sksl",
"wgsl/TernaryThenShortCircuit.sksl",
+ "wgsl/UniformArrays.sksl",
"wgsl/UniformMatrices.sksl",
"wgsl/UserDefinedPipelineIO.sksl",
"wgsl/VertexPositionOutputIsAlwaysDeclared.vert",
diff --git a/resources/sksl/BUILD.bazel b/resources/sksl/BUILD.bazel
index 2ed5acb..e88880d 100644
--- a/resources/sksl/BUILD.bazel
+++ b/resources/sksl/BUILD.bazel
@@ -1085,6 +1085,7 @@
"wgsl/OutParams.sksl",
"wgsl/Sample.sksl",
"wgsl/TernaryThenShortCircuit.sksl",
+ "wgsl/UniformArrays.sksl",
"wgsl/UniformMatrices.sksl",
"wgsl/UserDefinedPipelineIO.sksl",
"wgsl/VertexPositionOutputIsAlwaysDeclared.vert",
diff --git a/resources/sksl/shared/InterfaceBlockNamedArray.sksl b/resources/sksl/shared/InterfaceBlockNamedArray.sksl
index fc797be..69f1343 100644
--- a/resources/sksl/shared/InterfaceBlockNamedArray.sksl
+++ b/resources/sksl/shared/InterfaceBlockNamedArray.sksl
@@ -1,8 +1,10 @@
layout(binding=123) uniform testBlock {
- layout (offset=0) float x;
+ layout (offset=0) float s;
layout (offset=16) float2x2 m;
+ layout (offset=48) float a[2];
+ layout (offset=80) float2x2 am[2];
} test[2];
void main() {
- sk_FragColor = half4(test[0].x, test[0].m[0][1], test[1].m[1]);
+ sk_FragColor = half4(test[0].s, test[1].m[1][0], test[0].a[1], test[1].am[1][0][1]);
}
diff --git a/resources/sksl/wgsl/UniformArrays.sksl b/resources/sksl/wgsl/UniformArrays.sksl
new file mode 100644
index 0000000..7edbb11
--- /dev/null
+++ b/resources/sksl/wgsl/UniformArrays.sksl
@@ -0,0 +1,59 @@
+// Our buffers are in std140 layout, so the generated code will need to compensate.
+
+layout(set=0, binding=1) uniform UniformBuffer {
+ float uf[3];
+ float2 uf2[3];
+ float3 uf3[3];
+ float4 uf4[3];
+ half uh[3];
+ half2 uh2[3];
+ half3 uh3[3];
+ half4 uh4[3];
+ int ui[3];
+ int2 ui2[3];
+ int3 ui3[3];
+ int4 ui4[3];
+};
+
+layout(set=0, binding=2) buffer StorageBuffer {
+ float sf[4];
+ float2 sf2[4];
+ float3 sf3[4];
+ float4 sf4[4];
+ half sh[4];
+ half2 sh2[4];
+ half3 sh3[4];
+ half4 sh4[4];
+ int si[4];
+ int2 si2[4];
+ int3 si3[4];
+ int4 si4[4];
+};
+
+half4 main() {
+ float value = float(uf [1] ) +
+ float(uf2[1].x) +
+ float(uf3[1].x) +
+ float(uf4[1].x) +
+ float(uh [1] ) +
+ float(uh2[1].x) +
+ float(uh3[1].x) +
+ float(uh4[1].x) +
+ float(ui [1] ) +
+ float(ui2[1].x) +
+ float(ui3[1].x) +
+ float(ui4[1].x) +
+ float(sf [1] ) +
+ float(sf2[1].x) +
+ float(sf3[1].x) +
+ float(sf4[1].x) +
+ float(sh [1] ) +
+ float(sh2[1].x) +
+ float(sh3[1].x) +
+ float(sh4[1].x) +
+ float(si [1] ) +
+ float(si2[1].x) +
+ float(si3[1].x) +
+ float(si4[1].x);
+ return half4(value);
+}
diff --git a/resources/sksl/wgsl/UniformMatrices.sksl b/resources/sksl/wgsl/UniformMatrices.sksl
index e66f764..dde4984 100644
--- a/resources/sksl/wgsl/UniformMatrices.sksl
+++ b/resources/sksl/wgsl/UniformMatrices.sksl
@@ -10,6 +10,15 @@
float4x2 u42;
float4x3 u43;
float4x4 u44;
+ float2x2 au22[3];
+ float2x3 au23[3];
+ float2x4 au24[3];
+ float3x2 au32[3];
+ float3x3 au33[3];
+ float3x4 au34[3];
+ float4x2 au42[3];
+ float4x3 au43[3];
+ float4x4 au44[3];
};
layout(set=0, binding=2) buffer StorageBuffer {
@@ -22,8 +31,53 @@
float4x2 s42;
float4x3 s43;
float4x4 s44;
+ float2x2 as22[3];
+ float2x3 as23[3];
+ float2x4 as24[3];
+ float3x2 as32[3];
+ float3x3 as33[3];
+ float3x4 as34[3];
+ float4x2 as42[3];
+ float4x3 as43[3];
+ float4x4 as44[3];
};
half4 main() {
- return half4(0);
+ float value = u22[0][0] +
+ u23[0][0] +
+ u24[0][0] +
+ u32[0][0] +
+ u33[0][0] +
+ u34[0][0] +
+ u42[0][0] +
+ u43[0][0] +
+ au44[0][0][0] +
+ au22[0][0][0] +
+ au23[0][0][0] +
+ au24[0][0][0] +
+ au32[0][0][0] +
+ au33[0][0][0] +
+ au34[0][0][0] +
+ au42[0][0][0] +
+ au43[0][0][0] +
+ au44[0][0][0] +
+ s22[0][0] +
+ s23[0][0] +
+ s24[0][0] +
+ s32[0][0] +
+ s33[0][0] +
+ s34[0][0] +
+ s42[0][0] +
+ s43[0][0] +
+ as44[0][0][0] +
+ as22[0][0][0] +
+ as23[0][0][0] +
+ as24[0][0][0] +
+ as32[0][0][0] +
+ as33[0][0][0] +
+ as34[0][0][0] +
+ as42[0][0][0] +
+ as43[0][0][0] +
+ as44[0][0][0];
+ return half4(value);
}
diff --git a/src/sksl/codegen/SkSLWGSLCodeGenerator.cpp b/src/sksl/codegen/SkSLWGSLCodeGenerator.cpp
index a54753f..4987533 100644
--- a/src/sksl/codegen/SkSLWGSLCodeGenerator.cpp
+++ b/src/sksl/codegen/SkSLWGSLCodeGenerator.cpp
@@ -635,61 +635,89 @@
void WGSLCodeGenerator::writeUniformPolyfills() {
// If we didn't encounter any uniforms that need polyfilling, there is nothing to do.
- if (fMatrixPolyfillFields.empty()) {
+ if (fFieldPolyfillMap.empty()) {
return;
}
// We store the list of polyfilled fields as pointers in a hash-map, so the order can be
// inconsistent across runs. For determinism, we sort the polyfilled objects by name here.
- TArray<const MatrixPolyfillFieldMap::Pair*> matrixPolyfillOrderedFields;
- matrixPolyfillOrderedFields.reserve_exact(fMatrixPolyfillFields.count());
+ TArray<const FieldPolyfillMap::Pair*> orderedFields;
+ orderedFields.reserve_exact(fFieldPolyfillMap.count());
- fMatrixPolyfillFields.foreach([&](const MatrixPolyfillFieldMap::Pair& pair) {
- matrixPolyfillOrderedFields.push_back(&pair);
+ fFieldPolyfillMap.foreach([&](const FieldPolyfillMap::Pair& pair) {
+ orderedFields.push_back(&pair);
});
- std::sort(matrixPolyfillOrderedFields.begin(),
- matrixPolyfillOrderedFields.end(),
- [](const MatrixPolyfillFieldMap::Pair* a, const MatrixPolyfillFieldMap::Pair* b) {
+ std::sort(orderedFields.begin(),
+ orderedFields.end(),
+ [](const FieldPolyfillMap::Pair* a, const FieldPolyfillMap::Pair* b) {
return a->second.fReplacementName < b->second.fReplacementName;
});
+ THashSet<const Type*> writtenArrayElementPolyfill;
bool writtenUniformMatrixPolyfill[5][5] = {}; // m[column][row] for each matrix type
bool writtenUniformRowPolyfill[5] = {}; // for each matrix row-size
bool anyFieldAccessed = false;
- for (const MatrixPolyfillFieldMap::Pair* pair : matrixPolyfillOrderedFields) {
- // Create structs representing the matrix as an array of vectors, whether or not the matrix
- // is ever accessed by the SkSL. (The struct itself is mentioned in the list of uniforms.)
+ for (const FieldPolyfillMap::Pair* pair : orderedFields) {
const auto& [field, info] = *pair;
- int c = field->fType->columns();
- int r = field->fType->rows();
- if (!writtenUniformRowPolyfill[r]) {
- writtenUniformRowPolyfill[r] = true;
+ const Type* type = field->fType;
- this->write("struct _skRow");
- this->write(std::to_string(r));
- this->writeLine(" {");
- this->write(" @size(16) r : vec");
- this->write(std::to_string(r));
- this->write("<");
- this->write(to_wgsl_type(field->fType->componentType()));
- this->writeLine(">");
- this->writeLine("};");
+ if (info.fIsArray) {
+ type = &type->componentType();
+ if (!writtenArrayElementPolyfill.contains(type)) {
+ writtenArrayElementPolyfill.add(type);
+ this->write("struct _skArrayElement_");
+ this->write(type->abbreviatedName());
+ this->writeLine(" {");
+
+ if (info.fIsMatrix) {
+ // Create a struct representing the array containing std140-padded matrices.
+ this->write(" e : _skMatrix");
+ this->write(std::to_string(type->columns()));
+ this->writeLine(std::to_string(type->rows()));
+ } else {
+ // Create a struct representing the array with extra padding between elements.
+ this->write(" @size(16) e : ");
+ this->writeLine(to_wgsl_type(*type));
+ }
+ this->writeLine("};");
+ }
}
- if (!writtenUniformMatrixPolyfill[c][r]) {
- writtenUniformMatrixPolyfill[c][r] = true;
+ if (info.fIsMatrix) {
+ // Create structs representing the matrix as an array of vectors, whether or not the
+ // matrix is ever accessed by the SkSL. (The struct itself is mentioned in the list of
+ // uniforms.)
+ int c = type->columns();
+ int r = type->rows();
+ if (!writtenUniformRowPolyfill[r]) {
+ writtenUniformRowPolyfill[r] = true;
- this->write("struct _skMatrix");
- this->write(std::to_string(c));
- this->write(std::to_string(r));
- this->writeLine(" {");
- this->write(" c : array<_skRow");
- this->write(std::to_string(r));
- this->write(", ");
- this->write(std::to_string(c));
- this->writeLine(">");
- this->writeLine("};");
+ this->write("struct _skRow");
+ this->write(std::to_string(r));
+ this->writeLine(" {");
+ this->write(" @size(16) r : vec");
+ this->write(std::to_string(r));
+ this->write("<");
+ this->write(to_wgsl_type(type->componentType()));
+ this->writeLine(">");
+ this->writeLine("};");
+ }
+
+ if (!writtenUniformMatrixPolyfill[c][r]) {
+ writtenUniformMatrixPolyfill[c][r] = true;
+
+ this->write("struct _skMatrix");
+ this->write(std::to_string(c));
+ this->write(std::to_string(r));
+ this->writeLine(" {");
+ this->write(" c : array<_skRow");
+ this->write(std::to_string(r));
+ this->write(", ");
+ this->write(std::to_string(c));
+ this->writeLine(">");
+ this->writeLine("};");
+ }
}
// We create a polyfill variable only if the uniform was actually accessed.
@@ -723,7 +751,7 @@
this->writeLine("fn _skInitializePolyfilledUniforms() {");
++fIndentation;
- for (const MatrixPolyfillFieldMap::Pair* pair : matrixPolyfillOrderedFields) {
+ for (const FieldPolyfillMap::Pair* pair : orderedFields) {
// Only initialize a polyfill global if the uniform was actually accessed.
const auto& [field, info] = *pair;
if (!info.fWasAccessed) {
@@ -739,34 +767,69 @@
// Initialize the global variable associated with this uniform.
// If the interface block is arrayed, the associated global will be arrayed as well.
- int numElements = interfaceBlockType.isArray() ? interfaceBlockType.columns() : 1;
- for (int arrayIdx = 0; arrayIdx < numElements; ++arrayIdx) {
+ int numIBElements = interfaceBlockType.isArray() ? interfaceBlockType.columns() : 1;
+ for (int ibIdx = 0; ibIdx < numIBElements; ++ibIdx) {
this->write(info.fReplacementName);
if (interfaceBlockType.isArray()) {
this->write("[");
- this->write(std::to_string(arrayIdx));
+ this->write(std::to_string(ibIdx));
this->write("]");
}
this->write(" = ");
- this->write(to_wgsl_type(*field->fType));
- this->write("(");
- auto separator = String::Separator();
- int numColumns = field->fType->columns();
- for (int column = 0; column < numColumns; column++) {
- this->write(separator());
- this->write(instanceName);
- if (interfaceBlockType.isArray()) {
- this->write("[");
- this->write(std::to_string(arrayIdx));
- this->write("]");
- }
- this->write(".");
- this->write(this->assembleName(field->fName));
- this->write(".c[");
- this->write(std::to_string(column));
- this->write("].r");
+
+ const Type* type = field->fType;
+ int numArrayElements;
+ if (info.fIsArray) {
+ this->write(to_wgsl_type(*type));
+ this->write("(");
+ numArrayElements = type->columns();
+ type = &type->componentType();
+ } else{
+ numArrayElements = 1;
}
- this->writeLine(");");
+
+ auto arraySeparator = String::Separator();
+ for (int arrayIdx = 0; arrayIdx < numArrayElements; arrayIdx++) {
+ this->write(arraySeparator());
+
+ std::string fieldName{instanceName};
+ if (interfaceBlockType.isArray()) {
+ fieldName += '[';
+ fieldName += std::to_string(ibIdx);
+ fieldName += ']';
+ }
+ fieldName += '.';
+ fieldName += this->assembleName(field->fName);
+
+ if (info.fIsArray) {
+ fieldName += '[';
+ fieldName += std::to_string(arrayIdx);
+ fieldName += "].e";
+ }
+
+ if (info.fIsMatrix) {
+ this->write(to_wgsl_type(*type));
+ this->write("(");
+ int numColumns = type->columns();
+ auto matrixSeparator = String::Separator();
+ for (int column = 0; column < numColumns; column++) {
+ this->write(matrixSeparator());
+ this->write(fieldName);
+ this->write(".c[");
+ this->write(std::to_string(column));
+ this->write("].r");
+ }
+ this->write(")");
+ } else {
+ this->write(fieldName);
+ }
+ }
+
+ if (info.fIsArray) {
+ this->write(")");
+ }
+
+ this->writeLine(";");
}
}
@@ -1021,7 +1084,7 @@
// Initialize polyfilled matrix uniforms if any were used.
fIndentation++;
- for (const auto& [field, info] : fMatrixPolyfillFields) {
+ for (const auto& [field, info] : fFieldPolyfillMap) {
if (info.fWasAccessed) {
this->writeLine("_skInitializePolyfilledUniforms();");
break;
@@ -1890,15 +1953,15 @@
const Field* field = &f.base()->type().fields()[f.fieldIndex()];
std::string expr;
- if (MatrixPolyfillInfo* polyfillInfo = fMatrixPolyfillFields.find(field)) {
+ if (FieldPolyfillInfo* polyfillInfo = fFieldPolyfillMap.find(field)) {
// We found a matrix uniform. We are required to pass some matrix uniforms as array vectors,
// since the std140 layout for a matrix assumes 4-column vectors for each row, and WGSL
// tightly packs 2-column matrices. When emitting code, we replace the field-access
// expression with a global variable which holds an unpacked version of the uniform.
polyfillInfo->fWasAccessed = true;
- // The matrix polyfill can either be based directly onto a uniform in an interface block, or
- // it might be based on an index-expression onto a uniform if the block is arrayed.
+ // The polyfill can either be based directly onto a uniform in an interface block, or it
+ // might be based on an index-expression onto a uniform if the interface block is arrayed.
const Expression* base = f.base().get();
const IndexExpression* indexExpr = nullptr;
if (base->is<IndexExpression>()) {
@@ -3186,10 +3249,22 @@
this->write(this->assembleName(field.fName));
this->write(": ");
- if (fMatrixPolyfillFields.find(&field)) {
- this->write("_skMatrix");
- this->write(std::to_string(field.fType->columns()));
- this->write(std::to_string(field.fType->rows()));
+ if (const FieldPolyfillInfo* info = fFieldPolyfillMap.find(&field)) {
+ if (info->fIsArray) {
+ // This properly handles arrays of matrices, as well as arrays of other primitives.
+ SkASSERT(field.fType->isArray());
+ this->write("array<_skArrayElement_");
+ this->write(field.fType->abbreviatedName());
+ this->write(", ");
+ this->write(std::to_string(field.fType->columns()));
+ this->write(">");
+ } else if (info->fIsMatrix) {
+ this->write("_skMatrix");
+ this->write(std::to_string(field.fType->columns()));
+ this->write(std::to_string(field.fType->rows()));
+ } else {
+ SkDEBUGFAILF("need polyfill for %s", info->fReplacementName.c_str());
+ }
} else {
this->write(to_wgsl_type(*field.fType));
}
@@ -3332,21 +3407,41 @@
const Type& structType = interfaceBlock->var()->type().componentType();
for (const Field& field : structType.fields()) {
- // Matrices will be represented as 16-byte aligned arrays in std140, and reconstituted into
- // proper matrices as they are later accessed. We need to synthesize helpers for this.
- if (field.fType->isMatrix()) {
- // A polyfill is only necessary if the std140 layout (what Skia provides) actually
- // differs from native layout (what WGSL expects). Otherwise the matrix is used as-is.
- if (std140.stride(*field.fType) == native.stride(*field.fType)) {
- continue;
- }
+ const Type* type = field.fType;
+ bool needsArrayPolyfill = false;
+ bool needsMatrixPolyfill = false;
+ auto isPolyfillableMatrixType = [&](const Type* type) {
+ return type->isMatrix() && std140.stride(*type) != native.stride(*type);
+ };
+
+ if (isPolyfillableMatrixType(type)) {
+ // Matrices will be represented as 16-byte aligned arrays in std140, and reconstituted
+ // into proper matrices as they are later accessed. We need to synthesize polyfill.
+ needsMatrixPolyfill = true;
+ } else if (type->isArray() && !type->isUnsizedArray() &&
+ !type->componentType().isOpaque()) {
+ const Type* innerType = &type->componentType();
+ if (isPolyfillableMatrixType(innerType)) {
+ // Use a polyfill when the array contains a matrix that requires polyfill.
+ needsArrayPolyfill = true;
+ needsMatrixPolyfill = true;
+ } else if (native.size(*innerType) < 16) {
+ // Use a polyfill when the array elements are smaller than 16 bytes, since std140
+ // will pad elements to a 16-byte stride.
+ needsArrayPolyfill = true;
+ }
+ }
+
+ if (needsArrayPolyfill || needsMatrixPolyfill) {
// Add a polyfill for this matrix type.
- MatrixPolyfillInfo info;
+ FieldPolyfillInfo info;
info.fInterfaceBlock = interfaceBlock;
- info.fReplacementName = "_skUnpacked_" + std::string(instanceName) + '_'
- + this->assembleName(field.fName);
- fMatrixPolyfillFields.set(&field, info);
+ info.fReplacementName = "_skUnpacked_" + std::string(instanceName) + '_' +
+ this->assembleName(field.fName);
+ info.fIsArray = needsArrayPolyfill;
+ info.fIsMatrix = needsMatrixPolyfill;
+ fFieldPolyfillMap.set(&field, info);
}
}
}
diff --git a/src/sksl/codegen/SkSLWGSLCodeGenerator.h b/src/sksl/codegen/SkSLWGSLCodeGenerator.h
index 79166e3..3f08602 100644
--- a/src/sksl/codegen/SkSLWGSLCodeGenerator.h
+++ b/src/sksl/codegen/SkSLWGSLCodeGenerator.h
@@ -357,16 +357,20 @@
bool fWrittenInverse3 = false;
bool fWrittenInverse4 = false;
- // These fields control uniform-matrix polyfill support. Because our uniform data is provided in
- // std140 layout, matrices need to be represented as arrays of @size(16)-aligned vectors, and
- // are unpacked into globals at the shader entrypoint.
- struct MatrixPolyfillInfo {
+ // These fields control uniform polyfill support in cases where WGSL and std140 disagree.
+ // In std140 layout, matrices need to be represented as arrays of @size(16)-aligned vectors, and
+ // array elements are wrapped in a struct containing a single @size(16)-aligned element. Arrays
+ // of matrices combine both wrappers. These wrapper structs are unpacked into natively-typed
+ // globals at the shader entrypoint.
+ struct FieldPolyfillInfo {
const InterfaceBlock* fInterfaceBlock;
std::string fReplacementName;
+ bool fIsArray = false;
+ bool fIsMatrix = false;
bool fWasAccessed = false;
};
- using MatrixPolyfillFieldMap = skia_private::THashMap<const Field*, MatrixPolyfillInfo>;
- MatrixPolyfillFieldMap fMatrixPolyfillFields;
+ using FieldPolyfillMap = skia_private::THashMap<const Field*, FieldPolyfillInfo>;
+ FieldPolyfillMap fFieldPolyfillMap;
// Output processing state.
int fIndentation = 0;
diff --git a/tests/sksl/shared/InterfaceBlockNamedArray.asm.frag b/tests/sksl/shared/InterfaceBlockNamedArray.asm.frag
index b3daa42..632ae52 100644
--- a/tests/sksl/shared/InterfaceBlockNamedArray.asm.frag
+++ b/tests/sksl/shared/InterfaceBlockNamedArray.asm.frag
@@ -1,6 +1,6 @@
### Compilation failed:
-error: SPIR-V validation error: Block decoration on target <id> '10[%_arr_testBlock_int_2]' must be a structure type
+error: SPIR-V validation error: Block decoration on target <id> '12[%_arr_testBlock_int_2]' must be a structure type
OpDecorate %_arr_testBlock_int_2 Block
OpCapability Shader
@@ -9,16 +9,22 @@
OpEntryPoint Fragment %main "main" %sk_Clockwise %sk_FragColor
OpExecutionMode %main OriginUpperLeft
OpName %testBlock "testBlock"
- OpMemberName %testBlock 0 "x"
+ OpMemberName %testBlock 0 "s"
OpMemberName %testBlock 1 "m"
+ OpMemberName %testBlock 2 "a"
+ OpMemberName %testBlock 3 "am"
OpName %sk_Clockwise "sk_Clockwise"
OpName %sk_FragColor "sk_FragColor"
OpName %main "main"
+ OpDecorate %_arr_float_int_2 ArrayStride 16
+ OpDecorate %_arr_mat2v2float_int_2 ArrayStride 32
OpMemberDecorate %testBlock 0 Offset 0
OpMemberDecorate %testBlock 1 Offset 16
OpMemberDecorate %testBlock 1 ColMajor
OpMemberDecorate %testBlock 1 MatrixStride 16
- OpDecorate %_arr_testBlock_int_2 ArrayStride 48
+ OpMemberDecorate %testBlock 2 Offset 48
+ OpMemberDecorate %testBlock 3 Offset 80
+ OpDecorate %_arr_testBlock_int_2 ArrayStride 144
OpDecorate %_arr_testBlock_int_2 Block
OpDecorate %3 Binding 123
OpDecorate %3 DescriptorSet 0
@@ -26,15 +32,15 @@
OpDecorate %sk_FragColor RelaxedPrecision
OpDecorate %sk_FragColor Location 0
OpDecorate %sk_FragColor Index 0
- OpDecorate %32 RelaxedPrecision
- OpDecorate %33 RelaxedPrecision
- OpDecorate %34 RelaxedPrecision
+ OpDecorate %38 RelaxedPrecision
%float = OpTypeFloat 32
%v2float = OpTypeVector %float 2
%mat2v2float = OpTypeMatrix %v2float 2
- %testBlock = OpTypeStruct %float %mat2v2float
%int = OpTypeInt 32 1
%int_2 = OpConstant %int 2
+%_arr_float_int_2 = OpTypeArray %float %int_2
+%_arr_mat2v2float_int_2 = OpTypeArray %mat2v2float %int_2
+ %testBlock = OpTypeStruct %float %mat2v2float %_arr_float_int_2 %_arr_mat2v2float_int_2
%_arr_testBlock_int_2 = OpTypeArray %testBlock %int_2
%_ptr_Uniform__arr_testBlock_int_2 = OpTypePointer Uniform %_arr_testBlock_int_2
%3 = OpVariable %_ptr_Uniform__arr_testBlock_int_2 Uniform
@@ -45,24 +51,26 @@
%_ptr_Output_v4float = OpTypePointer Output %v4float
%sk_FragColor = OpVariable %_ptr_Output_v4float Output
%void = OpTypeVoid
- %19 = OpTypeFunction %void
+ %21 = OpTypeFunction %void
%int_0 = OpConstant %int 0
%_ptr_Uniform_float = OpTypePointer Uniform %float
%int_1 = OpConstant %int 1
%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
- %main = OpFunction %void None %19
- %20 = OpLabel
- %22 = OpAccessChain %_ptr_Uniform_float %3 %int_0 %int_0
- %24 = OpLoad %float %22
- %26 = OpAccessChain %_ptr_Uniform_v2float %3 %int_0 %int_1 %int_0
- %28 = OpLoad %v2float %26
- %29 = OpCompositeExtract %float %28 1
- %30 = OpAccessChain %_ptr_Uniform_v2float %3 %int_1 %int_1 %int_1
- %31 = OpLoad %v2float %30
- %32 = OpCompositeExtract %float %31 0
- %33 = OpCompositeExtract %float %31 1
- %34 = OpCompositeConstruct %v4float %24 %29 %32 %33
- OpStore %sk_FragColor %34
+ %int_3 = OpConstant %int 3
+ %main = OpFunction %void None %21
+ %22 = OpLabel
+ %24 = OpAccessChain %_ptr_Uniform_float %3 %int_0 %int_0
+ %26 = OpLoad %float %24
+ %28 = OpAccessChain %_ptr_Uniform_v2float %3 %int_1 %int_1 %int_1
+ %30 = OpLoad %v2float %28
+ %31 = OpCompositeExtract %float %30 0
+ %32 = OpAccessChain %_ptr_Uniform_float %3 %int_0 %int_2 %int_1
+ %33 = OpLoad %float %32
+ %35 = OpAccessChain %_ptr_Uniform_v2float %3 %int_1 %int_3 %int_1 %int_0
+ %36 = OpLoad %v2float %35
+ %37 = OpCompositeExtract %float %36 1
+ %38 = OpCompositeConstruct %v4float %26 %31 %33 %37
+ OpStore %sk_FragColor %38
OpReturn
OpFunctionEnd
diff --git a/tests/sksl/shared/InterfaceBlockNamedArray.glsl b/tests/sksl/shared/InterfaceBlockNamedArray.glsl
index 0d89aed..49ee265 100644
--- a/tests/sksl/shared/InterfaceBlockNamedArray.glsl
+++ b/tests/sksl/shared/InterfaceBlockNamedArray.glsl
@@ -1,9 +1,11 @@
out vec4 sk_FragColor;
layout (binding = 123) uniform testBlock {
- layout (offset = 0) float x;
+ layout (offset = 0) float s;
layout (offset = 16) mat2 m;
+ layout (offset = 48) float[2] a;
+ layout (offset = 80) mat2[2] am;
} test[2];
void main() {
- sk_FragColor = vec4(test[0].x, test[0].m[0].y, test[1].m[1]);
+ sk_FragColor = vec4(test[0].s, test[1].m[1].x, test[0].a[1], test[1].am[1][0].y);
}
diff --git a/tests/sksl/shared/InterfaceBlockNamedArray.hlsl b/tests/sksl/shared/InterfaceBlockNamedArray.hlsl
index b3daa42..632ae52 100644
--- a/tests/sksl/shared/InterfaceBlockNamedArray.hlsl
+++ b/tests/sksl/shared/InterfaceBlockNamedArray.hlsl
@@ -1,6 +1,6 @@
### Compilation failed:
-error: SPIR-V validation error: Block decoration on target <id> '10[%_arr_testBlock_int_2]' must be a structure type
+error: SPIR-V validation error: Block decoration on target <id> '12[%_arr_testBlock_int_2]' must be a structure type
OpDecorate %_arr_testBlock_int_2 Block
OpCapability Shader
@@ -9,16 +9,22 @@
OpEntryPoint Fragment %main "main" %sk_Clockwise %sk_FragColor
OpExecutionMode %main OriginUpperLeft
OpName %testBlock "testBlock"
- OpMemberName %testBlock 0 "x"
+ OpMemberName %testBlock 0 "s"
OpMemberName %testBlock 1 "m"
+ OpMemberName %testBlock 2 "a"
+ OpMemberName %testBlock 3 "am"
OpName %sk_Clockwise "sk_Clockwise"
OpName %sk_FragColor "sk_FragColor"
OpName %main "main"
+ OpDecorate %_arr_float_int_2 ArrayStride 16
+ OpDecorate %_arr_mat2v2float_int_2 ArrayStride 32
OpMemberDecorate %testBlock 0 Offset 0
OpMemberDecorate %testBlock 1 Offset 16
OpMemberDecorate %testBlock 1 ColMajor
OpMemberDecorate %testBlock 1 MatrixStride 16
- OpDecorate %_arr_testBlock_int_2 ArrayStride 48
+ OpMemberDecorate %testBlock 2 Offset 48
+ OpMemberDecorate %testBlock 3 Offset 80
+ OpDecorate %_arr_testBlock_int_2 ArrayStride 144
OpDecorate %_arr_testBlock_int_2 Block
OpDecorate %3 Binding 123
OpDecorate %3 DescriptorSet 0
@@ -26,15 +32,15 @@
OpDecorate %sk_FragColor RelaxedPrecision
OpDecorate %sk_FragColor Location 0
OpDecorate %sk_FragColor Index 0
- OpDecorate %32 RelaxedPrecision
- OpDecorate %33 RelaxedPrecision
- OpDecorate %34 RelaxedPrecision
+ OpDecorate %38 RelaxedPrecision
%float = OpTypeFloat 32
%v2float = OpTypeVector %float 2
%mat2v2float = OpTypeMatrix %v2float 2
- %testBlock = OpTypeStruct %float %mat2v2float
%int = OpTypeInt 32 1
%int_2 = OpConstant %int 2
+%_arr_float_int_2 = OpTypeArray %float %int_2
+%_arr_mat2v2float_int_2 = OpTypeArray %mat2v2float %int_2
+ %testBlock = OpTypeStruct %float %mat2v2float %_arr_float_int_2 %_arr_mat2v2float_int_2
%_arr_testBlock_int_2 = OpTypeArray %testBlock %int_2
%_ptr_Uniform__arr_testBlock_int_2 = OpTypePointer Uniform %_arr_testBlock_int_2
%3 = OpVariable %_ptr_Uniform__arr_testBlock_int_2 Uniform
@@ -45,24 +51,26 @@
%_ptr_Output_v4float = OpTypePointer Output %v4float
%sk_FragColor = OpVariable %_ptr_Output_v4float Output
%void = OpTypeVoid
- %19 = OpTypeFunction %void
+ %21 = OpTypeFunction %void
%int_0 = OpConstant %int 0
%_ptr_Uniform_float = OpTypePointer Uniform %float
%int_1 = OpConstant %int 1
%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float
- %main = OpFunction %void None %19
- %20 = OpLabel
- %22 = OpAccessChain %_ptr_Uniform_float %3 %int_0 %int_0
- %24 = OpLoad %float %22
- %26 = OpAccessChain %_ptr_Uniform_v2float %3 %int_0 %int_1 %int_0
- %28 = OpLoad %v2float %26
- %29 = OpCompositeExtract %float %28 1
- %30 = OpAccessChain %_ptr_Uniform_v2float %3 %int_1 %int_1 %int_1
- %31 = OpLoad %v2float %30
- %32 = OpCompositeExtract %float %31 0
- %33 = OpCompositeExtract %float %31 1
- %34 = OpCompositeConstruct %v4float %24 %29 %32 %33
- OpStore %sk_FragColor %34
+ %int_3 = OpConstant %int 3
+ %main = OpFunction %void None %21
+ %22 = OpLabel
+ %24 = OpAccessChain %_ptr_Uniform_float %3 %int_0 %int_0
+ %26 = OpLoad %float %24
+ %28 = OpAccessChain %_ptr_Uniform_v2float %3 %int_1 %int_1 %int_1
+ %30 = OpLoad %v2float %28
+ %31 = OpCompositeExtract %float %30 0
+ %32 = OpAccessChain %_ptr_Uniform_float %3 %int_0 %int_2 %int_1
+ %33 = OpLoad %float %32
+ %35 = OpAccessChain %_ptr_Uniform_v2float %3 %int_1 %int_3 %int_1 %int_0
+ %36 = OpLoad %v2float %35
+ %37 = OpCompositeExtract %float %36 1
+ %38 = OpCompositeConstruct %v4float %26 %31 %33 %37
+ OpStore %sk_FragColor %38
OpReturn
OpFunctionEnd
diff --git a/tests/sksl/shared/InterfaceBlockNamedArray.metal b/tests/sksl/shared/InterfaceBlockNamedArray.metal
index a2ec37b..66baadb 100644
--- a/tests/sksl/shared/InterfaceBlockNamedArray.metal
+++ b/tests/sksl/shared/InterfaceBlockNamedArray.metal
@@ -7,9 +7,13 @@
half4 sk_FragColor [[color(0)]];
};
struct testBlock {
- float x;
+ float s;
char pad0[12];
float2x2 m;
+ char pad1[16];
+ array<float, 2> a;
+ char pad2[24];
+ array<float2x2, 2> am;
} test[2];
struct Globals {
constant testBlock* test;
@@ -19,6 +23,6 @@
(void)_globals;
Outputs _out;
(void)_out;
- _out.sk_FragColor = half4(half(_uniforms.test[0].x), half(_uniforms.test[0].m[0].y), half2(_uniforms.test[1].m[1]));
+ _out.sk_FragColor = half4(half(_uniforms.test[0].s), half(_uniforms.test[1].m[1].x), half(_uniforms.test[0].a[1]), half(_uniforms.test[1].am[1][0].y));
return _out;
}
diff --git a/tests/sksl/shared/InterfaceBlockNamedArray.skrp b/tests/sksl/shared/InterfaceBlockNamedArray.skrp
index d630e33..2387e92 100644
--- a/tests/sksl/shared/InterfaceBlockNamedArray.skrp
+++ b/tests/sksl/shared/InterfaceBlockNamedArray.skrp
@@ -3,19 +3,22 @@
error: 1: interface blocks are not allowed in this kind of program
layout(binding=123) uniform testBlock {
^^^^^^^^^
-error: 6: 'main' must return: 'vec4', 'float4', or 'half4'
+error: 8: 'main' must return: 'vec4', 'float4', or 'half4'
void main() {
^^^^^^^^^^^
-error: 7: unknown identifier 'sk_FragColor'
- sk_FragColor = half4(test[0].x, test[0].m[0][1], test[1].m[1]);
+error: 9: unknown identifier 'sk_FragColor'
+ sk_FragColor = half4(test[0].s, test[1].m[1][0], test[0].a[1], test[1].am[1][0][1]);
^^^^^^^^^^^^
-error: 7: unknown identifier 'test'
- sk_FragColor = half4(test[0].x, test[0].m[0][1], test[1].m[1]);
+error: 9: unknown identifier 'test'
+ sk_FragColor = half4(test[0].s, test[1].m[1][0], test[0].a[1], test[1].am[1][0][1]);
^^^^
-error: 7: unknown identifier 'test'
- sk_FragColor = half4(test[0].x, test[0].m[0][1], test[1].m[1]);
+error: 9: unknown identifier 'test'
+ sk_FragColor = half4(test[0].s, test[1].m[1][0], test[0].a[1], test[1].am[1][0][1]);
^^^^
-error: 7: unknown identifier 'test'
- sk_FragColor = half4(test[0].x, test[0].m[0][1], test[1].m[1]);
+error: 9: unknown identifier 'test'
+ sk_FragColor = half4(test[0].s, test[1].m[1][0], test[0].a[1], test[1].am[1][0][1]);
^^^^
-6 errors
+error: 9: unknown identifier 'test'
+ sk_FragColor = half4(test[0].s, test[1].m[1][0], test[0].a[1], test[1].am[1][0][1]);
+ ^^^^
+7 errors
diff --git a/tests/sksl/shared/InterfaceBlockNamedArray.wgsl b/tests/sksl/shared/InterfaceBlockNamedArray.wgsl
index 9c7c248..4d59535 100644
--- a/tests/sksl/shared/InterfaceBlockNamedArray.wgsl
+++ b/tests/sksl/shared/InterfaceBlockNamedArray.wgsl
@@ -6,13 +6,15 @@
@location(0) sk_FragColor: vec4<f32>,
};
struct testBlock {
- @size(16) x: f32,
- m: _skMatrix22,
+ @size(16) s: f32,
+ @size(32) m: _skMatrix22,
+ @size(32) a: array<_skArrayElement_f, 2>,
+ am: array<_skArrayElement_f22, 2>,
};
@group(0) @binding(123) var<uniform> test : array<testBlock, 2>;
fn main(_stageOut: ptr<function, FSOut>) {
{
- (*_stageOut).sk_FragColor = vec4<f32>(f32(test[0].x), f32(_skUnpacked_test_m[0][0].y), vec2<f32>(_skUnpacked_test_m[1][1]));
+ (*_stageOut).sk_FragColor = vec4<f32>(f32(test[0].s), f32(_skUnpacked_test_m[1][1].x), f32(_skUnpacked_test_a[0][1]), f32(_skUnpacked_test_am[1][1][0].y));
}
}
@fragment fn fragmentMain(_stageIn: FSIn) -> FSOut {
@@ -21,14 +23,26 @@
main(&_stageOut);
return _stageOut;
}
+struct _skArrayElement_f {
+ @size(16) e : f32
+};
+var<private> _skUnpacked_test_a: array<array<f32, 2>, 2>;
+struct _skArrayElement_f22 {
+ e : _skMatrix22
+};
struct _skRow2 {
@size(16) r : vec2<f32>
};
struct _skMatrix22 {
c : array<_skRow2, 2>
};
+var<private> _skUnpacked_test_am: array<array<mat2x2<f32>, 2>, 2>;
var<private> _skUnpacked_test_m: array<mat2x2<f32>, 2>;
fn _skInitializePolyfilledUniforms() {
+ _skUnpacked_test_a[0] = array<f32, 2>(test[0].a[0].e, test[0].a[1].e);
+ _skUnpacked_test_a[1] = array<f32, 2>(test[1].a[0].e, test[1].a[1].e);
+ _skUnpacked_test_am[0] = array<mat2x2<f32>, 2>(mat2x2<f32>(test[0].am[0].e.c[0].r, test[0].am[0].e.c[1].r), mat2x2<f32>(test[0].am[1].e.c[0].r, test[0].am[1].e.c[1].r));
+ _skUnpacked_test_am[1] = array<mat2x2<f32>, 2>(mat2x2<f32>(test[1].am[0].e.c[0].r, test[1].am[0].e.c[1].r), mat2x2<f32>(test[1].am[1].e.c[0].r, test[1].am[1].e.c[1].r));
_skUnpacked_test_m[0] = mat2x2<f32>(test[0].m.c[0].r, test[0].m.c[1].r);
_skUnpacked_test_m[1] = mat2x2<f32>(test[1].m.c[0].r, test[1].m.c[1].r);
}
diff --git a/tests/sksl/shared/UniformBuffers.wgsl b/tests/sksl/shared/UniformBuffers.wgsl
index dd50029..81ce1f0 100644
--- a/tests/sksl/shared/UniformBuffers.wgsl
+++ b/tests/sksl/shared/UniformBuffers.wgsl
@@ -1,24 +1,3 @@
-### Compilation failed:
-
-error: :11:16 error: uniform storage requires that array elements are aligned to 16 bytes, but array element of type 'f32' has a stride of 4 bytes. Consider using a vector or struct as the element type instead.
- @size(32) y: array<f32, 2>,
- ^^^^^^^^^^^^^
-
-:8:1 note: see layout of struct:
-/* align(16) size(96) */ struct testBlock {
-/* offset( 0) align( 4) size( 4) */ x : f32;
-/* offset( 4) align( 4) size(12) */ w : i32;
-/* offset(16) align( 4) size(32) */ y : array<f32, 2>;
-/* offset(48) align(16) size(48) */ z : mat3x3<f32>;
-/* */ };
-struct testBlock {
-^^^^^^
-
-:14:36 note: 'testBlock' used in address space 'uniform' here
-@group(0) @binding(0) var<uniform> _uniform0 : testBlock;
- ^^^^^^^^^
-
-
diagnostic(off, derivative_uniformity);
struct FSIn {
@builtin(front_facing) sk_Clockwise: bool,
@@ -29,19 +8,25 @@
struct testBlock {
@size(4) x: f32,
@size(12) w: i32,
- @size(32) y: array<f32, 2>,
+ @size(32) y: array<_skArrayElement_h, 2>,
z: mat3x3<f32>,
};
@group(0) @binding(0) var<uniform> _uniform0 : testBlock;
fn main(_stageOut: ptr<function, FSOut>) {
{
- (*_stageOut).sk_FragColor = vec4<f32>(_uniform0.x, _uniform0.y[0], _uniform0.y[1], 0.0);
+ (*_stageOut).sk_FragColor = vec4<f32>(_uniform0.x, _skUnpacked__uniform0_y[0], _skUnpacked__uniform0_y[1], 0.0);
}
}
@fragment fn fragmentMain(_stageIn: FSIn) -> FSOut {
+ _skInitializePolyfilledUniforms();
var _stageOut: FSOut;
main(&_stageOut);
return _stageOut;
}
-
-1 error
+struct _skArrayElement_h {
+ @size(16) e : f32
+};
+var<private> _skUnpacked__uniform0_y: array<f32, 2>;
+fn _skInitializePolyfilledUniforms() {
+ _skUnpacked__uniform0_y = array<f32, 2>(_uniform0.y[0].e, _uniform0.y[1].e);
+}
diff --git a/tests/sksl/wgsl/UniformArrays.wgsl b/tests/sksl/wgsl/UniformArrays.wgsl
new file mode 100644
index 0000000..c11c2ed
--- /dev/null
+++ b/tests/sksl/wgsl/UniformArrays.wgsl
@@ -0,0 +1,114 @@
+diagnostic(off, derivative_uniformity);
+struct FSIn {
+ @builtin(front_facing) sk_Clockwise: bool,
+};
+struct FSOut {
+ @location(0) sk_FragColor: vec4<f32>,
+};
+struct UniformBuffer {
+ uf: array<_skArrayElement_f, 3>,
+ uf2: array<_skArrayElement_f2, 3>,
+ uf3: array<_skArrayElement_f3, 3>,
+ uf4: array<vec4<f32>, 3>,
+ uh: array<_skArrayElement_h, 3>,
+ uh2: array<_skArrayElement_h2, 3>,
+ uh3: array<_skArrayElement_h3, 3>,
+ uh4: array<vec4<f32>, 3>,
+ ui: array<_skArrayElement_i, 3>,
+ ui2: array<_skArrayElement_i2, 3>,
+ ui3: array<_skArrayElement_i3, 3>,
+ ui4: array<vec4<i32>, 3>,
+};
+@group(0) @binding(1) var<uniform> _uniform0 : UniformBuffer;
+struct StorageBuffer {
+ sf: array<_skArrayElement_f, 4>,
+ sf2: array<_skArrayElement_f2, 4>,
+ sf3: array<_skArrayElement_f3, 4>,
+ sf4: array<vec4<f32>, 4>,
+ sh: array<_skArrayElement_h, 4>,
+ sh2: array<_skArrayElement_h2, 4>,
+ sh3: array<_skArrayElement_h3, 4>,
+ sh4: array<vec4<f32>, 4>,
+ si: array<_skArrayElement_i, 4>,
+ si2: array<_skArrayElement_i2, 4>,
+ si3: array<_skArrayElement_i3, 4>,
+ si4: array<vec4<i32>, 4>,
+};
+@group(0) @binding(2) var<storage, read_write> _storage1 : StorageBuffer;
+fn main() -> vec4<f32> {
+ {
+ var value: f32 = ((((((((((((((((((((((_skUnpacked__uniform0_uf[1] + _skUnpacked__uniform0_uf2[1].x) + _skUnpacked__uniform0_uf3[1].x) + _uniform0.uf4[1].x) + f32(_skUnpacked__uniform0_uh[1])) + f32(_skUnpacked__uniform0_uh2[1].x)) + f32(_skUnpacked__uniform0_uh3[1].x)) + f32(_uniform0.uh4[1].x)) + f32(_skUnpacked__uniform0_ui[1])) + f32(_skUnpacked__uniform0_ui2[1].x)) + f32(_skUnpacked__uniform0_ui3[1].x)) + f32(_uniform0.ui4[1].x)) + _skUnpacked__storage1_sf[1]) + _skUnpacked__storage1_sf2[1].x) + _skUnpacked__storage1_sf3[1].x) + _storage1.sf4[1].x) + f32(_skUnpacked__storage1_sh[1])) + f32(_skUnpacked__storage1_sh2[1].x)) + f32(_skUnpacked__storage1_sh3[1].x)) + f32(_storage1.sh4[1].x)) + f32(_skUnpacked__storage1_si[1])) + f32(_skUnpacked__storage1_si2[1].x)) + f32(_skUnpacked__storage1_si3[1].x)) + f32(_storage1.si4[1].x);
+ return vec4<f32>(f32(value));
+ }
+}
+@fragment fn fragmentMain(_stageIn: FSIn) -> FSOut {
+ _skInitializePolyfilledUniforms();
+ var _stageOut: FSOut;
+ _stageOut.sk_FragColor = main();
+ return _stageOut;
+}
+struct _skArrayElement_f {
+ @size(16) e : f32
+};
+var<private> _skUnpacked__storage1_sf: array<f32, 4>;
+struct _skArrayElement_f2 {
+ @size(16) e : vec2<f32>
+};
+var<private> _skUnpacked__storage1_sf2: array<vec2<f32>, 4>;
+struct _skArrayElement_f3 {
+ @size(16) e : vec3<f32>
+};
+var<private> _skUnpacked__storage1_sf3: array<vec3<f32>, 4>;
+struct _skArrayElement_h {
+ @size(16) e : f32
+};
+var<private> _skUnpacked__storage1_sh: array<f32, 4>;
+struct _skArrayElement_h2 {
+ @size(16) e : vec2<f32>
+};
+var<private> _skUnpacked__storage1_sh2: array<vec2<f32>, 4>;
+struct _skArrayElement_h3 {
+ @size(16) e : vec3<f32>
+};
+var<private> _skUnpacked__storage1_sh3: array<vec3<f32>, 4>;
+struct _skArrayElement_i {
+ @size(16) e : i32
+};
+var<private> _skUnpacked__storage1_si: array<i32, 4>;
+struct _skArrayElement_i2 {
+ @size(16) e : vec2<i32>
+};
+var<private> _skUnpacked__storage1_si2: array<vec2<i32>, 4>;
+struct _skArrayElement_i3 {
+ @size(16) e : vec3<i32>
+};
+var<private> _skUnpacked__storage1_si3: array<vec3<i32>, 4>;
+var<private> _skUnpacked__uniform0_uf: array<f32, 3>;
+var<private> _skUnpacked__uniform0_uf2: array<vec2<f32>, 3>;
+var<private> _skUnpacked__uniform0_uf3: array<vec3<f32>, 3>;
+var<private> _skUnpacked__uniform0_uh: array<f32, 3>;
+var<private> _skUnpacked__uniform0_uh2: array<vec2<f32>, 3>;
+var<private> _skUnpacked__uniform0_uh3: array<vec3<f32>, 3>;
+var<private> _skUnpacked__uniform0_ui: array<i32, 3>;
+var<private> _skUnpacked__uniform0_ui2: array<vec2<i32>, 3>;
+var<private> _skUnpacked__uniform0_ui3: array<vec3<i32>, 3>;
+fn _skInitializePolyfilledUniforms() {
+ _skUnpacked__storage1_sf = array<f32, 4>(_storage1.sf[0].e, _storage1.sf[1].e, _storage1.sf[2].e, _storage1.sf[3].e);
+ _skUnpacked__storage1_sf2 = array<vec2<f32>, 4>(_storage1.sf2[0].e, _storage1.sf2[1].e, _storage1.sf2[2].e, _storage1.sf2[3].e);
+ _skUnpacked__storage1_sf3 = array<vec3<f32>, 4>(_storage1.sf3[0].e, _storage1.sf3[1].e, _storage1.sf3[2].e, _storage1.sf3[3].e);
+ _skUnpacked__storage1_sh = array<f32, 4>(_storage1.sh[0].e, _storage1.sh[1].e, _storage1.sh[2].e, _storage1.sh[3].e);
+ _skUnpacked__storage1_sh2 = array<vec2<f32>, 4>(_storage1.sh2[0].e, _storage1.sh2[1].e, _storage1.sh2[2].e, _storage1.sh2[3].e);
+ _skUnpacked__storage1_sh3 = array<vec3<f32>, 4>(_storage1.sh3[0].e, _storage1.sh3[1].e, _storage1.sh3[2].e, _storage1.sh3[3].e);
+ _skUnpacked__storage1_si = array<i32, 4>(_storage1.si[0].e, _storage1.si[1].e, _storage1.si[2].e, _storage1.si[3].e);
+ _skUnpacked__storage1_si2 = array<vec2<i32>, 4>(_storage1.si2[0].e, _storage1.si2[1].e, _storage1.si2[2].e, _storage1.si2[3].e);
+ _skUnpacked__storage1_si3 = array<vec3<i32>, 4>(_storage1.si3[0].e, _storage1.si3[1].e, _storage1.si3[2].e, _storage1.si3[3].e);
+ _skUnpacked__uniform0_uf = array<f32, 3>(_uniform0.uf[0].e, _uniform0.uf[1].e, _uniform0.uf[2].e);
+ _skUnpacked__uniform0_uf2 = array<vec2<f32>, 3>(_uniform0.uf2[0].e, _uniform0.uf2[1].e, _uniform0.uf2[2].e);
+ _skUnpacked__uniform0_uf3 = array<vec3<f32>, 3>(_uniform0.uf3[0].e, _uniform0.uf3[1].e, _uniform0.uf3[2].e);
+ _skUnpacked__uniform0_uh = array<f32, 3>(_uniform0.uh[0].e, _uniform0.uh[1].e, _uniform0.uh[2].e);
+ _skUnpacked__uniform0_uh2 = array<vec2<f32>, 3>(_uniform0.uh2[0].e, _uniform0.uh2[1].e, _uniform0.uh2[2].e);
+ _skUnpacked__uniform0_uh3 = array<vec3<f32>, 3>(_uniform0.uh3[0].e, _uniform0.uh3[1].e, _uniform0.uh3[2].e);
+ _skUnpacked__uniform0_ui = array<i32, 3>(_uniform0.ui[0].e, _uniform0.ui[1].e, _uniform0.ui[2].e);
+ _skUnpacked__uniform0_ui2 = array<vec2<i32>, 3>(_uniform0.ui2[0].e, _uniform0.ui2[1].e, _uniform0.ui2[2].e);
+ _skUnpacked__uniform0_ui3 = array<vec3<i32>, 3>(_uniform0.ui3[0].e, _uniform0.ui3[1].e, _uniform0.ui3[2].e);
+}
diff --git a/tests/sksl/wgsl/UniformMatrices.wgsl b/tests/sksl/wgsl/UniformMatrices.wgsl
index 367453d..83894cc 100644
--- a/tests/sksl/wgsl/UniformMatrices.wgsl
+++ b/tests/sksl/wgsl/UniformMatrices.wgsl
@@ -15,6 +15,15 @@
u42: _skMatrix42,
u43: mat4x3<f32>,
u44: mat4x4<f32>,
+ au22: array<_skArrayElement_f22, 3>,
+ au23: array<mat2x3<f32>, 3>,
+ au24: array<mat2x4<f32>, 3>,
+ au32: array<_skArrayElement_f32, 3>,
+ au33: array<mat3x3<f32>, 3>,
+ au34: array<mat3x4<f32>, 3>,
+ au42: array<_skArrayElement_f42, 3>,
+ au43: array<mat4x3<f32>, 3>,
+ au44: array<mat4x4<f32>, 3>,
};
@group(0) @binding(1) var<uniform> _uniform0 : UniformBuffer;
struct StorageBuffer {
@@ -27,27 +36,73 @@
s42: _skMatrix42,
s43: mat4x3<f32>,
s44: mat4x4<f32>,
+ as22: array<_skArrayElement_f22, 3>,
+ as23: array<mat2x3<f32>, 3>,
+ as24: array<mat2x4<f32>, 3>,
+ as32: array<_skArrayElement_f32, 3>,
+ as33: array<mat3x3<f32>, 3>,
+ as34: array<mat3x4<f32>, 3>,
+ as42: array<_skArrayElement_f42, 3>,
+ as43: array<mat4x3<f32>, 3>,
+ as44: array<mat4x4<f32>, 3>,
};
@group(0) @binding(2) var<storage, read_write> _storage1 : StorageBuffer;
fn main() -> vec4<f32> {
{
- return vec4<f32>(0.0);
+ var value: f32 = ((((((((((((((((((((((((((((((((((_skUnpacked__uniform0_u22[0].x + _uniform0.u23[0].x) + _uniform0.u24[0].x) + _skUnpacked__uniform0_u32[0].x) + _uniform0.u33[0].x) + _uniform0.u34[0].x) + _skUnpacked__uniform0_u42[0].x) + _uniform0.u43[0].x) + _uniform0.au44[0][0].x) + _skUnpacked__uniform0_au22[0][0].x) + _uniform0.au23[0][0].x) + _uniform0.au24[0][0].x) + _skUnpacked__uniform0_au32[0][0].x) + _uniform0.au33[0][0].x) + _uniform0.au34[0][0].x) + _skUnpacked__uniform0_au42[0][0].x) + _uniform0.au43[0][0].x) + _uniform0.au44[0][0].x) + _skUnpacked__storage1_s22[0].x) + _storage1.s23[0].x) + _storage1.s24[0].x) + _skUnpacked__storage1_s32[0].x) + _storage1.s33[0].x) + _storage1.s34[0].x) + _skUnpacked__storage1_s42[0].x) + _storage1.s43[0].x) + _storage1.as44[0][0].x) + _skUnpacked__storage1_as22[0][0].x) + _storage1.as23[0][0].x) + _storage1.as24[0][0].x) + _skUnpacked__storage1_as32[0][0].x) + _storage1.as33[0][0].x) + _storage1.as34[0][0].x) + _skUnpacked__storage1_as42[0][0].x) + _storage1.as43[0][0].x) + _storage1.as44[0][0].x;
+ return vec4<f32>(f32(value));
}
}
@fragment fn fragmentMain(_stageIn: FSIn) -> FSOut {
+ _skInitializePolyfilledUniforms();
var _stageOut: FSOut;
_stageOut.sk_FragColor = main();
return _stageOut;
}
+struct _skArrayElement_f22 {
+ e : _skMatrix22
+};
struct _skRow2 {
@size(16) r : vec2<f32>
};
struct _skMatrix22 {
c : array<_skRow2, 2>
};
+var<private> _skUnpacked__storage1_as22: array<mat2x2<f32>, 3>;
+struct _skArrayElement_f32 {
+ e : _skMatrix32
+};
struct _skMatrix32 {
c : array<_skRow2, 3>
};
+var<private> _skUnpacked__storage1_as32: array<mat3x2<f32>, 3>;
+struct _skArrayElement_f42 {
+ e : _skMatrix42
+};
struct _skMatrix42 {
c : array<_skRow2, 4>
};
+var<private> _skUnpacked__storage1_as42: array<mat4x2<f32>, 3>;
+var<private> _skUnpacked__storage1_s22: mat2x2<f32>;
+var<private> _skUnpacked__storage1_s32: mat3x2<f32>;
+var<private> _skUnpacked__storage1_s42: mat4x2<f32>;
+var<private> _skUnpacked__uniform0_au22: array<mat2x2<f32>, 3>;
+var<private> _skUnpacked__uniform0_au32: array<mat3x2<f32>, 3>;
+var<private> _skUnpacked__uniform0_au42: array<mat4x2<f32>, 3>;
+var<private> _skUnpacked__uniform0_u22: mat2x2<f32>;
+var<private> _skUnpacked__uniform0_u32: mat3x2<f32>;
+var<private> _skUnpacked__uniform0_u42: mat4x2<f32>;
+fn _skInitializePolyfilledUniforms() {
+ _skUnpacked__storage1_as22 = array<mat2x2<f32>, 3>(mat2x2<f32>(_storage1.as22[0].e.c[0].r, _storage1.as22[0].e.c[1].r), mat2x2<f32>(_storage1.as22[1].e.c[0].r, _storage1.as22[1].e.c[1].r), mat2x2<f32>(_storage1.as22[2].e.c[0].r, _storage1.as22[2].e.c[1].r));
+ _skUnpacked__storage1_as32 = array<mat3x2<f32>, 3>(mat3x2<f32>(_storage1.as32[0].e.c[0].r, _storage1.as32[0].e.c[1].r, _storage1.as32[0].e.c[2].r), mat3x2<f32>(_storage1.as32[1].e.c[0].r, _storage1.as32[1].e.c[1].r, _storage1.as32[1].e.c[2].r), mat3x2<f32>(_storage1.as32[2].e.c[0].r, _storage1.as32[2].e.c[1].r, _storage1.as32[2].e.c[2].r));
+ _skUnpacked__storage1_as42 = array<mat4x2<f32>, 3>(mat4x2<f32>(_storage1.as42[0].e.c[0].r, _storage1.as42[0].e.c[1].r, _storage1.as42[0].e.c[2].r, _storage1.as42[0].e.c[3].r), mat4x2<f32>(_storage1.as42[1].e.c[0].r, _storage1.as42[1].e.c[1].r, _storage1.as42[1].e.c[2].r, _storage1.as42[1].e.c[3].r), mat4x2<f32>(_storage1.as42[2].e.c[0].r, _storage1.as42[2].e.c[1].r, _storage1.as42[2].e.c[2].r, _storage1.as42[2].e.c[3].r));
+ _skUnpacked__storage1_s22 = mat2x2<f32>(_storage1.s22.c[0].r, _storage1.s22.c[1].r);
+ _skUnpacked__storage1_s32 = mat3x2<f32>(_storage1.s32.c[0].r, _storage1.s32.c[1].r, _storage1.s32.c[2].r);
+ _skUnpacked__storage1_s42 = mat4x2<f32>(_storage1.s42.c[0].r, _storage1.s42.c[1].r, _storage1.s42.c[2].r, _storage1.s42.c[3].r);
+ _skUnpacked__uniform0_au22 = array<mat2x2<f32>, 3>(mat2x2<f32>(_uniform0.au22[0].e.c[0].r, _uniform0.au22[0].e.c[1].r), mat2x2<f32>(_uniform0.au22[1].e.c[0].r, _uniform0.au22[1].e.c[1].r), mat2x2<f32>(_uniform0.au22[2].e.c[0].r, _uniform0.au22[2].e.c[1].r));
+ _skUnpacked__uniform0_au32 = array<mat3x2<f32>, 3>(mat3x2<f32>(_uniform0.au32[0].e.c[0].r, _uniform0.au32[0].e.c[1].r, _uniform0.au32[0].e.c[2].r), mat3x2<f32>(_uniform0.au32[1].e.c[0].r, _uniform0.au32[1].e.c[1].r, _uniform0.au32[1].e.c[2].r), mat3x2<f32>(_uniform0.au32[2].e.c[0].r, _uniform0.au32[2].e.c[1].r, _uniform0.au32[2].e.c[2].r));
+ _skUnpacked__uniform0_au42 = array<mat4x2<f32>, 3>(mat4x2<f32>(_uniform0.au42[0].e.c[0].r, _uniform0.au42[0].e.c[1].r, _uniform0.au42[0].e.c[2].r, _uniform0.au42[0].e.c[3].r), mat4x2<f32>(_uniform0.au42[1].e.c[0].r, _uniform0.au42[1].e.c[1].r, _uniform0.au42[1].e.c[2].r, _uniform0.au42[1].e.c[3].r), mat4x2<f32>(_uniform0.au42[2].e.c[0].r, _uniform0.au42[2].e.c[1].r, _uniform0.au42[2].e.c[2].r, _uniform0.au42[2].e.c[3].r));
+ _skUnpacked__uniform0_u22 = mat2x2<f32>(_uniform0.u22.c[0].r, _uniform0.u22.c[1].r);
+ _skUnpacked__uniform0_u32 = mat3x2<f32>(_uniform0.u32.c[0].r, _uniform0.u32.c[1].r, _uniform0.u32.c[2].r);
+ _skUnpacked__uniform0_u42 = mat4x2<f32>(_uniform0.u42.c[0].r, _uniform0.u42.c[1].r, _uniform0.u42.c[2].r, _uniform0.u42.c[3].r);
+}