mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-07-29 00:15:37 +00:00
This CL implements f16 in uniform and storage address space, allowing using f16 types in uniform and storage buffers on all backends. Tint uint tests and Dawn E2E tests are added to validate the f16 types work as expected. Bug: tint:1473, tint:1502 Change-Id: I15e3de1033d3727f2ea33f4657f682c5f13c2153 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/106320 Kokoro: Kokoro <noreply+kokoro@google.com> Commit-Queue: Zhaoming Jiang <zhaoming.jiang@intel.com> Reviewed-by: Ben Clayton <bclayton@google.com>
4891 lines
119 KiB
C++
4891 lines
119 KiB
C++
// Copyright 2022 The Tint Authors.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#include "src/tint/transform/std140.h"
|
|
|
|
#include <string>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#include "src/tint/transform/test_helper.h"
|
|
#include "src/tint/utils/string.h"
|
|
|
|
namespace tint::transform {
|
|
namespace {
|
|
|
|
enum class MatrixType { f32, f16 };
|
|
|
|
struct MatrixCase {
|
|
uint32_t columns;
|
|
uint32_t rows;
|
|
MatrixType type;
|
|
|
|
size_t ElementSize() const { return type == MatrixType::f16 ? 2 : 4; }
|
|
|
|
size_t ColumnVectorAlign() const { return (rows == 3 ? 4 : rows) * ElementSize(); }
|
|
|
|
bool NotStd140Compatible() const { return ColumnVectorAlign() != 16; }
|
|
|
|
// Return if this matrix type can be used as element type of an uniform buffer, i.e. the
|
|
// array stride is multiple of 16.
|
|
bool CanBeUsedAsUniformArrayElememts() const {
|
|
const size_t array_stride = columns * ColumnVectorAlign();
|
|
return (array_stride % 16 == 0);
|
|
}
|
|
|
|
std::string Shape() const { return std::to_string(columns) + "x" + std::to_string(rows); }
|
|
|
|
std::string ElementType() const { return type == MatrixType::f16 ? "f16" : "f32"; }
|
|
|
|
std::string Mat() const { return "mat" + Shape() + "<" + ElementType() + ">"; }
|
|
|
|
std::string ColumnVector() const {
|
|
return "vec" + std::to_string(rows) + "<" + (type == MatrixType::f32 ? "f32" : "f16") + ">";
|
|
}
|
|
|
|
std::string ColumnVectorSwizzle() const {
|
|
switch (rows) {
|
|
case 2:
|
|
return "yx";
|
|
case 3:
|
|
return "yzx";
|
|
case 4:
|
|
return "wzxy";
|
|
}
|
|
return "";
|
|
}
|
|
|
|
// For each column, replaces "${col_id_for_tmpl}" by column index in `tmpl` to get a string, and
|
|
// join all these strings with `seperator`. If `tmpl_for_last_column` is not empty, use it
|
|
// instead of `tmpl` for the last column.
|
|
std::string JoinTemplatedStringForEachMatrixColumn(
|
|
std::string tmpl,
|
|
std::string seperator,
|
|
std::string tmpl_for_last_column = "") const {
|
|
std::string result;
|
|
if (tmpl_for_last_column.size() == 0) {
|
|
tmpl_for_last_column = tmpl;
|
|
}
|
|
for (size_t c = 0; c < columns - 1; c++) {
|
|
if (c > 0) {
|
|
result += seperator;
|
|
}
|
|
std::string string_for_current_column =
|
|
utils::ReplaceAll(tmpl, "${col_id_for_tmpl}", std::to_string(c));
|
|
result += string_for_current_column;
|
|
}
|
|
result += seperator;
|
|
std::string string_for_last_column = utils::ReplaceAll(
|
|
tmpl_for_last_column, "${col_id_for_tmpl}", std::to_string(columns - 1));
|
|
result += string_for_last_column;
|
|
return result;
|
|
}
|
|
|
|
std::string ExpendedColumnVectors(uint32_t leading_space, std::string name) const {
|
|
std::string space(leading_space, ' ');
|
|
return JoinTemplatedStringForEachMatrixColumn(
|
|
space + name + "${col_id_for_tmpl} : " + ColumnVector() + ",", "\n");
|
|
}
|
|
|
|
std::string ExpendedColumnVectorsInline(std::string name, std::string seperator) const {
|
|
return JoinTemplatedStringForEachMatrixColumn(name + "${col_id_for_tmpl}", seperator);
|
|
}
|
|
|
|
std::string ExpendedColumnVectorsWithLastSize(uint32_t leading_space,
|
|
std::string name,
|
|
uint32_t last_size) const {
|
|
std::string space(leading_space, ' ');
|
|
return JoinTemplatedStringForEachMatrixColumn(
|
|
space + name + "${col_id_for_tmpl} : " + ColumnVector() + ",", "\n",
|
|
space + "@size(" + std::to_string(last_size) + ")\n" + space + name +
|
|
"${col_id_for_tmpl} : " + ColumnVector() + ",");
|
|
}
|
|
|
|
// Replace user-given fields and predefined fields in a given string `str`.
|
|
// First, for each pair of string in `replacement_pairs`, replace all occurrences of the first
|
|
// string of pair with second string. Then, replace several predefined fields with the matrix
|
|
// information. E.g. for a matrix mat4x3<f32>, would replace "${mat}" with "mat4x3<f32>",
|
|
// replace "${shape}" with "4x3", "${elem_type}" with "f32", "${col_vector_type}" with
|
|
// "vec3<f32>", and "${swizzle}" with "yzx".
|
|
std::string ReplaceFieldsInString(
|
|
std::string str,
|
|
std::initializer_list<std::pair<std::string, std::string>> replacement_pairs = {}) const {
|
|
for (auto& replace : replacement_pairs) {
|
|
str = utils::ReplaceAll(str, replace.first, replace.second);
|
|
}
|
|
str = utils::ReplaceAll(str, "${mat}", Mat());
|
|
str = utils::ReplaceAll(str, "${shape}", Shape());
|
|
str = utils::ReplaceAll(str, "${elem_type}", ElementType());
|
|
str = utils::ReplaceAll(str, "${col_vector_type}", ColumnVector());
|
|
str = utils::ReplaceAll(str, "${swizzle}", ColumnVectorSwizzle());
|
|
return str;
|
|
}
|
|
};
|
|
|
|
inline std::ostream& operator<<(std::ostream& os, const MatrixCase& c) {
|
|
return os << c.Mat();
|
|
}
|
|
|
|
using Std140Test_Matrix = TransformTestWithParam<MatrixCase>;
|
|
|
|
TEST_P(Std140Test_Matrix, SingleStructMatUniform) {
|
|
auto matrix = GetParam();
|
|
|
|
std::string src = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
m : ${mat},
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> s : S;
|
|
)";
|
|
src = matrix.ReplaceFieldsInString(src);
|
|
|
|
std::string expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
expect = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
m : ${mat},
|
|
}
|
|
|
|
struct S_std140 {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> s : S_std140;
|
|
)";
|
|
expect = matrix.ReplaceFieldsInString(
|
|
expect, {{"${col_vectors}", matrix.ExpendedColumnVectors(2, "m_")}});
|
|
|
|
} else {
|
|
expect = src;
|
|
}
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
TEST_P(Std140Test_Matrix, CustomAlign) {
|
|
auto matrix = GetParam();
|
|
|
|
std::string src = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
before : i32,
|
|
@align(128)
|
|
m : ${mat},
|
|
after : i32,
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> s : S;
|
|
)";
|
|
src = matrix.ReplaceFieldsInString(src);
|
|
|
|
std::string expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
expect = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
before : i32,
|
|
@align(128)
|
|
m : ${mat},
|
|
after : i32,
|
|
}
|
|
|
|
struct S_std140 {
|
|
before : i32,
|
|
@align(128i)
|
|
${col_vectors}
|
|
after : i32,
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> s : S_std140;
|
|
)";
|
|
expect = matrix.ReplaceFieldsInString(
|
|
expect, {{"${col_vectors}", matrix.ExpendedColumnVectors(2, "m_")}});
|
|
} else {
|
|
expect = src;
|
|
}
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
TEST_P(Std140Test_Matrix, CustomSizeMat) {
|
|
auto matrix = GetParam();
|
|
|
|
std::string src = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
before : i32,
|
|
@size(128)
|
|
m : ${mat},
|
|
after : i32,
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> s : S;
|
|
)";
|
|
src = matrix.ReplaceFieldsInString(src);
|
|
|
|
std::string expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
uint32_t last_size =
|
|
128 - static_cast<uint32_t>(matrix.ColumnVectorAlign() * (matrix.columns - 1));
|
|
|
|
expect = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
before : i32,
|
|
@size(128)
|
|
m : ${mat},
|
|
after : i32,
|
|
}
|
|
|
|
struct S_std140 {
|
|
before : i32,
|
|
${col_vectors}
|
|
after : i32,
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> s : S_std140;
|
|
)";
|
|
expect = matrix.ReplaceFieldsInString(
|
|
expect,
|
|
{{"${col_vectors}", matrix.ExpendedColumnVectorsWithLastSize(2, "m_", last_size)}});
|
|
} else {
|
|
expect = src;
|
|
}
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
TEST_P(Std140Test_Matrix, CustomAlignAndSize) {
|
|
auto matrix = GetParam();
|
|
|
|
std::string src = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
before : i32,
|
|
@align(128) @size(128)
|
|
m : ${mat},
|
|
after : i32,
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> s : S;
|
|
)";
|
|
src = matrix.ReplaceFieldsInString(src);
|
|
|
|
std::string expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
uint32_t last_size =
|
|
128 - static_cast<uint32_t>(matrix.ColumnVectorAlign() * (matrix.columns - 1));
|
|
|
|
expect = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
before : i32,
|
|
@align(128) @size(128)
|
|
m : ${mat},
|
|
after : i32,
|
|
}
|
|
|
|
struct S_std140 {
|
|
before : i32,
|
|
@align(128i)
|
|
${col_vectors}
|
|
after : i32,
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> s : S_std140;
|
|
)";
|
|
expect = matrix.ReplaceFieldsInString(
|
|
expect,
|
|
{{"${col_vectors}", matrix.ExpendedColumnVectorsWithLastSize(2, "m_", last_size)}});
|
|
} else {
|
|
expect = src;
|
|
}
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
TEST_P(Std140Test_Matrix, MatrixUsageInForLoop) {
|
|
auto matrix = GetParam();
|
|
|
|
std::string src = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
m : ${mat},
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> s : S;
|
|
|
|
fn f() {
|
|
for(var i = u32(s.m[0][0]); (i < u32(s.m[i][1])); i += u32(s.m[1][i])) {
|
|
}
|
|
}
|
|
)";
|
|
src = matrix.ReplaceFieldsInString(src);
|
|
|
|
std::string expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
expect = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
m : ${mat},
|
|
}
|
|
|
|
struct S_std140 {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> s : S_std140;
|
|
|
|
fn load_s_m_p0_1(p0 : u32) -> ${elem_type} {
|
|
switch(p0) {
|
|
${col_table}
|
|
default: {
|
|
return ${elem_type}();
|
|
}
|
|
}
|
|
}
|
|
|
|
fn f() {
|
|
for(var i = u32(s.m_0[0u]); (i < u32(load_s_m_p0_1(u32(i)))); i += u32(s.m_1[i])) {
|
|
}
|
|
}
|
|
)";
|
|
|
|
// col_table is the switch cases for all column index.
|
|
// Example for a matrix having 2 columns:
|
|
// case 0u: {
|
|
// return s.m_0[1u];
|
|
// }
|
|
// case 1u: {
|
|
// return s.m_1[1u];
|
|
// }
|
|
std::string col_table = matrix.JoinTemplatedStringForEachMatrixColumn( //
|
|
R"( case ${col_id_for_tmpl}u: {
|
|
return s.m_${col_id_for_tmpl}[1u];
|
|
})",
|
|
"\n");
|
|
expect = matrix.ReplaceFieldsInString(
|
|
expect, {{"${col_vectors}", matrix.ExpendedColumnVectors(2, "m_")},
|
|
{"${col_table}", col_table}});
|
|
} else {
|
|
expect = src;
|
|
}
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
TEST_P(Std140Test_Matrix, MatUniform_LoadMatrix) {
|
|
auto matrix = GetParam();
|
|
|
|
std::string src = R"(
|
|
enable f16;
|
|
|
|
@group(0) @binding(0) var<uniform> m : ${mat};
|
|
|
|
fn f() {
|
|
let l = m;
|
|
}
|
|
)";
|
|
src = matrix.ReplaceFieldsInString(src);
|
|
|
|
std::string expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
expect = R"(
|
|
enable f16;
|
|
|
|
struct mat${shape}_${elem_type} {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> m : mat${shape}_${elem_type};
|
|
|
|
fn conv_mat${shape}_${elem_type}(val : mat${shape}_${elem_type}) -> ${mat} {
|
|
return ${mat}(${col_vectors_inline});
|
|
}
|
|
|
|
fn f() {
|
|
let l = conv_mat${shape}_${elem_type}(m);
|
|
}
|
|
)";
|
|
expect = matrix.ReplaceFieldsInString(
|
|
expect,
|
|
{{"${col_vectors}", matrix.ExpendedColumnVectors(2, "col")},
|
|
{"${col_vectors_inline}", matrix.ExpendedColumnVectorsInline("val.col", ", ")}});
|
|
} else {
|
|
expect = src;
|
|
}
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
TEST_P(Std140Test_Matrix, MatUniform_LoadColumn_ConstIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
std::string tmpl_src = R"(
|
|
enable f16;
|
|
|
|
@group(0) @binding(0) var<uniform> a : ${mat};
|
|
|
|
fn f() {
|
|
let l = a[${cloumn_index}];
|
|
}
|
|
)";
|
|
tmpl_src = matrix.ReplaceFieldsInString(tmpl_src);
|
|
|
|
std::string tmpl_expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
tmpl_expect = R"(
|
|
enable f16;
|
|
|
|
struct mat${shape}_${elem_type} {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : mat${shape}_${elem_type};
|
|
|
|
fn f() {
|
|
let l = a.col${cloumn_index};
|
|
}
|
|
)";
|
|
tmpl_expect = matrix.ReplaceFieldsInString(
|
|
tmpl_expect, {{"${col_vectors}", matrix.ExpendedColumnVectors(2, "col")}});
|
|
} else {
|
|
tmpl_expect = tmpl_src;
|
|
}
|
|
|
|
for (uint32_t col = 0; col < matrix.columns; col++) {
|
|
std::string src = utils::ReplaceAll(tmpl_src, "${cloumn_index}", std::to_string(col));
|
|
std::string expect = utils::ReplaceAll(tmpl_expect, "${cloumn_index}", std::to_string(col));
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got)) << "accessing col " << col;
|
|
}
|
|
}
|
|
|
|
TEST_P(Std140Test_Matrix, MatUniform_LoadColumn_VariableIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
std::string src = R"(
|
|
enable f16;
|
|
|
|
@group(0) @binding(0) var<uniform> a : ${mat};
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let l = a[I];
|
|
}
|
|
)";
|
|
src = matrix.ReplaceFieldsInString(src);
|
|
|
|
std::string expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
expect = R"(
|
|
enable f16;
|
|
|
|
struct mat${shape}_${elem_type} {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : mat${shape}_${elem_type};
|
|
|
|
fn load_a_p0(p0 : u32) -> ${col_vector_type} {
|
|
switch(p0) {
|
|
${col_table}
|
|
default: {
|
|
return ${col_vector_type}();
|
|
}
|
|
}
|
|
}
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let l = load_a_p0(u32(I));
|
|
}
|
|
)";
|
|
// col_table is the switch cases for all column index.
|
|
// Example for a matrix having 2 columns:
|
|
// case 0u: {
|
|
// return a.col0;
|
|
// }
|
|
// case 1u: {
|
|
// return a.col1;
|
|
// }
|
|
std::string col_table = matrix.JoinTemplatedStringForEachMatrixColumn( //
|
|
R"( case ${col_id_for_tmpl}u: {
|
|
return a.col${col_id_for_tmpl};
|
|
})",
|
|
"\n");
|
|
expect = matrix.ReplaceFieldsInString(
|
|
expect, {{"${col_vectors}", matrix.ExpendedColumnVectors(2, "col")},
|
|
{"${col_table}", col_table}});
|
|
} else {
|
|
expect = src;
|
|
}
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
TEST_P(Std140Test_Matrix, MatUniform_LoadColumnSwizzle_ConstIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
std::string tmpl_src = R"(
|
|
enable f16;
|
|
|
|
@group(0) @binding(0) var<uniform> a : ${mat};
|
|
|
|
fn f() {
|
|
let l = a[${cloumn_index}].${swizzle};
|
|
}
|
|
)";
|
|
tmpl_src = matrix.ReplaceFieldsInString(tmpl_src);
|
|
|
|
std::string tmpl_expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
tmpl_expect = R"(
|
|
enable f16;
|
|
|
|
struct mat${shape}_${elem_type} {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : mat${shape}_${elem_type};
|
|
|
|
fn f() {
|
|
let l = a.col${cloumn_index}.${swizzle};
|
|
}
|
|
)";
|
|
tmpl_expect = matrix.ReplaceFieldsInString(
|
|
tmpl_expect, {{"${col_vectors}", matrix.ExpendedColumnVectors(2, "col")}});
|
|
} else {
|
|
tmpl_expect = tmpl_src;
|
|
}
|
|
|
|
for (uint32_t col = 0; col < matrix.columns; col++) {
|
|
std::string src = utils::ReplaceAll(tmpl_src, "${cloumn_index}", std::to_string(col));
|
|
std::string expect = utils::ReplaceAll(tmpl_expect, "${cloumn_index}", std::to_string(col));
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got)) << "accessing col " << col;
|
|
}
|
|
}
|
|
|
|
TEST_P(Std140Test_Matrix, MatUniform_LoadColumnSwizzle_VariableIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
std::string src = R"(
|
|
enable f16;
|
|
|
|
@group(0) @binding(0) var<uniform> a : ${mat};
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let l = a[I].${swizzle};
|
|
}
|
|
)";
|
|
src = matrix.ReplaceFieldsInString(src);
|
|
|
|
std::string expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
expect = R"(
|
|
enable f16;
|
|
|
|
struct mat${shape}_${elem_type} {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : mat${shape}_${elem_type};
|
|
|
|
fn load_a_p0_${swizzle}(p0 : u32) -> ${col_vector_type} {
|
|
switch(p0) {
|
|
${col_table}
|
|
default: {
|
|
return ${col_vector_type}();
|
|
}
|
|
}
|
|
}
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let l = load_a_p0_${swizzle}(u32(I));
|
|
}
|
|
)";
|
|
// col_table is the switch cases for all column index.
|
|
// Example for a matrix having 2 columns:
|
|
// case 0u: {
|
|
// return a.col0.${swizzle};
|
|
// }
|
|
// case 1u: {
|
|
// return a.col1.${swizzle};
|
|
// }
|
|
std::string col_table = matrix.JoinTemplatedStringForEachMatrixColumn( //
|
|
R"( case ${col_id_for_tmpl}u: {
|
|
return a.col${col_id_for_tmpl}.${swizzle};
|
|
})",
|
|
"\n");
|
|
expect = matrix.ReplaceFieldsInString(
|
|
expect, {{"${col_vectors}", matrix.ExpendedColumnVectors(2, "col")},
|
|
{"${col_table}", col_table}});
|
|
} else {
|
|
expect = src;
|
|
}
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
TEST_P(Std140Test_Matrix, MatUniform_LoadScalar_ConstColumnIndex_ConstRowIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
std::string tmpl_src = R"(
|
|
enable f16;
|
|
|
|
@group(0) @binding(0) var<uniform> a : ${mat};
|
|
|
|
fn f() {
|
|
let l = a[${col_index}][${row_index}];
|
|
}
|
|
)";
|
|
tmpl_src = matrix.ReplaceFieldsInString(tmpl_src);
|
|
|
|
std::string tmpl_expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
tmpl_expect = R"(
|
|
enable f16;
|
|
|
|
struct mat${shape}_${elem_type} {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : mat${shape}_${elem_type};
|
|
|
|
fn f() {
|
|
let l = a.col${col_index}[${row_index}u];
|
|
}
|
|
)";
|
|
tmpl_expect = matrix.ReplaceFieldsInString(
|
|
tmpl_expect, {{"${col_vectors}", matrix.ExpendedColumnVectors(2, "col")}});
|
|
} else {
|
|
tmpl_expect = tmpl_src;
|
|
}
|
|
|
|
for (uint32_t col = 0; col < matrix.columns; col++) {
|
|
for (uint32_t row = 0; row < matrix.rows; row++) {
|
|
std::string src = utils::ReplaceAll(tmpl_src, "${col_index}", std::to_string(col));
|
|
src = utils::ReplaceAll(src, "${row_index}", std::to_string(row));
|
|
std::string expect =
|
|
utils::ReplaceAll(tmpl_expect, "${col_index}", std::to_string(col));
|
|
expect = utils::ReplaceAll(expect, "${row_index}", std::to_string(row));
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got)) << "accessing col " << col << " row " << row;
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST_P(Std140Test_Matrix, MatUniform_LoadScalar_VariableColumnIndex_ConstRowIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
std::string tmpl_src = R"(
|
|
enable f16;
|
|
|
|
@group(0) @binding(0) var<uniform> a : ${mat};
|
|
|
|
fn f() {
|
|
let I = 0;
|
|
let l = a[I][${row_index}];
|
|
}
|
|
)";
|
|
tmpl_src = matrix.ReplaceFieldsInString(tmpl_src);
|
|
|
|
std::string tmpl_expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
tmpl_expect = R"(
|
|
enable f16;
|
|
|
|
struct mat${shape}_${elem_type} {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : mat${shape}_${elem_type};
|
|
|
|
fn load_a_p0_${row_index}(p0 : u32) -> ${elem_type} {
|
|
switch(p0) {
|
|
${col_table}
|
|
default: {
|
|
return ${elem_type}();
|
|
}
|
|
}
|
|
}
|
|
|
|
fn f() {
|
|
let I = 0;
|
|
let l = load_a_p0_${row_index}(u32(I));
|
|
}
|
|
)";
|
|
// col_table is the switch cases for all column index.
|
|
// Example for a matrix having 2 columns:
|
|
// case 0u: {
|
|
// return a.col0[${row_index}u];
|
|
// }
|
|
// case 1u: {
|
|
// return a.col1[${row_index}u];
|
|
// }
|
|
std::string col_table = matrix.JoinTemplatedStringForEachMatrixColumn( //
|
|
R"( case ${col_id_for_tmpl}u: {
|
|
return a.col${col_id_for_tmpl}[${row_index}u];
|
|
})",
|
|
"\n");
|
|
tmpl_expect = matrix.ReplaceFieldsInString(
|
|
tmpl_expect, {{"${col_vectors}", matrix.ExpendedColumnVectors(2, "col")},
|
|
{"${col_table}", col_table}});
|
|
} else {
|
|
tmpl_expect = tmpl_src;
|
|
}
|
|
|
|
for (uint32_t row = 0; row < matrix.rows; row++) {
|
|
std::string src = utils::ReplaceAll(tmpl_src, "${row_index}", std::to_string(row));
|
|
std::string expect = utils::ReplaceAll(tmpl_expect, "${row_index}", std::to_string(row));
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got)) << "accessing row " << row;
|
|
}
|
|
}
|
|
|
|
TEST_P(Std140Test_Matrix, MatUniform_LoadScalar_ConstColumnIndex_VariableRowIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
std::string tmpl_src = R"(
|
|
enable f16;
|
|
|
|
@group(0) @binding(0) var<uniform> a : ${mat};
|
|
|
|
fn f() {
|
|
let I = 0;
|
|
let l = a[${col_index}][I];
|
|
}
|
|
)";
|
|
tmpl_src = matrix.ReplaceFieldsInString(tmpl_src);
|
|
|
|
std::string tmpl_expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
tmpl_expect = R"(
|
|
enable f16;
|
|
|
|
struct mat${shape}_${elem_type} {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : mat${shape}_${elem_type};
|
|
|
|
fn f() {
|
|
let I = 0;
|
|
let l = a.col${col_index}[I];
|
|
}
|
|
)";
|
|
tmpl_expect = matrix.ReplaceFieldsInString(
|
|
tmpl_expect, {{"${col_vectors}", matrix.ExpendedColumnVectors(2, "col")}});
|
|
} else {
|
|
tmpl_expect = tmpl_src;
|
|
}
|
|
|
|
for (uint32_t col = 0; col < matrix.columns; col++) {
|
|
std::string src = utils::ReplaceAll(tmpl_src, "${col_index}", std::to_string(col));
|
|
std::string expect = utils::ReplaceAll(tmpl_expect, "${col_index}", std::to_string(col));
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got)) << "accessing col " << col;
|
|
}
|
|
}
|
|
|
|
TEST_P(Std140Test_Matrix, MatUniform_LoadScalar_VariableColumnIndex_VariableRowIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
std::string src = R"(
|
|
enable f16;
|
|
|
|
@group(0) @binding(0) var<uniform> a : ${mat};
|
|
|
|
fn f() {
|
|
let I = 0;
|
|
let l = a[I][I];
|
|
}
|
|
)";
|
|
src = matrix.ReplaceFieldsInString(src);
|
|
|
|
std::string expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
expect = R"(
|
|
enable f16;
|
|
|
|
struct mat${shape}_${elem_type} {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : mat${shape}_${elem_type};
|
|
|
|
fn load_a_p0_p1(p0 : u32, p1 : u32) -> ${elem_type} {
|
|
switch(p0) {
|
|
${col_table}
|
|
default: {
|
|
return ${elem_type}();
|
|
}
|
|
}
|
|
}
|
|
|
|
fn f() {
|
|
let I = 0;
|
|
let l = load_a_p0_p1(u32(I), u32(I));
|
|
}
|
|
)";
|
|
|
|
// col_table is the switch cases for all column index.
|
|
// Example for a matrix having 2 columns:
|
|
// case 0u: {
|
|
// return a.col0[p1];
|
|
// }
|
|
// case 1u: {
|
|
// return a.col1[p1];
|
|
// }
|
|
std::string col_table = matrix.JoinTemplatedStringForEachMatrixColumn( //
|
|
R"( case ${col_id_for_tmpl}u: {
|
|
return a.col${col_id_for_tmpl}[p1];
|
|
})",
|
|
"\n");
|
|
expect = matrix.ReplaceFieldsInString(
|
|
expect, {{"${col_vectors}", matrix.ExpendedColumnVectors(2, "col")},
|
|
{"${col_table}", col_table}});
|
|
} else {
|
|
expect = src;
|
|
}
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
TEST_P(Std140Test_Matrix, StructMatUniform_NameCollision) {
|
|
auto matrix = GetParam();
|
|
|
|
std::string src = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
m_1 : i32,
|
|
m : ${mat},
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> s : S;
|
|
)";
|
|
src = matrix.ReplaceFieldsInString(src);
|
|
|
|
std::string expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
expect = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
m_1 : i32,
|
|
m : ${mat},
|
|
}
|
|
|
|
struct S_std140 {
|
|
m_1 : i32,
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> s : S_std140;
|
|
)";
|
|
expect = matrix.ReplaceFieldsInString(
|
|
expect, {{"${col_vectors}", matrix.ExpendedColumnVectors(2, "m__")}});
|
|
} else {
|
|
expect = src;
|
|
}
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
TEST_P(Std140Test_Matrix, StructMatUniform_LoadStruct) {
|
|
auto matrix = GetParam();
|
|
|
|
std::string src = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
m : ${mat},
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> s : S;
|
|
|
|
fn f() {
|
|
let l = s;
|
|
}
|
|
)";
|
|
src = matrix.ReplaceFieldsInString(src);
|
|
|
|
std::string expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
expect = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
m : ${mat},
|
|
}
|
|
|
|
struct S_std140 {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> s : S_std140;
|
|
|
|
fn conv_S(val : S_std140) -> S {
|
|
return S(${mat}(${col_vectors_inline}));
|
|
}
|
|
|
|
fn f() {
|
|
let l = conv_S(s);
|
|
}
|
|
)";
|
|
expect = matrix.ReplaceFieldsInString(
|
|
expect,
|
|
{{"${col_vectors}", matrix.ExpendedColumnVectors(2, "m_")},
|
|
{"${col_vectors_inline}", matrix.ExpendedColumnVectorsInline("val.m_", ", ")}});
|
|
} else {
|
|
expect = src;
|
|
}
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
TEST_P(Std140Test_Matrix, StructMatUniform_LoadMatrix) {
|
|
auto matrix = GetParam();
|
|
|
|
std::string src = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
m : ${mat},
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> s : S;
|
|
|
|
fn f() {
|
|
let l = s.m;
|
|
}
|
|
)";
|
|
src = matrix.ReplaceFieldsInString(src);
|
|
|
|
std::string expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
expect = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
m : ${mat},
|
|
}
|
|
|
|
struct S_std140 {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> s : S_std140;
|
|
|
|
fn load_s_m() -> ${mat} {
|
|
let s = &(s);
|
|
return ${mat}(${col_vectors_inline});
|
|
}
|
|
|
|
fn f() {
|
|
let l = load_s_m();
|
|
}
|
|
)";
|
|
expect = matrix.ReplaceFieldsInString(
|
|
expect,
|
|
{{"${col_vectors}", matrix.ExpendedColumnVectors(2, "m_")},
|
|
{"${col_vectors_inline}", matrix.ExpendedColumnVectorsInline("(*(s)).m_", ", ")}});
|
|
} else {
|
|
expect = src;
|
|
}
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
TEST_P(Std140Test_Matrix, StructMatUniform_LoadColumn_ConstIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
std::string tmpl_src = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
m : ${mat},
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> s : S;
|
|
|
|
fn f() {
|
|
let l = s.m[${col_index}];
|
|
}
|
|
)";
|
|
tmpl_src = matrix.ReplaceFieldsInString(tmpl_src);
|
|
|
|
std::string tmpl_expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
tmpl_expect = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
m : ${mat},
|
|
}
|
|
|
|
struct S_std140 {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> s : S_std140;
|
|
|
|
fn f() {
|
|
let l = s.m_${col_index};
|
|
}
|
|
)";
|
|
tmpl_expect = matrix.ReplaceFieldsInString(
|
|
tmpl_expect, {{"${col_vectors}", matrix.ExpendedColumnVectors(2, "m_")}});
|
|
} else {
|
|
tmpl_expect = tmpl_src;
|
|
}
|
|
|
|
for (uint32_t col = 0; col < matrix.columns; col++) {
|
|
std::string src = utils::ReplaceAll(tmpl_src, "${col_index}", std::to_string(col));
|
|
std::string expect = utils::ReplaceAll(tmpl_expect, "${col_index}", std::to_string(col));
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got)) << "accessing col " << col;
|
|
}
|
|
}
|
|
|
|
TEST_P(Std140Test_Matrix, StructMatUniform_LoadColumn_VariableIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
std::string src = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
m : ${mat},
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> s : S;
|
|
|
|
fn f() {
|
|
let I = 0;
|
|
let l = s.m[I];
|
|
}
|
|
)";
|
|
src = matrix.ReplaceFieldsInString(src);
|
|
|
|
std::string expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
expect = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
m : ${mat},
|
|
}
|
|
|
|
struct S_std140 {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> s : S_std140;
|
|
|
|
fn load_s_m_p0(p0 : u32) -> ${col_vector_type} {
|
|
switch(p0) {
|
|
${col_table}
|
|
default: {
|
|
return ${col_vector_type}();
|
|
}
|
|
}
|
|
}
|
|
|
|
fn f() {
|
|
let I = 0;
|
|
let l = load_s_m_p0(u32(I));
|
|
}
|
|
)";
|
|
|
|
// col_table is the switch cases for all column index.
|
|
// Example for a matrix having 2 columns:
|
|
// case 0u: {
|
|
// return s.m_0;
|
|
// }
|
|
// case 1u: {
|
|
// return s.m_1;
|
|
// }
|
|
std::string col_table = matrix.JoinTemplatedStringForEachMatrixColumn( //
|
|
R"( case ${col_id_for_tmpl}u: {
|
|
return s.m_${col_id_for_tmpl};
|
|
})",
|
|
"\n");
|
|
expect = matrix.ReplaceFieldsInString(
|
|
expect, {{"${col_vector_type}", matrix.ColumnVector()},
|
|
{"${col_vectors}", matrix.ExpendedColumnVectors(2, "m_")},
|
|
{"${col_table}", col_table}});
|
|
} else {
|
|
expect = src;
|
|
}
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
TEST_P(Std140Test_Matrix, StructMatUniform_LoadScalar_ConstColumnIndex_ConstRowIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
std::string tmpl_src = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
m : ${mat},
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> s : S;
|
|
|
|
fn f() {
|
|
let l = s.m[${col_index}][${row_index}];
|
|
}
|
|
)";
|
|
tmpl_src = matrix.ReplaceFieldsInString(tmpl_src);
|
|
|
|
std::string tmpl_expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
tmpl_expect = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
m : ${mat},
|
|
}
|
|
|
|
struct S_std140 {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> s : S_std140;
|
|
|
|
fn f() {
|
|
let l = s.m_${col_index}[${row_index}u];
|
|
}
|
|
)";
|
|
tmpl_expect = matrix.ReplaceFieldsInString(
|
|
tmpl_expect, {{"${col_vectors}", matrix.ExpendedColumnVectors(2, "m_")}});
|
|
} else {
|
|
tmpl_expect = tmpl_src;
|
|
}
|
|
|
|
for (uint32_t col = 0; col < matrix.columns; col++) {
|
|
for (uint32_t row = 0; row < matrix.rows; row++) {
|
|
std::string src = utils::ReplaceAll(tmpl_src, "${col_index}", std::to_string(col));
|
|
src = utils::ReplaceAll(src, "${row_index}", std::to_string(row));
|
|
std::string expect =
|
|
utils::ReplaceAll(tmpl_expect, "${col_index}", std::to_string(col));
|
|
expect = utils::ReplaceAll(expect, "${row_index}", std::to_string(row));
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got)) << "accessing col " << col << " row " << row;
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST_P(Std140Test_Matrix, StructMatUniform_LoadScalar_VariableColumnIndex_ConstRowIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
std::string tmpl_src = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
m : ${mat},
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> s : S;
|
|
|
|
fn f() {
|
|
let I = 0;
|
|
let l = s.m[I][${row_index}];
|
|
}
|
|
)";
|
|
tmpl_src = matrix.ReplaceFieldsInString(tmpl_src);
|
|
|
|
std::string tmpl_expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
tmpl_expect = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
m : ${mat},
|
|
}
|
|
|
|
struct S_std140 {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> s : S_std140;
|
|
|
|
fn load_s_m_p0_${row_index}(p0 : u32) -> ${elem_type} {
|
|
switch(p0) {
|
|
${col_table}
|
|
default: {
|
|
return ${elem_type}();
|
|
}
|
|
}
|
|
}
|
|
|
|
fn f() {
|
|
let I = 0;
|
|
let l = load_s_m_p0_${row_index}(u32(I));
|
|
}
|
|
)";
|
|
// col_table is the switch cases for all column index.
|
|
// Example for a matrix having 2 columns:
|
|
// case 0u: {
|
|
// return s.m_0[${row_index}u];
|
|
// }
|
|
// case 1u: {
|
|
// return s.m_1[${row_index}u];
|
|
// }
|
|
std::string col_table = matrix.JoinTemplatedStringForEachMatrixColumn( //
|
|
R"( case ${col_id_for_tmpl}u: {
|
|
return s.m_${col_id_for_tmpl}[${row_index}u];
|
|
})",
|
|
"\n");
|
|
tmpl_expect = matrix.ReplaceFieldsInString(
|
|
tmpl_expect, {{"${col_vectors}", matrix.ExpendedColumnVectors(2, "m_")},
|
|
{"${col_table}", col_table}});
|
|
} else {
|
|
tmpl_expect = tmpl_src;
|
|
}
|
|
|
|
for (uint32_t row = 0; row < matrix.rows; row++) {
|
|
std::string src = utils::ReplaceAll(tmpl_src, "${row_index}", std::to_string(row));
|
|
std::string expect = utils::ReplaceAll(tmpl_expect, "${row_index}", std::to_string(row));
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got)) << "accessing row " << row;
|
|
}
|
|
}
|
|
|
|
TEST_P(Std140Test_Matrix, StructMatUniform_LoadScalar_ConstColumnIndex_VariableRowIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
std::string tmpl_src = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
m : ${mat},
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> s : S;
|
|
|
|
fn f() {
|
|
let I = 0;
|
|
let l = s.m[${col_index}][I];
|
|
}
|
|
)";
|
|
tmpl_src = matrix.ReplaceFieldsInString(tmpl_src);
|
|
|
|
std::string tmpl_expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
tmpl_expect = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
m : ${mat},
|
|
}
|
|
|
|
struct S_std140 {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> s : S_std140;
|
|
|
|
fn f() {
|
|
let I = 0;
|
|
let l = s.m_${col_index}[I];
|
|
}
|
|
)";
|
|
tmpl_expect = matrix.ReplaceFieldsInString(
|
|
tmpl_expect, {{"${col_vectors}", matrix.ExpendedColumnVectors(2, "m_")}});
|
|
} else {
|
|
tmpl_expect = tmpl_src;
|
|
}
|
|
|
|
for (uint32_t col = 0; col < matrix.columns; col++) {
|
|
std::string src = utils::ReplaceAll(tmpl_src, "${col_index}", std::to_string(col));
|
|
std::string expect = utils::ReplaceAll(tmpl_expect, "${col_index}", std::to_string(col));
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got)) << "accessing col " << col;
|
|
}
|
|
}
|
|
|
|
TEST_P(Std140Test_Matrix, StructMatUniform_LoadScalar_VariableColumnIndex_VariableRowIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
std::string src = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
m : ${mat},
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> s : S;
|
|
|
|
fn f() {
|
|
let I = 0;
|
|
let l = s.m[I][I];
|
|
}
|
|
)";
|
|
src = matrix.ReplaceFieldsInString(src);
|
|
|
|
std::string expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
expect = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
m : ${mat},
|
|
}
|
|
|
|
struct S_std140 {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> s : S_std140;
|
|
|
|
fn load_s_m_p0_p1(p0 : u32, p1 : u32) -> ${elem_type} {
|
|
switch(p0) {
|
|
${col_table}
|
|
default: {
|
|
return ${elem_type}();
|
|
}
|
|
}
|
|
}
|
|
|
|
fn f() {
|
|
let I = 0;
|
|
let l = load_s_m_p0_p1(u32(I), u32(I));
|
|
}
|
|
)";
|
|
|
|
// col_table is the switch cases for all column index.
|
|
// Example for a matrix having 2 columns:
|
|
// case 0u: {
|
|
// return s.m_0[p1];
|
|
// }
|
|
// case 1u: {
|
|
// return s.m_1[p1];
|
|
// }
|
|
std::string col_table = matrix.JoinTemplatedStringForEachMatrixColumn( //
|
|
R"( case ${col_id_for_tmpl}u: {
|
|
return s.m_${col_id_for_tmpl}[p1];
|
|
})",
|
|
"\n");
|
|
expect = matrix.ReplaceFieldsInString(
|
|
expect, {{"${col_vectors}", matrix.ExpendedColumnVectors(2, "m_")},
|
|
{"${col_table}", col_table}});
|
|
} else {
|
|
expect = src;
|
|
}
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
TEST_P(Std140Test_Matrix, ArrayStructMatUniform_LoadArray) {
|
|
auto matrix = GetParam();
|
|
|
|
std::string src = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
@size(64)
|
|
m : ${mat},
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<S, 3>;
|
|
|
|
fn f() {
|
|
let l = a;
|
|
}
|
|
)";
|
|
src = matrix.ReplaceFieldsInString(src);
|
|
|
|
std::string expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
expect = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
@size(64)
|
|
m : ${mat},
|
|
}
|
|
|
|
struct S_std140 {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<S_std140, 3u>;
|
|
|
|
fn conv_S(val : S_std140) -> S {
|
|
return S(${mat}(${col_vectors_inline}));
|
|
}
|
|
|
|
fn conv_arr3_S(val : array<S_std140, 3u>) -> array<S, 3u> {
|
|
var arr : array<S, 3u>;
|
|
for(var i : u32; (i < 3u); i = (i + 1)) {
|
|
arr[i] = conv_S(val[i]);
|
|
}
|
|
return arr;
|
|
}
|
|
|
|
fn f() {
|
|
let l = conv_arr3_S(a);
|
|
}
|
|
)";
|
|
uint32_t last_size =
|
|
64 - static_cast<uint32_t>(matrix.ColumnVectorAlign() * (matrix.columns - 1));
|
|
expect = matrix.ReplaceFieldsInString(
|
|
expect,
|
|
{{"${col_vectors}", matrix.ExpendedColumnVectorsWithLastSize(2, "m_", last_size)},
|
|
{"${col_vectors_inline}", matrix.ExpendedColumnVectorsInline("val.m_", ", ")}});
|
|
} else {
|
|
expect = src;
|
|
}
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
TEST_P(Std140Test_Matrix, ArrayStructMatUniform_LoadStruct_ConstIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
std::string tmpl_src = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
@size(64)
|
|
m : ${mat},
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<S, 3>;
|
|
|
|
fn f() {
|
|
let l = a[${array_index}];
|
|
}
|
|
)";
|
|
tmpl_src = matrix.ReplaceFieldsInString(tmpl_src);
|
|
|
|
std::string tmpl_expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
tmpl_expect = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
@size(64)
|
|
m : ${mat},
|
|
}
|
|
|
|
struct S_std140 {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<S_std140, 3u>;
|
|
|
|
fn conv_S(val : S_std140) -> S {
|
|
return S(${mat}(${col_vectors_inline}));
|
|
}
|
|
|
|
fn f() {
|
|
let l = conv_S(a[${array_index}u]);
|
|
}
|
|
)";
|
|
uint32_t last_size =
|
|
64 - static_cast<uint32_t>(matrix.ColumnVectorAlign() * (matrix.columns - 1));
|
|
tmpl_expect = matrix.ReplaceFieldsInString(
|
|
tmpl_expect,
|
|
{{"${col_vectors}", matrix.ExpendedColumnVectorsWithLastSize(2, "m_", last_size)},
|
|
{"${col_vectors_inline}", matrix.ExpendedColumnVectorsInline("val.m_", ", ")}});
|
|
} else {
|
|
tmpl_expect = tmpl_src;
|
|
}
|
|
|
|
for (uint32_t array_index = 0; array_index < 3; array_index++) {
|
|
std::string src =
|
|
utils::ReplaceAll(tmpl_src, "${array_index}", std::to_string(array_index));
|
|
std::string expect =
|
|
utils::ReplaceAll(tmpl_expect, "${array_index}", std::to_string(array_index));
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got)) << "accessing array element " << array_index;
|
|
}
|
|
}
|
|
|
|
TEST_P(Std140Test_Matrix, ArrayStructMatUniform_LoadStruct_VariableIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
std::string src = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
@size(64)
|
|
m : ${mat},
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<S, 3>;
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let l = a[I];
|
|
}
|
|
)";
|
|
src = matrix.ReplaceFieldsInString(src);
|
|
|
|
std::string expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
expect = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
@size(64)
|
|
m : ${mat},
|
|
}
|
|
|
|
struct S_std140 {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<S_std140, 3u>;
|
|
|
|
fn conv_S(val : S_std140) -> S {
|
|
return S(${mat}(${col_vectors_inline}));
|
|
}
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let l = conv_S(a[I]);
|
|
}
|
|
)";
|
|
uint32_t last_size =
|
|
64 - static_cast<uint32_t>(matrix.ColumnVectorAlign() * (matrix.columns - 1));
|
|
expect = matrix.ReplaceFieldsInString(
|
|
expect,
|
|
{{"${col_vectors}", matrix.ExpendedColumnVectorsWithLastSize(2, "m_", last_size)},
|
|
{"${col_vectors_inline}", matrix.ExpendedColumnVectorsInline("val.m_", ", ")}});
|
|
} else {
|
|
expect = src;
|
|
}
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
TEST_P(Std140Test_Matrix, ArrayStructMatUniform_LoadMatrix_ConstArrayIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
std::string tmpl_src = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
@size(64)
|
|
m : ${mat},
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<S, 3>;
|
|
|
|
fn f() {
|
|
let l = a[${array_index}].m;
|
|
}
|
|
)";
|
|
tmpl_src = matrix.ReplaceFieldsInString(tmpl_src);
|
|
|
|
std::string tmpl_expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
tmpl_expect = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
@size(64)
|
|
m : ${mat},
|
|
}
|
|
|
|
struct S_std140 {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<S_std140, 3u>;
|
|
|
|
fn load_a_${array_index}_m() -> ${mat} {
|
|
let s = &(a[${array_index}u]);
|
|
return ${mat}(${col_vectors_inline});
|
|
}
|
|
|
|
fn f() {
|
|
let l = load_a_${array_index}_m();
|
|
}
|
|
)";
|
|
uint32_t last_size =
|
|
64 - static_cast<uint32_t>(matrix.ColumnVectorAlign() * (matrix.columns - 1));
|
|
tmpl_expect = matrix.ReplaceFieldsInString(
|
|
tmpl_expect,
|
|
{{"${col_vectors}", matrix.ExpendedColumnVectorsWithLastSize(2, "m_", last_size)},
|
|
{"${col_vectors_inline}", matrix.ExpendedColumnVectorsInline("(*(s)).m_", ", ")}});
|
|
} else {
|
|
tmpl_expect = tmpl_src;
|
|
}
|
|
|
|
for (uint32_t array_index = 0; array_index < 3; array_index++) {
|
|
std::string src =
|
|
utils::ReplaceAll(tmpl_src, "${array_index}", std::to_string(array_index));
|
|
std::string expect =
|
|
utils::ReplaceAll(tmpl_expect, "${array_index}", std::to_string(array_index));
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got)) << "accessing array element " << array_index;
|
|
}
|
|
}
|
|
|
|
TEST_P(Std140Test_Matrix, ArrayStructMatUniform_LoadMatrix_VariableArrayIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
std::string src = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
@size(64)
|
|
m : ${mat},
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<S, 3>;
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let l = a[I].m;
|
|
}
|
|
)";
|
|
src = matrix.ReplaceFieldsInString(src);
|
|
|
|
std::string expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
expect = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
@size(64)
|
|
m : ${mat},
|
|
}
|
|
|
|
struct S_std140 {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<S_std140, 3u>;
|
|
|
|
fn load_a_p0_m(p0 : u32) -> ${mat} {
|
|
let s = &(a[p0]);
|
|
return ${mat}(${col_vectors_inline});
|
|
}
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let l = load_a_p0_m(u32(I));
|
|
}
|
|
)";
|
|
uint32_t last_size =
|
|
64 - static_cast<uint32_t>(matrix.ColumnVectorAlign() * (matrix.columns - 1));
|
|
expect = matrix.ReplaceFieldsInString(
|
|
expect,
|
|
{{"${col_vectors}", matrix.ExpendedColumnVectorsWithLastSize(2, "m_", last_size)},
|
|
{"${col_vectors_inline}", matrix.ExpendedColumnVectorsInline("(*(s)).m_", ", ")}});
|
|
} else {
|
|
expect = src;
|
|
}
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
TEST_P(Std140Test_Matrix, ArrayStructMatUniform_LoadColumn_ConstArrayIndex_ConstColumnIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
std::string tmpl_src = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
@size(64)
|
|
m : ${mat},
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<S, 3>;
|
|
|
|
fn f() {
|
|
let l = a[${array_index}].m[${cloumn_index}];
|
|
}
|
|
)";
|
|
tmpl_src = matrix.ReplaceFieldsInString(tmpl_src);
|
|
|
|
std::string tmpl_expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
tmpl_expect = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
@size(64)
|
|
m : ${mat},
|
|
}
|
|
|
|
struct S_std140 {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<S_std140, 3u>;
|
|
|
|
fn f() {
|
|
let l = a[${array_index}u].m_${cloumn_index};
|
|
}
|
|
)";
|
|
uint32_t last_size =
|
|
64 - static_cast<uint32_t>(matrix.ColumnVectorAlign() * (matrix.columns - 1));
|
|
tmpl_expect = matrix.ReplaceFieldsInString(
|
|
tmpl_expect,
|
|
{{"${col_vectors}", matrix.ExpendedColumnVectorsWithLastSize(2, "m_", last_size)}});
|
|
} else {
|
|
tmpl_expect = tmpl_src;
|
|
}
|
|
|
|
for (uint32_t array_index = 0; array_index < 3; array_index++) {
|
|
for (uint32_t col = 0; col < matrix.columns; col++) {
|
|
std::string src =
|
|
utils::ReplaceAll(tmpl_src, "${array_index}", std::to_string(array_index));
|
|
src = utils::ReplaceAll(src, "${cloumn_index}", std::to_string(col));
|
|
std::string expect =
|
|
utils::ReplaceAll(tmpl_expect, "${array_index}", std::to_string(array_index));
|
|
expect = utils::ReplaceAll(expect, "${cloumn_index}", std::to_string(col));
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got))
|
|
<< "accessing array element " << array_index << " col " << col;
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST_P(Std140Test_Matrix, ArrayStructMatUniform_LoadColumn_VariableArrayIndex_ConstColumnIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
std::string tmpl_src = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
@size(64)
|
|
m : ${mat},
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<S, 3>;
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let l = a[I].m[${cloumn_index}];
|
|
}
|
|
)";
|
|
tmpl_src = matrix.ReplaceFieldsInString(tmpl_src);
|
|
|
|
std::string tmpl_expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
tmpl_expect = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
@size(64)
|
|
m : ${mat},
|
|
}
|
|
|
|
struct S_std140 {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<S_std140, 3u>;
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let l = a[I].m_${cloumn_index};
|
|
}
|
|
)";
|
|
uint32_t last_size =
|
|
64 - static_cast<uint32_t>(matrix.ColumnVectorAlign() * (matrix.columns - 1));
|
|
tmpl_expect = matrix.ReplaceFieldsInString(
|
|
tmpl_expect,
|
|
{{"${col_vectors}", matrix.ExpendedColumnVectorsWithLastSize(2, "m_", last_size)}});
|
|
} else {
|
|
tmpl_expect = tmpl_src;
|
|
}
|
|
|
|
for (uint32_t col = 0; col < matrix.columns; col++) {
|
|
std::string src = utils::ReplaceAll(tmpl_src, "${cloumn_index}", std::to_string(col));
|
|
std::string expect = utils::ReplaceAll(tmpl_expect, "${cloumn_index}", std::to_string(col));
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got)) << "accessing col " << col;
|
|
}
|
|
}
|
|
|
|
TEST_P(Std140Test_Matrix, ArrayStructMatUniform_LoadColumn_ConstArrayIndex_VariableColumnIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
std::string tmpl_src = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
@size(64)
|
|
m : ${mat},
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<S, 3>;
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let l = a[${array_index}].m[I];
|
|
}
|
|
)";
|
|
tmpl_src = matrix.ReplaceFieldsInString(tmpl_src);
|
|
|
|
std::string tmpl_expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
tmpl_expect = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
@size(64)
|
|
m : ${mat},
|
|
}
|
|
|
|
struct S_std140 {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<S_std140, 3u>;
|
|
|
|
fn load_a_${array_index}_m_p0(p0 : u32) -> ${col_vector_type} {
|
|
switch(p0) {
|
|
${col_table}
|
|
default: {
|
|
return ${col_vector_type}();
|
|
}
|
|
}
|
|
}
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let l = load_a_${array_index}_m_p0(u32(I));
|
|
}
|
|
)";
|
|
// col_table is the switch cases for all column index.
|
|
// Example for a matrix having 2 columns:
|
|
// case 0u: {
|
|
// return a[${array_index}u].m_0;
|
|
// }
|
|
// case 1u: {
|
|
// return a[${array_index}u].m_1;
|
|
// }
|
|
std::string col_table = matrix.JoinTemplatedStringForEachMatrixColumn( //
|
|
R"( case ${col_id_for_tmpl}u: {
|
|
return a[${array_index}u].m_${col_id_for_tmpl};
|
|
})",
|
|
"\n");
|
|
uint32_t last_size =
|
|
64 - static_cast<uint32_t>(matrix.ColumnVectorAlign() * (matrix.columns - 1));
|
|
tmpl_expect = matrix.ReplaceFieldsInString(
|
|
tmpl_expect,
|
|
{{"${col_vectors}", matrix.ExpendedColumnVectorsWithLastSize(2, "m_", last_size)},
|
|
{"${col_table}", col_table}});
|
|
} else {
|
|
tmpl_expect = tmpl_src;
|
|
}
|
|
|
|
for (uint32_t array_index = 0; array_index < 3; array_index++) {
|
|
std::string src =
|
|
utils::ReplaceAll(tmpl_src, "${array_index}", std::to_string(array_index));
|
|
std::string expect =
|
|
utils::ReplaceAll(tmpl_expect, "${array_index}", std::to_string(array_index));
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got)) << "accessing array element " << array_index;
|
|
}
|
|
}
|
|
|
|
TEST_P(Std140Test_Matrix, ArrayStructMatUniform_LoadColumn_VariableArrayIndex_VariableColumnIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
std::string src = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
@size(64)
|
|
m : ${mat},
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<S, 3>;
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let l = a[I].m[I];
|
|
}
|
|
)";
|
|
src = matrix.ReplaceFieldsInString(src);
|
|
|
|
std::string expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
expect = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
@size(64)
|
|
m : ${mat},
|
|
}
|
|
|
|
struct S_std140 {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<S_std140, 3u>;
|
|
|
|
fn load_a_p0_m_p1(p0 : u32, p1 : u32) -> ${col_vector_type} {
|
|
switch(p1) {
|
|
${col_table}
|
|
default: {
|
|
return ${col_vector_type}();
|
|
}
|
|
}
|
|
}
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let l = load_a_p0_m_p1(u32(I), u32(I));
|
|
}
|
|
)";
|
|
// col_table is the switch cases for all column index.
|
|
// Example for a matrix having 2 columns:
|
|
// case 0u: {
|
|
// return a[p0].m_0;
|
|
// }
|
|
// case 1u: {
|
|
// return a[p0].m_1;
|
|
// }
|
|
std::string col_table = matrix.JoinTemplatedStringForEachMatrixColumn( //
|
|
R"( case ${col_id_for_tmpl}u: {
|
|
return a[p0].m_${col_id_for_tmpl};
|
|
})",
|
|
"\n");
|
|
uint32_t last_size =
|
|
64 - static_cast<uint32_t>(matrix.ColumnVectorAlign() * (matrix.columns - 1));
|
|
expect = matrix.ReplaceFieldsInString(
|
|
expect,
|
|
{{"${col_vectors}", matrix.ExpendedColumnVectorsWithLastSize(2, "m_", last_size)},
|
|
{"${col_table}", col_table}});
|
|
} else {
|
|
expect = src;
|
|
}
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
TEST_P(Std140Test_Matrix, ArrayStructArrayStructMatUniform_Loads) {
|
|
auto matrix = GetParam();
|
|
|
|
std::string src = R"(
|
|
enable f16;
|
|
|
|
struct Inner {
|
|
@size(64)
|
|
m : ${mat},
|
|
}
|
|
|
|
struct Outer {
|
|
a : array<Inner, 4>,
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<Outer, 4>;
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let J = 2;
|
|
let K = 0;
|
|
let l_a : array<Outer, 4> = a;
|
|
let l_a_1 : Outer = a[1];
|
|
let l_a_I : Outer = a[I];
|
|
let l_a_2_a : array<Inner, 4> = a[2].a;
|
|
let l_a_I_a : array<Inner, 4> = a[I].a;
|
|
let l_a_3_a_1 : Inner = a[3].a[1];
|
|
let l_a_3_a_I : Inner = a[3].a[I];
|
|
let l_a_I_a_1 : Inner = a[I].a[1];
|
|
let l_a_I_a_J : Inner = a[I].a[J];
|
|
let l_a_0_a_2_m : ${mat} = a[0].a[2].m;
|
|
let l_a_0_a_I_m : ${mat} = a[0].a[I].m;
|
|
let l_a_I_a_2_m : ${mat} = a[I].a[2].m;
|
|
let l_a_I_a_J_m : ${mat} = a[I].a[J].m;
|
|
let l_a_1_a_3_m_0 : ${col_vector_type} = a[1].a[3].m[0];
|
|
let l_a_I_a_J_m_K : ${col_vector_type} = a[I].a[J].m[K];
|
|
let l_a_2_a_0_m_1_0 : ${elem_type} = a[2].a[0].m[1][0];
|
|
let l_a_I_a_J_m_K_I : ${elem_type} = a[I].a[J].m[K][I];
|
|
}
|
|
)";
|
|
src = matrix.ReplaceFieldsInString(src);
|
|
|
|
std::string expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
expect = R"(
|
|
enable f16;
|
|
|
|
struct Inner {
|
|
@size(64)
|
|
m : ${mat},
|
|
}
|
|
|
|
struct Inner_std140 {
|
|
${col_vectors}
|
|
}
|
|
|
|
struct Outer {
|
|
a : array<Inner, 4>,
|
|
}
|
|
|
|
struct Outer_std140 {
|
|
a : array<Inner_std140, 4u>,
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<Outer_std140, 4u>;
|
|
|
|
fn conv_Inner(val : Inner_std140) -> Inner {
|
|
return Inner(${mat}(${col_vectors_inline_conv_Inner}));
|
|
}
|
|
|
|
fn conv_arr4_Inner(val : array<Inner_std140, 4u>) -> array<Inner, 4u> {
|
|
var arr : array<Inner, 4u>;
|
|
for(var i : u32; (i < 4u); i = (i + 1)) {
|
|
arr[i] = conv_Inner(val[i]);
|
|
}
|
|
return arr;
|
|
}
|
|
|
|
fn conv_Outer(val : Outer_std140) -> Outer {
|
|
return Outer(conv_arr4_Inner(val.a));
|
|
}
|
|
|
|
fn conv_arr4_Outer(val : array<Outer_std140, 4u>) -> array<Outer, 4u> {
|
|
var arr : array<Outer, 4u>;
|
|
for(var i : u32; (i < 4u); i = (i + 1)) {
|
|
arr[i] = conv_Outer(val[i]);
|
|
}
|
|
return arr;
|
|
}
|
|
|
|
fn load_a_0_a_2_m() -> ${mat} {
|
|
let s = &(a[0u].a[2u]);
|
|
return ${mat}(${col_vectors_inline_load_matrix});
|
|
}
|
|
|
|
fn load_a_0_a_p0_m(p0 : u32) -> ${mat} {
|
|
let s = &(a[0u].a[p0]);
|
|
return ${mat}(${col_vectors_inline_load_matrix});
|
|
}
|
|
|
|
fn load_a_p0_a_2_m(p0 : u32) -> ${mat} {
|
|
let s = &(a[p0].a[2u]);
|
|
return ${mat}(${col_vectors_inline_load_matrix});
|
|
}
|
|
|
|
fn load_a_p0_a_p1_m(p0 : u32, p1 : u32) -> ${mat} {
|
|
let s = &(a[p0].a[p1]);
|
|
return ${mat}(${col_vectors_inline_load_matrix});
|
|
}
|
|
|
|
fn load_a_p0_a_p1_m_p2(p0 : u32, p1 : u32, p2 : u32) -> ${col_vector_type} {
|
|
switch(p2) {
|
|
${col_table_load_column}
|
|
default: {
|
|
return ${col_vector_type}();
|
|
}
|
|
}
|
|
}
|
|
|
|
fn load_a_p0_a_p1_m_p2_p3(p0 : u32, p1 : u32, p2 : u32, p3 : u32) -> ${elem_type} {
|
|
switch(p2) {
|
|
${col_table_load_element}
|
|
default: {
|
|
return ${elem_type}();
|
|
}
|
|
}
|
|
}
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let J = 2;
|
|
let K = 0;
|
|
let l_a : array<Outer, 4> = conv_arr4_Outer(a);
|
|
let l_a_1 : Outer = conv_Outer(a[1u]);
|
|
let l_a_I : Outer = conv_Outer(a[I]);
|
|
let l_a_2_a : array<Inner, 4> = conv_arr4_Inner(a[2u].a);
|
|
let l_a_I_a : array<Inner, 4> = conv_arr4_Inner(a[I].a);
|
|
let l_a_3_a_1 : Inner = conv_Inner(a[3u].a[1u]);
|
|
let l_a_3_a_I : Inner = conv_Inner(a[3u].a[I]);
|
|
let l_a_I_a_1 : Inner = conv_Inner(a[I].a[1u]);
|
|
let l_a_I_a_J : Inner = conv_Inner(a[I].a[J]);
|
|
let l_a_0_a_2_m : ${mat} = load_a_0_a_2_m();
|
|
let l_a_0_a_I_m : ${mat} = load_a_0_a_p0_m(u32(I));
|
|
let l_a_I_a_2_m : ${mat} = load_a_p0_a_2_m(u32(I));
|
|
let l_a_I_a_J_m : ${mat} = load_a_p0_a_p1_m(u32(I), u32(J));
|
|
let l_a_1_a_3_m_0 : ${col_vector_type} = a[1u].a[3u].m_0;
|
|
let l_a_I_a_J_m_K : ${col_vector_type} = load_a_p0_a_p1_m_p2(u32(I), u32(J), u32(K));
|
|
let l_a_2_a_0_m_1_0 : ${elem_type} = a[2u].a[0u].m_1[0u];
|
|
let l_a_I_a_J_m_K_I : ${elem_type} = load_a_p0_a_p1_m_p2_p3(u32(I), u32(J), u32(K), u32(I));
|
|
}
|
|
)";
|
|
std::string col_tableLoadColumn = matrix.JoinTemplatedStringForEachMatrixColumn( //
|
|
R"( case ${col_id_for_tmpl}u: {
|
|
return a[p0].a[p1].m_${col_id_for_tmpl};
|
|
})",
|
|
"\n");
|
|
std::string col_tableLoadElement = matrix.JoinTemplatedStringForEachMatrixColumn( //
|
|
R"( case ${col_id_for_tmpl}u: {
|
|
return a[p0].a[p1].m_${col_id_for_tmpl}[p3];
|
|
})",
|
|
"\n");
|
|
uint32_t last_size =
|
|
64 - static_cast<uint32_t>(matrix.ColumnVectorAlign() * (matrix.columns - 1));
|
|
expect = matrix.ReplaceFieldsInString(
|
|
expect,
|
|
{{"${col_vectors}", matrix.ExpendedColumnVectorsWithLastSize(2, "m_", last_size)},
|
|
{"${col_vectors_inline_conv_Inner}",
|
|
matrix.ExpendedColumnVectorsInline("val.m_", ", ")},
|
|
{"${col_vectors_inline_load_matrix}",
|
|
matrix.ExpendedColumnVectorsInline("(*(s)).m_", ", ")},
|
|
{"${col_table_load_column}", col_tableLoadColumn},
|
|
{"${col_table_load_element}", col_tableLoadElement}});
|
|
} else {
|
|
expect = src;
|
|
}
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
TEST_P(Std140Test_Matrix, ArrayStructArrayStructMatUniform_LoadsViaPtrs) {
|
|
auto matrix = GetParam();
|
|
|
|
std::string src = R"(
|
|
enable f16;
|
|
|
|
struct Inner {
|
|
@size(64)
|
|
m : ${mat},
|
|
}
|
|
|
|
struct Outer {
|
|
a : array<Inner, 4>,
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<Outer, 4>;
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let J = 2;
|
|
let K = 0;
|
|
let p_a = &(a);
|
|
let p_a_3 = &((*(p_a))[3]);
|
|
let p_a_I = &((*(p_a))[I]);
|
|
let p_a_3_a = &((*(p_a_3)).a);
|
|
let p_a_I_a = &((*(p_a_I)).a);
|
|
let p_a_3_a_2 = &((*(p_a_3_a))[2]);
|
|
let p_a_3_a_I = &((*(p_a_3_a))[I]);
|
|
let p_a_I_a_2 = &((*(p_a_I_a))[2]);
|
|
let p_a_I_a_J = &((*(p_a_I_a))[J]);
|
|
let p_a_3_a_2_m = &((*(p_a_3_a_2)).m);
|
|
let p_a_3_a_I_m = &((*(p_a_3_a_I)).m);
|
|
let p_a_I_a_2_m = &((*(p_a_I_a_2)).m);
|
|
let p_a_I_a_J_m = &((*(p_a_I_a_J)).m);
|
|
let p_a_3_a_2_m_1 = &((*(p_a_3_a_2_m))[1]);
|
|
let p_a_I_a_J_m_K = &((*(p_a_I_a_J_m))[K]);
|
|
let l_a : array<Outer, 4> = *(p_a);
|
|
let l_a_3 : Outer = *(p_a_3);
|
|
let l_a_I : Outer = *(p_a_I);
|
|
let l_a_3_a : array<Inner, 4> = *(p_a_3_a);
|
|
let l_a_I_a : array<Inner, 4> = *(p_a_I_a);
|
|
let l_a_3_a_2 : Inner = *(p_a_3_a_2);
|
|
let l_a_3_a_I : Inner = *(p_a_3_a_I);
|
|
let l_a_I_a_2 : Inner = *(p_a_I_a_2);
|
|
let l_a_I_a_J : Inner = *(p_a_I_a_J);
|
|
let l_a_3_a_2_m : ${mat} = *(p_a_3_a_2_m);
|
|
let l_a_3_a_I_m : ${mat} = *(p_a_3_a_I_m);
|
|
let l_a_I_a_2_m : ${mat} = *(p_a_I_a_2_m);
|
|
let l_a_I_a_J_m : ${mat} = *(p_a_I_a_J_m);
|
|
let l_a_3_a_2_m_1 : ${col_vector_type} = *(p_a_3_a_2_m_1);
|
|
let l_a_I_a_J_m_K : ${col_vector_type} = *(p_a_I_a_J_m_K);
|
|
let l_a_2_a_0_m_1_0 : ${elem_type} = (*(p_a_3_a_2_m_1))[0];
|
|
let l_a_I_a_J_m_K_I : ${elem_type} = (*(p_a_I_a_J_m_K))[I];
|
|
}
|
|
)";
|
|
src = matrix.ReplaceFieldsInString(src);
|
|
|
|
std::string expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
expect = R"(
|
|
enable f16;
|
|
|
|
struct Inner {
|
|
@size(64)
|
|
m : ${mat},
|
|
}
|
|
|
|
struct Inner_std140 {
|
|
${col_vectors}
|
|
}
|
|
|
|
struct Outer {
|
|
a : array<Inner, 4>,
|
|
}
|
|
|
|
struct Outer_std140 {
|
|
a : array<Inner_std140, 4u>,
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<Outer_std140, 4u>;
|
|
|
|
fn conv_Inner(val : Inner_std140) -> Inner {
|
|
return Inner(${mat}(${col_vectors_inline_conv_Inner}));
|
|
}
|
|
|
|
fn conv_arr4_Inner(val : array<Inner_std140, 4u>) -> array<Inner, 4u> {
|
|
var arr : array<Inner, 4u>;
|
|
for(var i : u32; (i < 4u); i = (i + 1)) {
|
|
arr[i] = conv_Inner(val[i]);
|
|
}
|
|
return arr;
|
|
}
|
|
|
|
fn conv_Outer(val : Outer_std140) -> Outer {
|
|
return Outer(conv_arr4_Inner(val.a));
|
|
}
|
|
|
|
fn conv_arr4_Outer(val : array<Outer_std140, 4u>) -> array<Outer, 4u> {
|
|
var arr : array<Outer, 4u>;
|
|
for(var i : u32; (i < 4u); i = (i + 1)) {
|
|
arr[i] = conv_Outer(val[i]);
|
|
}
|
|
return arr;
|
|
}
|
|
|
|
fn load_a_3_a_2_m() -> ${mat} {
|
|
let s = &(a[3u].a[2u]);
|
|
return ${mat}(${col_vectors_inline_load_matrix});
|
|
}
|
|
|
|
fn load_a_3_a_p0_m(p0 : u32) -> ${mat} {
|
|
let s = &(a[3u].a[p0]);
|
|
return ${mat}(${col_vectors_inline_load_matrix});
|
|
}
|
|
|
|
fn load_a_p0_a_2_m(p0 : u32) -> ${mat} {
|
|
let s = &(a[p0].a[2u]);
|
|
return ${mat}(${col_vectors_inline_load_matrix});
|
|
}
|
|
|
|
fn load_a_p0_a_p1_m(p0 : u32, p1 : u32) -> ${mat} {
|
|
let s = &(a[p0].a[p1]);
|
|
return ${mat}(${col_vectors_inline_load_matrix});
|
|
}
|
|
|
|
fn load_a_p0_a_p1_m_p2(p0 : u32, p1 : u32, p2 : u32) -> ${col_vector_type} {
|
|
switch(p2) {
|
|
${col_table_load_column}
|
|
default: {
|
|
return ${col_vector_type}();
|
|
}
|
|
}
|
|
}
|
|
|
|
fn load_a_p0_a_p1_m_p2_p3(p0 : u32, p1 : u32, p2 : u32, p3 : u32) -> ${elem_type} {
|
|
switch(p2) {
|
|
${col_table_load_element}
|
|
default: {
|
|
return ${elem_type}();
|
|
}
|
|
}
|
|
}
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let J = 2;
|
|
let K = 0;
|
|
let p_a = conv_arr4_Outer(a);
|
|
let p_a_3 = conv_Outer(a[3u]);
|
|
let p_a_I = conv_Outer(a[I]);
|
|
let p_a_3_a = conv_arr4_Inner(a[3u].a);
|
|
let p_a_I_a = conv_arr4_Inner(a[I].a);
|
|
let p_a_3_a_2 = conv_Inner(a[3u].a[2u]);
|
|
let p_a_3_a_I = conv_Inner(a[3u].a[I]);
|
|
let p_a_I_a_2 = conv_Inner(a[I].a[2u]);
|
|
let p_a_I_a_J = conv_Inner(a[I].a[J]);
|
|
let p_a_3_a_2_m = load_a_3_a_2_m();
|
|
let p_a_3_a_I_m = load_a_3_a_p0_m(u32(I));
|
|
let p_a_I_a_2_m = load_a_p0_a_2_m(u32(I));
|
|
let p_a_I_a_J_m = load_a_p0_a_p1_m(u32(I), u32(J));
|
|
let p_a_3_a_2_m_1 = a[3u].a[2u].m_1;
|
|
let p_a_I_a_J_m_K = load_a_p0_a_p1_m_p2(u32(I), u32(J), u32(K));
|
|
let l_a : array<Outer, 4> = conv_arr4_Outer(a);
|
|
let l_a_3 : Outer = conv_Outer(a[3u]);
|
|
let l_a_I : Outer = conv_Outer(a[I]);
|
|
let l_a_3_a : array<Inner, 4> = conv_arr4_Inner(a[3u].a);
|
|
let l_a_I_a : array<Inner, 4> = conv_arr4_Inner(a[I].a);
|
|
let l_a_3_a_2 : Inner = conv_Inner(a[3u].a[2u]);
|
|
let l_a_3_a_I : Inner = conv_Inner(a[3u].a[I]);
|
|
let l_a_I_a_2 : Inner = conv_Inner(a[I].a[2u]);
|
|
let l_a_I_a_J : Inner = conv_Inner(a[I].a[J]);
|
|
let l_a_3_a_2_m : ${mat} = load_a_3_a_2_m();
|
|
let l_a_3_a_I_m : ${mat} = load_a_3_a_p0_m(u32(I));
|
|
let l_a_I_a_2_m : ${mat} = load_a_p0_a_2_m(u32(I));
|
|
let l_a_I_a_J_m : ${mat} = load_a_p0_a_p1_m(u32(I), u32(J));
|
|
let l_a_3_a_2_m_1 : ${col_vector_type} = a[3u].a[2u].m_1;
|
|
let l_a_I_a_J_m_K : ${col_vector_type} = load_a_p0_a_p1_m_p2(u32(I), u32(J), u32(K));
|
|
let l_a_2_a_0_m_1_0 : ${elem_type} = a[3u].a[2u].m_1[0u];
|
|
let l_a_I_a_J_m_K_I : ${elem_type} = load_a_p0_a_p1_m_p2_p3(u32(I), u32(J), u32(K), u32(I));
|
|
}
|
|
)";
|
|
std::string col_tableLoadColumn = matrix.JoinTemplatedStringForEachMatrixColumn( //
|
|
R"( case ${col_id_for_tmpl}u: {
|
|
return a[p0].a[p1].m_${col_id_for_tmpl};
|
|
})",
|
|
"\n");
|
|
std::string col_tableLoadElement = matrix.JoinTemplatedStringForEachMatrixColumn( //
|
|
R"( case ${col_id_for_tmpl}u: {
|
|
return a[p0].a[p1].m_${col_id_for_tmpl}[p3];
|
|
})",
|
|
"\n");
|
|
uint32_t last_size =
|
|
64 - static_cast<uint32_t>(matrix.ColumnVectorAlign() * (matrix.columns - 1));
|
|
expect = matrix.ReplaceFieldsInString(
|
|
expect,
|
|
{{"${col_vectors}", matrix.ExpendedColumnVectorsWithLastSize(2, "m_", last_size)},
|
|
{"${col_vectors_inline_conv_Inner}",
|
|
matrix.ExpendedColumnVectorsInline("val.m_", ", ")},
|
|
{"${col_vectors_inline_load_matrix}",
|
|
matrix.ExpendedColumnVectorsInline("(*(s)).m_", ", ")},
|
|
{"${col_table_load_column}", col_tableLoadColumn},
|
|
{"${col_table_load_element}", col_tableLoadElement}});
|
|
} else {
|
|
expect = src;
|
|
}
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
TEST_P(Std140Test_Matrix, ArrayStructMatUniform_CopyArray_UniformToStorage) {
|
|
auto matrix = GetParam();
|
|
|
|
std::string src = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
@size(64)
|
|
m : ${mat},
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> u : array<S, 4>;
|
|
|
|
@group(0) @binding(1) var<storage, read_write> s : array<S, 4>;
|
|
|
|
fn f() {
|
|
s = u;
|
|
}
|
|
)";
|
|
src = matrix.ReplaceFieldsInString(src);
|
|
|
|
std::string expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
expect = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
@size(64)
|
|
m : ${mat},
|
|
}
|
|
|
|
struct S_std140 {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> u : array<S_std140, 4u>;
|
|
|
|
@group(0) @binding(1) var<storage, read_write> s : array<S, 4>;
|
|
|
|
fn conv_S(val : S_std140) -> S {
|
|
return S(${mat}(${col_vectors_inline}));
|
|
}
|
|
|
|
fn conv_arr4_S(val : array<S_std140, 4u>) -> array<S, 4u> {
|
|
var arr : array<S, 4u>;
|
|
for(var i : u32; (i < 4u); i = (i + 1)) {
|
|
arr[i] = conv_S(val[i]);
|
|
}
|
|
return arr;
|
|
}
|
|
|
|
fn f() {
|
|
s = conv_arr4_S(u);
|
|
}
|
|
)";
|
|
uint32_t last_size =
|
|
64 - static_cast<uint32_t>(matrix.ColumnVectorAlign() * (matrix.columns - 1));
|
|
expect = matrix.ReplaceFieldsInString(
|
|
expect,
|
|
{{"${col_vectors}", matrix.ExpendedColumnVectorsWithLastSize(2, "m_", last_size)},
|
|
{"${col_vectors_inline}", matrix.ExpendedColumnVectorsInline("val.m_", ", ")}});
|
|
} else {
|
|
expect = src;
|
|
}
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
TEST_P(Std140Test_Matrix, ArrayStructMatUniform_CopyStruct_UniformToWorkgroup) {
|
|
auto matrix = GetParam();
|
|
|
|
std::string src = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
v : vec4<i32>,
|
|
@size(64)
|
|
m : ${mat},
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> u : array<S, 4>;
|
|
|
|
var<workgroup> w : array<S, 4>;
|
|
|
|
fn f() {
|
|
w[0] = u[1];
|
|
}
|
|
)";
|
|
src = matrix.ReplaceFieldsInString(src);
|
|
|
|
std::string expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
expect = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
v : vec4<i32>,
|
|
@size(64)
|
|
m : ${mat},
|
|
}
|
|
|
|
struct S_std140 {
|
|
v : vec4<i32>,
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> u : array<S_std140, 4u>;
|
|
|
|
var<workgroup> w : array<S, 4>;
|
|
|
|
fn conv_S(val : S_std140) -> S {
|
|
return S(val.v, ${mat}(${col_vectors_inline}));
|
|
}
|
|
|
|
fn f() {
|
|
w[0] = conv_S(u[1u]);
|
|
}
|
|
)";
|
|
uint32_t last_size =
|
|
64 - static_cast<uint32_t>(matrix.ColumnVectorAlign() * (matrix.columns - 1));
|
|
expect = matrix.ReplaceFieldsInString(
|
|
expect,
|
|
{{"${col_vectors}", matrix.ExpendedColumnVectorsWithLastSize(2, "m_", last_size)},
|
|
{"${col_vectors_inline}", matrix.ExpendedColumnVectorsInline("val.m_", ", ")}});
|
|
} else {
|
|
expect = src;
|
|
}
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
TEST_P(Std140Test_Matrix, ArrayStructMatUniform_CopyMatrix_UniformToPrivate) {
|
|
auto matrix = GetParam();
|
|
|
|
std::string src = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
v : vec4<i32>,
|
|
@size(64)
|
|
m : ${mat},
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> u : array<S, 3>;
|
|
|
|
var<private> p : array<S, 4>;
|
|
|
|
fn f() {
|
|
p[2].m = u[1].m;
|
|
}
|
|
)";
|
|
src = matrix.ReplaceFieldsInString(src);
|
|
|
|
std::string expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
expect = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
v : vec4<i32>,
|
|
@size(64)
|
|
m : ${mat},
|
|
}
|
|
|
|
struct S_std140 {
|
|
v : vec4<i32>,
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> u : array<S_std140, 3u>;
|
|
|
|
var<private> p : array<S, 4>;
|
|
|
|
fn load_u_1_m() -> ${mat} {
|
|
let s = &(u[1u]);
|
|
return ${mat}(${col_vectors_inline});
|
|
}
|
|
|
|
fn f() {
|
|
p[2].m = load_u_1_m();
|
|
}
|
|
)";
|
|
uint32_t last_size =
|
|
64 - static_cast<uint32_t>(matrix.ColumnVectorAlign() * (matrix.columns - 1));
|
|
expect = matrix.ReplaceFieldsInString(
|
|
expect,
|
|
{{"${col_vectors}", matrix.ExpendedColumnVectorsWithLastSize(2, "m_", last_size)},
|
|
{"${col_vectors_inline}", matrix.ExpendedColumnVectorsInline("(*(s)).m_", ", ")}});
|
|
} else {
|
|
expect = src;
|
|
}
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
TEST_P(Std140Test_Matrix, ArrayStructMatUniform_CopyColumn_UniformToStorage) {
|
|
auto matrix = GetParam();
|
|
|
|
std::string src = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
@size(64)
|
|
m : ${mat},
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> u : array<S, 3>;
|
|
|
|
@group(0) @binding(1) var<storage, read_write> s : array<S, 4>;
|
|
|
|
fn f() {
|
|
s[3].m[1] = u[2].m[0];
|
|
}
|
|
)";
|
|
src = matrix.ReplaceFieldsInString(src);
|
|
|
|
std::string expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
expect = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
@size(64)
|
|
m : ${mat},
|
|
}
|
|
|
|
struct S_std140 {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> u : array<S_std140, 3u>;
|
|
|
|
@group(0) @binding(1) var<storage, read_write> s : array<S, 4>;
|
|
|
|
fn f() {
|
|
s[3].m[1] = u[2u].m_0;
|
|
}
|
|
)";
|
|
uint32_t last_size =
|
|
64 - static_cast<uint32_t>(matrix.ColumnVectorAlign() * (matrix.columns - 1));
|
|
expect = matrix.ReplaceFieldsInString(
|
|
expect,
|
|
{{"${col_vectors}", matrix.ExpendedColumnVectorsWithLastSize(2, "m_", last_size)}});
|
|
} else {
|
|
expect = src;
|
|
}
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
TEST_P(Std140Test_Matrix, ArrayStructMatUniform_CopyColumnSwizzle_UniformToWorkgroup) {
|
|
auto matrix = GetParam();
|
|
|
|
std::string src = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
@size(64)
|
|
m : ${mat},
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> u : array<S, 4>;
|
|
|
|
var<workgroup> w : array<S, 4>;
|
|
|
|
fn f() {
|
|
w[3].m[1] = u[2].m[0].${swizzle}.${swizzle};
|
|
}
|
|
)";
|
|
src = matrix.ReplaceFieldsInString(src);
|
|
|
|
std::string expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
expect = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
@size(64)
|
|
m : ${mat},
|
|
}
|
|
|
|
struct S_std140 {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> u : array<S_std140, 4u>;
|
|
|
|
var<workgroup> w : array<S, 4>;
|
|
|
|
fn f() {
|
|
w[3].m[1] = u[2u].m_0.${swizzle}.${swizzle};
|
|
}
|
|
)";
|
|
uint32_t last_size =
|
|
64 - static_cast<uint32_t>(matrix.ColumnVectorAlign() * (matrix.columns - 1));
|
|
expect = matrix.ReplaceFieldsInString(
|
|
expect,
|
|
{{"${col_vectors}", matrix.ExpendedColumnVectorsWithLastSize(2, "m_", last_size)}});
|
|
} else {
|
|
expect = src;
|
|
}
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
TEST_P(Std140Test_Matrix, ArrayStructMatUniform_CopyScalar_UniformToPrivate) {
|
|
auto matrix = GetParam();
|
|
|
|
std::string src = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
v : vec4<i32>,
|
|
@size(64)
|
|
m : ${mat},
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> u : array<S, 3>;
|
|
|
|
var<private> p : array<S, 4>;
|
|
|
|
fn f() {
|
|
p[3].m[1].x = u[2].m[0].y;
|
|
}
|
|
)";
|
|
src = matrix.ReplaceFieldsInString(src);
|
|
|
|
std::string expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
expect = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
v : vec4<i32>,
|
|
@size(64)
|
|
m : ${mat},
|
|
}
|
|
|
|
struct S_std140 {
|
|
v : vec4<i32>,
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> u : array<S_std140, 3u>;
|
|
|
|
var<private> p : array<S, 4>;
|
|
|
|
fn f() {
|
|
p[3].m[1].x = u[2u].m_0[1u];
|
|
}
|
|
)";
|
|
uint32_t last_size =
|
|
64 - static_cast<uint32_t>(matrix.ColumnVectorAlign() * (matrix.columns - 1));
|
|
expect = matrix.ReplaceFieldsInString(
|
|
expect,
|
|
{{"${col_vectors}", matrix.ExpendedColumnVectorsWithLastSize(2, "m_", last_size)},
|
|
{"${col_vectors_inline}", matrix.ExpendedColumnVectorsInline("(*(s)).m_", ", ")}});
|
|
} else {
|
|
expect = src;
|
|
}
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
INSTANTIATE_TEST_SUITE_P(,
|
|
Std140Test_Matrix,
|
|
::testing::ValuesIn(std::vector<MatrixCase>{
|
|
{2, 2, MatrixType::f32},
|
|
{2, 3, MatrixType::f32},
|
|
{2, 4, MatrixType::f32},
|
|
{3, 2, MatrixType::f32},
|
|
{3, 3, MatrixType::f32},
|
|
{3, 4, MatrixType::f32},
|
|
{4, 2, MatrixType::f32},
|
|
{4, 3, MatrixType::f32},
|
|
{4, 4, MatrixType::f32},
|
|
{2, 2, MatrixType::f16},
|
|
{2, 3, MatrixType::f16},
|
|
{2, 4, MatrixType::f16},
|
|
{3, 2, MatrixType::f16},
|
|
{3, 3, MatrixType::f16},
|
|
{3, 4, MatrixType::f16},
|
|
{4, 2, MatrixType::f16},
|
|
{4, 3, MatrixType::f16},
|
|
{4, 4, MatrixType::f16},
|
|
}));
|
|
|
|
using Std140Test_MatrixArray = TransformTestWithParam<MatrixCase>;
|
|
|
|
TEST_P(Std140Test_MatrixArray, ArrayMatUniform_LoadArray) {
|
|
auto matrix = GetParam();
|
|
|
|
if (!matrix.CanBeUsedAsUniformArrayElememts()) {
|
|
// This permutation is invalid, skip the test.
|
|
return;
|
|
}
|
|
|
|
std::string src = R"(
|
|
enable f16;
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<${mat}, 3>;
|
|
|
|
fn f() {
|
|
let l = a;
|
|
}
|
|
)";
|
|
src = matrix.ReplaceFieldsInString(src);
|
|
|
|
std::string expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
expect = R"(
|
|
enable f16;
|
|
|
|
struct mat${shape}_${elem_type} {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<mat${shape}_${elem_type}, 3u>;
|
|
|
|
fn conv_mat${shape}_${elem_type}(val : mat${shape}_${elem_type}) -> ${mat} {
|
|
return ${mat}(${col_vectors_inline});
|
|
}
|
|
|
|
fn conv_arr3_mat${shape}_${elem_type}(val : array<mat${shape}_${elem_type}, 3u>) -> array<${mat}, 3u> {
|
|
var arr : array<${mat}, 3u>;
|
|
for(var i : u32; (i < 3u); i = (i + 1)) {
|
|
arr[i] = conv_mat${shape}_${elem_type}(val[i]);
|
|
}
|
|
return arr;
|
|
}
|
|
|
|
fn f() {
|
|
let l = conv_arr3_mat${shape}_${elem_type}(a);
|
|
}
|
|
)";
|
|
expect = matrix.ReplaceFieldsInString(
|
|
expect,
|
|
{{"${col_vectors}", matrix.ExpendedColumnVectors(2, "col")},
|
|
{"${col_vectors_inline}", matrix.ExpendedColumnVectorsInline("val.col", ", ")}});
|
|
} else {
|
|
expect = src;
|
|
}
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
TEST_P(Std140Test_MatrixArray, ArrayMatUniform_LoadMatrix_ConstArrayIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
if (!matrix.CanBeUsedAsUniformArrayElememts()) {
|
|
// This permutation is invalid, skip the test.
|
|
return;
|
|
}
|
|
|
|
std::string tmpl_src = R"(
|
|
enable f16;
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<${mat}, 3>;
|
|
|
|
fn f() {
|
|
let l = a[${array_index}];
|
|
}
|
|
)";
|
|
tmpl_src = matrix.ReplaceFieldsInString(tmpl_src);
|
|
|
|
std::string tmpl_expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
tmpl_expect = R"(
|
|
enable f16;
|
|
|
|
struct mat${shape}_${elem_type} {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<mat${shape}_${elem_type}, 3u>;
|
|
|
|
fn conv_mat${shape}_${elem_type}(val : mat${shape}_${elem_type}) -> ${mat} {
|
|
return ${mat}(${col_vectors_inline});
|
|
}
|
|
|
|
fn f() {
|
|
let l = conv_mat${shape}_${elem_type}(a[${array_index}u]);
|
|
}
|
|
)";
|
|
tmpl_expect = matrix.ReplaceFieldsInString(
|
|
tmpl_expect,
|
|
{{"${col_vectors}", matrix.ExpendedColumnVectors(2, "col")},
|
|
{"${col_vectors_inline}", matrix.ExpendedColumnVectorsInline("val.col", ", ")}});
|
|
} else {
|
|
tmpl_expect = tmpl_src;
|
|
}
|
|
|
|
for (uint32_t array_index = 0; array_index < 3; array_index++) {
|
|
std::string src =
|
|
utils::ReplaceAll(tmpl_src, "${array_index}", std::to_string(array_index));
|
|
std::string expect =
|
|
utils::ReplaceAll(tmpl_expect, "${array_index}", std::to_string(array_index));
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got)) << "accessing array element " << array_index;
|
|
}
|
|
}
|
|
|
|
TEST_P(Std140Test_MatrixArray, ArrayMatUniform_LoadMatrix_VariableArrayIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
if (!matrix.CanBeUsedAsUniformArrayElememts()) {
|
|
// This permutation is invalid, skip the test.
|
|
return;
|
|
}
|
|
|
|
std::string src = R"(
|
|
enable f16;
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<${mat}, 3>;
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let l = a[I];
|
|
}
|
|
)";
|
|
src = matrix.ReplaceFieldsInString(src);
|
|
|
|
std::string expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
expect = R"(
|
|
enable f16;
|
|
|
|
struct mat${shape}_${elem_type} {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<mat${shape}_${elem_type}, 3u>;
|
|
|
|
fn conv_mat${shape}_${elem_type}(val : mat${shape}_${elem_type}) -> ${mat} {
|
|
return ${mat}(${col_vectors_inline});
|
|
}
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let l = conv_mat${shape}_${elem_type}(a[I]);
|
|
}
|
|
)";
|
|
expect = matrix.ReplaceFieldsInString(
|
|
expect,
|
|
{{"${col_vectors}", matrix.ExpendedColumnVectors(2, "col")},
|
|
{"${col_vectors_inline}", matrix.ExpendedColumnVectorsInline("val.col", ", ")}});
|
|
} else {
|
|
expect = src;
|
|
}
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
TEST_P(Std140Test_MatrixArray, ArrayMatUniform_LoadColumn_ConstArrayIndex_ConstColumnIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
if (!matrix.CanBeUsedAsUniformArrayElememts()) {
|
|
// This permutation is invalid, skip the test.
|
|
return;
|
|
}
|
|
|
|
std::string tmpl_src = R"(
|
|
enable f16;
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<${mat}, 3>;
|
|
|
|
fn f() {
|
|
let l = a[${array_index}][${cloumn_index}];
|
|
}
|
|
)";
|
|
tmpl_src = matrix.ReplaceFieldsInString(tmpl_src);
|
|
|
|
std::string tmpl_expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
tmpl_expect = R"(
|
|
enable f16;
|
|
|
|
struct mat${shape}_${elem_type} {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<mat${shape}_${elem_type}, 3u>;
|
|
|
|
fn f() {
|
|
let l = a[${array_index}u].col${cloumn_index};
|
|
}
|
|
)";
|
|
tmpl_expect = matrix.ReplaceFieldsInString(
|
|
tmpl_expect, {{"${col_vectors}", matrix.ExpendedColumnVectors(2, "col")}});
|
|
} else {
|
|
tmpl_expect = tmpl_src;
|
|
}
|
|
|
|
for (uint32_t array_index = 0; array_index < 3; array_index++) {
|
|
for (uint32_t col = 0; col < matrix.columns; col++) {
|
|
std::string src =
|
|
utils::ReplaceAll(tmpl_src, "${array_index}", std::to_string(array_index));
|
|
src = utils::ReplaceAll(src, "${cloumn_index}", std::to_string(col));
|
|
std::string expect =
|
|
utils::ReplaceAll(tmpl_expect, "${array_index}", std::to_string(array_index));
|
|
expect = utils::ReplaceAll(expect, "${cloumn_index}", std::to_string(col));
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got))
|
|
<< "accessing array element " << array_index << " col " << col;
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST_P(Std140Test_MatrixArray, ArrayMatUniform_LoadColumn_VariableArrayIndex_ConstColumnIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
if (!matrix.CanBeUsedAsUniformArrayElememts()) {
|
|
// This permutation is invalid, skip the test.
|
|
return;
|
|
}
|
|
|
|
std::string tmpl_src = R"(
|
|
enable f16;
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<${mat}, 3>;
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let l = a[I][${cloumn_index}];
|
|
}
|
|
)";
|
|
tmpl_src = matrix.ReplaceFieldsInString(tmpl_src);
|
|
|
|
std::string tmpl_expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
tmpl_expect = R"(
|
|
enable f16;
|
|
|
|
struct mat${shape}_${elem_type} {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<mat${shape}_${elem_type}, 3u>;
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let l = a[I].col${cloumn_index};
|
|
}
|
|
)";
|
|
tmpl_expect = matrix.ReplaceFieldsInString(
|
|
tmpl_expect, {{"${col_vectors}", matrix.ExpendedColumnVectors(2, "col")}});
|
|
} else {
|
|
tmpl_expect = tmpl_src;
|
|
}
|
|
|
|
for (uint32_t col = 0; col < matrix.columns; col++) {
|
|
std::string src = utils::ReplaceAll(tmpl_src, "${cloumn_index}", std::to_string(col));
|
|
std::string expect = utils::ReplaceAll(tmpl_expect, "${cloumn_index}", std::to_string(col));
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got)) << "accessing col " << col;
|
|
}
|
|
}
|
|
|
|
TEST_P(Std140Test_MatrixArray, ArrayMatUniform_LoadColumn_ConstArrayIndex_VariableColumnIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
if (!matrix.CanBeUsedAsUniformArrayElememts()) {
|
|
// This permutation is invalid, skip the test.
|
|
return;
|
|
}
|
|
|
|
std::string tmpl_src = R"(
|
|
enable f16;
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<${mat}, 3>;
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let l = a[${array_index}][I];
|
|
}
|
|
)";
|
|
tmpl_src = matrix.ReplaceFieldsInString(tmpl_src);
|
|
|
|
std::string tmpl_expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
tmpl_expect = R"(
|
|
enable f16;
|
|
|
|
struct mat${shape}_${elem_type} {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<mat${shape}_${elem_type}, 3u>;
|
|
|
|
fn load_a_${array_index}_p0(p0 : u32) -> ${col_vector_type} {
|
|
switch(p0) {
|
|
${col_table}
|
|
default: {
|
|
return ${col_vector_type}();
|
|
}
|
|
}
|
|
}
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let l = load_a_${array_index}_p0(u32(I));
|
|
}
|
|
)";
|
|
// col_table is the switch cases for all column index.
|
|
// Example for a matrix having 2 columns:
|
|
// case 0u: {
|
|
// return a[${array_index}u].col0;
|
|
// }
|
|
// case 1u: {
|
|
// return a[${array_index}u].col1;
|
|
// }
|
|
std::string col_table = matrix.JoinTemplatedStringForEachMatrixColumn( //
|
|
R"( case ${col_id_for_tmpl}u: {
|
|
return a[${array_index}u].col${col_id_for_tmpl};
|
|
})",
|
|
"\n");
|
|
tmpl_expect = matrix.ReplaceFieldsInString(
|
|
tmpl_expect, {{"${col_vectors}", matrix.ExpendedColumnVectors(2, "col")},
|
|
{"${col_table}", col_table}});
|
|
} else {
|
|
tmpl_expect = tmpl_src;
|
|
}
|
|
|
|
for (uint32_t array_index = 0; array_index < 3; array_index++) {
|
|
std::string src =
|
|
utils::ReplaceAll(tmpl_src, "${array_index}", std::to_string(array_index));
|
|
std::string expect =
|
|
utils::ReplaceAll(tmpl_expect, "${array_index}", std::to_string(array_index));
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got)) << "accessing array element " << array_index;
|
|
}
|
|
}
|
|
|
|
TEST_P(Std140Test_MatrixArray, ArrayMatUniform_LoadColumn_VariableArrayIndex_VariableColumnIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
if (!matrix.CanBeUsedAsUniformArrayElememts()) {
|
|
// This permutation is invalid, skip the test.
|
|
return;
|
|
}
|
|
|
|
std::string src = R"(
|
|
enable f16;
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<${mat}, 3>;
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let l = a[I][I];
|
|
}
|
|
)";
|
|
src = matrix.ReplaceFieldsInString(src);
|
|
|
|
std::string expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
expect = R"(
|
|
enable f16;
|
|
|
|
struct mat${shape}_${elem_type} {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<mat${shape}_${elem_type}, 3u>;
|
|
|
|
fn load_a_p0_p1(p0 : u32, p1 : u32) -> ${col_vector_type} {
|
|
switch(p1) {
|
|
${col_table}
|
|
default: {
|
|
return ${col_vector_type}();
|
|
}
|
|
}
|
|
}
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let l = load_a_p0_p1(u32(I), u32(I));
|
|
}
|
|
)";
|
|
// col_table is the switch cases for all column index.
|
|
// Example for a matrix having 2 columns:
|
|
// case 0u: {
|
|
// return a[p0].col0;
|
|
// }
|
|
// case 1u: {
|
|
// return a[p0].col1;
|
|
// }
|
|
std::string col_table = matrix.JoinTemplatedStringForEachMatrixColumn( //
|
|
R"( case ${col_id_for_tmpl}u: {
|
|
return a[p0].col${col_id_for_tmpl};
|
|
})",
|
|
"\n");
|
|
expect = matrix.ReplaceFieldsInString(
|
|
expect, {{"${col_vectors}", matrix.ExpendedColumnVectors(2, "col")},
|
|
{"${col_table}", col_table}});
|
|
} else {
|
|
expect = src;
|
|
}
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
TEST_P(Std140Test_MatrixArray, StructArrayMatUniform_LoadStruct) {
|
|
auto matrix = GetParam();
|
|
|
|
if (!matrix.CanBeUsedAsUniformArrayElememts()) {
|
|
// This permutation is invalid, skip the test.
|
|
return;
|
|
}
|
|
|
|
std::string src = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
a : array<${mat}, 3>,
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> s : S;
|
|
|
|
fn f() {
|
|
let l = s;
|
|
}
|
|
)";
|
|
src = matrix.ReplaceFieldsInString(src);
|
|
|
|
std::string expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
expect = R"(
|
|
enable f16;
|
|
|
|
struct mat${shape}_${elem_type} {
|
|
${col_vectors}
|
|
}
|
|
|
|
struct S {
|
|
a : array<${mat}, 3>,
|
|
}
|
|
|
|
struct S_std140 {
|
|
a : array<mat${shape}_${elem_type}, 3u>,
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> s : S_std140;
|
|
|
|
fn conv_mat${shape}_${elem_type}(val : mat${shape}_${elem_type}) -> ${mat} {
|
|
return ${mat}(${col_vectors_inline});
|
|
}
|
|
|
|
fn conv_arr3_mat${shape}_${elem_type}(val : array<mat${shape}_${elem_type}, 3u>) -> array<${mat}, 3u> {
|
|
var arr : array<${mat}, 3u>;
|
|
for(var i : u32; (i < 3u); i = (i + 1)) {
|
|
arr[i] = conv_mat${shape}_${elem_type}(val[i]);
|
|
}
|
|
return arr;
|
|
}
|
|
|
|
fn conv_S(val : S_std140) -> S {
|
|
return S(conv_arr3_mat${shape}_${elem_type}(val.a));
|
|
}
|
|
|
|
fn f() {
|
|
let l = conv_S(s);
|
|
}
|
|
)";
|
|
expect = matrix.ReplaceFieldsInString(
|
|
expect,
|
|
{{"${col_vectors}", matrix.ExpendedColumnVectors(2, "col")},
|
|
{"${col_vectors_inline}", matrix.ExpendedColumnVectorsInline("val.col", ", ")}});
|
|
} else {
|
|
expect = src;
|
|
}
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
TEST_P(Std140Test_MatrixArray, StructArrayMatUniform_LoadArray) {
|
|
auto matrix = GetParam();
|
|
|
|
if (!matrix.CanBeUsedAsUniformArrayElememts()) {
|
|
// This permutation is invalid, skip the test.
|
|
return;
|
|
}
|
|
|
|
std::string src = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
a : array<${mat}, 3>,
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> s : S;
|
|
|
|
fn f() {
|
|
let l = s.a;
|
|
}
|
|
)";
|
|
src = matrix.ReplaceFieldsInString(src);
|
|
|
|
std::string expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
expect = R"(
|
|
enable f16;
|
|
|
|
struct mat${shape}_${elem_type} {
|
|
${col_vectors}
|
|
}
|
|
|
|
struct S {
|
|
a : array<${mat}, 3>,
|
|
}
|
|
|
|
struct S_std140 {
|
|
a : array<mat${shape}_${elem_type}, 3u>,
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> s : S_std140;
|
|
|
|
fn conv_mat${shape}_${elem_type}(val : mat${shape}_${elem_type}) -> ${mat} {
|
|
return ${mat}(${col_vectors_inline});
|
|
}
|
|
|
|
fn conv_arr3_mat${shape}_${elem_type}(val : array<mat${shape}_${elem_type}, 3u>) -> array<${mat}, 3u> {
|
|
var arr : array<${mat}, 3u>;
|
|
for(var i : u32; (i < 3u); i = (i + 1)) {
|
|
arr[i] = conv_mat${shape}_${elem_type}(val[i]);
|
|
}
|
|
return arr;
|
|
}
|
|
|
|
fn f() {
|
|
let l = conv_arr3_mat${shape}_${elem_type}(s.a);
|
|
}
|
|
)";
|
|
expect = matrix.ReplaceFieldsInString(
|
|
expect,
|
|
{{"${col_vectors}", matrix.ExpendedColumnVectors(2, "col")},
|
|
{"${col_vectors_inline}", matrix.ExpendedColumnVectorsInline("val.col", ", ")}});
|
|
} else {
|
|
expect = src;
|
|
}
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
TEST_P(Std140Test_MatrixArray, StructArrayMatUniform_LoadMatrix_ConstArrayIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
if (!matrix.CanBeUsedAsUniformArrayElememts()) {
|
|
// This permutation is invalid, skip the test.
|
|
return;
|
|
}
|
|
|
|
std::string tmpl_src = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
a : array<${mat}, 3>,
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> s : S;
|
|
|
|
fn f() {
|
|
let l = s.a[${array_index}];
|
|
}
|
|
)";
|
|
tmpl_src = matrix.ReplaceFieldsInString(tmpl_src);
|
|
|
|
std::string tmpl_expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
tmpl_expect = R"(
|
|
enable f16;
|
|
|
|
struct mat${shape}_${elem_type} {
|
|
${col_vectors}
|
|
}
|
|
|
|
struct S {
|
|
a : array<${mat}, 3>,
|
|
}
|
|
|
|
struct S_std140 {
|
|
a : array<mat${shape}_${elem_type}, 3u>,
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> s : S_std140;
|
|
|
|
fn conv_mat${shape}_${elem_type}(val : mat${shape}_${elem_type}) -> ${mat} {
|
|
return ${mat}(${col_vectors_inline});
|
|
}
|
|
|
|
fn f() {
|
|
let l = conv_mat${shape}_${elem_type}(s.a[${array_index}u]);
|
|
}
|
|
)";
|
|
tmpl_expect = matrix.ReplaceFieldsInString(
|
|
tmpl_expect,
|
|
{{"${col_vectors}", matrix.ExpendedColumnVectors(2, "col")},
|
|
{"${col_vectors_inline}", matrix.ExpendedColumnVectorsInline("val.col", ", ")}});
|
|
} else {
|
|
tmpl_expect = tmpl_src;
|
|
}
|
|
|
|
for (uint32_t array_index = 0; array_index < 3; array_index++) {
|
|
std::string src =
|
|
utils::ReplaceAll(tmpl_src, "${array_index}", std::to_string(array_index));
|
|
std::string expect =
|
|
utils::ReplaceAll(tmpl_expect, "${array_index}", std::to_string(array_index));
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got)) << "accessing array element " << array_index;
|
|
}
|
|
}
|
|
|
|
TEST_P(Std140Test_MatrixArray, StructArrayMatUniform_LoadMatrix_VariableArrayIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
if (!matrix.CanBeUsedAsUniformArrayElememts()) {
|
|
// This permutation is invalid, skip the test.
|
|
return;
|
|
}
|
|
|
|
std::string src = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
a : array<${mat}, 3>,
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> s : S;
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let l = s.a[I];
|
|
}
|
|
)";
|
|
src = matrix.ReplaceFieldsInString(src);
|
|
|
|
std::string expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
expect = R"(
|
|
enable f16;
|
|
|
|
struct mat${shape}_${elem_type} {
|
|
${col_vectors}
|
|
}
|
|
|
|
struct S {
|
|
a : array<${mat}, 3>,
|
|
}
|
|
|
|
struct S_std140 {
|
|
a : array<mat${shape}_${elem_type}, 3u>,
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> s : S_std140;
|
|
|
|
fn conv_mat${shape}_${elem_type}(val : mat${shape}_${elem_type}) -> ${mat} {
|
|
return ${mat}(${col_vectors_inline});
|
|
}
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let l = conv_mat${shape}_${elem_type}(s.a[I]);
|
|
}
|
|
)";
|
|
expect = matrix.ReplaceFieldsInString(
|
|
expect,
|
|
{{"${col_vectors}", matrix.ExpendedColumnVectors(2, "col")},
|
|
{"${col_vectors_inline}", matrix.ExpendedColumnVectorsInline("val.col", ", ")}});
|
|
} else {
|
|
expect = src;
|
|
}
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
TEST_P(Std140Test_MatrixArray, StructArrayMatUniform_LoadColumn_ConstArrayIndex_ConstColumnIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
if (!matrix.CanBeUsedAsUniformArrayElememts()) {
|
|
// This permutation is invalid, skip the test.
|
|
return;
|
|
}
|
|
|
|
std::string tmpl_src = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
a : array<${mat}, 3>,
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> s : S;
|
|
|
|
fn f() {
|
|
let l = s.a[${array_index}][${cloumn_index}];
|
|
}
|
|
)";
|
|
tmpl_src = matrix.ReplaceFieldsInString(tmpl_src);
|
|
|
|
std::string tmpl_expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
tmpl_expect = R"(
|
|
enable f16;
|
|
|
|
struct mat${shape}_${elem_type} {
|
|
${col_vectors}
|
|
}
|
|
|
|
struct S {
|
|
a : array<${mat}, 3>,
|
|
}
|
|
|
|
struct S_std140 {
|
|
a : array<mat${shape}_${elem_type}, 3u>,
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> s : S_std140;
|
|
|
|
fn f() {
|
|
let l = s.a[${array_index}u].col${cloumn_index};
|
|
}
|
|
)";
|
|
tmpl_expect = matrix.ReplaceFieldsInString(
|
|
tmpl_expect, {{"${col_vectors}", matrix.ExpendedColumnVectors(2, "col")}});
|
|
} else {
|
|
tmpl_expect = tmpl_src;
|
|
}
|
|
|
|
for (uint32_t array_index = 0; array_index < 3; array_index++) {
|
|
for (uint32_t col = 0; col < matrix.columns; col++) {
|
|
std::string src =
|
|
utils::ReplaceAll(tmpl_src, "${array_index}", std::to_string(array_index));
|
|
src = utils::ReplaceAll(src, "${cloumn_index}", std::to_string(col));
|
|
std::string expect =
|
|
utils::ReplaceAll(tmpl_expect, "${array_index}", std::to_string(array_index));
|
|
expect = utils::ReplaceAll(expect, "${cloumn_index}", std::to_string(col));
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got))
|
|
<< "accessing array element " << array_index << " col " << col;
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST_P(Std140Test_MatrixArray,
|
|
StructArrayMatUniform_LoadColumn_VariableArrayIndex_ConstColumnIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
if (!matrix.CanBeUsedAsUniformArrayElememts()) {
|
|
// This permutation is invalid, skip the test.
|
|
return;
|
|
}
|
|
|
|
std::string tmpl_src = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
a : array<${mat}, 3>,
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> s : S;
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let l = s.a[I][${cloumn_index}];
|
|
}
|
|
)";
|
|
tmpl_src = matrix.ReplaceFieldsInString(tmpl_src);
|
|
|
|
std::string tmpl_expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
tmpl_expect = R"(
|
|
enable f16;
|
|
|
|
struct mat${shape}_${elem_type} {
|
|
${col_vectors}
|
|
}
|
|
|
|
struct S {
|
|
a : array<${mat}, 3>,
|
|
}
|
|
|
|
struct S_std140 {
|
|
a : array<mat${shape}_${elem_type}, 3u>,
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> s : S_std140;
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let l = s.a[I].col${cloumn_index};
|
|
}
|
|
)";
|
|
tmpl_expect = matrix.ReplaceFieldsInString(
|
|
tmpl_expect, {{"${col_vectors}", matrix.ExpendedColumnVectors(2, "col")}});
|
|
} else {
|
|
tmpl_expect = tmpl_src;
|
|
}
|
|
|
|
for (uint32_t col = 0; col < matrix.columns; col++) {
|
|
std::string src = utils::ReplaceAll(tmpl_src, "${cloumn_index}", std::to_string(col));
|
|
std::string expect = utils::ReplaceAll(tmpl_expect, "${cloumn_index}", std::to_string(col));
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got)) << "accessing col " << col;
|
|
}
|
|
}
|
|
|
|
TEST_P(Std140Test_MatrixArray,
|
|
StructArrayMatUniform_LoadColumn_ConstArrayIndex_VariableColumnIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
if (!matrix.CanBeUsedAsUniformArrayElememts()) {
|
|
// This permutation is invalid, skip the test.
|
|
return;
|
|
}
|
|
|
|
std::string tmpl_src = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
a : array<${mat}, 3>,
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> s : S;
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let l = s.a[${array_index}][I];
|
|
}
|
|
)";
|
|
tmpl_src = matrix.ReplaceFieldsInString(tmpl_src);
|
|
|
|
std::string tmpl_expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
tmpl_expect = R"(
|
|
enable f16;
|
|
|
|
struct mat${shape}_${elem_type} {
|
|
${col_vectors}
|
|
}
|
|
|
|
struct S {
|
|
a : array<${mat}, 3>,
|
|
}
|
|
|
|
struct S_std140 {
|
|
a : array<mat${shape}_${elem_type}, 3u>,
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> s : S_std140;
|
|
|
|
fn load_s_a_${array_index}_p0(p0 : u32) -> ${col_vector_type} {
|
|
switch(p0) {
|
|
${col_table}
|
|
default: {
|
|
return ${col_vector_type}();
|
|
}
|
|
}
|
|
}
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let l = load_s_a_${array_index}_p0(u32(I));
|
|
}
|
|
)";
|
|
// col_table is the switch cases for all column index.
|
|
// Example for a matrix having 2 columns:
|
|
// case 0u: {
|
|
// return s.a[${array_index}u].col0;
|
|
// }
|
|
// case 1u: {
|
|
// return s.a[${array_index}u].col1;
|
|
// }
|
|
std::string col_table = matrix.JoinTemplatedStringForEachMatrixColumn( //
|
|
R"( case ${col_id_for_tmpl}u: {
|
|
return s.a[${array_index}u].col${col_id_for_tmpl};
|
|
})",
|
|
"\n");
|
|
tmpl_expect = matrix.ReplaceFieldsInString(
|
|
tmpl_expect, {{"${col_vectors}", matrix.ExpendedColumnVectors(2, "col")},
|
|
{"${col_table}", col_table}});
|
|
} else {
|
|
tmpl_expect = tmpl_src;
|
|
}
|
|
|
|
for (uint32_t array_index = 0; array_index < 3; array_index++) {
|
|
std::string src =
|
|
utils::ReplaceAll(tmpl_src, "${array_index}", std::to_string(array_index));
|
|
std::string expect =
|
|
utils::ReplaceAll(tmpl_expect, "${array_index}", std::to_string(array_index));
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got)) << "accessing array element " << array_index;
|
|
}
|
|
}
|
|
|
|
TEST_P(Std140Test_MatrixArray,
|
|
StructArrayMatUniform_LoadColumn_VariableArrayIndex_VariableColumnIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
if (!matrix.CanBeUsedAsUniformArrayElememts()) {
|
|
// This permutation is invalid, skip the test.
|
|
return;
|
|
}
|
|
|
|
std::string src = R"(
|
|
enable f16;
|
|
|
|
struct S {
|
|
a : array<${mat}, 3>,
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> s : S;
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let l = s.a[I][I];
|
|
}
|
|
)";
|
|
src = matrix.ReplaceFieldsInString(src);
|
|
|
|
std::string expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
expect = R"(
|
|
enable f16;
|
|
|
|
struct mat${shape}_${elem_type} {
|
|
${col_vectors}
|
|
}
|
|
|
|
struct S {
|
|
a : array<${mat}, 3>,
|
|
}
|
|
|
|
struct S_std140 {
|
|
a : array<mat${shape}_${elem_type}, 3u>,
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> s : S_std140;
|
|
|
|
fn load_s_a_p0_p1(p0 : u32, p1 : u32) -> ${col_vector_type} {
|
|
switch(p1) {
|
|
${col_table}
|
|
default: {
|
|
return ${col_vector_type}();
|
|
}
|
|
}
|
|
}
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let l = load_s_a_p0_p1(u32(I), u32(I));
|
|
}
|
|
)";
|
|
// col_table is the switch cases for all column index.
|
|
// Example for a matrix having 2 columns:
|
|
// case 0u: {
|
|
// return s.a[p0].col0;
|
|
// }
|
|
// case 1u: {
|
|
// return s.a[p0].col1;
|
|
// }
|
|
std::string col_table = matrix.JoinTemplatedStringForEachMatrixColumn( //
|
|
R"( case ${col_id_for_tmpl}u: {
|
|
return s.a[p0].col${col_id_for_tmpl};
|
|
})",
|
|
"\n");
|
|
expect = matrix.ReplaceFieldsInString(
|
|
expect, {{"${col_vectors}", matrix.ExpendedColumnVectors(2, "col")},
|
|
{"${col_table}", col_table}});
|
|
} else {
|
|
expect = src;
|
|
}
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
TEST_P(Std140Test_MatrixArray, ArrayArrayMatUniform_LoadArrays) {
|
|
auto matrix = GetParam();
|
|
|
|
if (!matrix.CanBeUsedAsUniformArrayElememts()) {
|
|
// This permutation is invalid, skip the test.
|
|
return;
|
|
}
|
|
|
|
std::string src = R"(
|
|
enable f16;
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<array<${mat}, 3>, 4>;
|
|
|
|
fn f() {
|
|
let l = a;
|
|
}
|
|
)";
|
|
src = matrix.ReplaceFieldsInString(src);
|
|
|
|
std::string expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
expect = R"(
|
|
enable f16;
|
|
|
|
struct mat${shape}_${elem_type} {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<array<mat${shape}_${elem_type}, 3u>, 4u>;
|
|
|
|
fn conv_mat${shape}_${elem_type}(val : mat${shape}_${elem_type}) -> ${mat} {
|
|
return ${mat}(${col_vectors_inline});
|
|
}
|
|
|
|
fn conv_arr3_mat${shape}_${elem_type}(val : array<mat${shape}_${elem_type}, 3u>) -> array<${mat}, 3u> {
|
|
var arr : array<${mat}, 3u>;
|
|
for(var i : u32; (i < 3u); i = (i + 1)) {
|
|
arr[i] = conv_mat${shape}_${elem_type}(val[i]);
|
|
}
|
|
return arr;
|
|
}
|
|
|
|
fn conv_arr4_arr3_mat${shape}_${elem_type}(val : array<array<mat${shape}_${elem_type}, 3u>, 4u>) -> array<array<${mat}, 3u>, 4u> {
|
|
var arr : array<array<${mat}, 3u>, 4u>;
|
|
for(var i : u32; (i < 4u); i = (i + 1)) {
|
|
arr[i] = conv_arr3_mat${shape}_${elem_type}(val[i]);
|
|
}
|
|
return arr;
|
|
}
|
|
|
|
fn f() {
|
|
let l = conv_arr4_arr3_mat${shape}_${elem_type}(a);
|
|
}
|
|
)";
|
|
expect = matrix.ReplaceFieldsInString(
|
|
expect,
|
|
{{"${col_vectors}", matrix.ExpendedColumnVectors(2, "col")},
|
|
{"${col_vectors_inline}", matrix.ExpendedColumnVectorsInline("val.col", ", ")}});
|
|
} else {
|
|
expect = src;
|
|
}
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
TEST_P(Std140Test_MatrixArray, ArrayArrayMatUniform_LoadArray_ConstOuterArrayIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
if (!matrix.CanBeUsedAsUniformArrayElememts()) {
|
|
// This permutation is invalid, skip the test.
|
|
return;
|
|
}
|
|
|
|
std::string tmpl_src = R"(
|
|
enable f16;
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<array<${mat}, 3>, 4>;
|
|
|
|
fn f() {
|
|
let l = a[${outer_array_index}];
|
|
}
|
|
)";
|
|
tmpl_src = matrix.ReplaceFieldsInString(tmpl_src);
|
|
|
|
std::string tmpl_expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
tmpl_expect = R"(
|
|
enable f16;
|
|
|
|
struct mat${shape}_${elem_type} {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<array<mat${shape}_${elem_type}, 3u>, 4u>;
|
|
|
|
fn conv_mat${shape}_${elem_type}(val : mat${shape}_${elem_type}) -> ${mat} {
|
|
return ${mat}(${col_vectors_inline});
|
|
}
|
|
|
|
fn conv_arr3_mat${shape}_${elem_type}(val : array<mat${shape}_${elem_type}, 3u>) -> array<${mat}, 3u> {
|
|
var arr : array<${mat}, 3u>;
|
|
for(var i : u32; (i < 3u); i = (i + 1)) {
|
|
arr[i] = conv_mat${shape}_${elem_type}(val[i]);
|
|
}
|
|
return arr;
|
|
}
|
|
|
|
fn f() {
|
|
let l = conv_arr3_mat${shape}_${elem_type}(a[${outer_array_index}u]);
|
|
}
|
|
)";
|
|
tmpl_expect = matrix.ReplaceFieldsInString(
|
|
tmpl_expect,
|
|
{{"${col_vectors}", matrix.ExpendedColumnVectors(2, "col")},
|
|
{"${col_vectors_inline}", matrix.ExpendedColumnVectorsInline("val.col", ", ")}});
|
|
} else {
|
|
tmpl_expect = tmpl_src;
|
|
}
|
|
|
|
for (uint32_t outer = 0; outer < 4; outer++) {
|
|
std::string src =
|
|
utils::ReplaceAll(tmpl_src, "${outer_array_index}", std::to_string(outer));
|
|
std::string expect =
|
|
utils::ReplaceAll(tmpl_expect, "${outer_array_index}", std::to_string(outer));
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got)) << "accessing array element " << outer;
|
|
}
|
|
}
|
|
|
|
TEST_P(Std140Test_MatrixArray, ArrayArrayMatUniform_LoadArray_VariableOuterArrayIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
if (!matrix.CanBeUsedAsUniformArrayElememts()) {
|
|
// This permutation is invalid, skip the test.
|
|
return;
|
|
}
|
|
|
|
std::string src = R"(
|
|
enable f16;
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<array<${mat}, 3>, 4>;
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let l = a[I];
|
|
}
|
|
)";
|
|
src = matrix.ReplaceFieldsInString(src);
|
|
|
|
std::string expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
expect = R"(
|
|
enable f16;
|
|
|
|
struct mat${shape}_${elem_type} {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<array<mat${shape}_${elem_type}, 3u>, 4u>;
|
|
|
|
fn conv_mat${shape}_${elem_type}(val : mat${shape}_${elem_type}) -> ${mat} {
|
|
return ${mat}(${col_vectors_inline});
|
|
}
|
|
|
|
fn conv_arr3_mat${shape}_${elem_type}(val : array<mat${shape}_${elem_type}, 3u>) -> array<${mat}, 3u> {
|
|
var arr : array<${mat}, 3u>;
|
|
for(var i : u32; (i < 3u); i = (i + 1)) {
|
|
arr[i] = conv_mat${shape}_${elem_type}(val[i]);
|
|
}
|
|
return arr;
|
|
}
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let l = conv_arr3_mat${shape}_${elem_type}(a[I]);
|
|
}
|
|
)";
|
|
expect = matrix.ReplaceFieldsInString(
|
|
expect,
|
|
{{"${col_vectors}", matrix.ExpendedColumnVectors(2, "col")},
|
|
{"${col_vectors_inline}", matrix.ExpendedColumnVectorsInline("val.col", ", ")}});
|
|
} else {
|
|
expect = src;
|
|
}
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
TEST_P(Std140Test_MatrixArray,
|
|
ArrayArrayMatUniform_LoadMatrix_ConstOuterArrayIndex_ConstInnerArrayIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
if (!matrix.CanBeUsedAsUniformArrayElememts()) {
|
|
// This permutation is invalid, skip the test.
|
|
return;
|
|
}
|
|
|
|
std::string tmpl_src = R"(
|
|
enable f16;
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<array<${mat}, 3>, 4>;
|
|
|
|
fn f() {
|
|
let l = a[${outer_array_index}][${inner_array_index}];
|
|
}
|
|
)";
|
|
tmpl_src = matrix.ReplaceFieldsInString(tmpl_src);
|
|
|
|
std::string tmpl_expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
tmpl_expect = R"(
|
|
enable f16;
|
|
|
|
struct mat${shape}_${elem_type} {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<array<mat${shape}_${elem_type}, 3u>, 4u>;
|
|
|
|
fn conv_mat${shape}_${elem_type}(val : mat${shape}_${elem_type}) -> ${mat} {
|
|
return ${mat}(${col_vectors_inline});
|
|
}
|
|
|
|
fn f() {
|
|
let l = conv_mat${shape}_${elem_type}(a[${outer_array_index}u][${inner_array_index}u]);
|
|
}
|
|
)";
|
|
tmpl_expect = matrix.ReplaceFieldsInString(
|
|
tmpl_expect,
|
|
{{"${col_vectors}", matrix.ExpendedColumnVectors(2, "col")},
|
|
{"${col_vectors_inline}", matrix.ExpendedColumnVectorsInline("val.col", ", ")}});
|
|
} else {
|
|
tmpl_expect = tmpl_src;
|
|
}
|
|
|
|
for (uint32_t outer = 0; outer < 4; outer++) {
|
|
for (uint32_t inner = 0; inner < 3; inner++) {
|
|
std::string src =
|
|
utils::ReplaceAll(tmpl_src, "${outer_array_index}", std::to_string(outer));
|
|
src = utils::ReplaceAll(src, "${inner_array_index}", std::to_string(inner));
|
|
std::string expect =
|
|
utils::ReplaceAll(tmpl_expect, "${outer_array_index}", std::to_string(outer));
|
|
expect = utils::ReplaceAll(expect, "${inner_array_index}", std::to_string(inner));
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got))
|
|
<< "accessing array element [" << outer << "][" << inner << "]";
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST_P(Std140Test_MatrixArray,
|
|
ArrayArrayMatUniform_LoadMatrix_ConstOuterArrayIndex_VariableInnerArrayIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
if (!matrix.CanBeUsedAsUniformArrayElememts()) {
|
|
// This permutation is invalid, skip the test.
|
|
return;
|
|
}
|
|
|
|
std::string tmpl_src = R"(
|
|
enable f16;
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<array<${mat}, 3>, 4>;
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let l = a[${outer_array_index}][I];
|
|
}
|
|
)";
|
|
tmpl_src = matrix.ReplaceFieldsInString(tmpl_src);
|
|
|
|
std::string tmpl_expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
tmpl_expect = R"(
|
|
enable f16;
|
|
|
|
struct mat${shape}_${elem_type} {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<array<mat${shape}_${elem_type}, 3u>, 4u>;
|
|
|
|
fn conv_mat${shape}_${elem_type}(val : mat${shape}_${elem_type}) -> ${mat} {
|
|
return ${mat}(${col_vectors_inline});
|
|
}
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let l = conv_mat${shape}_${elem_type}(a[${outer_array_index}u][I]);
|
|
}
|
|
)";
|
|
tmpl_expect = matrix.ReplaceFieldsInString(
|
|
tmpl_expect,
|
|
{{"${col_vectors}", matrix.ExpendedColumnVectors(2, "col")},
|
|
{"${col_vectors_inline}", matrix.ExpendedColumnVectorsInline("val.col", ", ")}});
|
|
} else {
|
|
tmpl_expect = tmpl_src;
|
|
}
|
|
|
|
for (uint32_t outer = 0; outer < 4; outer++) {
|
|
std::string src =
|
|
utils::ReplaceAll(tmpl_src, "${outer_array_index}", std::to_string(outer));
|
|
std::string expect =
|
|
utils::ReplaceAll(tmpl_expect, "${outer_array_index}", std::to_string(outer));
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got)) << "accessing array element [" << outer << "][I]";
|
|
}
|
|
}
|
|
|
|
TEST_P(Std140Test_MatrixArray,
|
|
ArrayArrayMatUniform_LoadMatrix_VariableOuterArrayIndex_ConstInnerArrayIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
if (!matrix.CanBeUsedAsUniformArrayElememts()) {
|
|
// This permutation is invalid, skip the test.
|
|
return;
|
|
}
|
|
|
|
std::string tmpl_src = R"(
|
|
enable f16;
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<array<${mat}, 3>, 4>;
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let l = a[I][${inner_array_index}];
|
|
}
|
|
)";
|
|
tmpl_src = matrix.ReplaceFieldsInString(tmpl_src);
|
|
|
|
std::string tmpl_expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
tmpl_expect = R"(
|
|
enable f16;
|
|
|
|
struct mat${shape}_${elem_type} {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<array<mat${shape}_${elem_type}, 3u>, 4u>;
|
|
|
|
fn conv_mat${shape}_${elem_type}(val : mat${shape}_${elem_type}) -> ${mat} {
|
|
return ${mat}(${col_vectors_inline});
|
|
}
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let l = conv_mat${shape}_${elem_type}(a[I][${inner_array_index}u]);
|
|
}
|
|
)";
|
|
tmpl_expect = matrix.ReplaceFieldsInString(
|
|
tmpl_expect,
|
|
{{"${col_vectors}", matrix.ExpendedColumnVectors(2, "col")},
|
|
{"${col_vectors_inline}", matrix.ExpendedColumnVectorsInline("val.col", ", ")}});
|
|
} else {
|
|
tmpl_expect = tmpl_src;
|
|
}
|
|
|
|
for (uint32_t inner = 0; inner < 3; inner++) {
|
|
std::string src =
|
|
utils::ReplaceAll(tmpl_src, "${inner_array_index}", std::to_string(inner));
|
|
std::string expect =
|
|
utils::ReplaceAll(tmpl_expect, "${inner_array_index}", std::to_string(inner));
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got)) << "accessing array element [I][" << inner << "]";
|
|
}
|
|
}
|
|
|
|
TEST_P(Std140Test_MatrixArray,
|
|
ArrayArrayMatUniform_LoadMatrix_VariableOuterArrayIndex_VariableInnerArrayIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
if (!matrix.CanBeUsedAsUniformArrayElememts()) {
|
|
// This permutation is invalid, skip the test.
|
|
return;
|
|
}
|
|
|
|
std::string src = R"(
|
|
enable f16;
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<array<${mat}, 3>, 4>;
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let l = a[I][I];
|
|
}
|
|
)";
|
|
src = matrix.ReplaceFieldsInString(src);
|
|
|
|
std::string expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
expect = R"(
|
|
enable f16;
|
|
|
|
struct mat${shape}_${elem_type} {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<array<mat${shape}_${elem_type}, 3u>, 4u>;
|
|
|
|
fn conv_mat${shape}_${elem_type}(val : mat${shape}_${elem_type}) -> ${mat} {
|
|
return ${mat}(${col_vectors_inline});
|
|
}
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let l = conv_mat${shape}_${elem_type}(a[I][I]);
|
|
}
|
|
)";
|
|
expect = matrix.ReplaceFieldsInString(
|
|
expect,
|
|
{{"${col_vectors}", matrix.ExpendedColumnVectors(2, "col")},
|
|
{"${col_vectors_inline}", matrix.ExpendedColumnVectorsInline("val.col", ", ")}});
|
|
} else {
|
|
expect = src;
|
|
}
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
TEST_P(Std140Test_MatrixArray,
|
|
ArrayArrayMatUniform_LoadColumn_ConstOuterArrayIndex_ConstInnerArrayIndex_ConstColumnIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
if (!matrix.CanBeUsedAsUniformArrayElememts()) {
|
|
// This permutation is invalid, skip the test.
|
|
return;
|
|
}
|
|
|
|
std::string tmpl_src = R"(
|
|
enable f16;
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<array<${mat}, 3>, 4>;
|
|
|
|
fn f() {
|
|
let l = a[${outer_array_index}][${inner_array_index}][${column_index}];
|
|
}
|
|
)";
|
|
tmpl_src = matrix.ReplaceFieldsInString(tmpl_src);
|
|
|
|
std::string tmpl_expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
tmpl_expect = R"(
|
|
enable f16;
|
|
|
|
struct mat${shape}_${elem_type} {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<array<mat${shape}_${elem_type}, 3u>, 4u>;
|
|
|
|
fn f() {
|
|
let l = a[${outer_array_index}u][${inner_array_index}u].col${column_index};
|
|
}
|
|
)";
|
|
tmpl_expect = matrix.ReplaceFieldsInString(
|
|
tmpl_expect,
|
|
{{"${col_vectors}", matrix.ExpendedColumnVectors(2, "col")},
|
|
{"${col_vectors_inline}", matrix.ExpendedColumnVectorsInline("val.col", ", ")}});
|
|
} else {
|
|
tmpl_expect = tmpl_src;
|
|
}
|
|
|
|
for (uint32_t outer = 0; outer < 4; outer++) {
|
|
for (uint32_t inner = 0; inner < 3; inner++) {
|
|
for (uint32_t col = 0; col < matrix.columns; col++) {
|
|
std::string src =
|
|
utils::ReplaceAll(tmpl_src, "${outer_array_index}", std::to_string(outer));
|
|
src = utils::ReplaceAll(src, "${inner_array_index}", std::to_string(inner));
|
|
src = utils::ReplaceAll(src, "${column_index}", std::to_string(col));
|
|
std::string expect =
|
|
utils::ReplaceAll(tmpl_expect, "${outer_array_index}", std::to_string(outer));
|
|
expect = utils::ReplaceAll(expect, "${inner_array_index}", std::to_string(inner));
|
|
expect = utils::ReplaceAll(expect, "${column_index}", std::to_string(col));
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got))
|
|
<< "accessing array element [" << outer << "][" << inner << "] col " << col;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST_P(
|
|
Std140Test_MatrixArray,
|
|
ArrayArrayMatUniform_LoadColumn_ConstOuterArrayIndex_ConstInnerArrayIndex_VariableColumnIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
if (!matrix.CanBeUsedAsUniformArrayElememts()) {
|
|
// This permutation is invalid, skip the test.
|
|
return;
|
|
}
|
|
|
|
std::string tmpl_src = R"(
|
|
enable f16;
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<array<${mat}, 3>, 4>;
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let l = a[${outer_array_index}][${inner_array_index}][I];
|
|
}
|
|
)";
|
|
tmpl_src = matrix.ReplaceFieldsInString(tmpl_src);
|
|
|
|
std::string tmpl_expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
tmpl_expect = R"(
|
|
enable f16;
|
|
|
|
struct mat${shape}_${elem_type} {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<array<mat${shape}_${elem_type}, 3u>, 4u>;
|
|
|
|
fn load_a_${outer_array_index}_${inner_array_index}_p0(p0 : u32) -> ${col_vector_type} {
|
|
switch(p0) {
|
|
${col_table}
|
|
default: {
|
|
return ${col_vector_type}();
|
|
}
|
|
}
|
|
}
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let l = load_a_${outer_array_index}_${inner_array_index}_p0(u32(I));
|
|
}
|
|
)";
|
|
// col_table is the switch cases for all column index.
|
|
// Example for a matrix having 2 columns:
|
|
// case 0u: {
|
|
// return a[${outer_array_index}u][${inner_array_index}u].col0;
|
|
// }
|
|
// case 1u: {
|
|
// return a[${outer_array_index}u][${inner_array_index}u].col1;
|
|
// }
|
|
std::string col_table = matrix.JoinTemplatedStringForEachMatrixColumn( //
|
|
R"( case ${col_id_for_tmpl}u: {
|
|
return a[${outer_array_index}u][${inner_array_index}u].col${col_id_for_tmpl};
|
|
})",
|
|
"\n");
|
|
tmpl_expect = matrix.ReplaceFieldsInString(
|
|
tmpl_expect, {{"${col_vectors}", matrix.ExpendedColumnVectors(2, "col")},
|
|
{"${col_table}", col_table}});
|
|
} else {
|
|
tmpl_expect = tmpl_src;
|
|
}
|
|
|
|
for (uint32_t outer = 0; outer < 4; outer++) {
|
|
for (uint32_t inner = 0; inner < 3; inner++) {
|
|
std::string src =
|
|
utils::ReplaceAll(tmpl_src, "${outer_array_index}", std::to_string(outer));
|
|
src = utils::ReplaceAll(src, "${inner_array_index}", std::to_string(inner));
|
|
std::string expect =
|
|
utils::ReplaceAll(tmpl_expect, "${outer_array_index}", std::to_string(outer));
|
|
expect = utils::ReplaceAll(expect, "${inner_array_index}", std::to_string(inner));
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got))
|
|
<< "accessing array element [" << outer << "][" << inner << "]";
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST_P(
|
|
Std140Test_MatrixArray,
|
|
ArrayArrayMatUniform_LoadColumn_ConstOuterArrayIndex_VariableInnerArrayIndex_ConstColumnIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
if (!matrix.CanBeUsedAsUniformArrayElememts()) {
|
|
// This permutation is invalid, skip the test.
|
|
return;
|
|
}
|
|
|
|
std::string tmpl_src = R"(
|
|
enable f16;
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<array<${mat}, 3>, 4>;
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let l = a[${outer_array_index}][I][${column_index}];
|
|
}
|
|
)";
|
|
tmpl_src = matrix.ReplaceFieldsInString(tmpl_src);
|
|
|
|
std::string tmpl_expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
tmpl_expect = R"(
|
|
enable f16;
|
|
|
|
struct mat${shape}_${elem_type} {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<array<mat${shape}_${elem_type}, 3u>, 4u>;
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let l = a[${outer_array_index}u][I].col${column_index};
|
|
}
|
|
)";
|
|
tmpl_expect = matrix.ReplaceFieldsInString(
|
|
tmpl_expect, {{"${col_vectors}", matrix.ExpendedColumnVectors(2, "col")}});
|
|
} else {
|
|
tmpl_expect = tmpl_src;
|
|
}
|
|
|
|
for (uint32_t outer = 0; outer < 4; outer++) {
|
|
for (uint32_t col = 0; col < matrix.columns; col++) {
|
|
std::string src =
|
|
utils::ReplaceAll(tmpl_src, "${outer_array_index}", std::to_string(outer));
|
|
src = utils::ReplaceAll(src, "${column_index}", std::to_string(col));
|
|
std::string expect =
|
|
utils::ReplaceAll(tmpl_expect, "${outer_array_index}", std::to_string(outer));
|
|
expect = utils::ReplaceAll(expect, "${column_index}", std::to_string(col));
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got))
|
|
<< "accessing array element [" << outer << "][I] col " << col;
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST_P(
|
|
Std140Test_MatrixArray,
|
|
ArrayArrayMatUniform_LoadColumn_ConstOuterArrayIndex_VariableInnerArrayIndex_VariableColumnIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
if (!matrix.CanBeUsedAsUniformArrayElememts()) {
|
|
// This permutation is invalid, skip the test.
|
|
return;
|
|
}
|
|
|
|
std::string tmpl_src = R"(
|
|
enable f16;
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<array<${mat}, 3>, 4>;
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let J = 2;
|
|
let l = a[${outer_array_index}][I][J];
|
|
}
|
|
)";
|
|
tmpl_src = matrix.ReplaceFieldsInString(tmpl_src);
|
|
|
|
std::string tmpl_expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
tmpl_expect = R"(
|
|
enable f16;
|
|
|
|
struct mat${shape}_${elem_type} {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<array<mat${shape}_${elem_type}, 3u>, 4u>;
|
|
|
|
fn load_a_${outer_array_index}_p0_p1(p0 : u32, p1 : u32) -> ${col_vector_type} {
|
|
switch(p1) {
|
|
${col_table}
|
|
default: {
|
|
return ${col_vector_type}();
|
|
}
|
|
}
|
|
}
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let J = 2;
|
|
let l = load_a_${outer_array_index}_p0_p1(u32(I), u32(J));
|
|
}
|
|
)";
|
|
// col_table is the switch cases for all column index.
|
|
// Example for a matrix having 2 columns:
|
|
// case 0u: {
|
|
// return a[${outer_array_index}u][p0].col0;
|
|
// }
|
|
// case 1u: {
|
|
// return a[${outer_array_index}u][p0].col1;
|
|
// }
|
|
std::string col_table = matrix.JoinTemplatedStringForEachMatrixColumn( //
|
|
R"( case ${col_id_for_tmpl}u: {
|
|
return a[${outer_array_index}u][p0].col${col_id_for_tmpl};
|
|
})",
|
|
"\n");
|
|
tmpl_expect = matrix.ReplaceFieldsInString(
|
|
tmpl_expect, {{"${col_vectors}", matrix.ExpendedColumnVectors(2, "col")},
|
|
{"${col_table}", col_table}});
|
|
} else {
|
|
tmpl_expect = tmpl_src;
|
|
}
|
|
|
|
for (uint32_t outer = 0; outer < 4; outer++) {
|
|
std::string src =
|
|
utils::ReplaceAll(tmpl_src, "${outer_array_index}", std::to_string(outer));
|
|
std::string expect =
|
|
utils::ReplaceAll(tmpl_expect, "${outer_array_index}", std::to_string(outer));
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got)) << "accessing array element [" << outer << "][I]";
|
|
}
|
|
}
|
|
|
|
TEST_P(
|
|
Std140Test_MatrixArray,
|
|
ArrayArrayMatUniform_LoadColumn_VariableOuterArrayIndex_ConstInnerArrayIndex_ConstColumnIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
if (!matrix.CanBeUsedAsUniformArrayElememts()) {
|
|
// This permutation is invalid, skip the test.
|
|
return;
|
|
}
|
|
|
|
std::string tmpl_src = R"(
|
|
enable f16;
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<array<${mat}, 3>, 4>;
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let l = a[I][${inner_array_index}][${column_index}];
|
|
}
|
|
)";
|
|
tmpl_src = matrix.ReplaceFieldsInString(tmpl_src);
|
|
|
|
std::string tmpl_expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
tmpl_expect = R"(
|
|
enable f16;
|
|
|
|
struct mat${shape}_${elem_type} {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<array<mat${shape}_${elem_type}, 3u>, 4u>;
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let l = a[I][${inner_array_index}u].col${column_index};
|
|
}
|
|
)";
|
|
tmpl_expect = matrix.ReplaceFieldsInString(
|
|
tmpl_expect, {{"${col_vectors}", matrix.ExpendedColumnVectors(2, "col")}});
|
|
} else {
|
|
tmpl_expect = tmpl_src;
|
|
}
|
|
|
|
for (uint32_t inner = 0; inner < 3; inner++) {
|
|
for (uint32_t col = 0; col < matrix.columns; col++) {
|
|
std::string src =
|
|
utils::ReplaceAll(tmpl_src, "${inner_array_index}", std::to_string(inner));
|
|
src = utils::ReplaceAll(src, "${column_index}", std::to_string(col));
|
|
std::string expect =
|
|
utils::ReplaceAll(tmpl_expect, "${inner_array_index}", std::to_string(inner));
|
|
expect = utils::ReplaceAll(expect, "${column_index}", std::to_string(col));
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got))
|
|
<< "accessing array element [I][" << inner << "] col " << col;
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST_P(
|
|
Std140Test_MatrixArray,
|
|
ArrayArrayMatUniform_LoadColumn_VariableOuterArrayIndex_ConstInnerArrayIndex_VariableColumnIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
if (!matrix.CanBeUsedAsUniformArrayElememts()) {
|
|
// This permutation is invalid, skip the test.
|
|
return;
|
|
}
|
|
|
|
std::string tmpl_src = R"(
|
|
enable f16;
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<array<${mat}, 3>, 4>;
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let J = 2;
|
|
let l = a[I][${inner_array_index}][J];
|
|
}
|
|
)";
|
|
tmpl_src = matrix.ReplaceFieldsInString(tmpl_src);
|
|
|
|
std::string tmpl_expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
tmpl_expect = R"(
|
|
enable f16;
|
|
|
|
struct mat${shape}_${elem_type} {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<array<mat${shape}_${elem_type}, 3u>, 4u>;
|
|
|
|
fn load_a_p0_${inner_array_index}_p1(p0 : u32, p1 : u32) -> ${col_vector_type} {
|
|
switch(p1) {
|
|
${col_table}
|
|
default: {
|
|
return ${col_vector_type}();
|
|
}
|
|
}
|
|
}
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let J = 2;
|
|
let l = load_a_p0_${inner_array_index}_p1(u32(I), u32(J));
|
|
}
|
|
)";
|
|
// col_table is the switch cases for all column index.
|
|
// Example for a matrix having 2 columns:
|
|
// case 0u: {
|
|
// return a[p0][${inner_array_index}u].col0;
|
|
// }
|
|
// case 1u: {
|
|
// return a[p0][${inner_array_index}u].col1;
|
|
// }
|
|
std::string col_table = matrix.JoinTemplatedStringForEachMatrixColumn( //
|
|
R"( case ${col_id_for_tmpl}u: {
|
|
return a[p0][${inner_array_index}u].col${col_id_for_tmpl};
|
|
})",
|
|
"\n");
|
|
tmpl_expect = matrix.ReplaceFieldsInString(
|
|
tmpl_expect, {{"${col_vectors}", matrix.ExpendedColumnVectors(2, "col")},
|
|
{"${col_table}", col_table}});
|
|
} else {
|
|
tmpl_expect = tmpl_src;
|
|
}
|
|
|
|
for (uint32_t inner = 0; inner < 3; inner++) {
|
|
std::string src =
|
|
utils::ReplaceAll(tmpl_src, "${inner_array_index}", std::to_string(inner));
|
|
std::string expect =
|
|
utils::ReplaceAll(tmpl_expect, "${inner_array_index}", std::to_string(inner));
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got)) << "accessing array element [I][" << inner << "]";
|
|
}
|
|
}
|
|
|
|
TEST_P(
|
|
Std140Test_MatrixArray,
|
|
ArrayArrayMatUniform_LoadColumn_VariableOuterArrayIndex_VariableInnerArrayIndex_ConstColumnIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
if (!matrix.CanBeUsedAsUniformArrayElememts()) {
|
|
// This permutation is invalid, skip the test.
|
|
return;
|
|
}
|
|
|
|
std::string tmpl_src = R"(
|
|
enable f16;
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<array<${mat}, 3>, 4>;
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let J = 2;
|
|
let l = a[I][J][${column_index}];
|
|
}
|
|
)";
|
|
tmpl_src = matrix.ReplaceFieldsInString(tmpl_src);
|
|
|
|
std::string tmpl_expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
tmpl_expect = R"(
|
|
enable f16;
|
|
|
|
struct mat${shape}_${elem_type} {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<array<mat${shape}_${elem_type}, 3u>, 4u>;
|
|
|
|
fn f() {
|
|
let I = 1;
|
|
let J = 2;
|
|
let l = a[I][J].col${column_index};
|
|
}
|
|
)";
|
|
tmpl_expect = matrix.ReplaceFieldsInString(
|
|
tmpl_expect, {{"${col_vectors}", matrix.ExpendedColumnVectors(2, "col")}});
|
|
} else {
|
|
tmpl_expect = tmpl_src;
|
|
}
|
|
|
|
for (uint32_t col = 0; col < matrix.columns; col++) {
|
|
std::string src = utils::ReplaceAll(tmpl_src, "${column_index}", std::to_string(col));
|
|
std::string expect = utils::ReplaceAll(tmpl_expect, "${column_index}", std::to_string(col));
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got)) << "accessing array element [I][J] col " << col;
|
|
}
|
|
}
|
|
|
|
TEST_P(
|
|
Std140Test_MatrixArray,
|
|
ArrayArrayMatUniform_LoadColumn_VariableOuterArrayIndex_VariableInnerArrayIndex_VariableColumnIndex) {
|
|
auto matrix = GetParam();
|
|
|
|
if (!matrix.CanBeUsedAsUniformArrayElememts()) {
|
|
// This permutation is invalid, skip the test.
|
|
return;
|
|
}
|
|
|
|
std::string src = R"(
|
|
enable f16;
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<array<${mat}, 3>, 4>;
|
|
|
|
fn f() {
|
|
let I = 0;
|
|
let J = 1;
|
|
let K = 2;
|
|
let l = a[I][J][K];
|
|
}
|
|
)";
|
|
src = matrix.ReplaceFieldsInString(src);
|
|
|
|
std::string expect;
|
|
if (matrix.NotStd140Compatible()) {
|
|
expect = R"(
|
|
enable f16;
|
|
|
|
struct mat${shape}_${elem_type} {
|
|
${col_vectors}
|
|
}
|
|
|
|
@group(0) @binding(0) var<uniform> a : array<array<mat${shape}_${elem_type}, 3u>, 4u>;
|
|
|
|
fn load_a_p0_p1_p2(p0 : u32, p1 : u32, p2 : u32) -> ${col_vector_type} {
|
|
switch(p2) {
|
|
${col_table}
|
|
default: {
|
|
return ${col_vector_type}();
|
|
}
|
|
}
|
|
}
|
|
|
|
fn f() {
|
|
let I = 0;
|
|
let J = 1;
|
|
let K = 2;
|
|
let l = load_a_p0_p1_p2(u32(I), u32(J), u32(K));
|
|
}
|
|
)";
|
|
// col_table is the switch cases for all column index.
|
|
// Example for a matrix having 2 columns:
|
|
// case 0u: {
|
|
// return a[p0][p1].col0;
|
|
// }
|
|
// case 1u: {
|
|
// return a[p0][p1].col1;
|
|
// }
|
|
std::string col_table = matrix.JoinTemplatedStringForEachMatrixColumn( //
|
|
R"( case ${col_id_for_tmpl}u: {
|
|
return a[p0][p1].col${col_id_for_tmpl};
|
|
})",
|
|
"\n");
|
|
expect = matrix.ReplaceFieldsInString(
|
|
expect, {{"${col_vectors}", matrix.ExpendedColumnVectors(2, "col")},
|
|
{"${col_table}", col_table}});
|
|
} else {
|
|
expect = src;
|
|
}
|
|
|
|
auto got = Run<Std140>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
INSTANTIATE_TEST_SUITE_P(,
|
|
Std140Test_MatrixArray,
|
|
::testing::ValuesIn(std::vector<MatrixCase>{
|
|
{2, 2, MatrixType::f32},
|
|
{2, 3, MatrixType::f32},
|
|
{2, 4, MatrixType::f32},
|
|
{3, 2, MatrixType::f32},
|
|
{3, 3, MatrixType::f32},
|
|
{3, 4, MatrixType::f32},
|
|
{4, 2, MatrixType::f32},
|
|
{4, 3, MatrixType::f32},
|
|
{4, 4, MatrixType::f32},
|
|
{2, 2, MatrixType::f16},
|
|
{2, 3, MatrixType::f16},
|
|
{2, 4, MatrixType::f16},
|
|
{3, 2, MatrixType::f16},
|
|
{3, 3, MatrixType::f16},
|
|
{3, 4, MatrixType::f16},
|
|
{4, 2, MatrixType::f16},
|
|
{4, 3, MatrixType::f16},
|
|
{4, 4, MatrixType::f16},
|
|
}));
|
|
|
|
} // namespace
|
|
} // namespace tint::transform
|