[msl] Delete AST backend
You will not be missed.
Bug: 388013849
Change-Id: Ia635c5dcc38ecc8025c8c117bcad53606278bd5c
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/224519
Reviewed-by: dan sinclair <dsinclair@chromium.org>
Commit-Queue: James Price <jrprice@google.com>
diff --git a/src/tint/cmd/loopy/main.cc b/src/tint/cmd/loopy/main.cc
index c47de84..57a90e5 100644
--- a/src/tint/cmd/loopy/main.cc
+++ b/src/tint/cmd/loopy/main.cc
@@ -270,14 +270,6 @@
input_program = &*flattened;
}
- tint::msl::writer::Options gen_options;
- gen_options.bindings = tint::msl::writer::GenerateBindings(program);
- gen_options.array_length_from_uniform.ubo_binding = 30;
- gen_options.array_length_from_uniform.bindpoint_to_size_index.emplace(tint::BindingPoint{0, 0},
- 0);
- gen_options.array_length_from_uniform.bindpoint_to_size_index.emplace(tint::BindingPoint{0, 1},
- 1);
-
// Convert the AST program to an IR module.
auto ir = tint::wgsl::reader::ProgramToLoweredIR(*input_program);
if (ir != tint::Success) {
@@ -285,6 +277,14 @@
return false;
}
+ tint::msl::writer::Options gen_options;
+ gen_options.bindings = tint::msl::writer::GenerateBindings(ir.Get());
+ gen_options.array_length_from_uniform.ubo_binding = 30;
+ gen_options.array_length_from_uniform.bindpoint_to_size_index.emplace(tint::BindingPoint{0, 0},
+ 0);
+ gen_options.array_length_from_uniform.bindpoint_to_size_index.emplace(tint::BindingPoint{0, 1},
+ 1);
+
// Generate MSL from Tint IR.
auto result = tint::msl::writer::Generate(ir.Get(), gen_options);
if (result != tint::Success) {
diff --git a/src/tint/cmd/test/BUILD.bazel b/src/tint/cmd/test/BUILD.bazel
index d232be0..6b188d2 100644
--- a/src/tint/cmd/test/BUILD.bazel
+++ b/src/tint/cmd/test/BUILD.bazel
@@ -117,18 +117,12 @@
"//conditions:default": [],
}) + select({
":tint_build_msl_writer": [
- "//src/tint/lang/msl/writer/ast_printer:test",
"//src/tint/lang/msl/writer/common:test",
"//src/tint/lang/msl/writer/raise:test",
"//src/tint/lang/msl/writer:test",
],
"//conditions:default": [],
}) + select({
- ":tint_build_msl_writer_and_tint_build_wgsl_reader_and_tint_build_wgsl_writer": [
- "//src/tint/lang/msl/writer/ast_raise:test",
- ],
- "//conditions:default": [],
- }) + select({
":tint_build_spv_reader": [
"//src/tint/lang/spirv/reader/common:test",
"//src/tint/lang/spirv/reader/parser:test",
@@ -260,14 +254,6 @@
],
)
selects.config_setting_group(
- name = "tint_build_msl_writer_and_tint_build_wgsl_reader_and_tint_build_wgsl_writer",
- match_all = [
- ":tint_build_msl_writer",
- ":tint_build_wgsl_reader",
- ":tint_build_wgsl_writer",
- ],
-)
-selects.config_setting_group(
name = "tint_build_spv_reader_and_tint_build_wgsl_reader_and_tint_build_wgsl_writer",
match_all = [
":tint_build_spv_reader",
diff --git a/src/tint/cmd/test/BUILD.cmake b/src/tint/cmd/test/BUILD.cmake
index 66d8c23..e5fa229 100644
--- a/src/tint/cmd/test/BUILD.cmake
+++ b/src/tint/cmd/test/BUILD.cmake
@@ -128,19 +128,12 @@
if(TINT_BUILD_MSL_WRITER)
tint_target_add_dependencies(tint_cmd_test_test_cmd test_cmd
- tint_lang_msl_writer_ast_printer_test
tint_lang_msl_writer_common_test
tint_lang_msl_writer_raise_test
tint_lang_msl_writer_test
)
endif(TINT_BUILD_MSL_WRITER)
-if(TINT_BUILD_MSL_WRITER AND TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
- tint_target_add_dependencies(tint_cmd_test_test_cmd test_cmd
- tint_lang_msl_writer_ast_raise_test
- )
-endif(TINT_BUILD_MSL_WRITER AND TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
-
if(TINT_BUILD_SPV_READER)
tint_target_add_dependencies(tint_cmd_test_test_cmd test_cmd
tint_lang_spirv_reader_common_test
diff --git a/src/tint/cmd/test/BUILD.gn b/src/tint/cmd/test/BUILD.gn
index 0b5a9b6..b767381 100644
--- a/src/tint/cmd/test/BUILD.gn
+++ b/src/tint/cmd/test/BUILD.gn
@@ -126,17 +126,11 @@
if (tint_build_msl_writer) {
deps += [
"${tint_src_dir}/lang/msl/writer:unittests",
- "${tint_src_dir}/lang/msl/writer/ast_printer:unittests",
"${tint_src_dir}/lang/msl/writer/common:unittests",
"${tint_src_dir}/lang/msl/writer/raise:unittests",
]
}
- if (tint_build_msl_writer && tint_build_wgsl_reader &&
- tint_build_wgsl_writer) {
- deps += [ "${tint_src_dir}/lang/msl/writer/ast_raise:unittests" ]
- }
-
if (tint_build_spv_reader) {
deps += [
"${tint_src_dir}/lang/spirv/reader:unittests",
diff --git a/src/tint/lang/msl/writer/BUILD.bazel b/src/tint/lang/msl/writer/BUILD.bazel
index d848197..de3d1ee 100644
--- a/src/tint/lang/msl/writer/BUILD.bazel
+++ b/src/tint/lang/msl/writer/BUILD.bazel
@@ -51,11 +51,6 @@
"//src/tint/lang/core/constant",
"//src/tint/lang/core/ir",
"//src/tint/lang/core/type",
- "//src/tint/lang/wgsl",
- "//src/tint/lang/wgsl/ast",
- "//src/tint/lang/wgsl/features",
- "//src/tint/lang/wgsl/program",
- "//src/tint/lang/wgsl/sem",
"//src/tint/utils",
"//src/tint/utils/containers",
"//src/tint/utils/diagnostic",
@@ -70,7 +65,6 @@
"//src/utils",
] + select({
":tint_build_msl_writer": [
- "//src/tint/lang/msl/writer/ast_printer",
"//src/tint/lang/msl/writer/common",
"//src/tint/lang/msl/writer/printer",
"//src/tint/lang/msl/writer/raise",
diff --git a/src/tint/lang/msl/writer/BUILD.cmake b/src/tint/lang/msl/writer/BUILD.cmake
index f986cbf..b26526b 100644
--- a/src/tint/lang/msl/writer/BUILD.cmake
+++ b/src/tint/lang/msl/writer/BUILD.cmake
@@ -34,8 +34,6 @@
# Do not modify this file directly
################################################################################
-include(lang/msl/writer/ast_printer/BUILD.cmake)
-include(lang/msl/writer/ast_raise/BUILD.cmake)
include(lang/msl/writer/common/BUILD.cmake)
include(lang/msl/writer/helpers/BUILD.cmake)
include(lang/msl/writer/printer/BUILD.cmake)
@@ -59,11 +57,6 @@
tint_lang_core_constant
tint_lang_core_ir
tint_lang_core_type
- tint_lang_wgsl
- tint_lang_wgsl_ast
- tint_lang_wgsl_features
- tint_lang_wgsl_program
- tint_lang_wgsl_sem
tint_utils
tint_utils_containers
tint_utils_diagnostic
@@ -83,7 +76,6 @@
if(TINT_BUILD_MSL_WRITER)
tint_target_add_dependencies(tint_lang_msl_writer lib
- tint_lang_msl_writer_ast_printer
tint_lang_msl_writer_common
tint_lang_msl_writer_printer
tint_lang_msl_writer_raise
@@ -221,11 +213,6 @@
tint_lang_core_constant
tint_lang_core_ir
tint_lang_core_type
- tint_lang_wgsl
- tint_lang_wgsl_ast
- tint_lang_wgsl_features
- tint_lang_wgsl_program
- tint_lang_wgsl_sem
tint_utils
tint_utils_bytes
tint_utils_containers
@@ -252,13 +239,4 @@
)
endif(TINT_BUILD_MSL_WRITER)
-if(TINT_BUILD_WGSL_READER)
- tint_target_add_sources(tint_lang_msl_writer_fuzz fuzz
- "lang/msl/writer/writer_ast_fuzz.cc"
- )
- tint_target_add_dependencies(tint_lang_msl_writer_fuzz fuzz
- tint_cmd_fuzz_wgsl_fuzz
- )
-endif(TINT_BUILD_WGSL_READER)
-
endif(TINT_BUILD_MSL_WRITER)
\ No newline at end of file
diff --git a/src/tint/lang/msl/writer/BUILD.gn b/src/tint/lang/msl/writer/BUILD.gn
index 9028589..6ef418a 100644
--- a/src/tint/lang/msl/writer/BUILD.gn
+++ b/src/tint/lang/msl/writer/BUILD.gn
@@ -56,11 +56,6 @@
"${tint_src_dir}/lang/core/constant",
"${tint_src_dir}/lang/core/ir",
"${tint_src_dir}/lang/core/type",
- "${tint_src_dir}/lang/wgsl",
- "${tint_src_dir}/lang/wgsl/ast",
- "${tint_src_dir}/lang/wgsl/features",
- "${tint_src_dir}/lang/wgsl/program",
- "${tint_src_dir}/lang/wgsl/sem",
"${tint_src_dir}/utils",
"${tint_src_dir}/utils/containers",
"${tint_src_dir}/utils/diagnostic",
@@ -76,7 +71,6 @@
if (tint_build_msl_writer) {
deps += [
- "${tint_src_dir}/lang/msl/writer/ast_printer",
"${tint_src_dir}/lang/msl/writer/common",
"${tint_src_dir}/lang/msl/writer/printer",
"${tint_src_dir}/lang/msl/writer/raise",
@@ -194,11 +188,6 @@
"${tint_src_dir}/lang/core/constant",
"${tint_src_dir}/lang/core/ir",
"${tint_src_dir}/lang/core/type",
- "${tint_src_dir}/lang/wgsl",
- "${tint_src_dir}/lang/wgsl/ast",
- "${tint_src_dir}/lang/wgsl/features",
- "${tint_src_dir}/lang/wgsl/program",
- "${tint_src_dir}/lang/wgsl/sem",
"${tint_src_dir}/utils",
"${tint_src_dir}/utils/bytes",
"${tint_src_dir}/utils/containers",
@@ -220,10 +209,5 @@
"${tint_src_dir}/lang/msl/writer/helpers",
]
}
-
- if (tint_build_wgsl_reader) {
- sources += [ "writer_ast_fuzz.cc" ]
- deps += [ "${tint_src_dir}/cmd/fuzz/wgsl:fuzz" ]
- }
}
}
diff --git a/src/tint/lang/msl/writer/ast_printer/BUILD.bazel b/src/tint/lang/msl/writer/ast_printer/BUILD.bazel
deleted file mode 100644
index 8f47803..0000000
--- a/src/tint/lang/msl/writer/ast_printer/BUILD.bazel
+++ /dev/null
@@ -1,159 +0,0 @@
-# Copyright 2023 The Dawn & Tint Authors
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#
-# 1. Redistributions of source code must retain the above copyright notice, this
-# list of conditions and the following disclaimer.
-#
-# 2. Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# 3. Neither the name of the copyright holder nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-################################################################################
-# File generated by 'tools/src/cmd/gen' using the template:
-# tools/src/cmd/gen/build/BUILD.bazel.tmpl
-#
-# To regenerate run: './tools/run gen'
-#
-# Do not modify this file directly
-################################################################################
-
-load("//src/tint:flags.bzl", "COPTS")
-load("@bazel_skylib//lib:selects.bzl", "selects")
-cc_library(
- name = "ast_printer",
- srcs = [
- "ast_printer.cc",
- ],
- hdrs = [
- "ast_printer.h",
- ],
- deps = [
- "//src/tint/api/common",
- "//src/tint/lang/core",
- "//src/tint/lang/core/common",
- "//src/tint/lang/core/constant",
- "//src/tint/lang/core/type",
- "//src/tint/lang/wgsl",
- "//src/tint/lang/wgsl/ast",
- "//src/tint/lang/wgsl/ast/transform",
- "//src/tint/lang/wgsl/features",
- "//src/tint/lang/wgsl/helpers",
- "//src/tint/lang/wgsl/program",
- "//src/tint/lang/wgsl/sem",
- "//src/tint/utils",
- "//src/tint/utils/containers",
- "//src/tint/utils/diagnostic",
- "//src/tint/utils/ice",
- "//src/tint/utils/macros",
- "//src/tint/utils/math",
- "//src/tint/utils/memory",
- "//src/tint/utils/result",
- "//src/tint/utils/rtti",
- "//src/tint/utils/symbol",
- "//src/tint/utils/text",
- "//src/utils",
- ] + select({
- ":tint_build_msl_writer": [
- "//src/tint/lang/msl/writer/ast_raise",
- "//src/tint/lang/msl/writer/common",
- ],
- "//conditions:default": [],
- }),
- copts = COPTS,
- visibility = ["//visibility:public"],
-)
-cc_library(
- name = "test",
- alwayslink = True,
- srcs = [
- "array_accessor_test.cc",
- "assign_test.cc",
- "ast_function_test.cc",
- "ast_printer_test.cc",
- "ast_type_test.cc",
- "binary_test.cc",
- "bitcast_test.cc",
- "block_test.cc",
- "break_test.cc",
- "builtin_test.cc",
- "builtin_texture_test.cc",
- "call_test.cc",
- "case_test.cc",
- "cast_test.cc",
- "const_assert_test.cc",
- "constructor_test.cc",
- "continue_test.cc",
- "discard_test.cc",
- "helper_test.h",
- "identifier_test.cc",
- "if_test.cc",
- "import_test.cc",
- "loop_test.cc",
- "member_accessor_test.cc",
- "module_constant_test.cc",
- "return_test.cc",
- "sanitizer_test.cc",
- "switch_test.cc",
- "unary_op_test.cc",
- "variable_decl_statement_test.cc",
- ],
- deps = [
- "//src/tint/api/common",
- "//src/tint/lang/core",
- "//src/tint/lang/core/constant",
- "//src/tint/lang/core/type",
- "//src/tint/lang/wgsl",
- "//src/tint/lang/wgsl/ast",
- "//src/tint/lang/wgsl/ast:test",
- "//src/tint/lang/wgsl/common",
- "//src/tint/lang/wgsl/features",
- "//src/tint/lang/wgsl/program",
- "//src/tint/lang/wgsl/resolver",
- "//src/tint/lang/wgsl/sem",
- "//src/tint/utils",
- "//src/tint/utils/containers",
- "//src/tint/utils/diagnostic",
- "//src/tint/utils/ice",
- "//src/tint/utils/macros",
- "//src/tint/utils/math",
- "//src/tint/utils/memory",
- "//src/tint/utils/result",
- "//src/tint/utils/rtti",
- "//src/tint/utils/symbol",
- "//src/tint/utils/text",
- "@gtest",
- "//src/utils",
- ] + select({
- ":tint_build_msl_writer": [
- "//src/tint/lang/msl/writer",
- "//src/tint/lang/msl/writer/ast_printer",
- "//src/tint/lang/msl/writer/common",
- ],
- "//conditions:default": [],
- }),
- copts = COPTS,
- visibility = ["//visibility:public"],
-)
-
-alias(
- name = "tint_build_msl_writer",
- actual = "//src/tint:tint_build_msl_writer_true",
-)
-
diff --git a/src/tint/lang/msl/writer/ast_printer/BUILD.cfg b/src/tint/lang/msl/writer/ast_printer/BUILD.cfg
deleted file mode 100644
index 1c7e256..0000000
--- a/src/tint/lang/msl/writer/ast_printer/BUILD.cfg
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "condition": "tint_build_msl_writer"
-}
diff --git a/src/tint/lang/msl/writer/ast_printer/BUILD.cmake b/src/tint/lang/msl/writer/ast_printer/BUILD.cmake
deleted file mode 100644
index c88dba8..0000000
--- a/src/tint/lang/msl/writer/ast_printer/BUILD.cmake
+++ /dev/null
@@ -1,164 +0,0 @@
-# Copyright 2023 The Dawn & Tint Authors
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#
-# 1. Redistributions of source code must retain the above copyright notice, this
-# list of conditions and the following disclaimer.
-#
-# 2. Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# 3. Neither the name of the copyright holder nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-################################################################################
-# File generated by 'tools/src/cmd/gen' using the template:
-# tools/src/cmd/gen/build/BUILD.cmake.tmpl
-#
-# To regenerate run: './tools/run gen'
-#
-# Do not modify this file directly
-################################################################################
-
-if(TINT_BUILD_MSL_WRITER)
-################################################################################
-# Target: tint_lang_msl_writer_ast_printer
-# Kind: lib
-# Condition: TINT_BUILD_MSL_WRITER
-################################################################################
-tint_add_target(tint_lang_msl_writer_ast_printer lib
- lang/msl/writer/ast_printer/ast_printer.cc
- lang/msl/writer/ast_printer/ast_printer.h
-)
-
-tint_target_add_dependencies(tint_lang_msl_writer_ast_printer lib
- tint_api_common
- tint_lang_core
- tint_lang_core_common
- tint_lang_core_constant
- tint_lang_core_type
- tint_lang_wgsl
- tint_lang_wgsl_ast
- tint_lang_wgsl_ast_transform
- tint_lang_wgsl_features
- tint_lang_wgsl_helpers
- tint_lang_wgsl_program
- tint_lang_wgsl_sem
- tint_utils
- tint_utils_containers
- tint_utils_diagnostic
- tint_utils_ice
- tint_utils_macros
- tint_utils_math
- tint_utils_memory
- tint_utils_result
- tint_utils_rtti
- tint_utils_symbol
- tint_utils_text
-)
-
-tint_target_add_external_dependencies(tint_lang_msl_writer_ast_printer lib
- "src_utils"
-)
-
-if(TINT_BUILD_MSL_WRITER)
- tint_target_add_dependencies(tint_lang_msl_writer_ast_printer lib
- tint_lang_msl_writer_ast_raise
- tint_lang_msl_writer_common
- )
-endif(TINT_BUILD_MSL_WRITER)
-
-endif(TINT_BUILD_MSL_WRITER)
-if(TINT_BUILD_MSL_WRITER)
-################################################################################
-# Target: tint_lang_msl_writer_ast_printer_test
-# Kind: test
-# Condition: TINT_BUILD_MSL_WRITER
-################################################################################
-tint_add_target(tint_lang_msl_writer_ast_printer_test test
- lang/msl/writer/ast_printer/array_accessor_test.cc
- lang/msl/writer/ast_printer/assign_test.cc
- lang/msl/writer/ast_printer/ast_function_test.cc
- lang/msl/writer/ast_printer/ast_printer_test.cc
- lang/msl/writer/ast_printer/ast_type_test.cc
- lang/msl/writer/ast_printer/binary_test.cc
- lang/msl/writer/ast_printer/bitcast_test.cc
- lang/msl/writer/ast_printer/block_test.cc
- lang/msl/writer/ast_printer/break_test.cc
- lang/msl/writer/ast_printer/builtin_test.cc
- lang/msl/writer/ast_printer/builtin_texture_test.cc
- lang/msl/writer/ast_printer/call_test.cc
- lang/msl/writer/ast_printer/case_test.cc
- lang/msl/writer/ast_printer/cast_test.cc
- lang/msl/writer/ast_printer/const_assert_test.cc
- lang/msl/writer/ast_printer/constructor_test.cc
- lang/msl/writer/ast_printer/continue_test.cc
- lang/msl/writer/ast_printer/discard_test.cc
- lang/msl/writer/ast_printer/helper_test.h
- lang/msl/writer/ast_printer/identifier_test.cc
- lang/msl/writer/ast_printer/if_test.cc
- lang/msl/writer/ast_printer/import_test.cc
- lang/msl/writer/ast_printer/loop_test.cc
- lang/msl/writer/ast_printer/member_accessor_test.cc
- lang/msl/writer/ast_printer/module_constant_test.cc
- lang/msl/writer/ast_printer/return_test.cc
- lang/msl/writer/ast_printer/sanitizer_test.cc
- lang/msl/writer/ast_printer/switch_test.cc
- lang/msl/writer/ast_printer/unary_op_test.cc
- lang/msl/writer/ast_printer/variable_decl_statement_test.cc
-)
-
-tint_target_add_dependencies(tint_lang_msl_writer_ast_printer_test test
- tint_api_common
- tint_lang_core
- tint_lang_core_constant
- tint_lang_core_type
- tint_lang_wgsl
- tint_lang_wgsl_ast
- tint_lang_wgsl_ast_test
- tint_lang_wgsl_common
- tint_lang_wgsl_features
- tint_lang_wgsl_program
- tint_lang_wgsl_resolver
- tint_lang_wgsl_sem
- tint_utils
- tint_utils_containers
- tint_utils_diagnostic
- tint_utils_ice
- tint_utils_macros
- tint_utils_math
- tint_utils_memory
- tint_utils_result
- tint_utils_rtti
- tint_utils_symbol
- tint_utils_text
-)
-
-tint_target_add_external_dependencies(tint_lang_msl_writer_ast_printer_test test
- "gtest"
- "src_utils"
-)
-
-if(TINT_BUILD_MSL_WRITER)
- tint_target_add_dependencies(tint_lang_msl_writer_ast_printer_test test
- tint_lang_msl_writer
- tint_lang_msl_writer_ast_printer
- tint_lang_msl_writer_common
- )
-endif(TINT_BUILD_MSL_WRITER)
-
-endif(TINT_BUILD_MSL_WRITER)
\ No newline at end of file
diff --git a/src/tint/lang/msl/writer/ast_printer/BUILD.gn b/src/tint/lang/msl/writer/ast_printer/BUILD.gn
deleted file mode 100644
index 0590ba4..0000000
--- a/src/tint/lang/msl/writer/ast_printer/BUILD.gn
+++ /dev/null
@@ -1,158 +0,0 @@
-# Copyright 2023 The Dawn & Tint Authors
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#
-# 1. Redistributions of source code must retain the above copyright notice, this
-# list of conditions and the following disclaimer.
-#
-# 2. Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# 3. Neither the name of the copyright holder nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-################################################################################
-# File generated by 'tools/src/cmd/gen' using the template:
-# tools/src/cmd/gen/build/BUILD.gn.tmpl
-#
-# To regenerate run: './tools/run gen'
-#
-# Do not modify this file directly
-################################################################################
-
-import("../../../../../../scripts/dawn_overrides_with_defaults.gni")
-import("../../../../../../scripts/tint_overrides_with_defaults.gni")
-
-import("${tint_src_dir}/tint.gni")
-
-if (tint_build_unittests || tint_build_benchmarks) {
- import("//testing/test.gni")
-}
-if (tint_build_msl_writer) {
- libtint_source_set("ast_printer") {
- sources = [
- "ast_printer.cc",
- "ast_printer.h",
- ]
- deps = [
- "${dawn_root}/src/utils:utils",
- "${tint_src_dir}/api/common",
- "${tint_src_dir}/lang/core",
- "${tint_src_dir}/lang/core/common",
- "${tint_src_dir}/lang/core/constant",
- "${tint_src_dir}/lang/core/type",
- "${tint_src_dir}/lang/wgsl",
- "${tint_src_dir}/lang/wgsl/ast",
- "${tint_src_dir}/lang/wgsl/ast/transform",
- "${tint_src_dir}/lang/wgsl/features",
- "${tint_src_dir}/lang/wgsl/helpers",
- "${tint_src_dir}/lang/wgsl/program",
- "${tint_src_dir}/lang/wgsl/sem",
- "${tint_src_dir}/utils",
- "${tint_src_dir}/utils/containers",
- "${tint_src_dir}/utils/diagnostic",
- "${tint_src_dir}/utils/ice",
- "${tint_src_dir}/utils/macros",
- "${tint_src_dir}/utils/math",
- "${tint_src_dir}/utils/memory",
- "${tint_src_dir}/utils/result",
- "${tint_src_dir}/utils/rtti",
- "${tint_src_dir}/utils/symbol",
- "${tint_src_dir}/utils/text",
- ]
-
- if (tint_build_msl_writer) {
- deps += [
- "${tint_src_dir}/lang/msl/writer/ast_raise",
- "${tint_src_dir}/lang/msl/writer/common",
- ]
- }
- }
-}
-if (tint_build_unittests) {
- if (tint_build_msl_writer) {
- tint_unittests_source_set("unittests") {
- sources = [
- "array_accessor_test.cc",
- "assign_test.cc",
- "ast_function_test.cc",
- "ast_printer_test.cc",
- "ast_type_test.cc",
- "binary_test.cc",
- "bitcast_test.cc",
- "block_test.cc",
- "break_test.cc",
- "builtin_test.cc",
- "builtin_texture_test.cc",
- "call_test.cc",
- "case_test.cc",
- "cast_test.cc",
- "const_assert_test.cc",
- "constructor_test.cc",
- "continue_test.cc",
- "discard_test.cc",
- "helper_test.h",
- "identifier_test.cc",
- "if_test.cc",
- "import_test.cc",
- "loop_test.cc",
- "member_accessor_test.cc",
- "module_constant_test.cc",
- "return_test.cc",
- "sanitizer_test.cc",
- "switch_test.cc",
- "unary_op_test.cc",
- "variable_decl_statement_test.cc",
- ]
- deps = [
- "${dawn_root}/src/utils:utils",
- "${tint_src_dir}:gmock_and_gtest",
- "${tint_src_dir}/api/common",
- "${tint_src_dir}/lang/core",
- "${tint_src_dir}/lang/core/constant",
- "${tint_src_dir}/lang/core/type",
- "${tint_src_dir}/lang/wgsl",
- "${tint_src_dir}/lang/wgsl/ast",
- "${tint_src_dir}/lang/wgsl/ast:unittests",
- "${tint_src_dir}/lang/wgsl/common",
- "${tint_src_dir}/lang/wgsl/features",
- "${tint_src_dir}/lang/wgsl/program",
- "${tint_src_dir}/lang/wgsl/resolver",
- "${tint_src_dir}/lang/wgsl/sem",
- "${tint_src_dir}/utils",
- "${tint_src_dir}/utils/containers",
- "${tint_src_dir}/utils/diagnostic",
- "${tint_src_dir}/utils/ice",
- "${tint_src_dir}/utils/macros",
- "${tint_src_dir}/utils/math",
- "${tint_src_dir}/utils/memory",
- "${tint_src_dir}/utils/result",
- "${tint_src_dir}/utils/rtti",
- "${tint_src_dir}/utils/symbol",
- "${tint_src_dir}/utils/text",
- ]
-
- if (tint_build_msl_writer) {
- deps += [
- "${tint_src_dir}/lang/msl/writer",
- "${tint_src_dir}/lang/msl/writer/ast_printer",
- "${tint_src_dir}/lang/msl/writer/common",
- ]
- }
- }
- }
-}
diff --git a/src/tint/lang/msl/writer/ast_printer/array_accessor_test.cc b/src/tint/lang/msl/writer/ast_printer/array_accessor_test.cc
deleted file mode 100644
index 4d8f4e5..0000000
--- a/src/tint/lang/msl/writer/ast_printer/array_accessor_test.cc
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2020 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/tint/lang/core/fluent_types.h"
-#include "src/tint/lang/msl/writer/ast_printer/helper_test.h"
-#include "src/tint/utils/text/string_stream.h"
-
-using namespace tint::core::number_suffixes; // NOLINT
-using namespace tint::core::fluent_types; // NOLINT
-
-namespace tint::msl::writer {
-namespace {
-
-using MslASTPrinterTest = TestHelper;
-
-TEST_F(MslASTPrinterTest, IndexAccessor) {
- auto* ary = Var("ary", ty.array<i32, 10>());
- auto* expr = IndexAccessor("ary", 5_i);
- WrapInFunction(ary, expr);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "ary[5]");
-}
-
-TEST_F(MslASTPrinterTest, IndexAccessor_OfDref) {
- GlobalVar("ary", ty.array<i32, 10>(), core::AddressSpace::kPrivate);
-
- auto* p = Let("p", AddressOf("ary"));
- auto* expr = IndexAccessor(Deref("p"), 5_i);
- WrapInFunction(p, expr);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "(*(p))[5]");
-}
-
-} // namespace
-} // namespace tint::msl::writer
diff --git a/src/tint/lang/msl/writer/ast_printer/assign_test.cc b/src/tint/lang/msl/writer/ast_printer/assign_test.cc
deleted file mode 100644
index 256ec61..0000000
--- a/src/tint/lang/msl/writer/ast_printer/assign_test.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2020 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/tint/lang/msl/writer/ast_printer/helper_test.h"
-
-namespace tint::msl::writer {
-namespace {
-
-using MslASTPrinterTest = TestHelper;
-
-TEST_F(MslASTPrinterTest, Emit_Assign) {
- auto* lhs = Var("lhs", ty.i32());
- auto* rhs = Var("rhs", ty.i32());
- auto* assign = Assign(lhs, rhs);
- WrapInFunction(lhs, rhs, assign);
-
- ASTPrinter& gen = Build();
-
- gen.IncrementIndent();
-
- ASSERT_TRUE(gen.EmitStatement(assign)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), " lhs = rhs;\n");
-}
-
-} // namespace
-} // namespace tint::msl::writer
diff --git a/src/tint/lang/msl/writer/ast_printer/ast_function_test.cc b/src/tint/lang/msl/writer/ast_printer/ast_function_test.cc
deleted file mode 100644
index c8a5fdd..0000000
--- a/src/tint/lang/msl/writer/ast_printer/ast_function_test.cc
+++ /dev/null
@@ -1,726 +0,0 @@
-// Copyright 2020 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/tint/lang/msl/writer/ast_printer/helper_test.h"
-#include "src/tint/lang/wgsl/ast/stage_attribute.h"
-#include "src/tint/lang/wgsl/ast/variable_decl_statement.h"
-
-namespace tint::msl::writer {
-namespace {
-
-using namespace tint::core::fluent_types; // NOLINT
-using namespace tint::core::number_suffixes; // NOLINT
-
-using MslASTPrinterTest = TestHelper;
-
-TEST_F(MslASTPrinterTest, Emit_Function) {
- Func("my_func", tint::Empty, ty.void_(),
- Vector{
- Return(),
- });
-
- ASTPrinter& gen = Build();
-
- gen.IncrementIndent();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"( #include <metal_stdlib>
-
- using namespace metal;
- void my_func() {
- return;
- }
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_Function_WithParams) {
- Func("my_func",
- Vector{
- Param("a", ty.f32()),
- Param("b", ty.i32()),
- },
- ty.void_(),
- Vector{
- Return(),
- });
-
- ASTPrinter& gen = Build();
-
- gen.IncrementIndent();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"( #include <metal_stdlib>
-
- using namespace metal;
- void my_func(float a, int b) {
- return;
- }
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_Attribute_EntryPoint_NoReturn_Void) {
- Func("main", tint::Empty, ty.void_(), {/* no explicit return */},
- Vector{Stage(ast::PipelineStage::kFragment)});
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-fragment void main() {
- return;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_Attribute_EntryPoint_WithInOutVars) {
- // fn frag_main(@location(0) foo : f32) -> @location(1) f32 {
- // return foo;
- // }
- auto* foo_in = Param("foo", ty.f32(), Vector{Location(0_a)});
- Func("frag_main", Vector{foo_in}, ty.f32(),
- Vector{
- Return("foo"),
- },
- Vector{
- Stage(ast::PipelineStage::kFragment),
- },
- Vector{
- Location(1_a),
- });
-
- ASTPrinter& gen = SanitizeAndBuild();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-struct tint_symbol_1 {
- float foo [[user(locn0)]];
-};
-
-struct tint_symbol_2 {
- float value [[color(1)]];
-};
-
-float frag_main_inner(float foo) {
- return foo;
-}
-
-fragment tint_symbol_2 frag_main(tint_symbol_1 tint_symbol [[stage_in]]) {
- float const inner_result = frag_main_inner(tint_symbol.foo);
- tint_symbol_2 wrapper_result = {};
- wrapper_result.value = inner_result;
- return wrapper_result;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_Attribute_EntryPoint_WithInOut_Builtins) {
- // fn frag_main(@position(0) coord : vec4<f32>) -> @frag_depth f32 {
- // return coord.x;
- // }
- auto* coord_in = Param("coord", ty.vec4<f32>(), Vector{Builtin(core::BuiltinValue::kPosition)});
- Func("frag_main", Vector{coord_in}, ty.f32(),
- Vector{
- Return(MemberAccessor("coord", "x")),
- },
- Vector{
- Stage(ast::PipelineStage::kFragment),
- },
- Vector{
- Builtin(core::BuiltinValue::kFragDepth),
- });
-
- ASTPrinter& gen = SanitizeAndBuild();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-struct tint_symbol {
- float value [[depth(any)]];
-};
-
-float frag_main_inner(float4 coord) {
- return coord[0];
-}
-
-fragment tint_symbol frag_main(float4 coord [[position]]) {
- float const inner_result = frag_main_inner(coord);
- tint_symbol wrapper_result = {};
- wrapper_result.value = inner_result;
- return wrapper_result;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_Attribute_EntryPoint_SharedStruct_DifferentStages) {
- // struct Interface {
- // @location(1) col1 : f32;
- // @location(2) col2 : f32;
- // @builtin(position) pos : vec4<f32>;
- // };
- // fn vert_main() -> Interface {
- // return Interface(0.5, 0.25, vec4<f32>());
- // }
- // fn frag_main(colors : Interface) {
- // const r = colors.col1;
- // const g = colors.col2;
- // }
- auto* interface_struct =
- Structure("Interface",
- Vector{
- Member("col1", ty.f32(), Vector{Location(1_a)}),
- Member("col2", ty.f32(), Vector{Location(2_a)}),
- Member("pos", ty.vec4<f32>(), Vector{Builtin(core::BuiltinValue::kPosition)}),
- });
-
- Func("vert_main", tint::Empty, ty.Of(interface_struct),
- Vector{Return(Call(ty.Of(interface_struct), 0.5_f, 0.25_f, Call<vec4<f32>>()))},
- Vector{Stage(ast::PipelineStage::kVertex)});
-
- Func("frag_main", Vector{Param("colors", ty.Of(interface_struct))}, ty.void_(),
- Vector{
- WrapInStatement(Let("r", ty.f32(), MemberAccessor("colors", "col1"))),
- WrapInStatement(Let("g", ty.f32(), MemberAccessor("colors", "col2"))),
- },
- Vector{Stage(ast::PipelineStage::kFragment)});
-
- ASTPrinter& gen = SanitizeAndBuild();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-struct Interface {
- float col1;
- float col2;
- float4 pos;
-};
-
-struct tint_symbol {
- float col1 [[user(locn1)]];
- float col2 [[user(locn2)]];
- float4 pos [[position]];
-};
-
-Interface vert_main_inner() {
- Interface const tint_symbol_3 = Interface{.col1=0.5f, .col2=0.25f, .pos=float4(0.0f)};
- return tint_symbol_3;
-}
-
-vertex tint_symbol vert_main() {
- Interface const inner_result = vert_main_inner();
- tint_symbol wrapper_result = {};
- wrapper_result.col1 = inner_result.col1;
- wrapper_result.col2 = inner_result.col2;
- wrapper_result.pos = inner_result.pos;
- return wrapper_result;
-}
-
-struct tint_symbol_2 {
- float col1 [[user(locn1)]];
- float col2 [[user(locn2)]];
-};
-
-void frag_main_inner(Interface colors) {
- float const r = colors.col1;
- float const g = colors.col2;
-}
-
-fragment void frag_main(float4 pos [[position]], tint_symbol_2 tint_symbol_1 [[stage_in]]) {
- Interface const tint_symbol_4 = Interface{.col1=tint_symbol_1.col1, .col2=tint_symbol_1.col2, .pos=pos};
- frag_main_inner(tint_symbol_4);
- return;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_Attribute_EntryPoint_SharedStruct_HelperFunction) {
- // struct VertexOutput {
- // @builtin(position) pos : vec4<f32>;
- // };
- // fn foo(x : f32) -> VertexOutput {
- // return VertexOutput(vec4<f32>(x, x, x, 1.0));
- // }
- // fn vert_main1() -> VertexOutput {
- // return foo(0.5);
- // }
- // fn vert_main2() -> VertexOutput {
- // return foo(0.25);
- // }
- auto* vertex_output_struct =
- Structure("VertexOutput",
- Vector{
- Member("pos", ty.vec4<f32>(), Vector{Builtin(core::BuiltinValue::kPosition)}),
- });
-
- Func("foo", Vector{Param("x", ty.f32())}, ty.Of(vertex_output_struct),
- Vector{
- Return(Call(ty.Of(vertex_output_struct), Call<vec4<f32>>("x", "x", "x", 1_f))),
- });
- Func("vert_main1", tint::Empty, ty.Of(vertex_output_struct),
- Vector{Return(Expr(Call("foo", Expr(0.5_f))))},
- Vector{Stage(ast::PipelineStage::kVertex)});
-
- Func("vert_main2", tint::Empty, ty.Of(vertex_output_struct),
- Vector{Return(Expr(Call("foo", Expr(0.25_f))))},
- Vector{Stage(ast::PipelineStage::kVertex)});
-
- ASTPrinter& gen = SanitizeAndBuild();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-struct VertexOutput {
- float4 pos;
-};
-
-VertexOutput foo(float x) {
- VertexOutput const tint_symbol_2 = VertexOutput{.pos=float4(x, x, x, 1.0f)};
- return tint_symbol_2;
-}
-
-struct tint_symbol {
- float4 pos [[position]];
-};
-
-VertexOutput vert_main1_inner() {
- return foo(0.5f);
-}
-
-vertex tint_symbol vert_main1() {
- VertexOutput const inner_result = vert_main1_inner();
- tint_symbol wrapper_result = {};
- wrapper_result.pos = inner_result.pos;
- return wrapper_result;
-}
-
-struct tint_symbol_1 {
- float4 pos [[position]];
-};
-
-VertexOutput vert_main2_inner() {
- return foo(0.25f);
-}
-
-vertex tint_symbol_1 vert_main2() {
- VertexOutput const inner_result_1 = vert_main2_inner();
- tint_symbol_1 wrapper_result_1 = {};
- wrapper_result_1.pos = inner_result_1.pos;
- return wrapper_result_1;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_FunctionAttribute_EntryPoint_With_RW_StorageBuffer) {
- auto* s = Structure("Data", Vector{
- Member("a", ty.i32()),
- Member("b", ty.f32()),
- });
-
- GlobalVar("coord", ty.Of(s), core::AddressSpace::kStorage, core::Access::kReadWrite, Group(0_a),
- Binding(0_a));
-
- auto* var = Var("v", ty.f32(), MemberAccessor("coord", "b"));
-
- Func("frag_main", tint::Empty, ty.void_(),
- Vector{
- Decl(var),
- Return(),
- },
- Vector{
- Stage(ast::PipelineStage::kFragment),
- });
-
- ASTPrinter& gen = SanitizeAndBuild();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-struct Data {
- /* 0x0000 */ int a;
- /* 0x0004 */ float b;
-};
-
-fragment void frag_main(device Data* tint_symbol [[buffer(0)]]) {
- float v = (*(tint_symbol)).b;
- return;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_FunctionAttribute_EntryPoint_With_RO_StorageBuffer) {
- auto* s = Structure("Data", Vector{
- Member("a", ty.i32()),
- Member("b", ty.f32()),
- });
-
- GlobalVar("coord", ty.Of(s), core::AddressSpace::kStorage, core::Access::kRead, Group(0_a),
- Binding(0_a));
-
- auto* var = Var("v", ty.f32(), MemberAccessor("coord", "b"));
-
- Func("frag_main", tint::Empty, ty.void_(),
- Vector{
- Decl(var),
- Return(),
- },
- Vector{
- Stage(ast::PipelineStage::kFragment),
- });
-
- ASTPrinter& gen = SanitizeAndBuild();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-struct Data {
- /* 0x0000 */ int a;
- /* 0x0004 */ float b;
-};
-
-fragment void frag_main(const device Data* tint_symbol [[buffer(0)]]) {
- float v = (*(tint_symbol)).b;
- return;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_Attribute_Called_By_EntryPoint_With_Uniform) {
- auto* ubo_ty = Structure("UBO", Vector{Member("coord", ty.vec4<f32>())});
- auto* ubo =
- GlobalVar("ubo", ty.Of(ubo_ty), core::AddressSpace::kUniform, Group(0_a), Binding(0_a));
-
- Func("sub_func",
- Vector{
- Param("param", ty.f32()),
- },
- ty.f32(),
- Vector{
- Return(MemberAccessor(MemberAccessor(ubo, "coord"), "x")),
- });
-
- auto* var = Var("v", ty.f32(), Call("sub_func", 1_f));
-
- Func("frag_main", tint::Empty, ty.void_(),
- Vector{
- Decl(var),
- Return(),
- },
- Vector{
- Stage(ast::PipelineStage::kFragment),
- });
-
- ASTPrinter& gen = SanitizeAndBuild();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-struct UBO {
- /* 0x0000 */ float4 coord;
-};
-
-float sub_func(float param, const constant UBO* const tint_symbol) {
- return (*(tint_symbol)).coord[0];
-}
-
-fragment void frag_main(const constant UBO* tint_symbol_1 [[buffer(0)]]) {
- float v = sub_func(1.0f, tint_symbol_1);
- return;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_FunctionAttribute_Called_By_EntryPoint_With_RW_StorageBuffer) {
- auto* s = Structure("Data", Vector{
- Member("a", ty.i32()),
- Member("b", ty.f32()),
- });
-
- GlobalVar("coord", ty.Of(s), core::AddressSpace::kStorage, core::Access::kReadWrite, Group(0_a),
- Binding(0_a));
-
- Func("sub_func",
- Vector{
- Param("param", ty.f32()),
- },
- ty.f32(),
- Vector{
- Return(MemberAccessor("coord", "b")),
- });
-
- auto* var = Var("v", ty.f32(), Call("sub_func", 1_f));
-
- Func("frag_main", tint::Empty, ty.void_(),
- Vector{
- Decl(var),
- Return(),
- },
- Vector{
- Stage(ast::PipelineStage::kFragment),
- });
-
- ASTPrinter& gen = SanitizeAndBuild();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-struct Data {
- /* 0x0000 */ int a;
- /* 0x0004 */ float b;
-};
-
-float sub_func(float param, device Data* const tint_symbol) {
- return (*(tint_symbol)).b;
-}
-
-fragment void frag_main(device Data* tint_symbol_1 [[buffer(0)]]) {
- float v = sub_func(1.0f, tint_symbol_1);
- return;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_FunctionAttribute_Called_By_EntryPoint_With_RO_StorageBuffer) {
- auto* s = Structure("Data", Vector{
- Member("a", ty.i32()),
- Member("b", ty.f32()),
- });
-
- GlobalVar("coord", ty.Of(s), core::AddressSpace::kStorage, core::Access::kRead, Group(0_a),
- Binding(0_a));
-
- Func("sub_func",
- Vector{
- Param("param", ty.f32()),
- },
- ty.f32(),
- Vector{
- Return(MemberAccessor("coord", "b")),
- });
-
- auto* var = Var("v", ty.f32(), Call("sub_func", 1_f));
-
- Func("frag_main", tint::Empty, ty.void_(),
- Vector{
- Decl(var),
- Return(),
- },
- Vector{
- Stage(ast::PipelineStage::kFragment),
- });
-
- ASTPrinter& gen = SanitizeAndBuild();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-struct Data {
- /* 0x0000 */ int a;
- /* 0x0004 */ float b;
-};
-
-float sub_func(float param, const device Data* const tint_symbol) {
- return (*(tint_symbol)).b;
-}
-
-fragment void frag_main(const device Data* tint_symbol_1 [[buffer(0)]]) {
- float v = sub_func(1.0f, tint_symbol_1);
- return;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_Function_WithArrayParams) {
- Func("my_func",
- Vector{
- Param("a", ty.array<f32, 5>()),
- },
- ty.void_(),
- Vector{
- Return(),
- });
-
- ASTPrinter& gen = SanitizeAndBuild();
-
- gen.IncrementIndent();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"( #include <metal_stdlib>
-
- using namespace metal;
-
-template<typename T, size_t N>
-struct tint_array {
- const constant T& operator[](size_t i) const constant { return elements[i]; }
- device T& operator[](size_t i) device { return elements[i]; }
- const device T& operator[](size_t i) const device { return elements[i]; }
- thread T& operator[](size_t i) thread { return elements[i]; }
- const thread T& operator[](size_t i) const thread { return elements[i]; }
- threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
- const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
- T elements[N];
-};
-
- void my_func(tint_array<float, 5> a) {
- return;
- }
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_Function_WithArrayReturn) {
- Func("my_func", tint::Empty, ty.array<f32, 5>(),
- Vector{
- Return(Call(ty.array<f32, 5>())),
- });
-
- ASTPrinter& gen = SanitizeAndBuild();
-
- gen.IncrementIndent();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"( #include <metal_stdlib>
-
- using namespace metal;
-
-template<typename T, size_t N>
-struct tint_array {
- const constant T& operator[](size_t i) const constant { return elements[i]; }
- device T& operator[](size_t i) device { return elements[i]; }
- const device T& operator[](size_t i) const device { return elements[i]; }
- thread T& operator[](size_t i) thread { return elements[i]; }
- const thread T& operator[](size_t i) const thread { return elements[i]; }
- threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
- const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
- T elements[N];
-};
-
- tint_array<float, 5> my_func() {
- tint_array<float, 5> const tint_symbol = tint_array<float, 5>{};
- return tint_symbol;
- }
-
-)");
-}
-
-// https://crbug.com/tint/297
-TEST_F(MslASTPrinterTest, Emit_Function_Multiple_EntryPoint_With_Same_ModuleVar) {
- // struct Data {
- // d : f32;
- // };
- // @binding(0) @group(0) var<storage> data : Data;
- //
- // @compute @workgroup_size(1)
- // fn a() {
- // return;
- // }
- //
- // @compute @workgroup_size(1)
- // fn b() {
- // return;
- // }
-
- auto* s = Structure("Data", Vector{Member("d", ty.f32())});
-
- GlobalVar("data", ty.Of(s), core::AddressSpace::kStorage, core::Access::kReadWrite, Group(0_a),
- Binding(0_a));
-
- {
- auto* var = Var("v", ty.f32(), MemberAccessor("data", "d"));
-
- Func("a", tint::Empty, ty.void_(),
- Vector{
- Decl(var),
- Return(),
- },
- Vector{
- Stage(ast::PipelineStage::kCompute),
- WorkgroupSize(1_i),
- });
- }
-
- {
- auto* var = Var("v", ty.f32(), MemberAccessor("data", "d"));
-
- Func("b", tint::Empty, ty.void_(),
- Vector{
- Decl(var),
- Return(),
- },
- Vector{
- Stage(ast::PipelineStage::kCompute),
- WorkgroupSize(1_i),
- });
- }
-
- ASTPrinter& gen = SanitizeAndBuild();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-struct Data {
- /* 0x0000 */ float d;
-};
-
-kernel void a(device Data* tint_symbol [[buffer(0)]]) {
- float v = (*(tint_symbol)).d;
- return;
-}
-
-kernel void b(device Data* tint_symbol_1 [[buffer(0)]]) {
- float v = (*(tint_symbol_1)).d;
- return;
-}
-
-)");
-}
-
-} // namespace
-} // namespace tint::msl::writer
diff --git a/src/tint/lang/msl/writer/ast_printer/ast_printer.cc b/src/tint/lang/msl/writer/ast_printer/ast_printer.cc
deleted file mode 100644
index 39c1e69..0000000
--- a/src/tint/lang/msl/writer/ast_printer/ast_printer.cc
+++ /dev/null
@@ -1,3378 +0,0 @@
-// Copyright 2020 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/tint/lang/msl/writer/ast_printer/ast_printer.h"
-
-#include <cmath>
-#include <iomanip>
-#include <limits>
-#include <utility>
-#include <vector>
-
-#include "src/tint/api/common/binding_point.h"
-#include "src/tint/lang/core/constant/splat.h"
-#include "src/tint/lang/core/constant/value.h"
-#include "src/tint/lang/core/fluent_types.h"
-#include "src/tint/lang/core/type/array.h"
-#include "src/tint/lang/core/type/atomic.h"
-#include "src/tint/lang/core/type/bool.h"
-#include "src/tint/lang/core/type/depth_multisampled_texture.h"
-#include "src/tint/lang/core/type/depth_texture.h"
-#include "src/tint/lang/core/type/f16.h"
-#include "src/tint/lang/core/type/f32.h"
-#include "src/tint/lang/core/type/i32.h"
-#include "src/tint/lang/core/type/matrix.h"
-#include "src/tint/lang/core/type/multisampled_texture.h"
-#include "src/tint/lang/core/type/pointer.h"
-#include "src/tint/lang/core/type/sampled_texture.h"
-#include "src/tint/lang/core/type/storage_texture.h"
-#include "src/tint/lang/core/type/texture_dimension.h"
-#include "src/tint/lang/core/type/u32.h"
-#include "src/tint/lang/core/type/vector.h"
-#include "src/tint/lang/core/type/void.h"
-#include "src/tint/lang/msl/writer/ast_raise/module_scope_var_to_entry_point_param.h"
-#include "src/tint/lang/msl/writer/ast_raise/packed_vec3.h"
-#include "src/tint/lang/msl/writer/ast_raise/pixel_local.h"
-#include "src/tint/lang/msl/writer/ast_raise/quad_swap.h"
-#include "src/tint/lang/msl/writer/ast_raise/subgroup_ballot.h"
-#include "src/tint/lang/msl/writer/common/option_helpers.h"
-#include "src/tint/lang/msl/writer/common/printer_support.h"
-#include "src/tint/lang/wgsl/ast/alias.h"
-#include "src/tint/lang/wgsl/ast/bool_literal_expression.h"
-#include "src/tint/lang/wgsl/ast/call_statement.h"
-#include "src/tint/lang/wgsl/ast/float_literal_expression.h"
-#include "src/tint/lang/wgsl/ast/interpolate_attribute.h"
-#include "src/tint/lang/wgsl/ast/transform/array_length_from_uniform.h"
-#include "src/tint/lang/wgsl/ast/transform/binding_remapper.h"
-#include "src/tint/lang/wgsl/ast/transform/builtin_polyfill.h"
-#include "src/tint/lang/wgsl/ast/transform/canonicalize_entry_point_io.h"
-#include "src/tint/lang/wgsl/ast/transform/demote_to_helper.h"
-#include "src/tint/lang/wgsl/ast/transform/disable_uniformity_analysis.h"
-#include "src/tint/lang/wgsl/ast/transform/expand_compound_assignment.h"
-#include "src/tint/lang/wgsl/ast/transform/fold_constants.h"
-#include "src/tint/lang/wgsl/ast/transform/manager.h"
-#include "src/tint/lang/wgsl/ast/transform/multiplanar_external_texture.h"
-#include "src/tint/lang/wgsl/ast/transform/preserve_padding.h"
-#include "src/tint/lang/wgsl/ast/transform/promote_initializers_to_let.h"
-#include "src/tint/lang/wgsl/ast/transform/promote_side_effects_to_decl.h"
-#include "src/tint/lang/wgsl/ast/transform/remove_continue_in_switch.h"
-#include "src/tint/lang/wgsl/ast/transform/remove_phonies.h"
-#include "src/tint/lang/wgsl/ast/transform/robustness.h"
-#include "src/tint/lang/wgsl/ast/transform/simplify_pointers.h"
-#include "src/tint/lang/wgsl/ast/transform/unshadow.h"
-#include "src/tint/lang/wgsl/ast/transform/vectorize_scalar_matrix_initializers.h"
-#include "src/tint/lang/wgsl/ast/transform/vertex_pulling.h"
-#include "src/tint/lang/wgsl/ast/transform/zero_init_workgroup_memory.h"
-#include "src/tint/lang/wgsl/ast/variable_decl_statement.h"
-#include "src/tint/lang/wgsl/helpers/check_supported_extensions.h"
-#include "src/tint/lang/wgsl/sem/call.h"
-#include "src/tint/lang/wgsl/sem/function.h"
-#include "src/tint/lang/wgsl/sem/member_accessor_expression.h"
-#include "src/tint/lang/wgsl/sem/module.h"
-#include "src/tint/lang/wgsl/sem/struct.h"
-#include "src/tint/lang/wgsl/sem/switch_statement.h"
-#include "src/tint/lang/wgsl/sem/value_constructor.h"
-#include "src/tint/lang/wgsl/sem/value_conversion.h"
-#include "src/tint/lang/wgsl/sem/variable.h"
-#include "src/tint/utils/containers/map.h"
-#include "src/tint/utils/macros/defer.h"
-#include "src/tint/utils/macros/scoped_assignment.h"
-#include "src/tint/utils/rtti/switch.h"
-#include "src/tint/utils/text/string_stream.h"
-
-using namespace tint::core::fluent_types; // NOLINT
-
-namespace tint::msl::writer {
-namespace {
-
-bool last_is_break(const ast::BlockStatement* stmts) {
- return tint::IsAnyOf<ast::BreakStatement>(stmts->Last());
-}
-
-class ScopedBitCast {
- public:
- ScopedBitCast(ASTPrinter* generator,
- StringStream& stream,
- const core::type::Type* curr_type,
- const core::type::Type* target_type)
- : s(stream) {
- auto* target_vec_type = target_type->As<core::type::Vector>();
-
- // If we need to promote from scalar to vector, bitcast the scalar to the
- // vector element type.
- if (curr_type->Is<core::type::Scalar>() && target_vec_type) {
- target_type = target_vec_type->Type();
- }
-
- // Bit cast
- s << "as_type<";
- generator->EmitType(s, target_type);
- s << ">(";
- }
-
- ~ScopedBitCast() { s << ")"; }
-
- private:
- StringStream& s;
-};
-
-} // namespace
-
-SanitizedResult::SanitizedResult() = default;
-SanitizedResult::~SanitizedResult() = default;
-SanitizedResult::SanitizedResult(SanitizedResult&&) = default;
-
-SanitizedResult Sanitize(const Program& in, const Options& options) {
- ast::transform::Manager manager;
- ast::transform::DataMap data;
-
- manager.Add<ast::transform::FoldConstants>();
-
- manager.Add<ast::transform::DisableUniformityAnalysis>();
-
- // ExpandCompoundAssignment must come before BuiltinPolyfill
- manager.Add<ast::transform::ExpandCompoundAssignment>();
-
- manager.Add<ast::transform::PreservePadding>();
-
- manager.Add<ast::transform::Unshadow>();
-
- manager.Add<ast::transform::PromoteSideEffectsToDecl>();
-
- // VertexPulling must come before Robustness.
- if (options.vertex_pulling_config) {
- ast::transform::VertexPulling::Config config;
- config.pulling_group = options.vertex_pulling_config->pulling_group;
- config.vertex_state = options.vertex_pulling_config->vertex_state;
- manager.Add<ast::transform::VertexPulling>();
- data.Add<ast::transform::VertexPulling::Config>(std::move(config));
- }
-
- if (!options.disable_robustness) {
- // Robustness must come after PromoteSideEffectsToDecl
- // Robustness must come before BuiltinPolyfill and CanonicalizeEntryPointIO
- // Robustness must come before ArrayLengthFromUniform
- manager.Add<ast::transform::Robustness>();
- }
-
- tint::transform::multiplanar::BindingsMap multiplanar_map{};
- RemapperData remapper_data{};
- ArrayLengthFromUniformOptions array_length_from_uniform_options{};
- PopulateBindingRelatedOptions(options, remapper_data, multiplanar_map,
- array_length_from_uniform_options);
-
- manager.Add<ast::transform::BindingRemapper>();
- data.Add<ast::transform::BindingRemapper::Remappings>(
- remapper_data, std::unordered_map<BindingPoint, core::Access>{},
- /* allow_collisions */ true);
-
- // Note: it is more efficient for MultiplanarExternalTexture to come after Robustness
- // MultiplanarExternalTexture must come after BindingRemapper
- data.Add<ast::transform::MultiplanarExternalTexture::NewBindingPoints>(
- multiplanar_map, /* allow_collisions */ true);
- manager.Add<ast::transform::MultiplanarExternalTexture>();
-
- { // Builtin polyfills
- ast::transform::BuiltinPolyfill::Builtins polyfills;
- polyfills.acosh = ast::transform::BuiltinPolyfill::Level::kRangeCheck;
- polyfills.atanh = ast::transform::BuiltinPolyfill::Level::kRangeCheck;
- polyfills.bitshift_modulo = true; // crbug.com/tint/1543
- polyfills.clamp_int = true;
- polyfills.conv_f32_to_iu32 = true;
- polyfills.extract_bits = ast::transform::BuiltinPolyfill::Level::kClampParameters;
- polyfills.first_leading_bit = true;
- polyfills.first_trailing_bit = true;
- polyfills.fwidth_fine = true;
- polyfills.insert_bits = ast::transform::BuiltinPolyfill::Level::kClampParameters;
- polyfills.int_div_mod = !options.disable_polyfill_integer_div_mod;
- polyfills.sign_int = true;
- polyfills.texture_sample_base_clamp_to_edge_2d_f32 = true;
- polyfills.workgroup_uniform_load = true;
- polyfills.dot_4x8_packed = true;
- polyfills.pack_unpack_4x8 = true;
- polyfills.pack_4xu8_clamp = true;
- data.Add<ast::transform::BuiltinPolyfill::Config>(polyfills);
- manager.Add<ast::transform::BuiltinPolyfill>();
- }
-
- if (!options.disable_workgroup_init) {
- // ZeroInitWorkgroupMemory must come before CanonicalizeEntryPointIO as
- // ZeroInitWorkgroupMemory may inject new builtin parameters.
- manager.Add<ast::transform::ZeroInitWorkgroupMemory>();
- }
-
- {
- PixelLocal::Config cfg;
- for (auto it : options.pixel_local_attachments) {
- cfg.attachments.Add(it.first, it.second);
- }
- data.Add<PixelLocal::Config>(cfg);
- manager.Add<PixelLocal>();
- }
-
- // Build the configs for the internal CanonicalizeEntryPointIO transform.
- auto entry_point_io_cfg = ast::transform::CanonicalizeEntryPointIO::Config(
- ast::transform::CanonicalizeEntryPointIO::ShaderStyle::kMsl, options.fixed_sample_mask,
- options.emit_vertex_point_size);
- // CanonicalizeEntryPointIO must come after Robustness
- manager.Add<ast::transform::CanonicalizeEntryPointIO>();
- data.Add<ast::transform::CanonicalizeEntryPointIO::Config>(std::move(entry_point_io_cfg));
-
- manager.Add<ast::transform::PromoteInitializersToLet>();
- manager.Add<ast::transform::RemoveContinueInSwitch>();
-
- // DemoteToHelper must come after PromoteSideEffectsToDecl and ExpandCompoundAssignment.
- // TODO(crbug.com/tint/1752): This is only necessary for Metal versions older than 2.3.
- manager.Add<ast::transform::DemoteToHelper>();
-
- manager.Add<ast::transform::VectorizeScalarMatrixInitializers>();
- manager.Add<ast::transform::RemovePhonies>();
- manager.Add<ast::transform::SimplifyPointers>();
-
- // SubgroupBallot() must come after CanonicalizeEntryPointIO.
- manager.Add<SubgroupBallot>();
-
- // QuadSwap() must come after CanonicalizeEntryPointIO.
- manager.Add<QuadSwap>();
-
- // ArrayLengthFromUniform must come after SimplifyPointers, as
- // it assumes that the form of the array length argument is &var.array.
- manager.Add<ast::transform::ArrayLengthFromUniform>();
- // Build the config for the internal ArrayLengthFromUniform transform.
- ast::transform::ArrayLengthFromUniform::Config array_length_from_uniform_cfg(
- BindingPoint{0, array_length_from_uniform_options.ubo_binding});
- array_length_from_uniform_cfg.bindpoint_to_size_index =
- std::move(array_length_from_uniform_options.bindpoint_to_size_index);
- data.Add<ast::transform::ArrayLengthFromUniform::Config>(
- std::move(array_length_from_uniform_cfg));
-
- // PackedVec3 must come after ExpandCompoundAssignment.
- manager.Add<PackedVec3>();
- manager.Add<ModuleScopeVarToEntryPointParam>();
-
- SanitizedResult result;
- ast::transform::DataMap outputs;
- result.program = manager.Run(in, data, outputs);
- if (!result.program.IsValid()) {
- return result;
- }
- if (auto* res = outputs.Get<ast::transform::ArrayLengthFromUniform::Result>()) {
- result.needs_storage_buffer_sizes = !res->used_size_indices.empty();
- }
- return result;
-}
-
-ASTPrinter::ASTPrinter(const Program& program, const Options& options)
- : builder_(ProgramBuilder::Wrap(program)), options_(options) {}
-
-ASTPrinter::~ASTPrinter() = default;
-
-bool ASTPrinter::Generate() {
- if (!tint::wgsl::CheckSupportedExtensions(
- "MSL", builder_.AST(), diagnostics_,
- Vector{
- wgsl::Extension::kChromiumDisableUniformityAnalysis,
- wgsl::Extension::kChromiumExperimentalFramebufferFetch,
- wgsl::Extension::kChromiumExperimentalPixelLocal,
- wgsl::Extension::kChromiumInternalGraphite,
- wgsl::Extension::kChromiumInternalRelaxedUniformLayout,
- wgsl::Extension::kClipDistances,
- wgsl::Extension::kF16,
- wgsl::Extension::kDualSourceBlending,
- wgsl::Extension::kSubgroups,
- wgsl::Extension::kSubgroupsF16,
- })) {
- return false;
- }
-
- Line() << "#include <metal_stdlib>";
- Line();
- Line() << "using namespace metal;";
-
- auto helpers_insertion_point = current_buffer_->lines.size();
-
- auto* mod = builder_.Sem().Module();
- for (auto* decl : mod->DependencyOrderedDeclarations()) {
- bool ok = Switch(
- decl, //
- [&](const ast::Struct* str) {
- TINT_DEFER(Line());
- return EmitTypeDecl(TypeOf(str));
- },
- [&](const ast::Alias*) {
- return true; // folded away by the writer
- },
- [&](const ast::Const*) {
- return true; // Constants are embedded at their use
- },
- [&](const ast::Override*) {
- // Override is removed with SubstituteOverride
- diagnostics_.AddError(Source{})
- << "override-expressions should have been removed with the "
- "SubstituteOverride transform.";
- return false;
- },
- [&](const ast::Function* func) {
- TINT_DEFER(Line());
- if (func->IsEntryPoint()) {
- return EmitEntryPointFunction(func);
- }
- return EmitFunction(func);
- },
- [&](const ast::DiagnosticDirective*) {
- // Do nothing for diagnostic directives in MSL
- return true;
- },
- [&](const ast::Enable*) {
- // Do nothing for enabling extension in MSL
- return true;
- },
- [&](const ast::Requires*) {
- // Do nothing for requiring language features in MSL.
- return true;
- },
- [&](const ast::ConstAssert*) {
- return true; // Not emitted
- }, //
- TINT_ICE_ON_NO_MATCH);
- if (!ok) {
- return false;
- }
- }
-
- if (!invariant_define_name_.empty()) {
- // 'invariant' attribute requires MSL 2.1 or higher.
- // WGSL can ignore the invariant attribute on pre MSL 2.1 devices.
- // See: https://github.com/gpuweb/gpuweb/issues/893#issuecomment-745537465
- Line(&helpers_) << "#if __METAL_VERSION__ >= 210";
- Line(&helpers_) << "#define " << invariant_define_name_ << " [[invariant]]";
- Line(&helpers_) << "#else";
- Line(&helpers_) << "#define " << invariant_define_name_;
- Line(&helpers_) << "#endif";
- Line(&helpers_);
- }
-
- if (!helpers_.lines.empty()) {
- current_buffer_->Insert("", helpers_insertion_point++, 0);
- current_buffer_->Insert(helpers_, helpers_insertion_point++, 0);
- }
-
- return true;
-}
-
-bool ASTPrinter::EmitTypeDecl(const core::type::Type* ty) {
- if (auto* str = ty->As<core::type::Struct>()) {
- if (!EmitStructType(current_buffer_, str)) {
- return false;
- }
- } else {
- diagnostics_.AddError(Source{}) << "unknown alias type: " << ty->FriendlyName();
- return false;
- }
-
- return true;
-}
-
-bool ASTPrinter::EmitIndexAccessor(StringStream& out, const ast::IndexAccessorExpression* expr) {
- bool paren_lhs =
- !expr->object
- ->IsAnyOf<ast::AccessorExpression, ast::CallExpression, ast::IdentifierExpression>();
-
- if (paren_lhs) {
- out << "(";
- }
- if (!EmitExpression(out, expr->object)) {
- return false;
- }
- if (paren_lhs) {
- out << ")";
- }
-
- out << "[";
-
- if (!EmitExpression(out, expr->index)) {
- return false;
- }
- out << "]";
-
- return true;
-}
-
-bool ASTPrinter::EmitBitcastCall(StringStream& out, const ast::CallExpression* call) {
- auto* arg = call->args[0];
- auto* dst_type = TypeOf(call);
-
- out << "as_type<";
- if (!EmitType(out, dst_type)) {
- return false;
- }
-
- out << ">(";
- if (!EmitExpression(out, arg)) {
- return false;
- }
-
- out << ")";
- return true;
-}
-
-bool ASTPrinter::EmitAssign(const ast::AssignmentStatement* stmt) {
- auto out = Line();
-
- if (!EmitExpression(out, stmt->lhs)) {
- return false;
- }
-
- out << " = ";
-
- if (!EmitExpression(out, stmt->rhs)) {
- return false;
- }
-
- out << ";";
-
- return true;
-}
-
-bool ASTPrinter::EmitBinary(StringStream& out, const ast::BinaryExpression* expr) {
- auto emit_op = [&] {
- out << " ";
-
- switch (expr->op) {
- case core::BinaryOp::kAnd:
- out << "&";
- break;
- case core::BinaryOp::kOr:
- out << "|";
- break;
- case core::BinaryOp::kXor:
- out << "^";
- break;
- case core::BinaryOp::kLogicalAnd:
- out << "&&";
- break;
- case core::BinaryOp::kLogicalOr:
- out << "||";
- break;
- case core::BinaryOp::kEqual:
- out << "==";
- break;
- case core::BinaryOp::kNotEqual:
- out << "!=";
- break;
- case core::BinaryOp::kLessThan:
- out << "<";
- break;
- case core::BinaryOp::kGreaterThan:
- out << ">";
- break;
- case core::BinaryOp::kLessThanEqual:
- out << "<=";
- break;
- case core::BinaryOp::kGreaterThanEqual:
- out << ">=";
- break;
- case core::BinaryOp::kShiftLeft:
- out << "<<";
- break;
- case core::BinaryOp::kShiftRight:
- // TODO(dsinclair): MSL is based on C++14, and >> in C++14 has
- // implementation-defined behaviour for negative LHS. We may have to
- // generate extra code to implement WGSL-specified behaviour for
- // negative LHS.
- out << R"(>>)";
- break;
-
- case core::BinaryOp::kAdd:
- out << "+";
- break;
- case core::BinaryOp::kSubtract:
- out << "-";
- break;
- case core::BinaryOp::kMultiply:
- out << "*";
- break;
- case core::BinaryOp::kDivide:
- out << "/";
- break;
- case core::BinaryOp::kModulo:
- out << "%";
- break;
- }
- out << " ";
- return true;
- };
-
- auto signed_type_of = [&](const core::type::Type* ty) -> const core::type::Type* {
- if (ty->IsIntegerScalar()) {
- return builder_.create<core::type::I32>();
- } else if (auto* v = ty->As<core::type::Vector>()) {
- return builder_.create<core::type::Vector>(builder_.create<core::type::I32>(),
- v->Width());
- }
- return {};
- };
-
- auto unsigned_type_of = [&](const core::type::Type* ty) -> const core::type::Type* {
- if (ty->IsIntegerScalar()) {
- return builder_.create<core::type::U32>();
- } else if (auto* v = ty->As<core::type::Vector>()) {
- return builder_.create<core::type::Vector>(builder_.create<core::type::U32>(),
- v->Width());
- }
- return {};
- };
-
- auto* lhs_type = TypeOf(expr->lhs)->UnwrapRef();
- auto* rhs_type = TypeOf(expr->rhs)->UnwrapRef();
-
- // Handle fmod
- if (expr->op == core::BinaryOp::kModulo && lhs_type->IsFloatScalarOrVector()) {
- out << "fmod";
- ScopedParen sp(out);
- if (!EmitExpression(out, expr->lhs)) {
- return false;
- }
- out << ", ";
- if (!EmitExpression(out, expr->rhs)) {
- return false;
- }
- return true;
- }
-
- // Handle +/-/* of signed values
- if ((expr->IsAdd() || expr->IsSubtract() || expr->IsMultiply()) &&
- lhs_type->IsSignedIntegerScalarOrVector() && rhs_type->IsSignedIntegerScalarOrVector()) {
- // If lhs or rhs is a vector, use that type (support implicit scalar to
- // vector promotion)
- auto* target_type = lhs_type->Is<core::type::Vector>()
- ? lhs_type
- : (rhs_type->Is<core::type::Vector>() ? rhs_type : lhs_type);
-
- // WGSL defines behaviour for signed overflow, MSL does not. For these
- // cases, bitcast operands to unsigned, then cast result to signed.
- ScopedBitCast outer_int_cast(this, out, target_type, signed_type_of(target_type));
- ScopedParen sp(out);
- {
- ScopedBitCast lhs_uint_cast(this, out, lhs_type, unsigned_type_of(target_type));
- if (!EmitExpression(out, expr->lhs)) {
- return false;
- }
- }
- if (!emit_op()) {
- return false;
- }
- {
- ScopedBitCast rhs_uint_cast(this, out, rhs_type, unsigned_type_of(target_type));
- if (!EmitExpression(out, expr->rhs)) {
- return false;
- }
- }
- return true;
- }
-
- // Handle left bit shifting a signed value
- // TODO(crbug.com/tint/1077): This may not be necessary. The MSL spec
- // seems to imply that left shifting a signed value is treated the same as
- // left shifting an unsigned value, but we need to make sure.
- if (expr->IsShiftLeft() && lhs_type->IsSignedIntegerScalarOrVector()) {
- // Shift left: discards top bits, so convert first operand to unsigned
- // first, then convert result back to signed
- ScopedBitCast outer_int_cast(this, out, lhs_type, signed_type_of(lhs_type));
- ScopedParen sp(out);
- {
- ScopedBitCast lhs_uint_cast(this, out, lhs_type, unsigned_type_of(lhs_type));
- if (!EmitExpression(out, expr->lhs)) {
- return false;
- }
- }
- if (!emit_op()) {
- return false;
- }
- if (!EmitExpression(out, expr->rhs)) {
- return false;
- }
- return true;
- }
-
- // Handle '&' and '|' of booleans.
- if ((expr->IsAnd() || expr->IsOr()) && lhs_type->Is<core::type::Bool>()) {
- out << "bool";
- ScopedParen sp(out);
- if (!EmitExpression(out, expr->lhs)) {
- return false;
- }
- if (!emit_op()) {
- return false;
- }
- if (!EmitExpression(out, expr->rhs)) {
- return false;
- }
- return true;
- }
-
- // Emit as usual
- ScopedParen sp(out);
- if (!EmitExpression(out, expr->lhs)) {
- return false;
- }
- if (!emit_op()) {
- return false;
- }
- if (!EmitExpression(out, expr->rhs)) {
- return false;
- }
-
- return true;
-}
-
-bool ASTPrinter::EmitBreak(const ast::BreakStatement*) {
- Line() << "break;";
- return true;
-}
-
-bool ASTPrinter::EmitBreakIf(const ast::BreakIfStatement* b) {
- auto out = Line();
- out << "if (";
- if (!EmitExpression(out, b->condition)) {
- return false;
- }
- out << ") { break; }";
- return true;
-}
-
-bool ASTPrinter::EmitCall(StringStream& out, const ast::CallExpression* expr) {
- auto* call = builder_.Sem().Get<sem::Call>(expr);
- auto* target = call->Target();
- return Switch(
- target, //
- [&](const sem::Function* func) { return EmitFunctionCall(out, call, func); },
- [&](const sem::BuiltinFn* builtin) { return EmitBuiltinCall(out, call, builtin); },
- [&](const sem::ValueConversion* conv) { return EmitTypeConversion(out, call, conv); },
- [&](const sem::ValueConstructor* ctor) { return EmitTypeInitializer(out, call, ctor); }, //
- TINT_ICE_ON_NO_MATCH);
-}
-
-bool ASTPrinter::EmitFunctionCall(StringStream& out,
- const sem::Call* call,
- const sem::Function* fn) {
- if (ast::GetAttribute<SubgroupBallot::SimdBallot>(fn->Declaration()->attributes) != nullptr) {
- out << "as_type<uint2>((ulong)simd_ballot(";
- if (!EmitExpression(out, call->Arguments()[0]->Declaration())) {
- return false;
- }
- out << "))";
- return true;
- }
-
- if (ast::GetAttribute<QuadSwap::QuadShuffle>(fn->Declaration()->attributes) != nullptr) {
- out << "quad_shuffle(";
- if (!EmitExpression(out, call->Arguments()[0]->Declaration())) {
- return false;
- }
- out << ",";
- if (!EmitExpression(out, call->Arguments()[1]->Declaration())) {
- return false;
- }
- out << ")";
- return true;
- }
-
- out << fn->Declaration()->name->symbol.Name() << "(";
-
- bool first = true;
- for (auto* arg : call->Arguments()) {
- if (!first) {
- out << ", ";
- }
- first = false;
-
- if (!EmitExpression(out, arg->Declaration())) {
- return false;
- }
- }
-
- out << ")";
- return true;
-}
-
-bool ASTPrinter::EmitBuiltinCall(StringStream& out,
- const sem::Call* call,
- const sem::BuiltinFn* builtin) {
- auto* expr = call->Declaration();
- if (builtin->IsAtomic()) {
- return EmitAtomicCall(out, expr, builtin);
- }
- if (builtin->IsTexture()) {
- return EmitTextureCall(out, call, builtin);
- }
-
- auto name = generate_builtin_name(builtin);
-
- switch (builtin->Fn()) {
- case wgsl::BuiltinFn::kBitcast:
- return EmitBitcastCall(out, expr);
- case wgsl::BuiltinFn::kDot:
- return EmitDotCall(out, expr, builtin);
- case wgsl::BuiltinFn::kModf:
- return EmitModfCall(out, expr, builtin);
- case wgsl::BuiltinFn::kFrexp:
- return EmitFrexpCall(out, expr, builtin);
- case wgsl::BuiltinFn::kDegrees:
- return EmitDegreesCall(out, expr, builtin);
- case wgsl::BuiltinFn::kRadians:
- return EmitRadiansCall(out, expr, builtin);
-
- case wgsl::BuiltinFn::kPack2X16Float:
- case wgsl::BuiltinFn::kUnpack2X16Float: {
- if (builtin->Fn() == wgsl::BuiltinFn::kPack2X16Float) {
- out << "as_type<uint>(half2(";
- } else {
- out << "float2(as_type<half2>(";
- }
- if (!EmitExpression(out, expr->args[0])) {
- return false;
- }
- out << "))";
- return true;
- }
- case wgsl::BuiltinFn::kQuantizeToF16: {
- std::string width = "";
- if (auto* vec = builtin->ReturnType()->As<core::type::Vector>()) {
- width = std::to_string(vec->Width());
- }
- out << "float" << width << "(half" << width << "(";
- if (!EmitExpression(out, expr->args[0])) {
- return false;
- }
- out << "))";
- return true;
- }
- // TODO(crbug.com/tint/661): Combine sequential barriers to a single
- // instruction.
- case wgsl::BuiltinFn::kStorageBarrier: {
- out << "threadgroup_barrier(mem_flags::mem_device)";
- return true;
- }
- case wgsl::BuiltinFn::kWorkgroupBarrier: {
- out << "threadgroup_barrier(mem_flags::mem_threadgroup)";
- return true;
- }
- case wgsl::BuiltinFn::kTextureBarrier: {
- out << "threadgroup_barrier(mem_flags::mem_texture)";
- return true;
- }
-
- case wgsl::BuiltinFn::kLength: {
- auto* sem = builder_.Sem().GetVal(expr->args[0]);
- if (sem->Type()->UnwrapRef()->Is<core::type::Scalar>()) {
- // Emulate scalar overload using fabs(x).
- name = "fabs";
- }
- break;
- }
-
- case wgsl::BuiltinFn::kDistance: {
- auto* sem = builder_.Sem().GetVal(expr->args[0]);
- if (sem->Type()->UnwrapRef()->Is<core::type::Scalar>()) {
- // Emulate scalar overload using fabs(x - y);
- out << "fabs";
- ScopedParen sp(out);
- if (!EmitExpression(out, expr->args[0])) {
- return false;
- }
- out << " - ";
- if (!EmitExpression(out, expr->args[1])) {
- return false;
- }
- return true;
- }
- break;
- }
-
- case wgsl::BuiltinFn::kSubgroupElect: {
- out << "simd_is_first()";
- return true;
- }
-
- case wgsl::BuiltinFn::kSubgroupBroadcast: {
- // The lane argument is ushort.
- out << "simd_broadcast(";
- if (!EmitExpression(out, expr->args[0])) {
- return false;
- }
- out << ",ushort(";
- if (!EmitExpression(out, expr->args[1])) {
- return false;
- }
- out << "))";
- return true;
- }
-
- case wgsl::BuiltinFn::kSubgroupBroadcastFirst: {
- out << "simd_broadcast_first(";
- if (!EmitExpression(out, expr->args[0])) {
- return false;
- }
- out << ")";
- return true;
- }
-
- case wgsl::BuiltinFn::kSubgroupShuffle: {
- out << "simd_shuffle(";
- if (!EmitExpression(out, expr->args[0])) {
- return false;
- }
- out << ",";
- if (!EmitExpression(out, expr->args[1])) {
- return false;
- }
- out << ")";
- return true;
- }
-
- case wgsl::BuiltinFn::kSubgroupShuffleXor: {
- out << "simd_shuffle_xor(";
- if (!EmitExpression(out, expr->args[0])) {
- return false;
- }
- out << ",";
- if (!EmitExpression(out, expr->args[1])) {
- return false;
- }
- out << ")";
- return true;
- }
-
- case wgsl::BuiltinFn::kSubgroupShuffleUp: {
- out << "simd_shuffle_up(";
- if (!EmitExpression(out, expr->args[0])) {
- return false;
- }
- out << ",";
- if (!EmitExpression(out, expr->args[1])) {
- return false;
- }
- out << ")";
- return true;
- }
-
- case wgsl::BuiltinFn::kSubgroupShuffleDown: {
- out << "simd_shuffle_down(";
- if (!EmitExpression(out, expr->args[0])) {
- return false;
- }
- out << ",";
- if (!EmitExpression(out, expr->args[1])) {
- return false;
- }
- out << ")";
- return true;
- }
-
- case wgsl::BuiltinFn::kSubgroupAdd: {
- out << "simd_sum(";
- if (!EmitExpression(out, expr->args[0])) {
- return false;
- }
- out << ")";
- return true;
- }
-
- case wgsl::BuiltinFn::kSubgroupInclusiveAdd: {
- out << "simd_prefix_inclusive_sum(";
- if (!EmitExpression(out, expr->args[0])) {
- return false;
- }
- out << ")";
- return true;
- }
-
- case wgsl::BuiltinFn::kSubgroupExclusiveAdd: {
- out << "simd_prefix_exclusive_sum(";
- if (!EmitExpression(out, expr->args[0])) {
- return false;
- }
- out << ")";
- return true;
- }
-
- case wgsl::BuiltinFn::kSubgroupMul: {
- out << "simd_product(";
- if (!EmitExpression(out, expr->args[0])) {
- return false;
- }
- out << ")";
- return true;
- }
-
- case wgsl::BuiltinFn::kSubgroupInclusiveMul: {
- out << "simd_prefix_inclusive_product(";
- if (!EmitExpression(out, expr->args[0])) {
- return false;
- }
- out << ")";
- return true;
- }
-
- case wgsl::BuiltinFn::kSubgroupExclusiveMul: {
- out << "simd_prefix_exclusive_product(";
- if (!EmitExpression(out, expr->args[0])) {
- return false;
- }
- out << ")";
- return true;
- }
-
- case wgsl::BuiltinFn::kSubgroupAnd: {
- out << "simd_and(";
- if (!EmitExpression(out, expr->args[0])) {
- return false;
- }
- out << ")";
- return true;
- }
-
- case wgsl::BuiltinFn::kSubgroupOr: {
- out << "simd_or(";
- if (!EmitExpression(out, expr->args[0])) {
- return false;
- }
- out << ")";
- return true;
- }
-
- case wgsl::BuiltinFn::kSubgroupXor: {
- out << "simd_xor(";
- if (!EmitExpression(out, expr->args[0])) {
- return false;
- }
- out << ")";
- return true;
- }
-
- case wgsl::BuiltinFn::kSubgroupMin: {
- out << "simd_min(";
- if (!EmitExpression(out, expr->args[0])) {
- return false;
- }
- out << ")";
- return true;
- }
-
- case wgsl::BuiltinFn::kSubgroupMax: {
- out << "simd_max(";
- if (!EmitExpression(out, expr->args[0])) {
- return false;
- }
- out << ")";
- return true;
- }
-
- case wgsl::BuiltinFn::kSubgroupAll: {
- out << "simd_all(";
- if (!EmitExpression(out, expr->args[0])) {
- return false;
- }
- out << ")";
- return true;
- }
-
- case wgsl::BuiltinFn::kSubgroupAny: {
- out << "simd_any(";
- if (!EmitExpression(out, expr->args[0])) {
- return false;
- }
- out << ")";
- return true;
- }
-
- case wgsl::BuiltinFn::kQuadBroadcast: {
- out << "quad_broadcast(";
- if (!EmitExpression(out, expr->args[0])) {
- return false;
- }
- out << ",";
- if (!EmitExpression(out, expr->args[1])) {
- return false;
- }
- out << ")";
- return true;
- }
-
- default:
- break;
- }
-
- if (name.empty()) {
- return false;
- }
-
- out << name << "(";
-
- bool first = true;
- for (auto* arg : expr->args) {
- if (!first) {
- out << ", ";
- }
- first = false;
-
- if (!EmitExpression(out, arg)) {
- return false;
- }
- }
-
- out << ")";
- return true;
-}
-
-bool ASTPrinter::EmitTypeConversion(StringStream& out,
- const sem::Call* call,
- const sem::ValueConversion* conv) {
- if (!EmitType(out, conv->Target())) {
- return false;
- }
- out << "(";
-
- if (!EmitExpression(out, call->Arguments()[0]->Declaration())) {
- return false;
- }
-
- out << ")";
- return true;
-}
-
-bool ASTPrinter::EmitTypeInitializer(StringStream& out,
- const sem::Call* call,
- const sem::ValueConstructor* ctor) {
- auto* type = ctor->ReturnType();
-
- const char* terminator = ")";
- TINT_DEFER(out << terminator);
-
- bool ok = Switch(
- type,
- [&](const core::type::Array*) {
- if (!EmitType(out, type)) {
- return false;
- }
- out << "{";
- terminator = "}";
- return true;
- },
- [&](const core::type::Struct*) {
- if (!EmitType(out, type)) {
- return false;
- }
- out << "{";
- terminator = "}";
- return true;
- },
- [&](Default) {
- if (!EmitType(out, type)) {
- return false;
- }
- out << "(";
- return true;
- });
- if (!ok) {
- return false;
- }
-
- size_t i = 0;
- for (auto* arg : call->Arguments()) {
- if (i > 0) {
- out << ", ";
- }
-
- if (auto* struct_ty = type->As<core::type::Struct>()) {
- // Emit field designators for structures to account for padding members.
- auto name = struct_ty->Members()[i]->Name().Name();
- out << "." << name << "=";
- }
-
- if (!EmitExpression(out, arg->Declaration())) {
- return false;
- }
-
- i++;
- }
-
- return true;
-}
-
-bool ASTPrinter::EmitAtomicCall(StringStream& out,
- const ast::CallExpression* expr,
- const sem::BuiltinFn* builtin) {
- auto call = [&](const std::string& name, bool append_memory_order_relaxed) {
- out << name;
- {
- ScopedParen sp(out);
- for (size_t i = 0; i < expr->args.Length(); i++) {
- auto* arg = expr->args[i];
- if (i > 0) {
- out << ", ";
- }
- if (!EmitExpression(out, arg)) {
- return false;
- }
- }
- if (append_memory_order_relaxed) {
- out << ", memory_order_relaxed";
- }
- }
- return true;
- };
-
- switch (builtin->Fn()) {
- case wgsl::BuiltinFn::kAtomicLoad:
- return call("atomic_load_explicit", true);
-
- case wgsl::BuiltinFn::kAtomicStore:
- return call("atomic_store_explicit", true);
-
- case wgsl::BuiltinFn::kAtomicAdd:
- return call("atomic_fetch_add_explicit", true);
-
- case wgsl::BuiltinFn::kAtomicSub:
- return call("atomic_fetch_sub_explicit", true);
-
- case wgsl::BuiltinFn::kAtomicMax:
- return call("atomic_fetch_max_explicit", true);
-
- case wgsl::BuiltinFn::kAtomicMin:
- return call("atomic_fetch_min_explicit", true);
-
- case wgsl::BuiltinFn::kAtomicAnd:
- return call("atomic_fetch_and_explicit", true);
-
- case wgsl::BuiltinFn::kAtomicOr:
- return call("atomic_fetch_or_explicit", true);
-
- case wgsl::BuiltinFn::kAtomicXor:
- return call("atomic_fetch_xor_explicit", true);
-
- case wgsl::BuiltinFn::kAtomicExchange:
- return call("atomic_exchange_explicit", true);
-
- case wgsl::BuiltinFn::kAtomicCompareExchangeWeak: {
- auto* ptr_ty = TypeOf(expr->args[0])->UnwrapRef()->As<core::type::Pointer>();
- auto sc = ptr_ty->AddressSpace();
- auto* str = builtin->ReturnType()->As<core::type::Struct>();
-
- auto func = tint::GetOrAdd(
- atomicCompareExchangeWeak_, ACEWKeyType{{sc, str}}, [&]() -> std::string {
- if (!EmitStructType(&helpers_,
- builtin->ReturnType()->As<core::type::Struct>())) {
- return "";
- }
-
- auto name = UniqueIdentifier("atomicCompareExchangeWeak");
- auto& buf = helpers_;
- auto* atomic_ty = builtin->Parameters()[0]->Type();
- auto* arg_ty = builtin->Parameters()[1]->Type();
-
- {
- auto f = Line(&buf);
- auto str_name = StructName(builtin->ReturnType()->As<core::type::Struct>());
- f << str_name << " " << name << "(";
- if (!EmitTypeAndName(f, atomic_ty, "atomic")) {
- return "";
- }
- f << ", ";
- if (!EmitTypeAndName(f, arg_ty, "compare")) {
- return "";
- }
- f << ", ";
- if (!EmitTypeAndName(f, arg_ty, "value")) {
- return "";
- }
- f << ") {";
- }
-
- buf.IncrementIndent();
- TINT_DEFER({
- buf.DecrementIndent();
- Line(&buf) << "}";
- Line(&buf);
- });
-
- {
- auto f = Line(&buf);
- if (!EmitTypeAndName(f, arg_ty, "old_value")) {
- return "";
- }
- f << " = compare;";
- }
- Line(&buf) << "bool exchanged = "
- "atomic_compare_exchange_weak_explicit(atomic, "
- "&old_value, value, memory_order_relaxed, "
- "memory_order_relaxed);";
- Line(&buf) << "return {old_value, exchanged};";
- return name;
- });
-
- if (func.empty()) {
- return false;
- }
- return call(func, false);
- }
-
- default:
- break;
- }
-
- TINT_UNREACHABLE() << "unsupported atomic builtin: " << builtin->Fn();
-}
-
-bool ASTPrinter::EmitTextureCall(StringStream& out,
- const sem::Call* call,
- const sem::BuiltinFn* builtin) {
- using Usage = core::ParameterUsage;
-
- auto& signature = builtin->Signature();
- auto* expr = call->Declaration();
- auto& arguments = call->Arguments();
-
- // Returns the argument with the given usage
- auto arg = [&](Usage usage) {
- int idx = signature.IndexOf(usage);
- return (idx >= 0) ? arguments[static_cast<size_t>(idx)] : nullptr;
- };
-
- auto* texture = arg(Usage::kTexture)->Declaration();
- if (DAWN_UNLIKELY(!texture)) {
- TINT_ICE() << "missing texture arg";
- }
-
- auto* texture_type = TypeOf(texture)->UnwrapRef()->As<core::type::Texture>();
-
- // Helper to emit the texture expression, wrapped in parentheses if the
- // expression includes an operator with lower precedence than the member
- // accessor used for the function calls.
- auto texture_expr = [&] {
- bool paren_lhs = !texture->IsAnyOf<ast::AccessorExpression, ast::CallExpression,
- ast::IdentifierExpression>();
- if (paren_lhs) {
- out << "(";
- }
- if (!EmitExpression(out, texture)) {
- return false;
- }
- if (paren_lhs) {
- out << ")";
- }
- return true;
- };
-
- // MSL requires that `lod` is a constant 0 for 1D textures.
- bool level_is_constant_zero = texture_type->Dim() == core::type::TextureDimension::k1d;
-
- switch (builtin->Fn()) {
- case wgsl::BuiltinFn::kTextureDimensions: {
- std::vector<const char*> dims;
- switch (texture_type->Dim()) {
- case core::type::TextureDimension::kNone:
- diagnostics_.AddError(Source{}) << "texture dimension is kNone";
- return false;
- case core::type::TextureDimension::k1d:
- dims = {"width"};
- break;
- case core::type::TextureDimension::k2d:
- case core::type::TextureDimension::k2dArray:
- case core::type::TextureDimension::kCube:
- case core::type::TextureDimension::kCubeArray:
- dims = {"width", "height"};
- break;
- case core::type::TextureDimension::k3d:
- dims = {"width", "height", "depth"};
- break;
- }
-
- auto get_dim = [&](const char* name) {
- if (!texture_expr()) {
- return false;
- }
- out << ".get_" << name << "(";
- if (level_is_constant_zero) {
- out << "0";
- } else {
- if (auto* level = arg(Usage::kLevel)) {
- if (!EmitExpression(out, level->Declaration())) {
- return false;
- }
- }
- }
- out << ")";
- return true;
- };
-
- if (dims.size() == 1) {
- get_dim(dims[0]);
- } else {
- EmitType(out, TypeOf(expr)->UnwrapRef());
- out << "(";
- for (size_t i = 0; i < dims.size(); i++) {
- if (i > 0) {
- out << ", ";
- }
- get_dim(dims[i]);
- }
- out << ")";
- }
- return true;
- }
- case wgsl::BuiltinFn::kTextureNumLayers: {
- if (!texture_expr()) {
- return false;
- }
- out << ".get_array_size()";
- return true;
- }
- case wgsl::BuiltinFn::kTextureNumLevels: {
- if (!texture_expr()) {
- return false;
- }
- out << ".get_num_mip_levels()";
- return true;
- }
- case wgsl::BuiltinFn::kTextureNumSamples: {
- if (!texture_expr()) {
- return false;
- }
- out << ".get_num_samples()";
- return true;
- }
- default:
- break;
- }
-
- if (!texture_expr()) {
- return false;
- }
-
- bool lod_param_is_named = true;
- bool is_gather_or_sample = false;
- switch (builtin->Fn()) {
- case wgsl::BuiltinFn::kTextureSample:
- case wgsl::BuiltinFn::kTextureSampleBias:
- case wgsl::BuiltinFn::kTextureSampleLevel:
- case wgsl::BuiltinFn::kTextureSampleGrad:
- out << ".sample(";
- is_gather_or_sample = true;
- break;
- case wgsl::BuiltinFn::kTextureSampleCompare:
- case wgsl::BuiltinFn::kTextureSampleCompareLevel:
- out << ".sample_compare(";
- is_gather_or_sample = true;
- break;
- case wgsl::BuiltinFn::kTextureGather:
- out << ".gather(";
- is_gather_or_sample = true;
- break;
- case wgsl::BuiltinFn::kTextureGatherCompare:
- out << ".gather_compare(";
- is_gather_or_sample = true;
- break;
- case wgsl::BuiltinFn::kTextureLoad:
- out << ".read(";
- lod_param_is_named = false;
- break;
- case wgsl::BuiltinFn::kTextureStore:
- out << ".write(";
- break;
- default:
- TINT_UNREACHABLE() << "Unhandled texture builtin '" << builtin->str() << "'";
- }
-
- bool first_arg = true;
- auto maybe_write_comma = [&] {
- if (!first_arg) {
- out << ", ";
- }
- first_arg = false;
- };
-
- for (auto usage : {Usage::kValue, Usage::kSampler, Usage::kCoords, Usage::kArrayIndex,
- Usage::kDepthRef, Usage::kSampleIndex}) {
- if (auto* e = arg(usage)) {
- maybe_write_comma();
-
- // Cast the coordinates to unsigned integers if necessary.
- bool inside_params = false;
- if (usage == Usage::kCoords && e->Type()->UnwrapRef()->IsIntegerScalarOrVector()) {
- inside_params = true;
- switch (texture_type->Dim()) {
- case core::type::TextureDimension::k1d:
- out << "uint(";
- break;
- case core::type::TextureDimension::k2d:
- case core::type::TextureDimension::k2dArray:
- out << "uint2(";
- break;
- case core::type::TextureDimension::k3d:
- out << "uint3(";
-
- break;
- default:
- TINT_ICE() << "unhandled texture dimensionality";
- }
- } else if (usage == Usage::kArrayIndex &&
- e->Type()->UnwrapRef()->IsSignedIntegerScalar() && is_gather_or_sample) {
- // Array index access for signed integers is zero lower bound clamped to emulate the
- // behavior of other platforms. See crbug.com/202355.
- out << "max(0, ";
- inside_params = true;
- }
-
- if (!EmitExpression(out, e->Declaration())) {
- return false;
- }
-
- if (inside_params) {
- out << ")";
- }
- }
- }
-
- if (auto* bias = arg(Usage::kBias)) {
- maybe_write_comma();
- out << "bias(";
- if (!EmitExpression(out, bias->Declaration())) {
- return false;
- }
- out << ")";
- }
- if (auto* level = arg(Usage::kLevel)) {
- maybe_write_comma();
- if (lod_param_is_named) {
- out << "level(";
- }
- if (level_is_constant_zero) {
- out << "0";
- } else {
- if (!EmitExpression(out, level->Declaration())) {
- return false;
- }
- }
- if (lod_param_is_named) {
- out << ")";
- }
- }
- if (builtin->Fn() == wgsl::BuiltinFn::kTextureSampleCompareLevel) {
- maybe_write_comma();
- out << "level(0)";
- }
- if (auto* ddx = arg(Usage::kDdx)) {
- auto dim = texture_type->Dim();
- switch (dim) {
- case core::type::TextureDimension::k2d:
- case core::type::TextureDimension::k2dArray:
- maybe_write_comma();
- out << "gradient2d(";
- break;
- case core::type::TextureDimension::k3d:
- maybe_write_comma();
- out << "gradient3d(";
- break;
- case core::type::TextureDimension::kCube:
- case core::type::TextureDimension::kCubeArray:
- maybe_write_comma();
- out << "gradientcube(";
- break;
- default: {
- diagnostics_.AddError(Source{})
- << "MSL does not support gradients for " << dim << " textures";
- return false;
- }
- }
- if (!EmitExpression(out, ddx->Declaration())) {
- return false;
- }
- out << ", ";
- if (!EmitExpression(out, arg(Usage::kDdy)->Declaration())) {
- return false;
- }
- out << ")";
- }
-
- bool has_offset = false;
- if (auto* offset = arg(Usage::kOffset)) {
- has_offset = true;
- maybe_write_comma();
- if (!EmitExpression(out, offset->Declaration())) {
- return false;
- }
- }
-
- if (auto* component = arg(Usage::kComponent)) {
- maybe_write_comma();
- if (!has_offset) {
- // offset argument may need to be provided if we have a component.
- switch (texture_type->Dim()) {
- case core::type::TextureDimension::k2d:
- case core::type::TextureDimension::k2dArray:
- out << "int2(0), ";
- break;
- default:
- break; // Other texture dimensions don't have an offset
- }
- }
- auto c = component->ConstantValue()->ValueAs<AInt>();
- switch (c.value) {
- case 0:
- out << "component::x";
- break;
- case 1:
- out << "component::y";
- break;
- case 2:
- out << "component::z";
- break;
- case 3:
- out << "component::w";
- break;
- default:
- TINT_ICE() << "invalid textureGather component: " << c;
- }
- }
-
- out << ")";
-
- // If this is a `textureStore()` for a read-write texture, add a fence to ensure that the
- // written values are visible to subsequent reads from the same thread.
- if (auto* storage = texture_type->As<core::type::StorageTexture>();
- builtin->Fn() == wgsl::BuiltinFn::kTextureStore &&
- storage->Access() == core::Access::kReadWrite) {
- out << "; ";
- texture_expr();
- out << ".fence()";
- }
-
- return true;
-}
-
-bool ASTPrinter::EmitDotCall(StringStream& out,
- const ast::CallExpression* expr,
- const sem::BuiltinFn* builtin) {
- auto* vec_ty = builtin->Parameters()[0]->Type()->As<core::type::Vector>();
- std::string fn = "dot";
- if (vec_ty->Type()->IsIntegerScalar()) {
- // MSL does not have a builtin for dot() with integer vector types.
- // Generate the helper function if it hasn't been created already
- fn = tint::GetOrAdd(int_dot_funcs_, vec_ty->Width(), [&]() -> std::string {
- TextBuffer b;
- TINT_DEFER(helpers_.Append(b));
-
- auto fn_name = UniqueIdentifier("tint_dot" + std::to_string(vec_ty->Width()));
- auto v = "vec<T," + std::to_string(vec_ty->Width()) + ">";
-
- Line(&b) << "template<typename T>";
- Line(&b) << "T " << fn_name << "(" << v << " a, " << v << " b) {";
- {
- auto l = Line(&b);
- l << " return ";
- for (uint32_t i = 0; i < vec_ty->Width(); i++) {
- if (i > 0) {
- l << " + ";
- }
- l << "a[" << i << "]*b[" << i << "]";
- }
- l << ";";
- }
- Line(&b) << "}";
- return fn_name;
- });
- }
-
- out << fn << "(";
- if (!EmitExpression(out, expr->args[0])) {
- return false;
- }
- out << ", ";
- if (!EmitExpression(out, expr->args[1])) {
- return false;
- }
- out << ")";
- return true;
-}
-
-bool ASTPrinter::EmitModfCall(StringStream& out,
- const ast::CallExpression* expr,
- const sem::BuiltinFn* builtin) {
- return CallBuiltinHelper(
- out, expr, builtin, [&](TextBuffer* b, const std::vector<std::string>& params) {
- auto* ty = builtin->Parameters()[0]->Type();
- auto in = params[0];
-
- std::string width;
- if (auto* vec = ty->As<core::type::Vector>()) {
- width = std::to_string(vec->Width());
- }
-
- // Emit the builtin return type unique to this overload. This does not
- // exist in the AST, so it will not be generated in Generate().
- if (!EmitStructType(&helpers_, builtin->ReturnType()->As<core::type::Struct>())) {
- return false;
- }
-
- Line(b) << StructName(builtin->ReturnType()->As<core::type::Struct>()) << " result;";
- Line(b) << "result.fract = modf(" << in << ", result.whole);";
- Line(b) << "return result;";
- return true;
- });
-}
-
-bool ASTPrinter::EmitFrexpCall(StringStream& out,
- const ast::CallExpression* expr,
- const sem::BuiltinFn* builtin) {
- return CallBuiltinHelper(
- out, expr, builtin, [&](TextBuffer* b, const std::vector<std::string>& params) {
- auto* ty = builtin->Parameters()[0]->Type();
- auto in = params[0];
-
- std::string width;
- if (auto* vec = ty->As<core::type::Vector>()) {
- width = std::to_string(vec->Width());
- }
-
- // Emit the builtin return type unique to this overload. This does not
- // exist in the AST, so it will not be generated in Generate().
- if (!EmitStructType(&helpers_, builtin->ReturnType()->As<core::type::Struct>())) {
- return false;
- }
-
- Line(b) << StructName(builtin->ReturnType()->As<core::type::Struct>()) << " result;";
- Line(b) << "result.fract = frexp(" << in << ", result.exp);";
- Line(b) << "return result;";
- return true;
- });
-}
-
-bool ASTPrinter::EmitDegreesCall(StringStream& out,
- const ast::CallExpression* expr,
- const sem::BuiltinFn* builtin) {
- return CallBuiltinHelper(out, expr, builtin,
- [&](TextBuffer* b, const std::vector<std::string>& params) {
- Line(b) << "return " << params[0] << " * " << std::setprecision(20)
- << sem::kRadToDeg << ";";
- return true;
- });
-}
-
-bool ASTPrinter::EmitRadiansCall(StringStream& out,
- const ast::CallExpression* expr,
- const sem::BuiltinFn* builtin) {
- return CallBuiltinHelper(out, expr, builtin,
- [&](TextBuffer* b, const std::vector<std::string>& params) {
- Line(b) << "return " << params[0] << " * " << std::setprecision(20)
- << sem::kDegToRad << ";";
- return true;
- });
-}
-
-std::string ASTPrinter::generate_builtin_name(const sem::BuiltinFn* builtin) {
- std::string out = "";
- switch (builtin->Fn()) {
- case wgsl::BuiltinFn::kAcos:
- case wgsl::BuiltinFn::kAcosh:
- case wgsl::BuiltinFn::kAll:
- case wgsl::BuiltinFn::kAny:
- case wgsl::BuiltinFn::kAsin:
- case wgsl::BuiltinFn::kAsinh:
- case wgsl::BuiltinFn::kAtanh:
- case wgsl::BuiltinFn::kAtan:
- case wgsl::BuiltinFn::kAtan2:
- case wgsl::BuiltinFn::kCeil:
- case wgsl::BuiltinFn::kCos:
- case wgsl::BuiltinFn::kCosh:
- case wgsl::BuiltinFn::kCross:
- case wgsl::BuiltinFn::kDeterminant:
- case wgsl::BuiltinFn::kDistance:
- case wgsl::BuiltinFn::kDot:
- case wgsl::BuiltinFn::kExp:
- case wgsl::BuiltinFn::kExp2:
- case wgsl::BuiltinFn::kFloor:
- case wgsl::BuiltinFn::kFma:
- case wgsl::BuiltinFn::kFract:
- case wgsl::BuiltinFn::kFrexp:
- case wgsl::BuiltinFn::kLength:
- case wgsl::BuiltinFn::kLdexp:
- case wgsl::BuiltinFn::kLog:
- case wgsl::BuiltinFn::kLog2:
- case wgsl::BuiltinFn::kMix:
- case wgsl::BuiltinFn::kModf:
- case wgsl::BuiltinFn::kNormalize:
- case wgsl::BuiltinFn::kReflect:
- case wgsl::BuiltinFn::kRefract:
- case wgsl::BuiltinFn::kSaturate:
- case wgsl::BuiltinFn::kSelect:
- case wgsl::BuiltinFn::kSin:
- case wgsl::BuiltinFn::kSinh:
- case wgsl::BuiltinFn::kSqrt:
- case wgsl::BuiltinFn::kStep:
- case wgsl::BuiltinFn::kTan:
- case wgsl::BuiltinFn::kTanh:
- case wgsl::BuiltinFn::kTranspose:
- case wgsl::BuiltinFn::kTrunc:
- case wgsl::BuiltinFn::kSign:
- case wgsl::BuiltinFn::kClamp:
- out += builtin->str();
- break;
- case wgsl::BuiltinFn::kPow:
- out += "powr";
- break;
- case wgsl::BuiltinFn::kAbs:
- if (builtin->ReturnType()->IsFloatScalarOrVector()) {
- out += "fabs";
- } else {
- out += "abs";
- }
- break;
- case wgsl::BuiltinFn::kCountLeadingZeros:
- out += "clz";
- break;
- case wgsl::BuiltinFn::kCountOneBits:
- out += "popcount";
- break;
- case wgsl::BuiltinFn::kCountTrailingZeros:
- out += "ctz";
- break;
- case wgsl::BuiltinFn::kDpdx:
- case wgsl::BuiltinFn::kDpdxCoarse:
- case wgsl::BuiltinFn::kDpdxFine:
- out += "dfdx";
- break;
- case wgsl::BuiltinFn::kDpdy:
- case wgsl::BuiltinFn::kDpdyCoarse:
- case wgsl::BuiltinFn::kDpdyFine:
- out += "dfdy";
- break;
- case wgsl::BuiltinFn::kExtractBits:
- out += "extract_bits";
- break;
- case wgsl::BuiltinFn::kInsertBits:
- out += "insert_bits";
- break;
- case wgsl::BuiltinFn::kFwidth:
- case wgsl::BuiltinFn::kFwidthCoarse:
- case wgsl::BuiltinFn::kFwidthFine:
- out += "fwidth";
- break;
- case wgsl::BuiltinFn::kMax:
- if (builtin->ReturnType()->IsFloatScalarOrVector()) {
- out += "fmax";
- } else {
- out += "max";
- }
- break;
- case wgsl::BuiltinFn::kMin:
- if (builtin->ReturnType()->IsFloatScalarOrVector()) {
- out += "fmin";
- } else {
- out += "min";
- }
- break;
- case wgsl::BuiltinFn::kFaceForward:
- out += "faceforward";
- break;
- case wgsl::BuiltinFn::kPack4X8Snorm:
- out += "pack_float_to_snorm4x8";
- break;
- case wgsl::BuiltinFn::kPack4X8Unorm:
- out += "pack_float_to_unorm4x8";
- break;
- case wgsl::BuiltinFn::kPack2X16Snorm:
- out += "pack_float_to_snorm2x16";
- break;
- case wgsl::BuiltinFn::kPack2X16Unorm:
- out += "pack_float_to_unorm2x16";
- break;
- case wgsl::BuiltinFn::kReverseBits:
- out += "reverse_bits";
- break;
- case wgsl::BuiltinFn::kRound:
- out += "rint";
- break;
- case wgsl::BuiltinFn::kSmoothstep:
- out += "smoothstep";
- break;
- case wgsl::BuiltinFn::kInverseSqrt:
- out += "rsqrt";
- break;
- case wgsl::BuiltinFn::kUnpack4X8Snorm:
- out += "unpack_snorm4x8_to_float";
- break;
- case wgsl::BuiltinFn::kUnpack4X8Unorm:
- out += "unpack_unorm4x8_to_float";
- break;
- case wgsl::BuiltinFn::kUnpack2X16Snorm:
- out += "unpack_snorm2x16_to_float";
- break;
- case wgsl::BuiltinFn::kUnpack2X16Unorm:
- out += "unpack_unorm2x16_to_float";
- break;
- case wgsl::BuiltinFn::kArrayLength:
- diagnostics_.AddError(Source{})
- << "Unable to translate builtin: " << builtin->Fn()
- << "\nDid you forget to pass array_length_from_uniform generator options?";
- return "";
- default:
- diagnostics_.AddError(Source{}) << "Unknown import method: " << builtin->Fn();
- return "";
- }
- return out;
-}
-
-bool ASTPrinter::EmitCase(const ast::CaseStatement* stmt) {
- auto* sem = builder_.Sem().Get<sem::CaseStatement>(stmt);
- for (auto* selector : sem->Selectors()) {
- auto out = Line();
-
- if (selector->IsDefault()) {
- out << "default";
- } else {
- out << "case ";
- if (!EmitConstant(out, selector->Value())) {
- return false;
- }
- }
- out << ":";
- if (selector == sem->Selectors().back()) {
- out << " {";
- }
- }
-
- {
- ScopedIndent si(this);
-
- for (auto* s : stmt->body->statements) {
- if (!EmitStatement(s)) {
- return false;
- }
- }
-
- if (!last_is_break(stmt->body)) {
- Line() << "break;";
- }
- }
-
- Line() << "}";
-
- return true;
-}
-
-bool ASTPrinter::EmitContinue(const ast::ContinueStatement*) {
- if (!emit_continuing_ || !emit_continuing_()) {
- return false;
- }
-
- Line() << "continue;";
- return true;
-}
-
-bool ASTPrinter::EmitZeroValue(StringStream& out, const core::type::Type* type) {
- return Switch(
- type,
- [&](const core::type::Bool*) {
- out << "false";
- return true;
- },
- [&](const core::type::F16*) {
- out << "0.0h";
- return true;
- },
- [&](const core::type::F32*) {
- out << "0.0f";
- return true;
- },
- [&](const core::type::I32*) {
- out << "0";
- return true;
- },
- [&](const core::type::U32*) {
- out << "0u";
- return true;
- },
- [&](const core::type::Vector* vec) { //
- return EmitZeroValue(out, vec->Type());
- },
- [&](const core::type::Matrix* mat) {
- if (!EmitType(out, mat)) {
- return false;
- }
- ScopedParen sp(out);
- return EmitZeroValue(out, mat->Type());
- },
- [&](const core::type::Array*) {
- out << "{}";
- return true;
- },
- [&](const core::type::Struct*) {
- out << "{}";
- return true;
- }, //
- TINT_ICE_ON_NO_MATCH);
-}
-
-bool ASTPrinter::EmitConstant(StringStream& out, const core::constant::Value* constant) {
- return Switch(
- constant->Type(), //
- [&](const core::type::Bool*) {
- out << (constant->ValueAs<AInt>() ? "true" : "false");
- return true;
- },
- [&](const core::type::F32*) {
- PrintF32(out, constant->ValueAs<f32>());
- return true;
- },
- [&](const core::type::F16*) {
- PrintF16(out, constant->ValueAs<f16>());
- return true;
- },
- [&](const core::type::I32*) {
- PrintI32(out, constant->ValueAs<i32>());
- return true;
- },
- [&](const core::type::U32*) {
- out << constant->ValueAs<AInt>() << "u";
- return true;
- },
- [&](const core::type::Vector* v) {
- if (!EmitType(out, v)) {
- return false;
- }
-
- ScopedParen sp(out);
-
- if (auto* splat = constant->As<core::constant::Splat>()) {
- if (!EmitConstant(out, splat->el)) {
- return false;
- }
- return true;
- }
-
- for (size_t i = 0; i < v->Width(); i++) {
- if (i > 0) {
- out << ", ";
- }
- if (!EmitConstant(out, constant->Index(i))) {
- return false;
- }
- }
- return true;
- },
- [&](const core::type::Matrix* m) {
- if (!EmitType(out, m)) {
- return false;
- }
-
- ScopedParen sp(out);
-
- for (size_t i = 0; i < m->Columns(); i++) {
- if (i > 0) {
- out << ", ";
- }
- if (!EmitConstant(out, constant->Index(i))) {
- return false;
- }
- }
- return true;
- },
- [&](const core::type::Array* a) {
- if (!EmitType(out, a)) {
- return false;
- }
-
- out << "{";
- TINT_DEFER(out << "}");
-
- if (constant->AllZero()) {
- return true;
- }
-
- auto count = a->ConstantCount();
- if (!count) {
- diagnostics_.AddError(Source{}) << core::type::Array::kErrExpectedConstantCount;
- return false;
- }
-
- for (size_t i = 0; i < count; i++) {
- if (i > 0) {
- out << ", ";
- }
- if (!EmitConstant(out, constant->Index(i))) {
- return false;
- }
- }
-
- return true;
- },
- [&](const core::type::Struct* s) {
- if (!EmitStructType(&helpers_, s)) {
- return false;
- }
-
- out << StructName(s) << "{";
- TINT_DEFER(out << "}");
-
- if (constant->AllZero()) {
- return true;
- }
-
- auto members = s->Members();
- for (size_t i = 0; i < members.Length(); i++) {
- if (i > 0) {
- out << ", ";
- }
- out << "." << members[i]->Name().Name() << "=";
- if (!EmitConstant(out, constant->Index(i))) {
- return false;
- }
- }
-
- return true;
- }, //
- TINT_ICE_ON_NO_MATCH);
-}
-
-bool ASTPrinter::EmitLiteral(StringStream& out, const ast::LiteralExpression* lit) {
- return Switch(
- lit,
- [&](const ast::BoolLiteralExpression* l) {
- out << (l->value ? "true" : "false");
- return true;
- },
- [&](const ast::FloatLiteralExpression* l) {
- if (l->suffix == ast::FloatLiteralExpression::Suffix::kH) {
- PrintF16(out, static_cast<float>(l->value));
- } else {
- PrintF32(out, static_cast<float>(l->value));
- }
- return true;
- },
- [&](const ast::IntLiteralExpression* i) {
- switch (i->suffix) {
- case ast::IntLiteralExpression::Suffix::kNone:
- case ast::IntLiteralExpression::Suffix::kI: {
- PrintI32(out, static_cast<int32_t>(i->value));
- return true;
- }
- case ast::IntLiteralExpression::Suffix::kU: {
- out << i->value << "u";
- return true;
- }
- }
- diagnostics_.AddError(Source{}) << "unknown integer literal suffix type";
- return false;
- }, //
- TINT_ICE_ON_NO_MATCH);
-}
-
-bool ASTPrinter::EmitExpression(StringStream& out, const ast::Expression* expr) {
- if (auto* sem = builder_.Sem().GetVal(expr)) {
- if (auto* constant = sem->ConstantValue()) {
- return EmitConstant(out, constant);
- }
- }
- return Switch(
- expr, //
- [&](const ast::IndexAccessorExpression* a) { return EmitIndexAccessor(out, a); },
- [&](const ast::BinaryExpression* b) { return EmitBinary(out, b); },
- [&](const ast::CallExpression* c) { return EmitCall(out, c); },
- [&](const ast::IdentifierExpression* i) { return EmitIdentifier(out, i); },
- [&](const ast::LiteralExpression* l) { return EmitLiteral(out, l); },
- [&](const ast::MemberAccessorExpression* m) { return EmitMemberAccessor(out, m); },
- [&](const ast::UnaryOpExpression* u) { return EmitUnaryOp(out, u); }, //
- TINT_ICE_ON_NO_MATCH);
-}
-
-void ASTPrinter::EmitStage(StringStream& out, ast::PipelineStage stage) {
- switch (stage) {
- case ast::PipelineStage::kFragment:
- out << "fragment";
- break;
- case ast::PipelineStage::kVertex:
- out << "vertex";
- break;
- case ast::PipelineStage::kCompute:
- out << "kernel";
- break;
- case ast::PipelineStage::kNone:
- break;
- }
- return;
-}
-
-bool ASTPrinter::EmitFunction(const ast::Function* func) {
- if (func->body == nullptr) {
- // An internal function. Do not emit.
- return true;
- }
-
- auto* func_sem = builder_.Sem().Get(func);
-
- {
- auto out = Line();
- if (!EmitType(out, func_sem->ReturnType())) {
- return false;
- }
- out << " " << func->name->symbol.Name() << "(";
-
- bool first = true;
- for (auto* v : func->params) {
- if (!first) {
- out << ", ";
- }
- first = false;
-
- auto* type = builder_.Sem().Get(v)->Type();
-
- if (!EmitType(out, type)) {
- return false;
- }
- if (type->Is<core::type::Pointer>()) {
- out << " const";
- }
- out << " " << v->name->symbol.Name();
- }
-
- out << ") {";
- }
-
- if (!EmitStatementsWithIndent(func->body->statements)) {
- return false;
- }
-
- Line() << "}";
-
- return true;
-}
-
-bool ASTPrinter::EmitEntryPointFunction(const ast::Function* func) {
- auto* func_sem = builder_.Sem().Get(func);
-
- auto func_name = func->name->symbol.Name();
- workgroup_allocations_.insert({func_name, {}});
-
- // Returns the binding index of a variable, requiring that the group
- // attribute have a value of zero.
- const uint32_t kInvalidBindingIndex = std::numeric_limits<uint32_t>::max();
- auto get_binding_index = [&](const ast::Parameter* param) -> uint32_t {
- if (DAWN_UNLIKELY(!param->HasBindingPoint())) {
- TINT_ICE() << "missing binding attributes for entry point parameter";
- }
- auto* param_sem = builder_.Sem().Get(param);
- auto bp = param_sem->Attributes().binding_point;
- if (DAWN_UNLIKELY(bp->group != 0)) {
- TINT_ICE() << "encountered non-zero resource group index (use BindingRemapper to fix)";
- }
- return bp->binding;
- };
-
- {
- auto out = Line();
-
- EmitStage(out, func->PipelineStage());
- out << " ";
- if (!EmitTypeAndName(out, func_sem->ReturnType(), func_name)) {
- return false;
- }
- out << "(";
-
- // Emit entry point parameters.
- bool first = true;
- for (auto* param : func->params) {
- if (!first) {
- out << ", ";
- }
- first = false;
-
- auto* type = builder_.Sem().Get(param)->Type()->UnwrapRef();
-
- if (!EmitType(out, type)) {
- return false;
- }
- out << " " << param->name->symbol.Name();
-
- bool ok = Switch(
- type, //
- [&](const core::type::Struct*) {
- out << " [[stage_in]]";
- return true;
- },
- [&](const core::type::Texture*) {
- uint32_t binding = get_binding_index(param);
- if (binding == kInvalidBindingIndex) {
- return false;
- }
- out << " [[texture(" << binding << ")]]";
- return true;
- },
- [&](const core::type::Sampler*) {
- uint32_t binding = get_binding_index(param);
- if (binding == kInvalidBindingIndex) {
- return false;
- }
- out << " [[sampler(" << binding << ")]]";
- return true;
- },
- [&](const core::type::Pointer* ptr) {
- switch (ptr->AddressSpace()) {
- case core::AddressSpace::kWorkgroup: {
- auto& allocations = workgroup_allocations_[func_name];
- out << " [[threadgroup(" << allocations.size() << ")]]";
- allocations.push_back(ptr->StoreType()->Size());
- return true;
- }
-
- case core::AddressSpace::kStorage:
- case core::AddressSpace::kUniform: {
- uint32_t binding = get_binding_index(param);
- if (binding == kInvalidBindingIndex) {
- return false;
- }
- out << " [[buffer(" << binding << ")]]";
- return true;
- }
-
- default:
- break;
- }
- TINT_ICE() << "invalid pointer address space for entry point parameter";
- },
- [&](Default) {
- auto& attrs = param->attributes;
- bool builtin_found = false;
- for (auto* attr : attrs) {
- if (attr->Is<QuadSwap::ThreadIndexInQuadgroup>()) {
- out << " [[thread_index_in_quadgroup]]";
- builtin_found = true;
- continue;
- }
-
- auto* builtin_attr = attr->As<ast::BuiltinAttribute>();
- if (!builtin_attr) {
- continue;
- }
-
- builtin_found = true;
-
- auto name = BuiltinToAttribute(builtin_attr->builtin);
- if (name.empty()) {
- diagnostics_.AddError(Source{}) << "unknown builtin";
- return false;
- }
-
- out << " [[" << name << "]]";
- }
- if (DAWN_UNLIKELY(!builtin_found)) {
- TINT_ICE() << "Unsupported entry point parameter";
- }
- return true;
- });
- if (!ok) {
- return false;
- }
- }
- out << ") {";
- }
-
- {
- ScopedIndent si(this);
-
- if (!EmitStatements(func->body->statements)) {
- return false;
- }
-
- if (!Is<ast::ReturnStatement>(func->body->Last())) {
- ast::ReturnStatement ret(GenerationID{}, ast::NodeID{}, Source{});
- if (!EmitStatement(&ret)) {
- return false;
- }
- }
- }
-
- Line() << "}";
- return true;
-}
-
-bool ASTPrinter::EmitIdentifier(StringStream& out, const ast::IdentifierExpression* expr) {
- out << expr->identifier->symbol.Name();
- return true;
-}
-
-bool ASTPrinter::EmitLoop(const ast::LoopStatement* stmt) {
- auto emit_continuing = [this, stmt] {
- if (stmt->continuing && !stmt->continuing->Empty()) {
- if (!EmitBlock(stmt->continuing)) {
- return false;
- }
- }
- return true;
- };
-
- TINT_SCOPED_ASSIGNMENT(emit_continuing_, emit_continuing);
- Line() << "while(true) {";
- {
- ScopedIndent si(this);
- IsolateUBIfNeeded();
- if (!EmitStatements(stmt->body->statements)) {
- return false;
- }
- if (!emit_continuing_()) {
- return false;
- }
- }
- Line() << "}";
-
- return true;
-}
-
-bool ASTPrinter::EmitForLoop(const ast::ForLoopStatement* stmt) {
- TextBuffer init_buf;
- if (auto* init = stmt->initializer) {
- TINT_SCOPED_ASSIGNMENT(current_buffer_, &init_buf);
- if (!EmitStatement(init)) {
- return false;
- }
- }
-
- TextBuffer cond_pre;
- StringStream cond_buf;
- if (auto* cond = stmt->condition) {
- TINT_SCOPED_ASSIGNMENT(current_buffer_, &cond_pre);
- if (!EmitExpression(cond_buf, cond)) {
- return false;
- }
- }
-
- TextBuffer cont_buf;
- if (auto* cont = stmt->continuing) {
- TINT_SCOPED_ASSIGNMENT(current_buffer_, &cont_buf);
- if (!EmitStatement(cont)) {
- return false;
- }
- }
-
- // If the for-loop has a multi-statement conditional and / or continuing,
- // then we cannot emit this as a regular for-loop in MSL. Instead we need to
- // generate a `while(true)` loop.
- bool emit_as_loop = cond_pre.lines.size() > 0 || cont_buf.lines.size() > 1;
-
- // If the for-loop has multi-statement initializer, or is going to be
- // emitted as a `while(true)` loop, then declare the initializer
- // statement(s) before the loop in a new block.
- bool nest_in_block = init_buf.lines.size() > 1 || (stmt->initializer && emit_as_loop);
- if (nest_in_block) {
- Line() << "{";
- IncrementIndent();
- current_buffer_->Append(init_buf);
- init_buf.lines.clear(); // Don't emit the initializer again in the 'for'
- }
- TINT_DEFER({
- if (nest_in_block) {
- DecrementIndent();
- Line() << "}";
- }
- });
-
- if (emit_as_loop) {
- auto emit_continuing = [&] {
- current_buffer_->Append(cont_buf);
- return true;
- };
-
- TINT_SCOPED_ASSIGNMENT(emit_continuing_, emit_continuing);
- Line() << "while(true) {";
- IncrementIndent();
- TINT_DEFER({
- DecrementIndent();
- Line() << "}";
- });
- IsolateUBIfNeeded();
-
- if (stmt->condition) {
- current_buffer_->Append(cond_pre);
- Line() << "if (!(" << cond_buf.str() << ")) { break; }";
- }
-
- if (!EmitStatements(stmt->body->statements)) {
- return false;
- }
-
- if (!emit_continuing_()) {
- return false;
- }
- } else {
- // For-loop can be generated.
- {
- auto out = Line();
- out << "for";
- {
- ScopedParen sp(out);
-
- if (!init_buf.lines.empty()) {
- out << init_buf.lines[0].content << " ";
- } else {
- out << "; ";
- }
-
- out << cond_buf.str() << "; ";
-
- if (!cont_buf.lines.empty()) {
- out << tint::TrimSuffix(cont_buf.lines[0].content, ";");
- }
- }
- out << " {";
- }
- {
- IncrementIndent();
- IsolateUBIfNeeded();
- DecrementIndent();
- auto emit_continuing = [] { return true; };
- TINT_SCOPED_ASSIGNMENT(emit_continuing_, emit_continuing);
- if (!EmitStatementsWithIndent(stmt->body->statements)) {
- return false;
- }
- }
- Line() << "}";
- }
-
- return true;
-}
-
-bool ASTPrinter::EmitWhile(const ast::WhileStatement* stmt) {
- TextBuffer cond_pre;
- StringStream cond_buf;
-
- {
- auto* cond = stmt->condition;
- TINT_SCOPED_ASSIGNMENT(current_buffer_, &cond_pre);
- if (!EmitExpression(cond_buf, cond)) {
- return false;
- }
- }
-
- auto emit_continuing = [&] { return true; };
- TINT_SCOPED_ASSIGNMENT(emit_continuing_, emit_continuing);
-
- // If the while has a multi-statement conditional, then we cannot emit this
- // as a regular while in MSL. Instead we need to generate a `while(true)` loop.
- bool emit_as_loop = cond_pre.lines.size() > 0;
- if (emit_as_loop) {
- Line() << "while(true) {";
- IncrementIndent();
- IsolateUBIfNeeded();
- TINT_DEFER({
- DecrementIndent();
- Line() << "}";
- });
-
- current_buffer_->Append(cond_pre);
- Line() << "if (!(" << cond_buf.str() << ")) { break; }";
- if (!EmitStatements(stmt->body->statements)) {
- return false;
- }
- } else {
- // While can be generated.
- Line() << "while(" << cond_buf.str() << ") {";
- IncrementIndent();
- IsolateUBIfNeeded();
- DecrementIndent();
- if (!EmitStatementsWithIndent(stmt->body->statements)) {
- return false;
- }
- Line() << "}";
- }
- return true;
-}
-
-bool ASTPrinter::EmitDiscard(const ast::DiscardStatement*) {
- // TODO(dsinclair): Verify this is correct when the discard semantics are
- // defined for WGSL (https://github.com/gpuweb/gpuweb/issues/361)
- Line() << "discard_fragment();";
- return true;
-}
-
-bool ASTPrinter::EmitIf(const ast::IfStatement* stmt) {
- {
- auto out = Line();
- out << "if (";
- if (!EmitExpression(out, stmt->condition)) {
- return false;
- }
- out << ") {";
- }
-
- if (!EmitStatementsWithIndent(stmt->body->statements)) {
- return false;
- }
-
- if (stmt->else_statement) {
- Line() << "} else {";
- if (auto* block = stmt->else_statement->As<ast::BlockStatement>()) {
- if (!EmitStatementsWithIndent(block->statements)) {
- return false;
- }
- } else {
- if (!EmitStatementsWithIndent(Vector{stmt->else_statement})) {
- return false;
- }
- }
- }
- Line() << "}";
-
- return true;
-}
-
-bool ASTPrinter::EmitMemberAccessor(StringStream& out, const ast::MemberAccessorExpression* expr) {
- auto write_lhs = [&] {
- bool paren_lhs = !expr->object->IsAnyOf<ast::AccessorExpression, ast::CallExpression,
- ast::IdentifierExpression>();
- if (paren_lhs) {
- out << "(";
- }
- if (!EmitExpression(out, expr->object)) {
- return false;
- }
- if (paren_lhs) {
- out << ")";
- }
- return true;
- };
-
- auto* sem = builder_.Sem().Get(expr)->UnwrapLoad();
-
- return Switch(
- sem,
- [&](const sem::Swizzle* swizzle) {
- // Metal did not add support for swizzle syntax with packed vector types until
- // Metal 2.1, so we need to use the index operator for single-element selection instead.
- // For multi-component swizzles, the PackedVec3 transform will have inserted casts to
- // the non-packed types, so we can safely use swizzle syntax here.
- if (swizzle->Indices().Length() == 1) {
- if (!write_lhs()) {
- return false;
- }
- out << "[" << swizzle->Indices()[0] << "]";
- } else {
- if (!write_lhs()) {
- return false;
- }
- out << "." << expr->member->symbol.Name();
- }
- return true;
- },
- [&](const sem::StructMemberAccess* member_access) {
- if (!write_lhs()) {
- return false;
- }
- out << "." << member_access->Member()->Name().Name();
- return true;
- }, //
- TINT_ICE_ON_NO_MATCH);
-}
-
-bool ASTPrinter::EmitReturn(const ast::ReturnStatement* stmt) {
- auto out = Line();
- out << "return";
- if (stmt->value) {
- out << " ";
- if (!EmitExpression(out, stmt->value)) {
- return false;
- }
- }
- out << ";";
- return true;
-}
-
-bool ASTPrinter::EmitBlock(const ast::BlockStatement* stmt) {
- Line() << "{";
-
- if (!EmitStatementsWithIndent(stmt->statements)) {
- return false;
- }
-
- Line() << "}";
-
- return true;
-}
-
-bool ASTPrinter::EmitStatement(const ast::Statement* stmt) {
- return Switch(
- stmt,
- [&](const ast::AssignmentStatement* a) { //
- return EmitAssign(a);
- },
- [&](const ast::BlockStatement* b) { //
- return EmitBlock(b);
- },
- [&](const ast::BreakStatement* b) { //
- return EmitBreak(b);
- },
- [&](const ast::BreakIfStatement* b) { //
- return EmitBreakIf(b);
- },
- [&](const ast::CallStatement* c) { //
- auto out = Line();
- if (!EmitCall(out, c->expr)) { //
- return false;
- }
- out << ";";
- return true;
- },
- [&](const ast::ContinueStatement* c) { //
- return EmitContinue(c);
- },
- [&](const ast::DiscardStatement* d) { //
- return EmitDiscard(d);
- },
- [&](const ast::IfStatement* i) { //
- return EmitIf(i);
- },
- [&](const ast::LoopStatement* l) { //
- return EmitLoop(l);
- },
- [&](const ast::ForLoopStatement* l) { //
- return EmitForLoop(l);
- },
- [&](const ast::WhileStatement* l) { //
- return EmitWhile(l);
- },
- [&](const ast::ReturnStatement* r) { //
- return EmitReturn(r);
- },
- [&](const ast::SwitchStatement* s) { //
- return EmitSwitch(s);
- },
- [&](const ast::VariableDeclStatement* v) { //
- return Switch(
- v->variable, //
- [&](const ast::Var* var) { return EmitVar(var); },
- [&](const ast::Let* let) { return EmitLet(let); },
- [&](const ast::Const*) {
- return true; // Constants are embedded at their use
- }, //
- TINT_ICE_ON_NO_MATCH);
- },
- [&](const ast::ConstAssert*) {
- return true; // Not emitted
- }, //
- TINT_ICE_ON_NO_MATCH);
-}
-
-bool ASTPrinter::EmitStatements(VectorRef<const ast::Statement*> stmts) {
- for (auto* s : stmts) {
- if (!EmitStatement(s)) {
- return false;
- }
- }
- return true;
-}
-
-bool ASTPrinter::EmitStatementsWithIndent(VectorRef<const ast::Statement*> stmts) {
- ScopedIndent si(this);
- return EmitStatements(stmts);
-}
-
-bool ASTPrinter::EmitSwitch(const ast::SwitchStatement* stmt) {
- {
- auto out = Line();
- out << "switch(";
- if (!EmitExpression(out, stmt->condition)) {
- return false;
- }
- out << ") {";
- }
-
- {
- ScopedIndent si(this);
- for (auto* s : stmt->body) {
- if (!EmitCase(s)) {
- return false;
- }
- }
- }
-
- Line() << "}";
-
- return true;
-}
-
-bool ASTPrinter::EmitType(StringStream& out, const core::type::Type* type) {
- return Switch(
- type,
- [&](const core::type::Atomic* atomic) {
- if (atomic->Type()->Is<core::type::I32>()) {
- out << "atomic_int";
- return true;
- }
- if (DAWN_LIKELY(atomic->Type()->Is<core::type::U32>())) {
- out << "atomic_uint";
- return true;
- }
- TINT_ICE() << "unhandled atomic type " << atomic->Type()->FriendlyName();
- },
- [&](const core::type::Array* arr) {
- out << ArrayType() << "<";
- if (!EmitType(out, arr->ElemType())) {
- return false;
- }
- out << ", ";
- if (arr->Count()->Is<core::type::RuntimeArrayCount>()) {
- out << "1";
- } else {
- auto count = arr->ConstantCount();
- if (!count) {
- diagnostics_.AddError(Source{}) << core::type::Array::kErrExpectedConstantCount;
- return false;
- }
-
- out << count.value();
- }
- out << ">";
- return true;
- },
- [&](const core::type::Bool*) {
- out << "bool";
- return true;
- },
- [&](const core::type::F16*) {
- out << "half";
- return true;
- },
- [&](const core::type::F32*) {
- out << "float";
- return true;
- },
- [&](const core::type::I32*) {
- out << "int";
- return true;
- },
- [&](const core::type::Matrix* mat) {
- if (!EmitType(out, mat->Type())) {
- return false;
- }
- out << mat->Columns() << "x" << mat->Rows();
- return true;
- },
- [&](const core::type::Pointer* ptr) {
- if (ptr->Access() == core::Access::kRead) {
- out << "const ";
- }
- if (!EmitAddressSpace(out, ptr->AddressSpace())) {
- return false;
- }
- out << " ";
- if (!EmitType(out, ptr->StoreType())) {
- return false;
- }
- out << "*";
- return true;
- },
- [&](const core::type::Sampler*) {
- out << "sampler";
- return true;
- },
- [&](const core::type::Struct* str) {
- // Make sure the struct type gets emitted. There are some cases where the types are
- // defined internal (like modf) which can end up in structures. The usage may be
- // removed by phonies, but the declaration still needs to exist.
- if (!EmitStructType(&helpers_, str)) {
- return false;
- }
-
- // The struct type emits as just the name. The declaration would be
- // emitted as part of emitting the declared types.
- out << StructName(str);
- return true;
- },
- [&](const core::type::Texture* tex) {
- if (DAWN_UNLIKELY(tex->Is<core::type::ExternalTexture>())) {
- TINT_ICE() << "Multiplanar external texture transform was not run.";
- }
-
- if (tex->IsAnyOf<core::type::DepthTexture, core::type::DepthMultisampledTexture>()) {
- out << "depth";
- } else {
- out << "texture";
- }
-
- switch (tex->Dim()) {
- case core::type::TextureDimension::k1d:
- out << "1d";
- break;
- case core::type::TextureDimension::k2d:
- out << "2d";
- break;
- case core::type::TextureDimension::k2dArray:
- out << "2d_array";
- break;
- case core::type::TextureDimension::k3d:
- out << "3d";
- break;
- case core::type::TextureDimension::kCube:
- out << "cube";
- break;
- case core::type::TextureDimension::kCubeArray:
- out << "cube_array";
- break;
- default:
- diagnostics_.AddError(Source{}) << "Invalid texture dimensions";
- return false;
- }
- if (tex->IsAnyOf<core::type::MultisampledTexture,
- core::type::DepthMultisampledTexture>()) {
- out << "_ms";
- }
- out << "<";
- TINT_DEFER(out << ">");
-
- return Switch(
- tex,
- [&](const core::type::DepthTexture*) {
- out << "float, access::sample";
- return true;
- },
- [&](const core::type::DepthMultisampledTexture*) {
- out << "float, access::read";
- return true;
- },
- [&](const core::type::StorageTexture* storage) {
- if (!EmitType(out, storage->Type())) {
- return false;
- }
-
- std::string access_str;
- if (storage->Access() == core::Access::kRead) {
- out << ", access::read";
- } else if (storage->Access() == core::Access::kReadWrite) {
- out << ", access::read_write";
- } else if (storage->Access() == core::Access::kWrite) {
- out << ", access::write";
- } else {
- diagnostics_.AddError(Source{})
- << "Invalid access control for storage texture";
- return false;
- }
- return true;
- },
- [&](const core::type::MultisampledTexture* ms) {
- if (!EmitType(out, ms->Type())) {
- return false;
- }
- out << ", access::read";
- return true;
- },
- [&](const core::type::SampledTexture* sampled) {
- if (!EmitType(out, sampled->Type())) {
- return false;
- }
- out << ", access::sample";
- return true;
- }, //
- TINT_ICE_ON_NO_MATCH);
- },
- [&](const core::type::U32*) {
- out << "uint";
- return true;
- },
- [&](const core::type::Vector* vec) {
- if (vec->Packed()) {
- out << "packed_";
- }
- if (!EmitType(out, vec->Type())) {
- return false;
- }
- out << vec->Width();
- return true;
- },
- [&](const core::type::Void*) {
- out << "void";
- return true;
- }, //
- TINT_ICE_ON_NO_MATCH);
-}
-
-bool ASTPrinter::EmitTypeAndName(StringStream& out,
- const core::type::Type* type,
- const std::string& name) {
- if (!EmitType(out, type)) {
- return false;
- }
- out << " " << name;
- return true;
-}
-
-bool ASTPrinter::EmitAddressSpace(StringStream& out, core::AddressSpace sc) {
- switch (sc) {
- case core::AddressSpace::kFunction:
- case core::AddressSpace::kPrivate:
- case core::AddressSpace::kHandle:
- out << "thread";
- return true;
- case core::AddressSpace::kWorkgroup:
- out << "threadgroup";
- return true;
- case core::AddressSpace::kStorage:
- out << "device";
- return true;
- case core::AddressSpace::kUniform:
- out << "constant";
- return true;
- default:
- break;
- }
- TINT_ICE() << "unhandled address space: " << sc;
-}
-
-bool ASTPrinter::EmitStructType(TextBuffer* b, const core::type::Struct* str) {
- auto it = emitted_structs_.emplace(str);
- if (!it.second) {
- return true;
- }
-
- Line(b) << "struct " << StructName(str) << " {";
-
- bool is_host_shareable = str->IsHostShareable();
-
- // Emits a `/* 0xnnnn */` byte offset comment for a struct member.
- auto add_byte_offset_comment = [&](StringStream& out, uint32_t offset) {
- std::ios_base::fmtflags saved_flag_state(out.flags());
- out << "/* 0x" << std::hex << std::setfill('0') << std::setw(4) << offset << " */ ";
- out.flags(saved_flag_state);
- };
-
- auto add_padding = [&](uint32_t size, uint32_t msl_offset) {
- std::string name;
- do {
- name = UniqueIdentifier("tint_pad");
- } while (str->FindMember(builder_.Symbols().Get(name)));
-
- auto out = Line(b);
- add_byte_offset_comment(out, msl_offset);
- out << ArrayType() << "<int8_t, " << size << "> " << name << ";";
- };
-
- b->IncrementIndent();
-
- uint32_t msl_offset = 0;
- for (auto* mem : str->Members()) {
- auto out = Line(b);
- auto mem_name = mem->Name().Name();
- auto wgsl_offset = mem->Offset();
-
- if (is_host_shareable) {
- if (DAWN_UNLIKELY(wgsl_offset < msl_offset)) {
- // Unimplementable layout
- TINT_ICE() << "Structure member WGSL offset (" << wgsl_offset
- << ") is behind MSL offset (" << msl_offset << ")";
- }
-
- // Generate padding if required
- if (auto padding = wgsl_offset - msl_offset) {
- add_padding(padding, msl_offset);
- msl_offset += padding;
- }
-
- add_byte_offset_comment(out, msl_offset);
- }
-
- auto* ty = mem->Type();
-
- // Emit attributes
- auto& attributes = mem->Attributes();
- std::string builtin_value_name;
- if (auto builtin = attributes.builtin) {
- builtin_value_name = BuiltinToAttribute(builtin.value());
- if (builtin_value_name.empty()) {
- diagnostics_.AddError(Source{}) << "unknown builtin";
- return false;
- }
-
- // Emit `[[clip_distance]]` as a C-style f32 array
- if (builtin == core::BuiltinValue::kClipDistances) {
- const auto* arrayType = mem->Type()->As<core::type::Array>();
- if (DAWN_UNLIKELY(arrayType == nullptr ||
- !arrayType->ConstantCount().has_value())) {
- TINT_ICE() << "The type of `clip_distances` is not a sized array";
- } else {
- out << "float " << mem_name << " [[" << builtin_value_name << "]] ["
- << *arrayType->ConstantCount() << "];";
- }
- continue;
- }
- }
-
- if (!EmitType(out, mem->Type())) {
- return false;
- }
-
- out << " " << mem_name;
-
- if (!builtin_value_name.empty()) {
- out << " [[" << builtin_value_name << "]]";
- }
-
- if (auto location = attributes.location) {
- auto& pipeline_stage_uses = str->PipelineStageUses();
- if (DAWN_UNLIKELY(pipeline_stage_uses.Count() != 1)) {
- TINT_ICE() << "invalid entry point IO struct uses for " << str->Name().NameView();
- }
-
- if (pipeline_stage_uses.Contains(core::type::PipelineStageUsage::kVertexInput)) {
- out << " [[attribute(" + std::to_string(location.value()) + ")]]";
- } else if (pipeline_stage_uses.Contains(
- core::type::PipelineStageUsage::kVertexOutput)) {
- out << " [[user(locn" + std::to_string(location.value()) + ")]]";
- } else if (pipeline_stage_uses.Contains(
- core::type::PipelineStageUsage::kFragmentInput)) {
- out << " [[user(locn" + std::to_string(location.value()) + ")]]";
- } else if (DAWN_LIKELY(pipeline_stage_uses.Contains(
- core::type::PipelineStageUsage::kFragmentOutput))) {
- if (auto blend_src = attributes.blend_src) {
- out << " [[color(" + std::to_string(location.value()) + ") index(" +
- std::to_string(blend_src.value()) + ")]]";
- } else {
- out << " [[color(" + std::to_string(location.value()) + ")]]";
- }
- } else {
- TINT_ICE() << "invalid use of location decoration";
- }
- }
-
- if (auto color = attributes.color) {
- out << " [[color(" + std::to_string(color.value()) + ")]]";
- }
-
- if (auto interpolation = attributes.interpolation) {
- auto name = InterpolationToAttribute(interpolation->type, interpolation->sampling);
- if (name.empty()) {
- diagnostics_.AddError(Source{}) << "unknown interpolation attribute";
- return false;
- }
- out << " [[" << name << "]]";
- }
-
- if (attributes.invariant) {
- invariant_define_name_ = UniqueIdentifier("TINT_INVARIANT");
- out << " " << invariant_define_name_;
- }
-
- out << ";";
-
- if (is_host_shareable) {
- // Calculate new MSL offset
- auto size_align = MslPackedTypeSizeAndAlign(ty);
- if (DAWN_UNLIKELY(msl_offset % size_align.align)) {
- TINT_ICE() << "Misaligned MSL structure member " << ty->FriendlyName() << " "
- << mem_name;
- }
- msl_offset += size_align.size;
- }
- }
-
- if (is_host_shareable && str->Size() != msl_offset) {
- add_padding(str->Size() - msl_offset, msl_offset);
- }
-
- b->DecrementIndent();
-
- Line(b) << "};";
- return true;
-}
-
-bool ASTPrinter::EmitUnaryOp(StringStream& out, const ast::UnaryOpExpression* expr) {
- // Handle `-e` when `e` is signed, so that we ensure that if `e` is the
- // largest negative value, it returns `e`.
- auto* expr_type = TypeOf(expr->expr)->UnwrapRef();
- if (expr->op == core::UnaryOp::kNegation && expr_type->IsSignedIntegerScalarOrVector()) {
- auto fn = tint::GetOrAdd(unary_minus_funcs_, expr_type, [&]() -> std::string {
- // e.g.:
- // int tint_unary_minus(const int v) {
- // return (v == -2147483648) ? v : -v;
- // }
- TextBuffer b;
- TINT_DEFER(helpers_.Append(b));
-
- auto fn_name = UniqueIdentifier("tint_unary_minus");
- {
- auto decl = Line(&b);
- if (!EmitTypeAndName(decl, expr_type, fn_name)) {
- return "";
- }
- decl << "(const ";
- if (!EmitType(decl, expr_type)) {
- return "";
- }
- decl << " v) {";
- }
-
- {
- ScopedIndent si(&b);
- const auto largest_negative_value =
- std::to_string(std::numeric_limits<int32_t>::min());
- Line(&b) << "return select(-v, v, v == " << largest_negative_value << ");";
- }
- Line(&b) << "}";
- Line(&b);
- return fn_name;
- });
-
- out << fn << "(";
- if (!EmitExpression(out, expr->expr)) {
- return false;
- }
- out << ")";
- return true;
- }
-
- switch (expr->op) {
- case core::UnaryOp::kAddressOf:
- out << "&";
- break;
- case core::UnaryOp::kComplement:
- out << "~";
- break;
- case core::UnaryOp::kIndirection:
- out << "*";
- break;
- case core::UnaryOp::kNot:
- out << "!";
- break;
- case core::UnaryOp::kNegation:
- out << "-";
- break;
- }
- out << "(";
-
- if (!EmitExpression(out, expr->expr)) {
- return false;
- }
-
- out << ")";
-
- return true;
-}
-
-bool ASTPrinter::EmitVar(const ast::Var* var) {
- auto* sem = builder_.Sem().Get(var);
- auto* type = sem->Type()->UnwrapRef();
-
- auto out = Line();
-
- switch (sem->AddressSpace()) {
- case core::AddressSpace::kFunction:
- case core::AddressSpace::kHandle:
- break;
- case core::AddressSpace::kPrivate:
- out << "thread ";
- break;
- case core::AddressSpace::kWorkgroup:
- out << "threadgroup ";
- break;
- default:
- TINT_ICE() << "unhandled variable address space";
- }
-
- if (!EmitType(out, type)) {
- return false;
- }
- out << " " << var->name->symbol.Name();
-
- if (var->initializer != nullptr) {
- out << " = ";
- if (!EmitExpression(out, var->initializer)) {
- return false;
- }
- } else if (sem->AddressSpace() == core::AddressSpace::kPrivate ||
- sem->AddressSpace() == core::AddressSpace::kFunction ||
- sem->AddressSpace() == core::AddressSpace::kUndefined) {
- out << " = ";
- if (!EmitZeroValue(out, type)) {
- return false;
- }
- }
- out << ";";
-
- return true;
-}
-
-bool ASTPrinter::EmitLet(const ast::Let* let) {
- auto* sem = builder_.Sem().Get(let);
- auto* type = sem->Type();
-
- auto out = Line();
-
- switch (sem->AddressSpace()) {
- case core::AddressSpace::kFunction:
- case core::AddressSpace::kHandle:
- case core::AddressSpace::kUndefined:
- break;
- case core::AddressSpace::kPrivate:
- out << "thread ";
- break;
- case core::AddressSpace::kWorkgroup:
- out << "threadgroup ";
- break;
- default:
- TINT_ICE() << "unhandled variable address space";
- }
-
- if (!EmitType(out, type)) {
- return false;
- }
- out << " const " << let->name->symbol.Name();
-
- out << " = ";
- if (!EmitExpression(out, let->initializer)) {
- return false;
- }
- out << ";";
-
- return true;
-}
-
-void ASTPrinter::IsolateUBIfNeeded() {
- if (!options_.disable_robustness) {
- Line() << IsolateUB();
- }
-}
-
-std::string ASTPrinter::IsolateUB() {
- if (isolate_ub_macro_name_.empty()) {
- isolate_ub_macro_name_ = UniqueIdentifier("TINT_ISOLATE_UB");
- Line(&helpers_) << "#define " << isolate_ub_macro_name_ << "(VOLATILE_NAME) \\";
- Line(&helpers_) << " {volatile bool VOLATILE_NAME = false; if (VOLATILE_NAME) break;}";
- Line(&helpers_);
- }
- StringStream ss;
- ss << isolate_ub_macro_name_ << "(" << UniqueIdentifier("tint_volatile_false") << ");";
- return ss.str();
-}
-
-template <typename F>
-bool ASTPrinter::CallBuiltinHelper(StringStream& out,
- const ast::CallExpression* call,
- const sem::BuiltinFn* builtin,
- F&& build) {
- // Generate the helper function if it hasn't been created already
- auto fn = tint::GetOrAdd(builtins_, builtin, [&]() -> std::string {
- TextBuffer b;
- TINT_DEFER(helpers_.Append(b));
-
- auto fn_name = UniqueIdentifier(std::string("tint_") + wgsl::str(builtin->Fn()));
- std::vector<std::string> parameter_names;
- {
- auto decl = Line(&b);
- if (!EmitTypeAndName(decl, builtin->ReturnType(), fn_name)) {
- return "";
- }
- {
- ScopedParen sp(decl);
- for (auto* param : builtin->Parameters()) {
- if (!parameter_names.empty()) {
- decl << ", ";
- }
- auto param_name = "param_" + std::to_string(parameter_names.size());
- if (!EmitTypeAndName(decl, param->Type(), param_name)) {
- return "";
- }
- parameter_names.emplace_back(std::move(param_name));
- }
- }
- decl << " {";
- }
- {
- ScopedIndent si(&b);
- if (!build(&b, parameter_names)) {
- return "";
- }
- }
- Line(&b) << "}";
- Line(&b);
- return fn_name;
- });
-
- if (fn.empty()) {
- return false;
- }
-
- // Call the helper
- out << fn;
- {
- ScopedParen sp(out);
- bool first = true;
- for (auto* arg : call->args) {
- if (!first) {
- out << ", ";
- }
- first = false;
- if (!EmitExpression(out, arg)) {
- return false;
- }
- }
- }
- return true;
-}
-
-const std::string& ASTPrinter::ArrayType() {
- if (array_template_name_.empty()) {
- array_template_name_ = UniqueIdentifier("tint_array");
- auto* buf = &helpers_;
- Line(buf) << "template<typename T, size_t N>";
- Line(buf) << "struct " << array_template_name_ << " {";
- Line(buf) << " const constant T& operator[](size_t i) const constant"
- << " { return elements[i]; }";
- for (auto* space : {"device", "thread", "threadgroup"}) {
- Line(buf) << " " << space << " T& operator[](size_t i) " << space
- << " { return elements[i]; }";
- Line(buf) << " const " << space << " T& operator[](size_t i) const " << space
- << " { return elements[i]; }";
- }
- Line(buf) << " T elements[N];";
- Line(buf) << "};";
- Line(buf);
- }
- return array_template_name_;
-}
-
-std::string ASTPrinter::StructName(const core::type::Struct* s) {
- auto name = s->Name().Name();
- if (HasPrefix(name, "__")) {
- name = tint::GetOrAdd(builtin_struct_names_, s,
- [&] { return UniqueIdentifier(name.substr(2)); });
- }
- return name;
-}
-
-std::string ASTPrinter::UniqueIdentifier(const std::string& prefix /* = "" */) {
- return builder_.Symbols().New(prefix).Name();
-}
-
-} // namespace tint::msl::writer
diff --git a/src/tint/lang/msl/writer/ast_printer/ast_printer.h b/src/tint/lang/msl/writer/ast_printer/ast_printer.h
deleted file mode 100644
index 780d676..0000000
--- a/src/tint/lang/msl/writer/ast_printer/ast_printer.h
+++ /dev/null
@@ -1,482 +0,0 @@
-// Copyright 2020 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef SRC_TINT_LANG_MSL_WRITER_AST_PRINTER_AST_PRINTER_H_
-#define SRC_TINT_LANG_MSL_WRITER_AST_PRINTER_AST_PRINTER_H_
-
-#include <string>
-#include <tuple>
-#include <unordered_map>
-#include <unordered_set>
-#include <vector>
-
-#include "src/tint/lang/core/builtin_value.h"
-#include "src/tint/lang/msl/writer/common/options.h"
-#include "src/tint/lang/wgsl/ast/assignment_statement.h"
-#include "src/tint/lang/wgsl/ast/binary_expression.h"
-#include "src/tint/lang/wgsl/ast/break_statement.h"
-#include "src/tint/lang/wgsl/ast/continue_statement.h"
-#include "src/tint/lang/wgsl/ast/discard_statement.h"
-#include "src/tint/lang/wgsl/ast/expression.h"
-#include "src/tint/lang/wgsl/ast/if_statement.h"
-#include "src/tint/lang/wgsl/ast/index_accessor_expression.h"
-#include "src/tint/lang/wgsl/ast/interpolate_attribute.h"
-#include "src/tint/lang/wgsl/ast/loop_statement.h"
-#include "src/tint/lang/wgsl/ast/member_accessor_expression.h"
-#include "src/tint/lang/wgsl/ast/return_statement.h"
-#include "src/tint/lang/wgsl/ast/switch_statement.h"
-#include "src/tint/lang/wgsl/ast/unary_op_expression.h"
-#include "src/tint/lang/wgsl/program/program.h"
-#include "src/tint/lang/wgsl/program/program_builder.h"
-#include "src/tint/lang/wgsl/sem/struct.h"
-#include "src/tint/utils/containers/scope_stack.h"
-#include "src/tint/utils/text/string_stream.h"
-#include "src/tint/utils/text_generator.h"
-
-namespace tint::sem {
-class BuiltinFn;
-class Call;
-class ValueConstructor;
-class ValueConversion;
-} // namespace tint::sem
-
-namespace tint::msl::writer {
-
-/// The result of sanitizing a program for generation.
-struct SanitizedResult {
- /// Constructor
- SanitizedResult();
- /// Destructor
- ~SanitizedResult();
- /// Move constructor
- SanitizedResult(SanitizedResult&&);
-
- /// The sanitized program.
- Program program;
- /// True if the shader needs a UBO of buffer sizes.
- bool needs_storage_buffer_sizes = false;
-};
-
-/// Sanitize a program in preparation for generating MSL.
-/// @param program The program to sanitize
-/// @param options The MSL generator options.
-/// @returns the sanitized program and any supplementary information
-SanitizedResult Sanitize(const Program& program, const Options& options);
-
-/// Implementation class for MSL generator
-class ASTPrinter : public tint::TextGenerator {
- public:
- /// Constructor
- /// @param program the program to generate
- /// @param options emission options
- explicit ASTPrinter(const Program& program, const Options& options = {});
- ~ASTPrinter() override;
-
- /// @returns true on successful generation; false otherwise
- bool Generate();
-
- /// @returns true if an invariant attribute was generated
- bool HasInvariant() { return !invariant_define_name_.empty(); }
-
- /// @returns a map from entry point to list of required workgroup allocations
- const std::unordered_map<std::string, std::vector<uint32_t>>& DynamicWorkgroupAllocations()
- const {
- return workgroup_allocations_;
- }
-
- /// Handles generating a declared type
- /// @param ty the declared type to generate
- /// @returns true if the declared type was emitted
- bool EmitTypeDecl(const core::type::Type* ty);
- /// Handles an index accessor expression
- /// @param out the output of the expression stream
- /// @param expr the expression to emit
- /// @returns true if the index accessor was emitted
- bool EmitIndexAccessor(StringStream& out, const ast::IndexAccessorExpression* expr);
- /// Handles an assignment statement
- /// @param stmt the statement to emit
- /// @returns true if the statement was emitted successfully
- bool EmitAssign(const ast::AssignmentStatement* stmt);
- /// Handles generating a binary expression
- /// @param out the output of the expression stream
- /// @param expr the binary expression
- /// @returns true if the expression was emitted, false otherwise
- bool EmitBinary(StringStream& out, const ast::BinaryExpression* expr);
- /// Handles generating a bitcast expression
- /// @param out the output of the expression stream
- /// @param expr the bitcast expression
- /// @returns true if the bitcast was emitted
- bool EmitBitcastCall(StringStream& out, const ast::CallExpression* expr);
- /// Handles a block statement
- /// @param stmt the statement to emit
- /// @returns true if the statement was emitted successfully
- bool EmitBlock(const ast::BlockStatement* stmt);
- /// Handles a break statement
- /// @param stmt the statement to emit
- /// @returns true if the statement was emitted successfully
- bool EmitBreak(const ast::BreakStatement* stmt);
- /// Handles a break-if statement
- /// @param stmt the statement to emit
- /// @returns true if the statement was emitted successfully
- bool EmitBreakIf(const ast::BreakIfStatement* stmt);
- /// Handles generating a call expression
- /// @param out the output of the expression stream
- /// @param expr the call expression
- /// @returns true if the call expression is emitted
- bool EmitCall(StringStream& out, const ast::CallExpression* expr);
- /// Handles generating a builtin call expression
- /// @param out the output of the expression stream
- /// @param call the call expression
- /// @param builtin the builtin being called
- /// @returns true if the call expression is emitted
- bool EmitBuiltinCall(StringStream& out, const sem::Call* call, const sem::BuiltinFn* builtin);
- /// Handles generating a value conversion expression
- /// @param out the output of the expression stream
- /// @param call the call expression
- /// @param conv the value conversion
- /// @returns true if the expression is emitted
- bool EmitTypeConversion(StringStream& out,
- const sem::Call* call,
- const sem::ValueConversion* conv);
- /// Handles generating a value constructor
- /// @param out the output of the expression stream
- /// @param call the call expression
- /// @param ctor the value constructor
- /// @returns true if the initializer is emitted
- bool EmitTypeInitializer(StringStream& out,
- const sem::Call* call,
- const sem::ValueConstructor* ctor);
- /// Handles generating a function call
- /// @param out the output of the expression stream
- /// @param call the call expression
- /// @param func the target function
- /// @returns true if the call is emitted
- bool EmitFunctionCall(StringStream& out, const sem::Call* call, const sem::Function* func);
- /// Handles generating a call to an atomic function (`atomicAdd`,
- /// `atomicMax`, etc)
- /// @param out the output of the expression stream
- /// @param expr the call expression
- /// @param builtin the semantic information for the atomic builtin
- /// @returns true if the call expression is emitted
- bool EmitAtomicCall(StringStream& out,
- const ast::CallExpression* expr,
- const sem::BuiltinFn* builtin);
- /// Handles generating a call to a texture function (`textureSample`,
- /// `textureSampleGrad`, etc)
- /// @param out the output of the expression stream
- /// @param call the call expression
- /// @param builtin the semantic information for the texture builtin
- /// @returns true if the call expression is emitted
- bool EmitTextureCall(StringStream& out, const sem::Call* call, const sem::BuiltinFn* builtin);
- /// Handles generating a call to the `dot()` builtin
- /// @param out the output of the expression stream
- /// @param expr the call expression
- /// @param builtin the semantic information for the builtin
- /// @returns true if the call expression is emitted
- bool EmitDotCall(StringStream& out,
- const ast::CallExpression* expr,
- const sem::BuiltinFn* builtin);
- /// Handles generating a call to the `modf()` builtin
- /// @param out the output of the expression stream
- /// @param expr the call expression
- /// @param builtin the semantic information for the builtin
- /// @returns true if the call expression is emitted
- bool EmitModfCall(StringStream& out,
- const ast::CallExpression* expr,
- const sem::BuiltinFn* builtin);
- /// Handles generating a call to the `frexp()` builtin
- /// @param out the output of the expression stream
- /// @param expr the call expression
- /// @param builtin the semantic information for the builtin
- /// @returns true if the call expression is emitted
- bool EmitFrexpCall(StringStream& out,
- const ast::CallExpression* expr,
- const sem::BuiltinFn* builtin);
- /// Handles generating a call to the `degrees()` builtin
- /// @param out the output of the expression stream
- /// @param expr the call expression
- /// @param builtin the semantic information for the builtin
- /// @returns true if the call expression is emitted
- bool EmitDegreesCall(StringStream& out,
- const ast::CallExpression* expr,
- const sem::BuiltinFn* builtin);
- /// Handles generating a call to the `radians()` builtin
- /// @param out the output of the expression stream
- /// @param expr the call expression
- /// @param builtin the semantic information for the builtin
- /// @returns true if the call expression is emitted
- bool EmitRadiansCall(StringStream& out,
- const ast::CallExpression* expr,
- const sem::BuiltinFn* builtin);
- /// Handles a case statement
- /// @param stmt the statement
- /// @returns true if the statement was emitted successfully
- bool EmitCase(const ast::CaseStatement* stmt);
- /// Handles a continue statement
- /// @param stmt the statement to emit
- /// @returns true if the statement was emitted successfully
- bool EmitContinue(const ast::ContinueStatement* stmt);
- /// Handles generating a discard statement
- /// @param stmt the discard statement
- /// @returns true if the statement was successfully emitted
- bool EmitDiscard(const ast::DiscardStatement* stmt);
- /// Handles emitting the entry point function
- /// @param func the entry point function
- /// @returns true if the entry point function was emitted
- bool EmitEntryPointFunction(const ast::Function* func);
- /// Handles generate an Expression
- /// @param out the output of the expression stream
- /// @param expr the expression
- /// @returns true if the expression was emitted
- bool EmitExpression(StringStream& out, const ast::Expression* expr);
- /// Handles generating a function
- /// @param func the function to generate
- /// @returns true if the function was emitted
- bool EmitFunction(const ast::Function* func);
- /// Handles generating an identifier expression
- /// @param out the output of the expression stream
- /// @param expr the identifier expression
- /// @returns true if the identifier was emitted
- bool EmitIdentifier(StringStream& out, const ast::IdentifierExpression* expr);
- /// Handles an if statement
- /// @param stmt the statement to emit
- /// @returns true if the statement was successfully emitted
- bool EmitIf(const ast::IfStatement* stmt);
- /// Handles a constant value
- /// @param out the output stream
- /// @param constant the constant value to emit
- /// @returns true if the constant value was successfully emitted
- bool EmitConstant(StringStream& out, const core::constant::Value* constant);
- /// Handles a literal
- /// @param out the output of the expression stream
- /// @param lit the literal to emit
- /// @returns true if the literal was successfully emitted
- bool EmitLiteral(StringStream& out, const ast::LiteralExpression* lit);
- /// Handles a loop statement
- /// @param stmt the statement to emit
- /// @returns true if the statement was emitted
- bool EmitLoop(const ast::LoopStatement* stmt);
- /// Handles a for loop statement
- /// @param stmt the statement to emit
- /// @returns true if the statement was emitted
- bool EmitForLoop(const ast::ForLoopStatement* stmt);
- /// Handles a while statement
- /// @param stmt the statement to emit
- /// @returns true if the statement was emitted
- bool EmitWhile(const ast::WhileStatement* stmt);
- /// Handles a member accessor expression
- /// @param out the output of the expression stream
- /// @param expr the member accessor expression
- /// @returns true if the member accessor was emitted
- bool EmitMemberAccessor(StringStream& out, const ast::MemberAccessorExpression* expr);
- /// Handles return statements
- /// @param stmt the statement to emit
- /// @returns true if the statement was successfully emitted
- bool EmitReturn(const ast::ReturnStatement* stmt);
- /// Handles emitting a pipeline stage name
- /// @param out the output of the expression stream
- /// @param stage the stage to emit
- void EmitStage(StringStream& out, ast::PipelineStage stage);
- /// Handles statement
- /// @param stmt the statement to emit
- /// @returns true if the statement was emitted
- bool EmitStatement(const ast::Statement* stmt);
- /// Emits a list of statements
- /// @param stmts the statement list
- /// @returns true if the statements were emitted successfully
- bool EmitStatements(VectorRef<const ast::Statement*> stmts);
- /// Emits a list of statements with an indentation
- /// @param stmts the statement list
- /// @returns true if the statements were emitted successfully
- bool EmitStatementsWithIndent(VectorRef<const ast::Statement*> stmts);
- /// Handles generating a switch statement
- /// @param stmt the statement to emit
- /// @returns true if the statement was emitted
- bool EmitSwitch(const ast::SwitchStatement* stmt);
- /// Handles generating a type
- /// @param out the output of the type stream
- /// @param type the type to generate
- /// @returns true if the type is emitted
- bool EmitType(StringStream& out, const core::type::Type* type);
- /// Handles generating type and name
- /// @param out the output stream
- /// @param type the type to generate
- /// @param name the name to emit
- /// @returns true if the type is emitted
- bool EmitTypeAndName(StringStream& out, const core::type::Type* type, const std::string& name);
- /// Handles generating a address space
- /// @param out the output of the type stream
- /// @param sc the address space to generate
- /// @returns true if the address space is emitted
- bool EmitAddressSpace(StringStream& out, core::AddressSpace sc);
- /// Handles generating a struct declaration. If the structure has already been emitted, then
- /// this function will simply return `true` without emitting anything.
- /// @param buffer the text buffer that the type declaration will be written to
- /// @param str the struct to generate
- /// @returns true if the struct is emitted
- bool EmitStructType(TextBuffer* buffer, const core::type::Struct* str);
- /// Handles a unary op expression
- /// @param out the output of the expression stream
- /// @param expr the expression to emit
- /// @returns true if the expression was emitted
- bool EmitUnaryOp(StringStream& out, const ast::UnaryOpExpression* expr);
- /// Handles generating a 'var' declaration
- /// @param var the variable to generate
- /// @returns true if the variable was emitted
- bool EmitVar(const ast::Var* var);
- /// Handles generating a 'let' declaration
- /// @param let the variable to generate
- /// @returns true if the variable was emitted
- bool EmitLet(const ast::Let* let);
- /// Emits the zero value for the given type
- /// @param out the output of the expression stream
- /// @param type the type to emit the value for
- /// @returns true if the zero value was successfully emitted.
- bool EmitZeroValue(StringStream& out, const core::type::Type* type);
- /// Handles generating a call to the `dot4I8Packed()` builtin
- /// @param out the output of the expression stream
- /// @param expr the call expression
- /// @param builtin the semantic information for the builtin
- /// @returns true if the call expression is emitted
- bool EmitDot4I8PackedCall(StringStream& out,
- const ast::CallExpression* expr,
- const sem::BuiltinFn* builtin);
- /// Handles generating a call to the `dot4U8Packed()` builtin
- /// @param out the output of the expression stream
- /// @param expr the call expression
- /// @param builtin the semantic information for the builtin
- /// @returns true if the call expression is emitted
- bool EmitDot4U8PackedCall(StringStream& out,
- const ast::CallExpression* expr,
- const sem::BuiltinFn* builtin);
-
- /// If robustness is required, emits code to prevent the MSL compiler
- /// from believing the loop is infinite.
- /// Otherwise does nothing.
- void IsolateUBIfNeeded();
-
- /// Lazily generates the TINT_ISOLATE_UB macro, and returns a call to
- /// the macro, passing in a unique identifier. The call tricks the MSL
- /// compiler into thinking it might execute a `break`, but otherwise
- /// has no effect in the generated code.
- ///
- /// Invoke this inside the body of a loop to prevent the MSL compiler
- /// from inferring the loop never terminates.
- /// @return the MSL to call the TINT_ISOLATE_UB macro.
- std::string IsolateUB();
-
- /// Handles generating a builtin name
- /// @param builtin the semantic info for the builtin
- /// @returns the name or "" if not valid
- std::string generate_builtin_name(const sem::BuiltinFn* builtin);
-
- private:
- /// CallBuiltinHelper will call the builtin helper function, creating it
- /// if it hasn't been built already. If the builtin needs to be built then
- /// CallBuiltinHelper will generate the function signature and will call
- /// `build` to emit the body of the function.
- /// @param out the output of the expression stream
- /// @param call the call expression
- /// @param builtin the semantic information for the builtin
- /// @param build a function with the signature:
- /// `bool(TextBuffer* buffer, const std::vector<std::string>& params)`
- /// Where:
- /// `buffer` is the body of the generated function
- /// `params` is the name of all the generated function parameters
- /// @returns true if the call expression is emitted
- template <typename F>
- bool CallBuiltinHelper(StringStream& out,
- const ast::CallExpression* call,
- const sem::BuiltinFn* builtin,
- F&& build);
-
- /// @returns the name of the templated tint_array helper type, generating it if this is the
- /// first call.
- const std::string& ArrayType();
-
- /// @param s the structure
- /// @returns the name of the structure, taking special care of builtin structures that start
- /// with double underscores. If the structure is a builtin, then the returned name will be a
- /// unique name without the leading underscores.
- std::string StructName(const core::type::Struct* s);
-
- /// @return a new, unique identifier with the given prefix.
- /// @param prefix optional prefix to apply to the generated identifier. If empty "tint_symbol"
- /// will be used.
- std::string UniqueIdentifier(const std::string& prefix = "");
-
- /// Alias for builder_.TypeOf(ptr)
- template <typename T>
- auto TypeOf(T* ptr) {
- return builder_.TypeOf(ptr);
- }
-
- ProgramBuilder builder_;
- Options options_;
-
- TextBuffer helpers_; // Helper functions emitted at the top of the output
-
- /// Map of builtin structure to unique generated name
- std::unordered_map<const core::type::Struct*, std::string> builtin_struct_names_;
-
- std::function<bool()> emit_continuing_;
-
- /// The name of the macro used to prevent UB affecting later control flow.
- /// Do not use this directly, instead call IsolateUB().
- std::string isolate_ub_macro_name_;
-
- /// Name of atomicCompareExchangeWeak() helper for the given pointer storage
- /// class and struct return type
- using ACEWKeyType =
- tint::UnorderedKeyWrapper<std::tuple<core::AddressSpace, const core::type::Struct*>>;
- std::unordered_map<ACEWKeyType, std::string> atomicCompareExchangeWeak_;
-
- /// Unique name of the 'TINT_INVARIANT' preprocessor define.
- /// Non-empty only if an invariant attribute has been generated.
- std::string invariant_define_name_;
-
- /// The generated name for the packed vec3 type.
- std::string packed_vec3_ty_;
-
- /// Unique name of the tint_array<T, N> template.
- /// Non-empty only if the template has been generated.
- std::string array_template_name_;
-
- /// A map from entry point name to a list of dynamic workgroup allocations.
- /// Each entry in the vector is the size of the workgroup allocation that
- /// should be created for that index.
- std::unordered_map<std::string, std::vector<uint32_t>> workgroup_allocations_;
-
- std::unordered_map<const sem::BuiltinFn*, std::string> builtins_;
- std::unordered_map<const core::type::Type*, std::string> unary_minus_funcs_;
- std::unordered_map<uint32_t, std::string> int_dot_funcs_;
- std::unordered_set<const core::type::Struct*> emitted_structs_;
-};
-
-} // namespace tint::msl::writer
-
-#endif // SRC_TINT_LANG_MSL_WRITER_AST_PRINTER_AST_PRINTER_H_
diff --git a/src/tint/lang/msl/writer/ast_printer/ast_printer_test.cc b/src/tint/lang/msl/writer/ast_printer/ast_printer_test.cc
deleted file mode 100644
index 5548533..0000000
--- a/src/tint/lang/msl/writer/ast_printer/ast_printer_test.cc
+++ /dev/null
@@ -1,531 +0,0 @@
-// Copyright 2020 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/tint/lang/core/fluent_types.h"
-#include "src/tint/lang/msl/writer/ast_printer/helper_test.h"
-#include "src/tint/lang/msl/writer/writer.h"
-#include "src/tint/lang/wgsl/ast/stage_attribute.h"
-
-using namespace tint::core::number_suffixes; // NOLINT
-using namespace tint::core::fluent_types; // NOLINT
-
-namespace tint::msl::writer {
-namespace {
-
-using MslASTPrinterTest = TestHelper;
-
-TEST_F(MslASTPrinterTest, InvalidProgram) {
- Diagnostics().AddError(Source{}) << "make the program invalid";
- ASSERT_FALSE(IsValid());
- auto program = resolver::Resolve(*this);
- ASSERT_FALSE(program.IsValid());
- auto result = Generate(program, Options{});
- EXPECT_NE(result, Success);
- EXPECT_EQ(result.Failure().reason.Str(), "error: make the program invalid");
-}
-
-TEST_F(MslASTPrinterTest, UnsupportedExtension) {
- Enable(Source{{12, 34}}, wgsl::Extension::kChromiumExperimentalPushConstant);
-
- ASTPrinter& gen = Build();
-
- ASSERT_FALSE(gen.Generate());
- EXPECT_EQ(
- gen.Diagnostics().Str(),
- R"(12:34 error: MSL backend does not support extension 'chromium_experimental_push_constant')");
-}
-
-TEST_F(MslASTPrinterTest, RequiresDirective) {
- Require(wgsl::LanguageFeature::kReadonlyAndReadwriteStorageTextures);
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-)");
-}
-
-TEST_F(MslASTPrinterTest, Generate) {
- Func("my_func", tint::Empty, ty.void_(), tint::Empty,
- Vector{
- Stage(ast::PipelineStage::kCompute),
- WorkgroupSize(1_i),
- });
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-kernel void my_func() {
- return;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, HasInvariantAttribute_True) {
- auto* out = Structure("Out", Vector{
- Member("pos", ty.vec4<f32>(),
- Vector{
- Builtin(core::BuiltinValue::kPosition),
- Invariant(),
- }),
- });
- Func("vert_main", tint::Empty, ty.Of(out), Vector{Return(Call(ty.Of(out)))},
- Vector{
- Stage(ast::PipelineStage::kVertex),
- });
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_TRUE(gen.HasInvariant());
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-
-#if __METAL_VERSION__ >= 210
-#define TINT_INVARIANT [[invariant]]
-#else
-#define TINT_INVARIANT
-#endif
-
-struct Out {
- float4 pos [[position]] TINT_INVARIANT;
-};
-
-vertex Out vert_main() {
- return Out{};
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, HasInvariantAttribute_False) {
- auto* out = Structure("Out", Vector{
- Member("pos", ty.vec4<f32>(),
- Vector{
- Builtin(core::BuiltinValue::kPosition),
- }),
- });
- Func("vert_main", tint::Empty, ty.Of(out), Vector{Return(Call(ty.Of(out)))},
- Vector{
- Stage(ast::PipelineStage::kVertex),
- });
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_FALSE(gen.HasInvariant());
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-struct Out {
- float4 pos [[position]];
-};
-
-vertex Out vert_main() {
- return Out{};
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, WorkgroupMatrix) {
- GlobalVar("m", ty.mat2x2<f32>(), core::AddressSpace::kWorkgroup);
- Func("comp_main", tint::Empty, ty.void_(), Vector{Decl(Let("x", Expr("m")))},
- Vector{
- Stage(ast::PipelineStage::kCompute),
- WorkgroupSize(1_i),
- });
-
- ASTPrinter& gen = SanitizeAndBuild();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-struct tint_symbol_4 {
- float2x2 m;
-};
-
-void tint_zero_workgroup_memory(uint local_idx, threadgroup float2x2* const tint_symbol) {
- if ((local_idx < 1u)) {
- *(tint_symbol) = float2x2(float2(0.0f), float2(0.0f));
- }
- threadgroup_barrier(mem_flags::mem_threadgroup);
-}
-
-void comp_main_inner(uint local_invocation_index, threadgroup float2x2* const tint_symbol_1) {
- tint_zero_workgroup_memory(local_invocation_index, tint_symbol_1);
- float2x2 const x = *(tint_symbol_1);
-}
-
-kernel void comp_main(threadgroup tint_symbol_4* tint_symbol_3 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
- threadgroup float2x2* const tint_symbol_2 = &((*(tint_symbol_3)).m);
- comp_main_inner(local_invocation_index, tint_symbol_2);
- return;
-}
-
-)");
-
- auto allocations = gen.DynamicWorkgroupAllocations();
- ASSERT_TRUE(allocations.count("comp_main"));
- ASSERT_EQ(allocations.at("comp_main").size(), 1u);
- EXPECT_EQ(allocations.at("comp_main")[0], 2u * 2u * sizeof(float));
-}
-
-TEST_F(MslASTPrinterTest, WorkgroupMatrixInArray) {
- GlobalVar("m", ty.array(ty.mat2x2<f32>(), 4_i), core::AddressSpace::kWorkgroup);
- Func("comp_main", tint::Empty, ty.void_(), Vector{Decl(Let("x", Expr("m")))},
- Vector{
- Stage(ast::PipelineStage::kCompute),
- WorkgroupSize(1_i),
- });
-
- ASTPrinter& gen = SanitizeAndBuild();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-
-template<typename T, size_t N>
-struct tint_array {
- const constant T& operator[](size_t i) const constant { return elements[i]; }
- device T& operator[](size_t i) device { return elements[i]; }
- const device T& operator[](size_t i) const device { return elements[i]; }
- thread T& operator[](size_t i) thread { return elements[i]; }
- const thread T& operator[](size_t i) const thread { return elements[i]; }
- threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
- const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
- T elements[N];
-};
-
-struct tint_symbol_4 {
- tint_array<float2x2, 4> m;
-};
-
-void tint_zero_workgroup_memory(uint local_idx, threadgroup tint_array<float2x2, 4>* const tint_symbol) {
- for(uint idx = local_idx; (idx < 4u); idx = (idx + 1u)) {
- uint const i = idx;
- (*(tint_symbol))[i] = float2x2(float2(0.0f), float2(0.0f));
- }
- threadgroup_barrier(mem_flags::mem_threadgroup);
-}
-
-void comp_main_inner(uint local_invocation_index, threadgroup tint_array<float2x2, 4>* const tint_symbol_1) {
- tint_zero_workgroup_memory(local_invocation_index, tint_symbol_1);
- tint_array<float2x2, 4> const x = *(tint_symbol_1);
-}
-
-kernel void comp_main(threadgroup tint_symbol_4* tint_symbol_3 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
- threadgroup tint_array<float2x2, 4>* const tint_symbol_2 = &((*(tint_symbol_3)).m);
- comp_main_inner(local_invocation_index, tint_symbol_2);
- return;
-}
-
-)");
-
- auto allocations = gen.DynamicWorkgroupAllocations();
- ASSERT_TRUE(allocations.count("comp_main"));
- ASSERT_EQ(allocations.at("comp_main").size(), 1u);
- EXPECT_EQ(allocations.at("comp_main")[0], 4u * 2u * 2u * sizeof(float));
-}
-
-TEST_F(MslASTPrinterTest, WorkgroupMatrixInStruct) {
- Structure("S1", Vector{
- Member("m1", ty.mat2x2<f32>()),
- Member("m2", ty.mat4x4<f32>()),
- });
- Structure("S2", Vector{
- Member("s", ty("S1")),
- });
- GlobalVar("s", ty("S2"), core::AddressSpace::kWorkgroup);
- Func("comp_main", tint::Empty, ty.void_(), Vector{Decl(Let("x", Expr("s")))},
- Vector{
- Stage(ast::PipelineStage::kCompute),
- WorkgroupSize(1_i),
- });
-
- ASTPrinter& gen = SanitizeAndBuild();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-struct S1 {
- float2x2 m1;
- float4x4 m2;
-};
-
-struct S2 {
- S1 s;
-};
-
-struct tint_symbol_5 {
- S2 s;
-};
-
-void tint_zero_workgroup_memory(uint local_idx, threadgroup S2* const tint_symbol_1) {
- if ((local_idx < 1u)) {
- S2 const tint_symbol = S2{};
- *(tint_symbol_1) = tint_symbol;
- }
- threadgroup_barrier(mem_flags::mem_threadgroup);
-}
-
-void comp_main_inner(uint local_invocation_index, threadgroup S2* const tint_symbol_2) {
- tint_zero_workgroup_memory(local_invocation_index, tint_symbol_2);
- S2 const x = *(tint_symbol_2);
-}
-
-kernel void comp_main(threadgroup tint_symbol_5* tint_symbol_4 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
- threadgroup S2* const tint_symbol_3 = &((*(tint_symbol_4)).s);
- comp_main_inner(local_invocation_index, tint_symbol_3);
- return;
-}
-
-)");
-
- auto allocations = gen.DynamicWorkgroupAllocations();
- ASSERT_TRUE(allocations.count("comp_main"));
- ASSERT_EQ(allocations.at("comp_main").size(), 1u);
- EXPECT_EQ(allocations.at("comp_main")[0], (2 * 2 * sizeof(float)) + (4u * 4u * sizeof(float)));
-}
-
-TEST_F(MslASTPrinterTest, WorkgroupMatrix_Multiples) {
- GlobalVar("m1", ty.mat2x2<f32>(), core::AddressSpace::kWorkgroup);
- GlobalVar("m2", ty.mat2x3<f32>(), core::AddressSpace::kWorkgroup);
- GlobalVar("m3", ty.mat2x4<f32>(), core::AddressSpace::kWorkgroup);
- GlobalVar("m4", ty.mat3x2<f32>(), core::AddressSpace::kWorkgroup);
- GlobalVar("m5", ty.mat3x3<f32>(), core::AddressSpace::kWorkgroup);
- GlobalVar("m6", ty.mat3x4<f32>(), core::AddressSpace::kWorkgroup);
- GlobalVar("m7", ty.mat4x2<f32>(), core::AddressSpace::kWorkgroup);
- GlobalVar("m8", ty.mat4x3<f32>(), core::AddressSpace::kWorkgroup);
- GlobalVar("m9", ty.mat4x4<f32>(), core::AddressSpace::kWorkgroup);
- Func("main1", tint::Empty, ty.void_(),
- Vector{
- Decl(Let("a1", Expr("m1"))),
- Decl(Let("a2", Expr("m2"))),
- Decl(Let("a3", Expr("m3"))),
- },
- Vector{
- Stage(ast::PipelineStage::kCompute),
- WorkgroupSize(1_i),
- });
- Func("main2", tint::Empty, ty.void_(),
- Vector{
- Decl(Let("a1", Expr("m4"))),
- Decl(Let("a2", Expr("m5"))),
- Decl(Let("a3", Expr("m6"))),
- },
- Vector{
- Stage(ast::PipelineStage::kCompute),
- WorkgroupSize(1_i),
- });
- Func("main3", tint::Empty, ty.void_(),
- Vector{
- Decl(Let("a1", Expr("m7"))),
- Decl(Let("a2", Expr("m8"))),
- Decl(Let("a3", Expr("m9"))),
- },
- Vector{
- Stage(ast::PipelineStage::kCompute),
- WorkgroupSize(1_i),
- });
- Func("main4_no_usages", tint::Empty, ty.void_(), tint::Empty,
- Vector{
- Stage(ast::PipelineStage::kCompute),
- WorkgroupSize(1_i),
- });
-
- ASTPrinter& gen = SanitizeAndBuild();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-
-template<typename T, size_t N>
-struct tint_array {
- const constant T& operator[](size_t i) const constant { return elements[i]; }
- device T& operator[](size_t i) device { return elements[i]; }
- const device T& operator[](size_t i) const device { return elements[i]; }
- thread T& operator[](size_t i) thread { return elements[i]; }
- const thread T& operator[](size_t i) const thread { return elements[i]; }
- threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
- const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
- T elements[N];
-};
-
-struct tint_symbol_16 {
- float2x2 m1;
- float2x4 m3;
-};
-
-struct tint_symbol_24 {
- float3x2 m4;
- float3x4 m6;
-};
-
-struct tint_symbol_32 {
- float4x2 m7;
- float4x4 m9;
-};
-
-struct tint_packed_vec3_f32_array_element {
- packed_float3 elements;
-};
-
-float2x3 tint_unpack_vec3_in_composite(tint_array<tint_packed_vec3_f32_array_element, 2> in) {
- float2x3 result = float2x3(float3(in[0].elements), float3(in[1].elements));
- return result;
-}
-
-float3x3 tint_unpack_vec3_in_composite_1(tint_array<tint_packed_vec3_f32_array_element, 3> in) {
- float3x3 result = float3x3(float3(in[0].elements), float3(in[1].elements), float3(in[2].elements));
- return result;
-}
-
-float4x3 tint_unpack_vec3_in_composite_2(tint_array<tint_packed_vec3_f32_array_element, 4> in) {
- float4x3 result = float4x3(float3(in[0].elements), float3(in[1].elements), float3(in[2].elements), float3(in[3].elements));
- return result;
-}
-
-tint_array<tint_packed_vec3_f32_array_element, 2> tint_pack_vec3_in_composite(float2x3 in) {
- tint_array<tint_packed_vec3_f32_array_element, 2> result = tint_array<tint_packed_vec3_f32_array_element, 2>{tint_packed_vec3_f32_array_element{.elements=packed_float3(in[0])}, tint_packed_vec3_f32_array_element{.elements=packed_float3(in[1])}};
- return result;
-}
-
-tint_array<tint_packed_vec3_f32_array_element, 3> tint_pack_vec3_in_composite_1(float3x3 in) {
- tint_array<tint_packed_vec3_f32_array_element, 3> result = tint_array<tint_packed_vec3_f32_array_element, 3>{tint_packed_vec3_f32_array_element{.elements=packed_float3(in[0])}, tint_packed_vec3_f32_array_element{.elements=packed_float3(in[1])}, tint_packed_vec3_f32_array_element{.elements=packed_float3(in[2])}};
- return result;
-}
-
-tint_array<tint_packed_vec3_f32_array_element, 4> tint_pack_vec3_in_composite_2(float4x3 in) {
- tint_array<tint_packed_vec3_f32_array_element, 4> result = tint_array<tint_packed_vec3_f32_array_element, 4>{tint_packed_vec3_f32_array_element{.elements=packed_float3(in[0])}, tint_packed_vec3_f32_array_element{.elements=packed_float3(in[1])}, tint_packed_vec3_f32_array_element{.elements=packed_float3(in[2])}, tint_packed_vec3_f32_array_element{.elements=packed_float3(in[3])}};
- return result;
-}
-
-void tint_zero_workgroup_memory(uint local_idx, threadgroup float2x2* const tint_symbol, threadgroup tint_array<tint_packed_vec3_f32_array_element, 2>* const tint_symbol_1, threadgroup float2x4* const tint_symbol_2) {
- if ((local_idx < 1u)) {
- *(tint_symbol) = float2x2(float2(0.0f), float2(0.0f));
- *(tint_symbol_1) = tint_pack_vec3_in_composite(float2x3(float3(0.0f), float3(0.0f)));
- *(tint_symbol_2) = float2x4(float4(0.0f), float4(0.0f));
- }
- threadgroup_barrier(mem_flags::mem_threadgroup);
-}
-
-void tint_zero_workgroup_memory_1(uint local_idx_1, threadgroup float3x2* const tint_symbol_3, threadgroup tint_array<tint_packed_vec3_f32_array_element, 3>* const tint_symbol_4, threadgroup float3x4* const tint_symbol_5) {
- if ((local_idx_1 < 1u)) {
- *(tint_symbol_3) = float3x2(float2(0.0f), float2(0.0f), float2(0.0f));
- *(tint_symbol_4) = tint_pack_vec3_in_composite_1(float3x3(float3(0.0f), float3(0.0f), float3(0.0f)));
- *(tint_symbol_5) = float3x4(float4(0.0f), float4(0.0f), float4(0.0f));
- }
- threadgroup_barrier(mem_flags::mem_threadgroup);
-}
-
-void tint_zero_workgroup_memory_2(uint local_idx_2, threadgroup float4x2* const tint_symbol_6, threadgroup tint_array<tint_packed_vec3_f32_array_element, 4>* const tint_symbol_7, threadgroup float4x4* const tint_symbol_8) {
- if ((local_idx_2 < 1u)) {
- *(tint_symbol_6) = float4x2(float2(0.0f), float2(0.0f), float2(0.0f), float2(0.0f));
- *(tint_symbol_7) = tint_pack_vec3_in_composite_2(float4x3(float3(0.0f), float3(0.0f), float3(0.0f), float3(0.0f)));
- *(tint_symbol_8) = float4x4(float4(0.0f), float4(0.0f), float4(0.0f), float4(0.0f));
- }
- threadgroup_barrier(mem_flags::mem_threadgroup);
-}
-
-void main1_inner(uint local_invocation_index, threadgroup float2x2* const tint_symbol_9, threadgroup tint_array<tint_packed_vec3_f32_array_element, 2>* const tint_symbol_10, threadgroup float2x4* const tint_symbol_11) {
- tint_zero_workgroup_memory(local_invocation_index, tint_symbol_9, tint_symbol_10, tint_symbol_11);
- float2x2 const a1 = *(tint_symbol_9);
- float2x3 const a2 = tint_unpack_vec3_in_composite(*(tint_symbol_10));
- float2x4 const a3 = *(tint_symbol_11);
-}
-
-kernel void main1(threadgroup tint_symbol_16* tint_symbol_13 [[threadgroup(0)]], uint local_invocation_index [[thread_index_in_threadgroup]]) {
- threadgroup float2x2* const tint_symbol_12 = &((*(tint_symbol_13)).m1);
- threadgroup tint_array<tint_packed_vec3_f32_array_element, 2> tint_symbol_14;
- threadgroup float2x4* const tint_symbol_15 = &((*(tint_symbol_13)).m3);
- main1_inner(local_invocation_index, tint_symbol_12, &(tint_symbol_14), tint_symbol_15);
- return;
-}
-
-void main2_inner(uint local_invocation_index_1, threadgroup float3x2* const tint_symbol_17, threadgroup tint_array<tint_packed_vec3_f32_array_element, 3>* const tint_symbol_18, threadgroup float3x4* const tint_symbol_19) {
- tint_zero_workgroup_memory_1(local_invocation_index_1, tint_symbol_17, tint_symbol_18, tint_symbol_19);
- float3x2 const a1 = *(tint_symbol_17);
- float3x3 const a2 = tint_unpack_vec3_in_composite_1(*(tint_symbol_18));
- float3x4 const a3 = *(tint_symbol_19);
-}
-
-kernel void main2(threadgroup tint_symbol_24* tint_symbol_21 [[threadgroup(0)]], uint local_invocation_index_1 [[thread_index_in_threadgroup]]) {
- threadgroup float3x2* const tint_symbol_20 = &((*(tint_symbol_21)).m4);
- threadgroup tint_array<tint_packed_vec3_f32_array_element, 3> tint_symbol_22;
- threadgroup float3x4* const tint_symbol_23 = &((*(tint_symbol_21)).m6);
- main2_inner(local_invocation_index_1, tint_symbol_20, &(tint_symbol_22), tint_symbol_23);
- return;
-}
-
-void main3_inner(uint local_invocation_index_2, threadgroup float4x2* const tint_symbol_25, threadgroup tint_array<tint_packed_vec3_f32_array_element, 4>* const tint_symbol_26, threadgroup float4x4* const tint_symbol_27) {
- tint_zero_workgroup_memory_2(local_invocation_index_2, tint_symbol_25, tint_symbol_26, tint_symbol_27);
- float4x2 const a1 = *(tint_symbol_25);
- float4x3 const a2 = tint_unpack_vec3_in_composite_2(*(tint_symbol_26));
- float4x4 const a3 = *(tint_symbol_27);
-}
-
-kernel void main3(threadgroup tint_symbol_32* tint_symbol_29 [[threadgroup(0)]], uint local_invocation_index_2 [[thread_index_in_threadgroup]]) {
- threadgroup float4x2* const tint_symbol_28 = &((*(tint_symbol_29)).m7);
- threadgroup tint_array<tint_packed_vec3_f32_array_element, 4> tint_symbol_30;
- threadgroup float4x4* const tint_symbol_31 = &((*(tint_symbol_29)).m9);
- main3_inner(local_invocation_index_2, tint_symbol_28, &(tint_symbol_30), tint_symbol_31);
- return;
-}
-
-kernel void main4_no_usages() {
- return;
-}
-
-)");
-
- auto allocations = gen.DynamicWorkgroupAllocations();
- ASSERT_TRUE(allocations.count("main1"));
- ASSERT_TRUE(allocations.count("main2"));
- ASSERT_TRUE(allocations.count("main3"));
- ASSERT_EQ(allocations.at("main1").size(), 1u);
- EXPECT_EQ(allocations.at("main1")[0], 12u * sizeof(float));
- ASSERT_EQ(allocations.at("main2").size(), 1u);
- EXPECT_EQ(allocations.at("main2")[0], 20u * sizeof(float));
- ASSERT_EQ(allocations.at("main3").size(), 1u);
- EXPECT_EQ(allocations.at("main3")[0], 24u * sizeof(float));
- EXPECT_EQ(allocations.at("main4_no_usages").size(), 0u);
-}
-
-} // namespace
-} // namespace tint::msl::writer
diff --git a/src/tint/lang/msl/writer/ast_printer/ast_type_test.cc b/src/tint/lang/msl/writer/ast_printer/ast_type_test.cc
deleted file mode 100644
index e39b685..0000000
--- a/src/tint/lang/msl/writer/ast_printer/ast_type_test.cc
+++ /dev/null
@@ -1,932 +0,0 @@
-// Copyright 2020 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include <array>
-
-#include "gmock/gmock.h"
-
-#include "src/tint/lang/core/type/depth_multisampled_texture.h"
-#include "src/tint/lang/core/type/depth_texture.h"
-#include "src/tint/lang/core/type/multisampled_texture.h"
-#include "src/tint/lang/core/type/sampled_texture.h"
-#include "src/tint/lang/core/type/sampler.h"
-#include "src/tint/lang/core/type/storage_texture.h"
-#include "src/tint/lang/core/type/texture_dimension.h"
-#include "src/tint/lang/msl/writer/ast_printer/helper_test.h"
-#include "src/tint/utils/text/string_stream.h"
-
-// Done except for two questions on:
-// TEST_F(MslASTPrinterTest, EmitType_Struct_WithAttribute) {
-// TEST_F(MslASTPrinterTest, EmitType_Pointer) {
-
-namespace tint::msl::writer {
-namespace {
-
-using ::testing::HasSubstr;
-using namespace tint::core::fluent_types; // NOLINT
-using namespace tint::core::number_suffixes; // NOLINT
-
-void FormatMSLField(StringStream& out,
- const char* addr,
- const char* type,
- size_t array_count,
- const char* name) {
- out << " /* " << std::string(addr) << " */ ";
- if (array_count == 0) {
- out << type << " ";
- } else {
- out << "tint_array<" << type << ", " << std::to_string(array_count) << "> ";
- }
- out << name << ";\n";
-}
-
-#define CHECK_TYPE_SIZE_AND_ALIGN(TYPE, SIZE, ALIGN) \
- static_assert(sizeof(TYPE) == SIZE, "Bad type size"); \
- static_assert(alignof(TYPE) == ALIGN, "Bad type alignment")
-
-// Declare C++ types that match the size and alignment of the types of the same
-// name in MSL.
-#define DECLARE_TYPE(NAME, SIZE, ALIGN) \
- struct alignas(ALIGN) NAME { \
- uint8_t _[SIZE]; \
- }; \
- CHECK_TYPE_SIZE_AND_ALIGN(NAME, SIZE, ALIGN)
-
-// Size and alignments taken from the MSL spec:
-// https://developer.apple.com/metal/Metal-Shading-Language-Specification.pdf
-DECLARE_TYPE(float2, 8, 8);
-DECLARE_TYPE(float3, 12, 4);
-DECLARE_TYPE(float4, 16, 16);
-DECLARE_TYPE(float2x2, 16, 8);
-DECLARE_TYPE(float2x3, 32, 16);
-DECLARE_TYPE(float2x4, 32, 16);
-DECLARE_TYPE(float3x2, 24, 8);
-DECLARE_TYPE(float3x3, 48, 16);
-DECLARE_TYPE(float3x4, 48, 16);
-DECLARE_TYPE(float4x2, 32, 8);
-DECLARE_TYPE(float4x3, 64, 16);
-DECLARE_TYPE(float4x4, 64, 16);
-DECLARE_TYPE(half2, 4, 4);
-DECLARE_TYPE(packed_half3, 6, 2);
-DECLARE_TYPE(half4, 8, 8);
-DECLARE_TYPE(half2x2, 8, 4);
-DECLARE_TYPE(half2x3, 16, 8);
-DECLARE_TYPE(half2x4, 16, 8);
-DECLARE_TYPE(half3x2, 12, 4);
-DECLARE_TYPE(half3x3, 24, 8);
-DECLARE_TYPE(half3x4, 24, 8);
-DECLARE_TYPE(half4x2, 16, 4);
-DECLARE_TYPE(half4x3, 32, 8);
-DECLARE_TYPE(half4x4, 32, 8);
-using uint = unsigned int;
-
-using MslASTPrinterTest = TestHelper;
-
-// MslPrinterTest.EmitType_Array
-TEST_F(MslASTPrinterTest, EmitType_Array) {
- auto arr = ty.array<bool, 4>();
- ast::Type type = GlobalVar("G", arr, core::AddressSpace::kPrivate)->type;
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitType(out, program->TypeOf(type))) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "tint_array<bool, 4>");
-}
-
-// MslPrinterTest.EmitType_ArrayOfArray
-TEST_F(MslASTPrinterTest, EmitType_ArrayOfArray) {
- auto a = ty.array<bool, 4>();
- auto b = ty.array(a, 5_u);
- ast::Type type = GlobalVar("G", b, core::AddressSpace::kPrivate)->type;
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitType(out, program->TypeOf(type))) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "tint_array<tint_array<bool, 4>, 5>");
-}
-
-// MslPrinterTest.EmitType_ArrayOfArrayOfArray
-TEST_F(MslASTPrinterTest, EmitType_ArrayOfArrayOfArray) {
- auto a = ty.array<bool, 4>();
- auto b = ty.array(a, 5_u);
- auto c = ty.array(b, 6_u);
- ast::Type type = GlobalVar("G", c, core::AddressSpace::kPrivate)->type;
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitType(out, program->TypeOf(type))) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "tint_array<tint_array<tint_array<bool, 4>, 5>, 6>");
-}
-
-// TODO(dsinclair): Port? Not sure if this is relevant ...
-TEST_F(MslASTPrinterTest, EmitType_Array_WithoutName) {
- auto arr = ty.array<bool, 4>();
- ast::Type type = GlobalVar("G", arr, core::AddressSpace::kPrivate)->type;
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitType(out, program->TypeOf(type))) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "tint_array<bool, 4>");
-}
-
-// MslPrinterTest.EmitType_RuntimeArray
-TEST_F(MslASTPrinterTest, EmitType_RuntimeArray) {
- auto arr = ty.array<bool, 1>();
- ast::Type type = GlobalVar("G", arr, core::AddressSpace::kPrivate)->type;
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitType(out, program->TypeOf(type))) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "tint_array<bool, 1>");
-}
-
-// MSLPrinterTest.EmitType_Bool
-TEST_F(MslASTPrinterTest, EmitType_Bool) {
- auto* bool_ = create<core::type::Bool>();
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitType(out, bool_)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "bool");
-}
-
-// MSLPrintertest.EmitType_F32
-TEST_F(MslASTPrinterTest, EmitType_F32) {
- auto* f32 = create<core::type::F32>();
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitType(out, f32)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "float");
-}
-
-// MSLPrinterTest.EmitType_F16
-TEST_F(MslASTPrinterTest, EmitType_F16) {
- auto* f16 = create<core::type::F16>();
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitType(out, f16)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "half");
-}
-
-// MSLPrinterTest.EmitType_I32
-TEST_F(MslASTPrinterTest, EmitType_I32) {
- auto* i32 = create<core::type::I32>();
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitType(out, i32)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "int");
-}
-
-// MSLPrinterTest.EmitType_Matrix_F32
-TEST_F(MslASTPrinterTest, EmitType_Matrix_F32) {
- auto* f32 = create<core::type::F32>();
- auto* vec3 = create<core::type::Vector>(f32, 3u);
- auto* mat2x3 = create<core::type::Matrix>(vec3, 2u);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitType(out, mat2x3)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "float2x3");
-}
-
-// MSLPrinterTest.EmitType_Matrix_F16
-TEST_F(MslASTPrinterTest, EmitType_Matrix_F16) {
- auto* f16 = create<core::type::F16>();
- auto* vec3 = create<core::type::Vector>(f16, 3u);
- auto* mat2x3 = create<core::type::Matrix>(vec3, 2u);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitType(out, mat2x3)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "half2x3");
-}
-
-// TODO(dsinclair): Not sure if this is relevant? MslPrinterTest.EmitType_Pointer_Workgroup
-TEST_F(MslASTPrinterTest, EmitType_Pointer) {
- auto* f32 = create<core::type::F32>();
- auto* p =
- create<core::type::Pointer>(core::AddressSpace::kWorkgroup, f32, core::Access::kReadWrite);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitType(out, p)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "threadgroup float*");
-}
-
-TEST_F(MslASTPrinterTest, EmitType_Struct) {
- auto* s = Structure("S", Vector{
- Member("a", ty.i32()),
- Member("b", ty.f32()),
- });
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitType(out, program->TypeOf(s))) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "S");
-}
-
-// MSLPrinterTest.EmitType_Struct
-TEST_F(MslASTPrinterTest, EmitType_StructDecl) {
- auto* s = Structure("S", Vector{
- Member("a", ty.i32()),
- Member("b", ty.f32()),
- });
-
- ASTPrinter& gen = Build();
-
- tint::TextGenerator::TextBuffer buf;
- auto* str = program->TypeOf(s)->As<core::type::Struct>();
- ASSERT_TRUE(gen.EmitStructType(&buf, str)) << gen.Diagnostics();
- EXPECT_EQ(buf.String(), R"(struct S {
- int a;
- float b;
-};
-)");
-}
-
-// MSLPrinterTest.EmitType_Struct_Layout_NonComposites
-TEST_F(MslASTPrinterTest, EmitType_Struct_Layout_NonComposites) {
- auto* s =
- Structure("S", Vector{
- Member("a", ty.i32(), Vector{MemberSize(32_a)}),
- Member("b", ty.f32(), Vector{MemberAlign(128_i), MemberSize(128_a)}),
- Member("c", ty.vec2<f32>()),
- Member("d", ty.u32()),
- Member("e", ty.vec3<f32>()),
- Member("f", ty.u32()),
- Member("g", ty.vec4<f32>()),
- Member("h", ty.u32()),
- Member("i", ty.mat2x2<f32>()),
- Member("j", ty.u32()),
- Member("k", ty.mat2x3<f32>()),
- Member("l", ty.u32()),
- Member("m", ty.mat2x4<f32>()),
- Member("n", ty.u32()),
- Member("o", ty.mat3x2<f32>()),
- Member("p", ty.u32()),
- Member("q", ty.mat3x3<f32>()),
- Member("r", ty.u32()),
- Member("s", ty.mat3x4<f32>()),
- Member("t", ty.u32()),
- Member("u", ty.mat4x2<f32>()),
- Member("v", ty.u32()),
- Member("w", ty.mat4x3<f32>()),
- Member("x", ty.u32()),
- Member("y", ty.mat4x4<f32>()),
- Member("z", ty.f32()),
- });
-
- ast::Type type = GlobalVar("G", ty.Of(s), core::AddressSpace::kStorage, core::Access::kRead,
- Binding(0_a), Group(0_a))
- ->type;
-
- ASTPrinter& gen = Build();
-
- tint::TextGenerator::TextBuffer buf;
- auto* str = program->TypeOf(type)->As<core::type::Struct>();
- ASSERT_TRUE(gen.EmitStructType(&buf, str)) << gen.Diagnostics();
-
- // ALL_FIELDS() calls the macro FIELD(ADDR, TYPE, ARRAY_COUNT, NAME)
- // for each field of the structure s.
-#define ALL_FIELDS() \
- FIELD(0x0000, int, 0, a) \
- FIELD(0x0004, int8_t, 124, tint_pad) \
- FIELD(0x0080, float, 0, b) \
- FIELD(0x0084, int8_t, 124, tint_pad_1) \
- FIELD(0x0100, float2, 0, c) \
- FIELD(0x0108, uint, 0, d) \
- FIELD(0x010c, int8_t, 4, tint_pad_2) \
- FIELD(0x0110, float3, 0, e) \
- FIELD(0x011c, uint, 0, f) \
- FIELD(0x0120, float4, 0, g) \
- FIELD(0x0130, uint, 0, h) \
- FIELD(0x0134, int8_t, 4, tint_pad_3) \
- FIELD(0x0138, float2x2, 0, i) \
- FIELD(0x0148, uint, 0, j) \
- FIELD(0x014c, int8_t, 4, tint_pad_4) \
- FIELD(0x0150, float2x3, 0, k) \
- FIELD(0x0170, uint, 0, l) \
- FIELD(0x0174, int8_t, 12, tint_pad_5) \
- FIELD(0x0180, float2x4, 0, m) \
- FIELD(0x01a0, uint, 0, n) \
- FIELD(0x01a4, int8_t, 4, tint_pad_6) \
- FIELD(0x01a8, float3x2, 0, o) \
- FIELD(0x01c0, uint, 0, p) \
- FIELD(0x01c4, int8_t, 12, tint_pad_7) \
- FIELD(0x01d0, float3x3, 0, q) \
- FIELD(0x0200, uint, 0, r) \
- FIELD(0x0204, int8_t, 12, tint_pad_8) \
- FIELD(0x0210, float3x4, 0, s) \
- FIELD(0x0240, uint, 0, t) \
- FIELD(0x0244, int8_t, 4, tint_pad_9) \
- FIELD(0x0248, float4x2, 0, u) \
- FIELD(0x0268, uint, 0, v) \
- FIELD(0x026c, int8_t, 4, tint_pad_10) \
- FIELD(0x0270, float4x3, 0, w) \
- FIELD(0x02b0, uint, 0, x) \
- FIELD(0x02b4, int8_t, 12, tint_pad_11) \
- FIELD(0x02c0, float4x4, 0, y) \
- FIELD(0x0300, float, 0, z) \
- FIELD(0x0304, int8_t, 124, tint_pad_12)
-
- // Check that the generated string is as expected.
- StringStream expect;
- expect << "struct S {\n";
-#define FIELD(ADDR, TYPE, ARRAY_COUNT, NAME) \
- FormatMSLField(expect, #ADDR, #TYPE, ARRAY_COUNT, #NAME);
- ALL_FIELDS()
-#undef FIELD
- expect << "};\n";
- EXPECT_EQ(buf.String(), expect.str());
-
- // 1.4 Metal and C++14
- // The Metal programming language is a C++14-based Specification with
- // extensions and restrictions. Refer to the C++14 Specification (also known
- // as the ISO/IEC JTC1/SC22/WG21 N4431 Language Specification) for a detailed
- // description of the language grammar.
- //
- // Tint is written in C++14, so use the compiler to verify the generated
- // layout is as expected for C++14 / MSL.
- {
- struct S {
-#define FIELD(ADDR, TYPE, ARRAY_COUNT, NAME) std::array<TYPE, ARRAY_COUNT ? ARRAY_COUNT : 1> NAME;
- ALL_FIELDS()
-#undef FIELD
- };
-
-#define FIELD(ADDR, TYPE, ARRAY_COUNT, NAME) \
- EXPECT_EQ(ADDR, static_cast<int>(offsetof(S, NAME))) << "Field " << #NAME;
- ALL_FIELDS()
-#undef FIELD
- }
-#undef ALL_FIELDS
-}
-
-// MSLPrinterTest.EmitType_Struct_Layout_Structures
-TEST_F(MslASTPrinterTest, EmitType_Struct_Layout_Structures) {
- // inner_x: size(1024), align(512)
- auto* inner_x = Structure("inner_x", Vector{
- Member("a", ty.i32()),
- Member("b", ty.f32(), Vector{MemberAlign(512_i)}),
- });
-
- // inner_y: size(516), align(4)
- auto* inner_y = Structure("inner_y", Vector{
- Member("a", ty.i32(), Vector{MemberSize(512_a)}),
- Member("b", ty.f32()),
- });
-
- auto* s = Structure("S", Vector{
- Member("a", ty.i32()),
- Member("b", ty.Of(inner_x)),
- Member("c", ty.f32()),
- Member("d", ty.Of(inner_y)),
- Member("e", ty.f32()),
- });
-
- ast::Type type = GlobalVar("G", ty.Of(s), core::AddressSpace::kStorage, core::Access::kRead,
- Binding(0_a), Group(0_a))
- ->type;
-
- ASTPrinter& gen = Build();
-
- tint::TextGenerator::TextBuffer buf;
- auto* str = program->TypeOf(type)->As<core::type::Struct>();
- ASSERT_TRUE(gen.EmitStructType(&buf, str)) << gen.Diagnostics();
-
- // ALL_FIELDS() calls the macro FIELD(ADDR, TYPE, ARRAY_COUNT, NAME)
- // for each field of the structure s.
-#define ALL_FIELDS() \
- FIELD(0x0000, int, 0, a) \
- FIELD(0x0004, int8_t, 508, tint_pad) \
- FIELD(0x0200, inner_x, 0, b) \
- FIELD(0x0600, float, 0, c) \
- FIELD(0x0604, inner_y, 0, d) \
- FIELD(0x0808, float, 0, e) \
- FIELD(0x080c, int8_t, 500, tint_pad_4)
-
- // Check that the generated string is as expected.
- StringStream expect;
- expect << "struct S {\n";
-#define FIELD(ADDR, TYPE, ARRAY_COUNT, NAME) \
- FormatMSLField(expect, #ADDR, #TYPE, ARRAY_COUNT, #NAME);
- ALL_FIELDS()
-#undef FIELD
- expect << "};\n";
- EXPECT_EQ(buf.String(), expect.str());
-
- // 1.4 Metal and C++14
- // The Metal programming language is a C++14-based Specification with
- // extensions and restrictions. Refer to the C++14 Specification (also known
- // as the ISO/IEC JTC1/SC22/WG21 N4431 Language Specification) for a detailed
- // description of the language grammar.
- //
- // Tint is written in C++14, so use the compiler to verify the generated
- // layout is as expected for C++14 / MSL.
- {
- struct inner_x {
- uint32_t a;
- alignas(512) float b;
- };
- CHECK_TYPE_SIZE_AND_ALIGN(inner_x, 1024, 512);
-
- struct inner_y {
- uint32_t a[128];
- float b;
- };
- CHECK_TYPE_SIZE_AND_ALIGN(inner_y, 516, 4);
-
- struct S {
-#define FIELD(ADDR, TYPE, ARRAY_COUNT, NAME) std::array<TYPE, ARRAY_COUNT ? ARRAY_COUNT : 1> NAME;
- ALL_FIELDS()
-#undef FIELD
- };
-
-#define FIELD(ADDR, TYPE, ARRAY_COUNT, NAME) \
- EXPECT_EQ(ADDR, static_cast<int>(offsetof(S, NAME))) << "Field " << #NAME;
- ALL_FIELDS()
-#undef FIELD
- }
-
-#undef ALL_FIELDS
-}
-
-// MSLPrinterTest.EmitType_Struct_Layout_ArrayDefaultStride
-TEST_F(MslASTPrinterTest, EmitType_Struct_Layout_ArrayDefaultStride) {
- // inner: size(1024), align(512)
- auto* inner = Structure("inner", Vector{
- Member("a", ty.i32()),
- Member("b", ty.f32(), Vector{MemberAlign(512_i)}),
- });
-
- // array_x: size(28), align(4)
- auto array_x = ty.array<f32, 7>();
-
- // array_y: size(4096), align(512)
- auto array_y = ty.array(ty.Of(inner), 4_u);
-
- // array_z: size(4), align(4)
- auto array_z = ty.array<f32>();
-
- auto* s = Structure("S", Vector{
- Member("a", ty.i32()),
- Member("b", array_x),
- Member("c", ty.f32()),
- Member("d", array_y),
- Member("e", ty.f32()),
- Member("f", array_z),
- });
-
- ast::Type type = GlobalVar("G", ty.Of(s), core::AddressSpace::kStorage, core::Access::kRead,
- Binding(0_a), Group(0_a))
- ->type;
-
- ASTPrinter& gen = Build();
-
- tint::TextGenerator::TextBuffer buf;
- auto* str = program->TypeOf(type)->As<core::type::Struct>();
- ASSERT_TRUE(gen.EmitStructType(&buf, str)) << gen.Diagnostics();
-
- // ALL_FIELDS() calls the macro FIELD(ADDR, TYPE, ARRAY_COUNT, NAME)
- // for each field of the structure s.
-#define ALL_FIELDS() \
- FIELD(0x0000, int, 0, a) \
- FIELD(0x0004, float, 7, b) \
- FIELD(0x0020, float, 0, c) \
- FIELD(0x0024, int8_t, 476, tint_pad) \
- FIELD(0x0200, inner, 4, d) \
- FIELD(0x1200, float, 0, e) \
- FIELD(0x1204, float, 1, f) \
- FIELD(0x1208, int8_t, 504, tint_pad_3)
-
- // Check that the generated string is as expected.
- StringStream expect;
- expect << "struct S {\n";
-#define FIELD(ADDR, TYPE, ARRAY_COUNT, NAME) \
- FormatMSLField(expect, #ADDR, #TYPE, ARRAY_COUNT, #NAME);
- ALL_FIELDS()
-#undef FIELD
- expect << "};\n";
- EXPECT_EQ(buf.String(), expect.str());
-
- // 1.4 Metal and C++14
- // The Metal programming language is a C++14-based Specification with
- // extensions and restrictions. Refer to the C++14 Specification (also known
- // as the ISO/IEC JTC1/SC22/WG21 N4431 Language Specification) for a detailed
- // description of the language grammar.
- //
- // Tint is written in C++14, so use the compiler to verify the generated
- // layout is as expected for C++14 / MSL.
- {
- struct inner {
- uint32_t a;
- alignas(512) float b;
- };
- CHECK_TYPE_SIZE_AND_ALIGN(inner, 1024, 512);
-
- // array_x: size(28), align(4)
- using array_x = std::array<float, 7>;
- CHECK_TYPE_SIZE_AND_ALIGN(array_x, 28, 4);
-
- // array_y: size(4096), align(512)
- using array_y = std::array<inner, 4>;
- CHECK_TYPE_SIZE_AND_ALIGN(array_y, 4096, 512);
-
- // array_z: size(4), align(4)
- using array_z = std::array<float, 1>;
- CHECK_TYPE_SIZE_AND_ALIGN(array_z, 4, 4);
-
- struct S {
-#define FIELD(ADDR, TYPE, ARRAY_COUNT, NAME) std::array<TYPE, ARRAY_COUNT ? ARRAY_COUNT : 1> NAME;
- ALL_FIELDS()
-#undef FIELD
- };
-
-#define FIELD(ADDR, TYPE, ARRAY_COUNT, NAME) \
- EXPECT_EQ(ADDR, static_cast<int>(offsetof(S, NAME))) << "Field " << #NAME;
- ALL_FIELDS()
-#undef FIELD
- }
-
-#undef ALL_FIELDS
-}
-
-// MslPrinterTest.EmitType_Struct_Layout_ArrayVec3DefaultStride
-TEST_F(MslASTPrinterTest, EmitType_Struct_Layout_ArrayVec3DefaultStride) {
- // array: size(64), align(16)
- auto array = ty.array<vec3<f32>, 4>();
-
- auto* s = Structure("S", Vector{
- Member("a", ty.i32()),
- Member("b", array),
- Member("c", ty.i32()),
- });
-
- ast::Type type = GlobalVar("G", ty.Of(s), core::AddressSpace::kStorage, core::Access::kRead,
- Binding(0_a), Group(0_a))
- ->type;
-
- ASTPrinter& gen = Build();
-
- tint::TextGenerator::TextBuffer buf;
- auto* str = program->TypeOf(type)->As<core::type::Struct>();
- ASSERT_TRUE(gen.EmitStructType(&buf, str)) << gen.Diagnostics();
-
- // ALL_FIELDS() calls the macro FIELD(ADDR, TYPE, ARRAY_COUNT, NAME)
- // for each field of the structure s.
-#define ALL_FIELDS() \
- FIELD(0x0000, int, 0, a) \
- FIELD(0x0004, int8_t, 12, tint_pad) \
- FIELD(0x0010, float3, 4, b) \
- FIELD(0x0050, int, 0, c) \
- FIELD(0x0054, int8_t, 12, tint_pad_1)
-
- // Check that the generated string is as expected.
- StringStream expect;
- expect << "struct S {\n";
-#define FIELD(ADDR, TYPE, ARRAY_COUNT, NAME) \
- FormatMSLField(expect, #ADDR, #TYPE, ARRAY_COUNT, #NAME);
- ALL_FIELDS()
-#undef FIELD
- expect << "};\n";
- EXPECT_EQ(buf.String(), expect.str());
-}
-
-// MslPrinterTest.AttemptTintPadSymbolCollision
-TEST_F(MslASTPrinterTest, AttemptTintPadSymbolCollision) {
- auto* s = Structure(
- "S", Vector{
- // uses symbols tint_pad_[0..9] and tint_pad_[20..35]
- Member("tint_pad_2", ty.i32(), Vector{MemberSize(32_a)}),
- Member("tint_pad_20", ty.f32(), Vector{MemberAlign(128_i), MemberSize(128_u)}),
- Member("tint_pad_33", ty.vec2<f32>()),
- Member("tint_pad_1", ty.u32()),
- Member("tint_pad_3", ty.vec3<f32>()),
- Member("tint_pad_7", ty.u32()),
- Member("tint_pad_25", ty.vec4<f32>()),
- Member("tint_pad_5", ty.u32()),
- Member("tint_pad_27", ty.mat2x2<f32>()),
- Member("tint_pad_24", ty.u32()),
- Member("tint_pad_23", ty.mat2x3<f32>()),
- Member("tint_pad", ty.u32()),
- Member("tint_pad_8", ty.mat2x4<f32>()),
- Member("tint_pad_26", ty.u32()),
- Member("tint_pad_29", ty.mat3x2<f32>()),
- Member("tint_pad_6", ty.u32()),
- Member("tint_pad_22", ty.mat3x3<f32>()),
- Member("tint_pad_32", ty.u32()),
- Member("tint_pad_34", ty.mat3x4<f32>()),
- Member("tint_pad_35", ty.u32()),
- Member("tint_pad_30", ty.mat4x2<f32>()),
- Member("tint_pad_9", ty.u32()),
- Member("tint_pad_31", ty.mat4x3<f32>()),
- Member("tint_pad_28", ty.u32()),
- Member("tint_pad_4", ty.mat4x4<f32>()),
- Member("tint_pad_21", ty.f32()),
- });
-
- ast::Type type = GlobalVar("G", ty.Of(s), core::AddressSpace::kStorage, core::Access::kRead,
- Binding(0_a), Group(0_a))
- ->type;
-
- ASTPrinter& gen = Build();
-
- tint::TextGenerator::TextBuffer buf;
- auto* str = program->TypeOf(type)->As<core::type::Struct>();
- ASSERT_TRUE(gen.EmitStructType(&buf, str)) << gen.Diagnostics();
- EXPECT_EQ(buf.String(), R"(struct S {
- /* 0x0000 */ int tint_pad_2;
- /* 0x0004 */ tint_array<int8_t, 124> tint_pad_10;
- /* 0x0080 */ float tint_pad_20;
- /* 0x0084 */ tint_array<int8_t, 124> tint_pad_11;
- /* 0x0100 */ float2 tint_pad_33;
- /* 0x0108 */ uint tint_pad_1;
- /* 0x010c */ tint_array<int8_t, 4> tint_pad_12;
- /* 0x0110 */ float3 tint_pad_3;
- /* 0x011c */ uint tint_pad_7;
- /* 0x0120 */ float4 tint_pad_25;
- /* 0x0130 */ uint tint_pad_5;
- /* 0x0134 */ tint_array<int8_t, 4> tint_pad_13;
- /* 0x0138 */ float2x2 tint_pad_27;
- /* 0x0148 */ uint tint_pad_24;
- /* 0x014c */ tint_array<int8_t, 4> tint_pad_14;
- /* 0x0150 */ float2x3 tint_pad_23;
- /* 0x0170 */ uint tint_pad;
- /* 0x0174 */ tint_array<int8_t, 12> tint_pad_15;
- /* 0x0180 */ float2x4 tint_pad_8;
- /* 0x01a0 */ uint tint_pad_26;
- /* 0x01a4 */ tint_array<int8_t, 4> tint_pad_16;
- /* 0x01a8 */ float3x2 tint_pad_29;
- /* 0x01c0 */ uint tint_pad_6;
- /* 0x01c4 */ tint_array<int8_t, 12> tint_pad_17;
- /* 0x01d0 */ float3x3 tint_pad_22;
- /* 0x0200 */ uint tint_pad_32;
- /* 0x0204 */ tint_array<int8_t, 12> tint_pad_18;
- /* 0x0210 */ float3x4 tint_pad_34;
- /* 0x0240 */ uint tint_pad_35;
- /* 0x0244 */ tint_array<int8_t, 4> tint_pad_19;
- /* 0x0248 */ float4x2 tint_pad_30;
- /* 0x0268 */ uint tint_pad_9;
- /* 0x026c */ tint_array<int8_t, 4> tint_pad_36;
- /* 0x0270 */ float4x3 tint_pad_31;
- /* 0x02b0 */ uint tint_pad_28;
- /* 0x02b4 */ tint_array<int8_t, 12> tint_pad_37;
- /* 0x02c0 */ float4x4 tint_pad_4;
- /* 0x0300 */ float tint_pad_21;
- /* 0x0304 */ tint_array<int8_t, 124> tint_pad_38;
-};
-)");
-}
-
-// TODO(dsinclair): Missing from IR tests, but test also doesn't look right.
-TEST_F(MslASTPrinterTest, EmitType_Struct_WithAttribute) {
- auto* s = Structure("S", Vector{
- Member("a", ty.i32()),
- Member("b", ty.f32()),
- });
-
- ast::Type type = GlobalVar("G", ty.Of(s), core::AddressSpace::kStorage, core::Access::kRead,
- Binding(0_a), Group(0_a))
- ->type;
-
- ASTPrinter& gen = Build();
-
- tint::TextGenerator::TextBuffer buf;
- auto* str = program->TypeOf(type)->As<core::type::Struct>();
- ASSERT_TRUE(gen.EmitStructType(&buf, str)) << gen.Diagnostics();
- EXPECT_EQ(buf.String(), R"(struct S {
- /* 0x0000 */ int a;
- /* 0x0004 */ float b;
-};
-)");
-}
-
-// MSLPrinterTest.EmitType_U32
-TEST_F(MslASTPrinterTest, EmitType_U32) {
- auto* u32 = create<core::type::U32>();
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitType(out, u32)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "uint");
-}
-
-// MSLPrinterTest.EmitType_Vector
-TEST_F(MslASTPrinterTest, EmitType_Vector) {
- auto* f32 = create<core::type::F32>();
- auto* vec3 = create<core::type::Vector>(f32, 3u);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitType(out, vec3)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "float3");
-}
-
-// MSLPrinterTest.EmitType_Void
-TEST_F(MslASTPrinterTest, EmitType_Void) {
- auto* void_ = create<core::type::Void>();
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitType(out, void_)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "void");
-}
-
-// MSLPrinterTest.EmitType_Sampler
-TEST_F(MslASTPrinterTest, EmitType_Sampler) {
- auto* sampler = create<core::type::Sampler>(core::type::SamplerKind::kSampler);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitType(out, sampler)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "sampler");
-}
-
-// MSLPrinterTest.EmitType_SamplerComparison
-TEST_F(MslASTPrinterTest, EmitType_SamplerComparison) {
- auto* sampler = create<core::type::Sampler>(core::type::SamplerKind::kComparisonSampler);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitType(out, sampler)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "sampler");
-}
-
-struct MslDepthTextureData {
- core::type::TextureDimension dim;
- std::string result;
-};
-inline std::ostream& operator<<(std::ostream& out, MslDepthTextureData data) {
- StringStream str;
- str << data.dim;
- out << str.str();
- return out;
-}
-using MslDepthTexturesTest = TestParamHelper<MslDepthTextureData>;
-// MslPrinterDepthTexturesTest.Emit
-TEST_P(MslDepthTexturesTest, Emit) {
- auto params = GetParam();
-
- core::type::DepthTexture s(params.dim);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitType(out, &s)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), params.result);
-}
-INSTANTIATE_TEST_SUITE_P(
- MslASTPrinterTest,
- MslDepthTexturesTest,
- testing::Values(MslDepthTextureData{core::type::TextureDimension::k2d,
- "depth2d<float, access::sample>"},
- MslDepthTextureData{core::type::TextureDimension::k2dArray,
- "depth2d_array<float, access::sample>"},
- MslDepthTextureData{core::type::TextureDimension::kCube,
- "depthcube<float, access::sample>"},
- MslDepthTextureData{core::type::TextureDimension::kCubeArray,
- "depthcube_array<float, access::sample>"}));
-
-using MslDepthMultisampledTexturesTest = TestHelper;
-// MSLPrinterTest.EmitType_DepthMultisampledTexture
-TEST_F(MslDepthMultisampledTexturesTest, Emit) {
- core::type::DepthMultisampledTexture s(core::type::TextureDimension::k2d);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitType(out, &s)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "depth2d_ms<float, access::read>");
-}
-
-struct MslTextureData {
- core::type::TextureDimension dim;
- std::string result;
-};
-inline std::ostream& operator<<(std::ostream& out, MslTextureData data) {
- StringStream str;
- str << data.dim;
- out << str.str();
- return out;
-}
-using MslSampledtexturesTest = TestParamHelper<MslTextureData>;
-// MslPrinterSampledTexturesTest.Emit
-TEST_P(MslSampledtexturesTest, Emit) {
- auto params = GetParam();
-
- auto* f32 = create<core::type::F32>();
- auto* s = create<core::type::SampledTexture>(params.dim, f32);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitType(out, s)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), params.result);
-}
-INSTANTIATE_TEST_SUITE_P(
- MslASTPrinterTest,
- MslSampledtexturesTest,
- testing::Values(
- MslTextureData{core::type::TextureDimension::k1d, "texture1d<float, access::sample>"},
- MslTextureData{core::type::TextureDimension::k2d, "texture2d<float, access::sample>"},
- MslTextureData{core::type::TextureDimension::k2dArray,
- "texture2d_array<float, access::sample>"},
- MslTextureData{core::type::TextureDimension::k3d, "texture3d<float, access::sample>"},
- MslTextureData{core::type::TextureDimension::kCube, "texturecube<float, access::sample>"},
- MslTextureData{core::type::TextureDimension::kCubeArray,
- "texturecube_array<float, access::sample>"}));
-
-// MslPrinterTest.Emit_TypeMultisampledTexture
-TEST_F(MslASTPrinterTest, Emit_TypeMultisampledTexture) {
- auto* u32 = create<core::type::U32>();
- auto* ms = create<core::type::MultisampledTexture>(core::type::TextureDimension::k2d, u32);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitType(out, ms)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "texture2d_ms<uint, access::read>");
-}
-
-struct MslStorageTextureData {
- core::type::TextureDimension dim;
- std::string result;
-};
-inline std::ostream& operator<<(std::ostream& out, MslStorageTextureData data) {
- StringStream str;
- str << data.dim;
- return out << str.str();
-}
-using MslStorageTexturesTest = TestParamHelper<MslStorageTextureData>;
-// MslPrinterStorageTexturesTest.Emit
-TEST_P(MslStorageTexturesTest, Emit) {
- auto params = GetParam();
-
- auto s = ty.storage_texture(params.dim, core::TexelFormat::kR32Float, core::Access::kWrite);
- ast::Type type = GlobalVar("test_var", s, Binding(0_a), Group(0_a))->type;
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitType(out, program->TypeOf(type))) << gen.Diagnostics();
- EXPECT_EQ(out.str(), params.result);
-}
-INSTANTIATE_TEST_SUITE_P(MslASTPrinterTest,
- MslStorageTexturesTest,
- testing::Values(MslStorageTextureData{core::type::TextureDimension::k1d,
- "texture1d<float, access::write>"},
- MslStorageTextureData{core::type::TextureDimension::k2d,
- "texture2d<float, access::write>"},
- MslStorageTextureData{
- core::type::TextureDimension::k2dArray,
- "texture2d_array<float, access::write>"},
- MslStorageTextureData{core::type::TextureDimension::k3d,
- "texture3d<float, access::write>"}));
-
-} // namespace
-} // namespace tint::msl::writer
diff --git a/src/tint/lang/msl/writer/ast_printer/binary_test.cc b/src/tint/lang/msl/writer/ast_printer/binary_test.cc
deleted file mode 100644
index 70601fc..0000000
--- a/src/tint/lang/msl/writer/ast_printer/binary_test.cc
+++ /dev/null
@@ -1,258 +0,0 @@
-// Copyright 2020 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/tint/lang/core/fluent_types.h"
-#include "src/tint/lang/msl/writer/ast_printer/helper_test.h"
-#include "src/tint/utils/text/string_stream.h"
-
-// All ported to IR.
-
-using namespace tint::core::fluent_types; // NOLINT
-
-namespace tint::msl::writer {
-namespace {
-
-struct BinaryData {
- const char* result;
- core::BinaryOp op;
-};
-inline std::ostream& operator<<(std::ostream& out, BinaryData data) {
- StringStream str;
- str << data.op;
- out << str.str();
- return out;
-}
-
-// MSLPrinterBinaryTest.Emit
-using MslBinaryTest = TestParamHelper<BinaryData>;
-TEST_P(MslBinaryTest, Emit) {
- auto params = GetParam();
-
- auto type = [&] {
- return ((params.op == core::BinaryOp::kLogicalAnd) ||
- (params.op == core::BinaryOp::kLogicalOr))
- ? ty.bool_()
- : ty.u32();
- };
-
- auto* left = Var("left", type());
- auto* right = Var("right", type());
-
- auto* expr = create<ast::BinaryExpression>(params.op, Expr(left), Expr(right));
- WrapInFunction(left, right, expr);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), params.result);
-}
-INSTANTIATE_TEST_SUITE_P(
- MslASTPrinterTest,
- MslBinaryTest,
- testing::Values(BinaryData{"(left & right)", core::BinaryOp::kAnd},
- BinaryData{"(left | right)", core::BinaryOp::kOr},
- BinaryData{"(left ^ right)", core::BinaryOp::kXor},
- BinaryData{"(left && right)", core::BinaryOp::kLogicalAnd},
- BinaryData{"(left || right)", core::BinaryOp::kLogicalOr},
- BinaryData{"(left == right)", core::BinaryOp::kEqual},
- BinaryData{"(left != right)", core::BinaryOp::kNotEqual},
- BinaryData{"(left < right)", core::BinaryOp::kLessThan},
- BinaryData{"(left > right)", core::BinaryOp::kGreaterThan},
- BinaryData{"(left <= right)", core::BinaryOp::kLessThanEqual},
- BinaryData{"(left >= right)", core::BinaryOp::kGreaterThanEqual},
- BinaryData{"(left << right)", core::BinaryOp::kShiftLeft},
- BinaryData{"(left >> right)", core::BinaryOp::kShiftRight},
- BinaryData{"(left + right)", core::BinaryOp::kAdd},
- BinaryData{"(left - right)", core::BinaryOp::kSubtract},
- BinaryData{"(left * right)", core::BinaryOp::kMultiply},
- BinaryData{"(left / right)", core::BinaryOp::kDivide},
- BinaryData{"(left % right)", core::BinaryOp::kModulo}));
-
-// MSLPrinterBinaryTest_SignedOverflowDefinedBehaviour.Emit
-using MslBinaryTest_SignedOverflowDefinedBehaviour = TestParamHelper<BinaryData>;
-TEST_P(MslBinaryTest_SignedOverflowDefinedBehaviour, Emit) {
- auto params = GetParam();
-
- auto a_type = ty.i32();
- auto b_type =
- (params.op == core::BinaryOp::kShiftLeft || params.op == core::BinaryOp::kShiftRight)
- ? ty.u32()
- : ty.i32();
-
- auto* a = Var("a", a_type);
- auto* b = Var("b", b_type);
-
- auto* expr = create<ast::BinaryExpression>(params.op, Expr(a), Expr(b));
- WrapInFunction(a, b, expr);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), params.result);
-}
-using Op = core::BinaryOp;
-constexpr BinaryData signed_overflow_defined_behaviour_cases[] = {
- {"as_type<int>((as_type<uint>(a) << b))", Op::kShiftLeft},
- {"(a >> b)", Op::kShiftRight},
- {"as_type<int>((as_type<uint>(a) + as_type<uint>(b)))", Op::kAdd},
- {"as_type<int>((as_type<uint>(a) - as_type<uint>(b)))", Op::kSubtract},
- {"as_type<int>((as_type<uint>(a) * as_type<uint>(b)))", Op::kMultiply}};
-INSTANTIATE_TEST_SUITE_P(MslASTPrinterTest,
- MslBinaryTest_SignedOverflowDefinedBehaviour,
- testing::ValuesIn(signed_overflow_defined_behaviour_cases));
-
-// MSLPrinterBinaryTest_ShiftSignedOverflowDefinedBehaviour_Chained.Emit
-using MslBinaryTest_SignedOverflowDefinedBehaviour_Chained = TestParamHelper<BinaryData>;
-TEST_P(MslBinaryTest_SignedOverflowDefinedBehaviour_Chained, Emit) {
- auto params = GetParam();
-
- auto a_type = ty.i32();
- auto b_type =
- (params.op == core::BinaryOp::kShiftLeft || params.op == core::BinaryOp::kShiftRight)
- ? ty.u32()
- : ty.i32();
-
- auto* a = Var("a", a_type);
- auto* b = Var("b", b_type);
-
- auto* expr1 = create<ast::BinaryExpression>(params.op, Expr(a), Expr(b));
- auto* expr2 = create<ast::BinaryExpression>(params.op, expr1, Expr(b));
- WrapInFunction(a, b, expr2);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitExpression(out, expr2)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), params.result);
-}
-using Op = core::BinaryOp;
-constexpr BinaryData signed_overflow_defined_behaviour_chained_cases[] = {
- {R"(as_type<int>((as_type<uint>(as_type<int>((as_type<uint>(a) << b))) << b)))",
- Op::kShiftLeft},
- {R"(((a >> b) >> b))", Op::kShiftRight},
- {R"(as_type<int>((as_type<uint>(as_type<int>((as_type<uint>(a) + as_type<uint>(b)))) + as_type<uint>(b))))",
- Op::kAdd},
- {R"(as_type<int>((as_type<uint>(as_type<int>((as_type<uint>(a) - as_type<uint>(b)))) - as_type<uint>(b))))",
- Op::kSubtract},
- {R"(as_type<int>((as_type<uint>(as_type<int>((as_type<uint>(a) * as_type<uint>(b)))) * as_type<uint>(b))))",
- Op::kMultiply}};
-INSTANTIATE_TEST_SUITE_P(MslASTPrinterTest,
- MslBinaryTest_SignedOverflowDefinedBehaviour_Chained,
- testing::ValuesIn(signed_overflow_defined_behaviour_chained_cases));
-
-// MslPrinterTest.BinaryModF32
-TEST_F(MslBinaryTest, ModF32) {
- auto* left = Var("left", ty.f32());
- auto* right = Var("right", ty.f32());
- auto* expr = create<ast::BinaryExpression>(core::BinaryOp::kModulo, Expr(left), Expr(right));
- WrapInFunction(left, right, expr);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "fmod(left, right)");
-}
-
-// MslPrinterTest.BinaryModF16
-TEST_F(MslBinaryTest, ModF16) {
- Enable(wgsl::Extension::kF16);
-
- auto* left = Var("left", ty.f16());
- auto* right = Var("right", ty.f16());
- auto* expr = create<ast::BinaryExpression>(core::BinaryOp::kModulo, Expr(left), Expr(right));
- WrapInFunction(left, right, expr);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "fmod(left, right)");
-}
-
-// MslBinaryTest.BinaryModVecF32
-TEST_F(MslBinaryTest, ModVec3F32) {
- auto* left = Var("left", ty.vec3<f32>());
- auto* right = Var("right", ty.vec3<f32>());
- auto* expr = create<ast::BinaryExpression>(core::BinaryOp::kModulo, Expr(left), Expr(right));
- WrapInFunction(left, right, expr);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "fmod(left, right)");
-}
-
-// MslPrinterTest.BinaryModVec3F16
-TEST_F(MslBinaryTest, ModVec3F16) {
- Enable(wgsl::Extension::kF16);
-
- auto* left = Var("left", ty.vec3<f16>());
- auto* right = Var("right", ty.vec3<f16>());
- auto* expr = create<ast::BinaryExpression>(core::BinaryOp::kModulo, Expr(left), Expr(right));
- WrapInFunction(left, right, expr);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "fmod(left, right)");
-}
-
-// MslPrinterTest.BinaryBoolAnd
-TEST_F(MslBinaryTest, BoolAnd) {
- auto* left = Var("left", Expr(true));
- auto* right = Var("right", Expr(false));
- auto* expr = create<ast::BinaryExpression>(core::BinaryOp::kAnd, Expr(left), Expr(right));
- WrapInFunction(left, right, expr);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "bool(left & right)");
-}
-
-// MslPrinterTest.BinaryBoolOr
-TEST_F(MslBinaryTest, BoolOr) {
- auto* left = Var("left", Expr(true));
- auto* right = Var("right", Expr(false));
- auto* expr = create<ast::BinaryExpression>(core::BinaryOp::kOr, Expr(left), Expr(right));
- WrapInFunction(left, right, expr);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "bool(left | right)");
-}
-
-} // namespace
-} // namespace tint::msl::writer
diff --git a/src/tint/lang/msl/writer/ast_printer/bitcast_test.cc b/src/tint/lang/msl/writer/ast_printer/bitcast_test.cc
deleted file mode 100644
index 351da46..0000000
--- a/src/tint/lang/msl/writer/ast_printer/bitcast_test.cc
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2020 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/tint/lang/core/fluent_types.h"
-#include "src/tint/lang/msl/writer/ast_printer/helper_test.h"
-#include "src/tint/utils/text/string_stream.h"
-
-using namespace tint::core::number_suffixes; // NOLINT
-using namespace tint::core::fluent_types; // NOLINT
-
-namespace tint::msl::writer {
-namespace {
-
-using MslASTPrinterTest = TestHelper;
-
-TEST_F(MslASTPrinterTest, EmitExpression_Bitcast) {
- auto* a = Let("a", Expr(1_i));
- auto* bitcast = Bitcast<f32>(Expr("a"));
- WrapInFunction(a, bitcast);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitExpression(out, bitcast)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "as_type<float>(a)");
-}
-
-} // namespace
-} // namespace tint::msl::writer
diff --git a/src/tint/lang/msl/writer/ast_printer/block_test.cc b/src/tint/lang/msl/writer/ast_printer/block_test.cc
deleted file mode 100644
index 41d43c7..0000000
--- a/src/tint/lang/msl/writer/ast_printer/block_test.cc
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 2020 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/tint/lang/msl/writer/ast_printer/helper_test.h"
-
-namespace tint::msl::writer {
-namespace {
-
-using MslASTPrinterTest = TestHelper;
-
-TEST_F(MslASTPrinterTest, Emit_Block) {
- auto* b = Block(Return());
- WrapInFunction(b);
-
- ASTPrinter& gen = Build();
-
- gen.IncrementIndent();
-
- ASSERT_TRUE(gen.EmitStatement(b)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"( {
- return;
- }
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_Block_WithoutNewline) {
- auto* b = Block(Return());
- WrapInFunction(b);
-
- ASTPrinter& gen = Build();
-
- gen.IncrementIndent();
-
- ASSERT_TRUE(gen.EmitBlock(b)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"( {
- return;
- }
-)");
-}
-
-} // namespace
-} // namespace tint::msl::writer
diff --git a/src/tint/lang/msl/writer/ast_printer/break_test.cc b/src/tint/lang/msl/writer/ast_printer/break_test.cc
deleted file mode 100644
index a71988a..0000000
--- a/src/tint/lang/msl/writer/ast_printer/break_test.cc
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2020 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/tint/lang/msl/writer/ast_printer/helper_test.h"
-
-namespace tint::msl::writer {
-namespace {
-
-using MslASTPrinterTest = TestHelper;
-
-TEST_F(MslASTPrinterTest, Emit_Break) {
- auto* b = create<ast::BreakStatement>();
- WrapInFunction(Loop(Block(b)));
-
- ASTPrinter& gen = Build();
-
- gen.IncrementIndent();
-
- ASSERT_TRUE(gen.EmitStatement(b)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), " break;\n");
-}
-
-} // namespace
-} // namespace tint::msl::writer
diff --git a/src/tint/lang/msl/writer/ast_printer/builtin_test.cc b/src/tint/lang/msl/writer/ast_printer/builtin_test.cc
deleted file mode 100644
index fff3db0..0000000
--- a/src/tint/lang/msl/writer/ast_printer/builtin_test.cc
+++ /dev/null
@@ -1,1206 +0,0 @@
-// Copyright 2020 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/tint/lang/msl/writer/ast_printer/helper_test.h"
-#include "src/tint/lang/wgsl/ast/call_statement.h"
-#include "src/tint/lang/wgsl/sem/call.h"
-#include "src/tint/utils/text/string_stream.h"
-
-namespace tint::msl::writer {
-namespace {
-
-using namespace tint::core::fluent_types; // NOLINT
-using namespace tint::core::number_suffixes; // NOLINT
-
-using MslASTPrinterTest = TestHelper;
-
-enum class CallParamType {
- kF32,
- kU32,
- kBool,
- kF16,
-};
-
-struct BuiltinData {
- wgsl::BuiltinFn builtin;
- CallParamType type;
- const char* msl_name;
-};
-inline std::ostream& operator<<(std::ostream& out, BuiltinData data) {
- out << data.msl_name << "<";
- switch (data.type) {
- case CallParamType::kF32:
- out << "f32";
- break;
- case CallParamType::kU32:
- out << "u32";
- break;
- case CallParamType::kBool:
- out << "bool";
- break;
- case CallParamType::kF16:
- out << "f16";
- break;
- }
- out << ">";
- return out;
-}
-
-const ast::CallExpression* GenerateCall(wgsl::BuiltinFn builtin,
- CallParamType type,
- ProgramBuilder* builder) {
- std::string name;
- StringStream str;
- str << name << builtin;
- switch (builtin) {
- case wgsl::BuiltinFn::kAcos:
- case wgsl::BuiltinFn::kAsin:
- case wgsl::BuiltinFn::kAtan:
- case wgsl::BuiltinFn::kCeil:
- case wgsl::BuiltinFn::kCos:
- case wgsl::BuiltinFn::kCosh:
- case wgsl::BuiltinFn::kDpdx:
- case wgsl::BuiltinFn::kDpdxCoarse:
- case wgsl::BuiltinFn::kDpdxFine:
- case wgsl::BuiltinFn::kDpdy:
- case wgsl::BuiltinFn::kDpdyCoarse:
- case wgsl::BuiltinFn::kDpdyFine:
- case wgsl::BuiltinFn::kExp:
- case wgsl::BuiltinFn::kExp2:
- case wgsl::BuiltinFn::kFloor:
- case wgsl::BuiltinFn::kFract:
- case wgsl::BuiltinFn::kFwidth:
- case wgsl::BuiltinFn::kFwidthCoarse:
- case wgsl::BuiltinFn::kFwidthFine:
- case wgsl::BuiltinFn::kInverseSqrt:
- case wgsl::BuiltinFn::kLength:
- case wgsl::BuiltinFn::kLog:
- case wgsl::BuiltinFn::kLog2:
- case wgsl::BuiltinFn::kNormalize:
- case wgsl::BuiltinFn::kRound:
- case wgsl::BuiltinFn::kSin:
- case wgsl::BuiltinFn::kSinh:
- case wgsl::BuiltinFn::kSqrt:
- case wgsl::BuiltinFn::kTan:
- case wgsl::BuiltinFn::kTanh:
- case wgsl::BuiltinFn::kTrunc:
- case wgsl::BuiltinFn::kSign:
- if (type == CallParamType::kF16) {
- return builder->Call(str.str(), "h2");
- } else {
- return builder->Call(str.str(), "f2");
- }
- case wgsl::BuiltinFn::kLdexp:
- if (type == CallParamType::kF16) {
- return builder->Call(str.str(), "h2", "i2");
- } else {
- return builder->Call(str.str(), "f2", "i2");
- }
- case wgsl::BuiltinFn::kAtan2:
- case wgsl::BuiltinFn::kDot:
- case wgsl::BuiltinFn::kDistance:
- case wgsl::BuiltinFn::kPow:
- case wgsl::BuiltinFn::kReflect:
- case wgsl::BuiltinFn::kStep:
- if (type == CallParamType::kF16) {
- return builder->Call(str.str(), "h2", "h2");
- } else {
- return builder->Call(str.str(), "f2", "f2");
- }
- case wgsl::BuiltinFn::kStorageBarrier:
- return builder->Call(str.str());
- case wgsl::BuiltinFn::kCross:
- if (type == CallParamType::kF16) {
- return builder->Call(str.str(), "h3", "h3");
- } else {
- return builder->Call(str.str(), "f3", "f3");
- }
- case wgsl::BuiltinFn::kFma:
- case wgsl::BuiltinFn::kMix:
- case wgsl::BuiltinFn::kFaceForward:
- case wgsl::BuiltinFn::kSmoothstep:
- if (type == CallParamType::kF16) {
- return builder->Call(str.str(), "h2", "h2", "h2");
- } else {
- return builder->Call(str.str(), "f2", "f2", "f2");
- }
- case wgsl::BuiltinFn::kAll:
- case wgsl::BuiltinFn::kAny:
- return builder->Call(str.str(), "b2");
- case wgsl::BuiltinFn::kAbs:
- if (type == CallParamType::kF32) {
- return builder->Call(str.str(), "f2");
- } else if (type == CallParamType::kF16) {
- return builder->Call(str.str(), "h2");
- } else {
- return builder->Call(str.str(), "u2");
- }
- case wgsl::BuiltinFn::kCountLeadingZeros:
- case wgsl::BuiltinFn::kCountOneBits:
- case wgsl::BuiltinFn::kCountTrailingZeros:
- case wgsl::BuiltinFn::kReverseBits:
- return builder->Call(str.str(), "u2");
- case wgsl::BuiltinFn::kExtractBits:
- return builder->Call(str.str(), "u2", "u1", "u1");
- case wgsl::BuiltinFn::kInsertBits:
- return builder->Call(str.str(), "u2", "u2", "u1", "u1");
- case wgsl::BuiltinFn::kMax:
- case wgsl::BuiltinFn::kMin:
- if (type == CallParamType::kF32) {
- return builder->Call(str.str(), "f2", "f2");
- } else if (type == CallParamType::kF16) {
- return builder->Call(str.str(), "h2", "h2");
- } else {
- return builder->Call(str.str(), "u2", "u2");
- }
- case wgsl::BuiltinFn::kClamp:
- if (type == CallParamType::kF32) {
- return builder->Call(str.str(), "f2", "f2", "f2");
- } else if (type == CallParamType::kF16) {
- return builder->Call(str.str(), "h2", "h2", "h2");
- } else {
- return builder->Call(str.str(), "u2", "u2", "u2");
- }
- case wgsl::BuiltinFn::kSelect:
- if (type == CallParamType::kF16) {
- return builder->Call(str.str(), "h2", "h2", "b2");
- } else {
- return builder->Call(str.str(), "f2", "f2", "b2");
- }
- case wgsl::BuiltinFn::kDeterminant:
- if (type == CallParamType::kF16) {
- return builder->Call(str.str(), "hm2x2");
- } else {
- return builder->Call(str.str(), "m2x2");
- }
- case wgsl::BuiltinFn::kPack2X16Snorm:
- case wgsl::BuiltinFn::kPack2X16Unorm:
- return builder->Call(str.str(), "f2");
- case wgsl::BuiltinFn::kPack4X8Snorm:
- case wgsl::BuiltinFn::kPack4X8Unorm:
- return builder->Call(str.str(), "f4");
- case wgsl::BuiltinFn::kUnpack4X8Snorm:
- case wgsl::BuiltinFn::kUnpack4X8Unorm:
- case wgsl::BuiltinFn::kUnpack2X16Snorm:
- case wgsl::BuiltinFn::kUnpack2X16Unorm:
- return builder->Call(str.str(), "u1");
- case wgsl::BuiltinFn::kWorkgroupBarrier:
- return builder->Call(str.str());
- case wgsl::BuiltinFn::kTranspose:
- if (type == CallParamType::kF16) {
- return builder->Call(str.str(), "hm3x2");
- } else {
- return builder->Call(str.str(), "m3x2");
- }
- default:
- break;
- }
- return nullptr;
-}
-
-using MslBuiltinTest = TestParamHelper<BuiltinData>;
-TEST_P(MslBuiltinTest, Emit) {
- auto param = GetParam();
-
- if (param.type == CallParamType::kF16) {
- Enable(wgsl::Extension::kF16);
-
- GlobalVar("h2", ty.vec2<f16>(), core::AddressSpace::kPrivate);
- GlobalVar("h3", ty.vec3<f16>(), core::AddressSpace::kPrivate);
- GlobalVar("hm2x2", ty.mat2x2<f16>(), core::AddressSpace::kPrivate);
- GlobalVar("hm3x2", ty.mat3x2<f16>(), core::AddressSpace::kPrivate);
- }
-
- GlobalVar("f2", ty.vec2<f32>(), core::AddressSpace::kPrivate);
- GlobalVar("f3", ty.vec3<f32>(), core::AddressSpace::kPrivate);
- GlobalVar("f4", ty.vec4<f32>(), core::AddressSpace::kPrivate);
- GlobalVar("u1", ty.u32(), core::AddressSpace::kPrivate);
- GlobalVar("u2", ty.vec2<u32>(), core::AddressSpace::kPrivate);
- GlobalVar("i2", ty.vec2<i32>(), core::AddressSpace::kPrivate);
- GlobalVar("b2", ty.vec2<bool>(), core::AddressSpace::kPrivate);
- GlobalVar("m2x2", ty.mat2x2<f32>(), core::AddressSpace::kPrivate);
- GlobalVar("m3x2", ty.mat3x2<f32>(), core::AddressSpace::kPrivate);
-
- auto* call = GenerateCall(param.builtin, param.type, this);
- ASSERT_NE(nullptr, call) << "Unhandled builtin";
- Func("func", tint::Empty, ty.void_(), Vector{Ignore(call)},
- Vector{create<ast::StageAttribute>(ast::PipelineStage::kFragment)});
-
- ASTPrinter& gen = Build();
-
- auto* sem = program->Sem().Get<sem::Call>(call);
- ASSERT_NE(sem, nullptr);
- auto* target = sem->Target();
- ASSERT_NE(target, nullptr);
- auto* builtin = target->As<sem::BuiltinFn>();
- ASSERT_NE(builtin, nullptr);
-
- EXPECT_EQ(gen.generate_builtin_name(builtin), param.msl_name);
-}
-INSTANTIATE_TEST_SUITE_P(
- MslASTPrinterTest,
- MslBuiltinTest,
- testing::Values(
- /* Logical built-in */
- BuiltinData{wgsl::BuiltinFn::kAll, CallParamType::kBool, "all"},
- BuiltinData{wgsl::BuiltinFn::kAny, CallParamType::kBool, "any"},
- BuiltinData{wgsl::BuiltinFn::kSelect, CallParamType::kF32, "select"},
- /* Float built-in */
- BuiltinData{wgsl::BuiltinFn::kAbs, CallParamType::kF32, "fabs"},
- BuiltinData{wgsl::BuiltinFn::kAbs, CallParamType::kF16, "fabs"},
- BuiltinData{wgsl::BuiltinFn::kAcos, CallParamType::kF32, "acos"},
- BuiltinData{wgsl::BuiltinFn::kAcos, CallParamType::kF16, "acos"},
- BuiltinData{wgsl::BuiltinFn::kAsin, CallParamType::kF32, "asin"},
- BuiltinData{wgsl::BuiltinFn::kAsin, CallParamType::kF16, "asin"},
- BuiltinData{wgsl::BuiltinFn::kAtan, CallParamType::kF32, "atan"},
- BuiltinData{wgsl::BuiltinFn::kAtan, CallParamType::kF16, "atan"},
- BuiltinData{wgsl::BuiltinFn::kAtan2, CallParamType::kF32, "atan2"},
- BuiltinData{wgsl::BuiltinFn::kAtan2, CallParamType::kF16, "atan2"},
- BuiltinData{wgsl::BuiltinFn::kCeil, CallParamType::kF32, "ceil"},
- BuiltinData{wgsl::BuiltinFn::kCeil, CallParamType::kF16, "ceil"},
- BuiltinData{wgsl::BuiltinFn::kClamp, CallParamType::kF32, "clamp"},
- BuiltinData{wgsl::BuiltinFn::kClamp, CallParamType::kF16, "clamp"},
- BuiltinData{wgsl::BuiltinFn::kCos, CallParamType::kF32, "cos"},
- BuiltinData{wgsl::BuiltinFn::kCos, CallParamType::kF16, "cos"},
- BuiltinData{wgsl::BuiltinFn::kCosh, CallParamType::kF32, "cosh"},
- BuiltinData{wgsl::BuiltinFn::kCosh, CallParamType::kF16, "cosh"},
- BuiltinData{wgsl::BuiltinFn::kCross, CallParamType::kF32, "cross"},
- BuiltinData{wgsl::BuiltinFn::kCross, CallParamType::kF16, "cross"},
- BuiltinData{wgsl::BuiltinFn::kDistance, CallParamType::kF32, "distance"},
- BuiltinData{wgsl::BuiltinFn::kDistance, CallParamType::kF16, "distance"},
- BuiltinData{wgsl::BuiltinFn::kExp, CallParamType::kF32, "exp"},
- BuiltinData{wgsl::BuiltinFn::kExp, CallParamType::kF16, "exp"},
- BuiltinData{wgsl::BuiltinFn::kExp2, CallParamType::kF32, "exp2"},
- BuiltinData{wgsl::BuiltinFn::kExp2, CallParamType::kF16, "exp2"},
- BuiltinData{wgsl::BuiltinFn::kFaceForward, CallParamType::kF32, "faceforward"},
- BuiltinData{wgsl::BuiltinFn::kFaceForward, CallParamType::kF16, "faceforward"},
- BuiltinData{wgsl::BuiltinFn::kFloor, CallParamType::kF32, "floor"},
- BuiltinData{wgsl::BuiltinFn::kFloor, CallParamType::kF16, "floor"},
- BuiltinData{wgsl::BuiltinFn::kFma, CallParamType::kF32, "fma"},
- BuiltinData{wgsl::BuiltinFn::kFma, CallParamType::kF16, "fma"},
- BuiltinData{wgsl::BuiltinFn::kFract, CallParamType::kF32, "fract"},
- BuiltinData{wgsl::BuiltinFn::kFract, CallParamType::kF16, "fract"},
- BuiltinData{wgsl::BuiltinFn::kInverseSqrt, CallParamType::kF32, "rsqrt"},
- BuiltinData{wgsl::BuiltinFn::kInverseSqrt, CallParamType::kF16, "rsqrt"},
- BuiltinData{wgsl::BuiltinFn::kLdexp, CallParamType::kF32, "ldexp"},
- BuiltinData{wgsl::BuiltinFn::kLdexp, CallParamType::kF16, "ldexp"},
- BuiltinData{wgsl::BuiltinFn::kLength, CallParamType::kF32, "length"},
- BuiltinData{wgsl::BuiltinFn::kLength, CallParamType::kF16, "length"},
- BuiltinData{wgsl::BuiltinFn::kLog, CallParamType::kF32, "log"},
- BuiltinData{wgsl::BuiltinFn::kLog, CallParamType::kF16, "log"},
- BuiltinData{wgsl::BuiltinFn::kLog2, CallParamType::kF32, "log2"},
- BuiltinData{wgsl::BuiltinFn::kLog2, CallParamType::kF16, "log2"},
- BuiltinData{wgsl::BuiltinFn::kMax, CallParamType::kF32, "fmax"},
- BuiltinData{wgsl::BuiltinFn::kMax, CallParamType::kF16, "fmax"},
- BuiltinData{wgsl::BuiltinFn::kMin, CallParamType::kF32, "fmin"},
- BuiltinData{wgsl::BuiltinFn::kMin, CallParamType::kF16, "fmin"},
- BuiltinData{wgsl::BuiltinFn::kNormalize, CallParamType::kF32, "normalize"},
- BuiltinData{wgsl::BuiltinFn::kNormalize, CallParamType::kF16, "normalize"},
- BuiltinData{wgsl::BuiltinFn::kPow, CallParamType::kF32, "powr"},
- BuiltinData{wgsl::BuiltinFn::kPow, CallParamType::kF16, "powr"},
- BuiltinData{wgsl::BuiltinFn::kReflect, CallParamType::kF32, "reflect"},
- BuiltinData{wgsl::BuiltinFn::kReflect, CallParamType::kF16, "reflect"},
- BuiltinData{wgsl::BuiltinFn::kSign, CallParamType::kF32, "sign"},
- BuiltinData{wgsl::BuiltinFn::kSign, CallParamType::kF16, "sign"},
- BuiltinData{wgsl::BuiltinFn::kSin, CallParamType::kF32, "sin"},
- BuiltinData{wgsl::BuiltinFn::kSin, CallParamType::kF16, "sin"},
- BuiltinData{wgsl::BuiltinFn::kSinh, CallParamType::kF32, "sinh"},
- BuiltinData{wgsl::BuiltinFn::kSinh, CallParamType::kF16, "sinh"},
- BuiltinData{wgsl::BuiltinFn::kSmoothstep, CallParamType::kF32, "smoothstep"},
- BuiltinData{wgsl::BuiltinFn::kSmoothstep, CallParamType::kF16, "smoothstep"},
- BuiltinData{wgsl::BuiltinFn::kSqrt, CallParamType::kF32, "sqrt"},
- BuiltinData{wgsl::BuiltinFn::kSqrt, CallParamType::kF16, "sqrt"},
- BuiltinData{wgsl::BuiltinFn::kStep, CallParamType::kF32, "step"},
- BuiltinData{wgsl::BuiltinFn::kStep, CallParamType::kF16, "step"},
- BuiltinData{wgsl::BuiltinFn::kTan, CallParamType::kF32, "tan"},
- BuiltinData{wgsl::BuiltinFn::kTan, CallParamType::kF16, "tan"},
- BuiltinData{wgsl::BuiltinFn::kTanh, CallParamType::kF32, "tanh"},
- BuiltinData{wgsl::BuiltinFn::kTanh, CallParamType::kF16, "tanh"},
- BuiltinData{wgsl::BuiltinFn::kTrunc, CallParamType::kF32, "trunc"},
- BuiltinData{wgsl::BuiltinFn::kTrunc, CallParamType::kF16, "trunc"},
- /* Integer built-in */
- BuiltinData{wgsl::BuiltinFn::kAbs, CallParamType::kU32, "abs"},
- BuiltinData{wgsl::BuiltinFn::kClamp, CallParamType::kU32, "clamp"},
- BuiltinData{wgsl::BuiltinFn::kCountLeadingZeros, CallParamType::kU32, "clz"},
- BuiltinData{wgsl::BuiltinFn::kCountOneBits, CallParamType::kU32, "popcount"},
- BuiltinData{wgsl::BuiltinFn::kCountTrailingZeros, CallParamType::kU32, "ctz"},
- BuiltinData{wgsl::BuiltinFn::kExtractBits, CallParamType::kU32, "extract_bits"},
- BuiltinData{wgsl::BuiltinFn::kInsertBits, CallParamType::kU32, "insert_bits"},
- BuiltinData{wgsl::BuiltinFn::kMax, CallParamType::kU32, "max"},
- BuiltinData{wgsl::BuiltinFn::kMin, CallParamType::kU32, "min"},
- BuiltinData{wgsl::BuiltinFn::kReverseBits, CallParamType::kU32, "reverse_bits"},
- BuiltinData{wgsl::BuiltinFn::kRound, CallParamType::kU32, "rint"},
- /* Matrix built-in */
- BuiltinData{wgsl::BuiltinFn::kDeterminant, CallParamType::kF32, "determinant"},
- BuiltinData{wgsl::BuiltinFn::kTranspose, CallParamType::kF32, "transpose"},
- /* Vector built-in */
- BuiltinData{wgsl::BuiltinFn::kDot, CallParamType::kF32, "dot"},
- /* Derivate built-in */
- BuiltinData{wgsl::BuiltinFn::kDpdx, CallParamType::kF32, "dfdx"},
- BuiltinData{wgsl::BuiltinFn::kDpdxCoarse, CallParamType::kF32, "dfdx"},
- BuiltinData{wgsl::BuiltinFn::kDpdxFine, CallParamType::kF32, "dfdx"},
- BuiltinData{wgsl::BuiltinFn::kDpdy, CallParamType::kF32, "dfdy"},
- BuiltinData{wgsl::BuiltinFn::kDpdyCoarse, CallParamType::kF32, "dfdy"},
- BuiltinData{wgsl::BuiltinFn::kDpdyFine, CallParamType::kF32, "dfdy"},
- BuiltinData{wgsl::BuiltinFn::kFwidth, CallParamType::kF32, "fwidth"},
- BuiltinData{wgsl::BuiltinFn::kFwidthCoarse, CallParamType::kF32, "fwidth"},
- BuiltinData{wgsl::BuiltinFn::kFwidthFine, CallParamType::kF32, "fwidth"},
- /* Data packing builtin */
- BuiltinData{wgsl::BuiltinFn::kPack4X8Snorm, CallParamType::kF32, "pack_float_to_snorm4x8"},
- BuiltinData{wgsl::BuiltinFn::kPack4X8Unorm, CallParamType::kF32, "pack_float_to_unorm4x8"},
- BuiltinData{wgsl::BuiltinFn::kPack2X16Snorm, CallParamType::kF32,
- "pack_float_to_snorm2x16"},
- BuiltinData{wgsl::BuiltinFn::kPack2X16Unorm, CallParamType::kF32,
- "pack_float_to_unorm2x16"},
- /* Data unpacking builtin */
- BuiltinData{wgsl::BuiltinFn::kUnpack4X8Snorm, CallParamType::kU32,
- "unpack_snorm4x8_to_float"},
- BuiltinData{wgsl::BuiltinFn::kUnpack4X8Unorm, CallParamType::kU32,
- "unpack_unorm4x8_to_float"},
- BuiltinData{wgsl::BuiltinFn::kUnpack2X16Snorm, CallParamType::kU32,
- "unpack_snorm2x16_to_float"},
- BuiltinData{wgsl::BuiltinFn::kUnpack2X16Unorm, CallParamType::kU32,
- "unpack_unorm2x16_to_float"}));
-
-TEST_F(MslASTPrinterTest, Builtin_Call) {
- GlobalVar("param1", ty.vec2<f32>(), core::AddressSpace::kPrivate);
- GlobalVar("param2", ty.vec2<f32>(), core::AddressSpace::kPrivate);
-
- auto* call = Call("dot", "param1", "param2");
- WrapInFunction(Decl(Var("r", call)));
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "dot(param1, param2)");
-}
-
-TEST_F(MslASTPrinterTest, StorageBarrier) {
- auto* call = Call("storageBarrier");
- WrapInFunction(CallStmt(call));
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "threadgroup_barrier(mem_flags::mem_device)");
-}
-
-TEST_F(MslASTPrinterTest, WorkgroupBarrier) {
- auto* call = Call("workgroupBarrier");
- WrapInFunction(CallStmt(call));
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "threadgroup_barrier(mem_flags::mem_threadgroup)");
-}
-
-TEST_F(MslASTPrinterTest, Runtime_Modf_Scalar_f32) {
- WrapInFunction(Decl(Let("f", Expr(1.5_f))), //
- Decl(Let("v", Call("modf", "f"))));
-
- ASTPrinter& gen = SanitizeAndBuild();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-
-struct modf_result_f32 {
- float fract;
- float whole;
-};
-modf_result_f32 tint_modf(float param_0) {
- modf_result_f32 result;
- result.fract = modf(param_0, result.whole);
- return result;
-}
-
-kernel void test_function() {
- float const f = 1.5f;
- modf_result_f32 const v = tint_modf(f);
- return;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Runtime_Modf_Scalar_f16) {
- Enable(wgsl::Extension::kF16);
-
- WrapInFunction(Decl(Let("f", Expr(1.5_h))), //
- Decl(Let("v", Call("modf", "f"))));
-
- ASTPrinter& gen = SanitizeAndBuild();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-
-struct modf_result_f16 {
- half fract;
- half whole;
-};
-modf_result_f16 tint_modf(half param_0) {
- modf_result_f16 result;
- result.fract = modf(param_0, result.whole);
- return result;
-}
-
-kernel void test_function() {
- half const f = 1.5h;
- modf_result_f16 const v = tint_modf(f);
- return;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Runtime_Modf_Vector_f32) {
- WrapInFunction(Decl(Let("f", Call<vec3<f32>>(1.5_f, 2.5_f, 3.5_f))), //
- Decl(Let("v", Call("modf", "f"))));
-
- ASTPrinter& gen = SanitizeAndBuild();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-
-struct modf_result_vec3_f32 {
- float3 fract;
- float3 whole;
-};
-modf_result_vec3_f32 tint_modf(float3 param_0) {
- modf_result_vec3_f32 result;
- result.fract = modf(param_0, result.whole);
- return result;
-}
-
-kernel void test_function() {
- float3 const f = float3(1.5f, 2.5f, 3.5f);
- modf_result_vec3_f32 const v = tint_modf(f);
- return;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Runtime_Modf_Vector_f16) {
- Enable(wgsl::Extension::kF16);
-
- WrapInFunction(Decl(Let("f", Call<vec3<f16>>(1.5_h, 2.5_h, 3.5_h))), //
- Decl(Let("v", Call("modf", "f"))));
-
- ASTPrinter& gen = SanitizeAndBuild();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-
-struct modf_result_vec3_f16 {
- half3 fract;
- half3 whole;
-};
-modf_result_vec3_f16 tint_modf(half3 param_0) {
- modf_result_vec3_f16 result;
- result.fract = modf(param_0, result.whole);
- return result;
-}
-
-kernel void test_function() {
- half3 const f = half3(1.5h, 2.5h, 3.5h);
- modf_result_vec3_f16 const v = tint_modf(f);
- return;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Const_Modf_Scalar_f32) {
- WrapInFunction(Decl(Let("v", Call("modf", 1.5_f))));
-
- ASTPrinter& gen = SanitizeAndBuild();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-
-struct modf_result_f32 {
- float fract;
- float whole;
-};
-kernel void test_function() {
- modf_result_f32 const v = modf_result_f32{.fract=0.5f, .whole=1.0f};
- return;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Const_Modf_Scalar_f16) {
- Enable(wgsl::Extension::kF16);
-
- WrapInFunction(Decl(Let("v", Call("modf", 1.5_h))));
-
- ASTPrinter& gen = SanitizeAndBuild();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-
-struct modf_result_f16 {
- half fract;
- half whole;
-};
-kernel void test_function() {
- modf_result_f16 const v = modf_result_f16{.fract=0.5h, .whole=1.0h};
- return;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Const_Modf_Vector_f32) {
- WrapInFunction(Decl(Let("v", Call("modf", Call<vec3<f32>>(1.5_f, 2.5_f, 3.5_f)))));
-
- ASTPrinter& gen = SanitizeAndBuild();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-
-struct modf_result_vec3_f32 {
- float3 fract;
- float3 whole;
-};
-kernel void test_function() {
- modf_result_vec3_f32 const v = modf_result_vec3_f32{.fract=float3(0.5f), .whole=float3(1.0f, 2.0f, 3.0f)};
- return;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Const_Modf_Vector_f16) {
- Enable(wgsl::Extension::kF16);
-
- WrapInFunction(Decl(Let("v", Call("modf", Call<vec3<f16>>(1.5_h, 2.5_h, 3.5_h)))));
-
- ASTPrinter& gen = SanitizeAndBuild();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-
-struct modf_result_vec3_f16 {
- half3 fract;
- half3 whole;
-};
-kernel void test_function() {
- modf_result_vec3_f16 const v = modf_result_vec3_f16{.fract=half3(0.5h), .whole=half3(1.0h, 2.0h, 3.0h)};
- return;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Runtime_Frexp_Scalar_f32) {
- WrapInFunction(Var("f", Expr(1_f)), //
- Var("v", Call("frexp", "f")));
-
- ASTPrinter& gen = SanitizeAndBuild();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-
-struct frexp_result_f32 {
- float fract;
- int exp;
-};
-frexp_result_f32 tint_frexp(float param_0) {
- frexp_result_f32 result;
- result.fract = frexp(param_0, result.exp);
- return result;
-}
-
-kernel void test_function() {
- float f = 1.0f;
- frexp_result_f32 v = tint_frexp(f);
- return;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Runtime_Frexp_Scalar_f16) {
- Enable(wgsl::Extension::kF16);
-
- WrapInFunction(Var("f", Expr(1_h)), //
- Var("v", Call("frexp", "f")));
-
- ASTPrinter& gen = SanitizeAndBuild();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-
-struct frexp_result_f16 {
- half fract;
- int exp;
-};
-frexp_result_f16 tint_frexp(half param_0) {
- frexp_result_f16 result;
- result.fract = frexp(param_0, result.exp);
- return result;
-}
-
-kernel void test_function() {
- half f = 1.0h;
- frexp_result_f16 v = tint_frexp(f);
- return;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Runtime_Frexp_Vector_f32) {
- WrapInFunction(Var("f", Call<vec3<f32>>()), //
- Var("v", Call("frexp", "f")));
-
- ASTPrinter& gen = SanitizeAndBuild();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-
-struct frexp_result_vec3_f32 {
- float3 fract;
- int3 exp;
-};
-frexp_result_vec3_f32 tint_frexp(float3 param_0) {
- frexp_result_vec3_f32 result;
- result.fract = frexp(param_0, result.exp);
- return result;
-}
-
-kernel void test_function() {
- float3 f = float3(0.0f);
- frexp_result_vec3_f32 v = tint_frexp(f);
- return;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Runtime_Frexp_Vector_f16) {
- Enable(wgsl::Extension::kF16);
-
- WrapInFunction(Var("f", Call<vec3<f16>>()), //
- Var("v", Call("frexp", "f")));
-
- ASTPrinter& gen = SanitizeAndBuild();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-
-struct frexp_result_vec3_f16 {
- half3 fract;
- int3 exp;
-};
-frexp_result_vec3_f16 tint_frexp(half3 param_0) {
- frexp_result_vec3_f16 result;
- result.fract = frexp(param_0, result.exp);
- return result;
-}
-
-kernel void test_function() {
- half3 f = half3(0.0h);
- frexp_result_vec3_f16 v = tint_frexp(f);
- return;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Const_Frexp_Scalar_f32) {
- WrapInFunction(Decl(Let("v", Call("frexp", 1_f))));
-
- ASTPrinter& gen = SanitizeAndBuild();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-
-struct frexp_result_f32 {
- float fract;
- int exp;
-};
-kernel void test_function() {
- frexp_result_f32 const v = frexp_result_f32{.fract=0.5f, .exp=1};
- return;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Const_Frexp_Scalar_f16) {
- Enable(wgsl::Extension::kF16);
-
- WrapInFunction(Decl(Let("v", Call("frexp", 1_h))));
-
- ASTPrinter& gen = SanitizeAndBuild();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-
-struct frexp_result_f16 {
- half fract;
- int exp;
-};
-kernel void test_function() {
- frexp_result_f16 const v = frexp_result_f16{.fract=0.5h, .exp=1};
- return;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Const_Frexp_Vector_f32) {
- WrapInFunction(Decl(Let("v", Call("frexp", Call<vec3<f32>>()))));
-
- ASTPrinter& gen = SanitizeAndBuild();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-
-struct frexp_result_vec3_f32 {
- float3 fract;
- int3 exp;
-};
-kernel void test_function() {
- frexp_result_vec3_f32 const v = frexp_result_vec3_f32{};
- return;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Const_Frexp_Vector_f16) {
- Enable(wgsl::Extension::kF16);
-
- WrapInFunction(Decl(Let("v", Call("frexp", Call<vec3<f16>>()))));
-
- ASTPrinter& gen = SanitizeAndBuild();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-
-struct frexp_result_vec3_f16 {
- half3 fract;
- int3 exp;
-};
-kernel void test_function() {
- frexp_result_vec3_f16 const v = frexp_result_vec3_f16{};
- return;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Degrees_Scalar_f32) {
- auto* val = Var("val", ty.f32());
- auto* call = Call("degrees", val);
- WrapInFunction(val, call);
-
- ASTPrinter& gen = SanitizeAndBuild();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-
-float tint_degrees(float param_0) {
- return param_0 * 57.29577951308232286465;
-}
-
-kernel void test_function() {
- float val = 0.0f;
- float const tint_symbol = tint_degrees(val);
- return;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Degrees_Vector_f32) {
- auto* val = Var("val", ty.vec3<f32>());
- auto* call = Call("degrees", val);
- WrapInFunction(val, call);
-
- ASTPrinter& gen = SanitizeAndBuild();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-
-float3 tint_degrees(float3 param_0) {
- return param_0 * 57.29577951308232286465;
-}
-
-kernel void test_function() {
- float3 val = 0.0f;
- float3 const tint_symbol = tint_degrees(val);
- return;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Degrees_Scalar_f16) {
- Enable(wgsl::Extension::kF16);
-
- auto* val = Var("val", ty.f16());
- auto* call = Call("degrees", val);
- WrapInFunction(val, call);
-
- ASTPrinter& gen = SanitizeAndBuild();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-
-half tint_degrees(half param_0) {
- return param_0 * 57.29577951308232286465;
-}
-
-kernel void test_function() {
- half val = 0.0h;
- half const tint_symbol = tint_degrees(val);
- return;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Degrees_Vector_f16) {
- Enable(wgsl::Extension::kF16);
-
- auto* val = Var("val", ty.vec3<f16>());
- auto* call = Call("degrees", val);
- WrapInFunction(val, call);
-
- ASTPrinter& gen = SanitizeAndBuild();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-
-half3 tint_degrees(half3 param_0) {
- return param_0 * 57.29577951308232286465;
-}
-
-kernel void test_function() {
- half3 val = 0.0h;
- half3 const tint_symbol = tint_degrees(val);
- return;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Radians_Scalar_f32) {
- auto* val = Var("val", ty.f32());
- auto* call = Call("radians", val);
- WrapInFunction(val, call);
-
- ASTPrinter& gen = SanitizeAndBuild();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-
-float tint_radians(float param_0) {
- return param_0 * 0.01745329251994329547;
-}
-
-kernel void test_function() {
- float val = 0.0f;
- float const tint_symbol = tint_radians(val);
- return;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Radians_Vector_f32) {
- auto* val = Var("val", ty.vec3<f32>());
- auto* call = Call("radians", val);
- WrapInFunction(val, call);
-
- ASTPrinter& gen = SanitizeAndBuild();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-
-float3 tint_radians(float3 param_0) {
- return param_0 * 0.01745329251994329547;
-}
-
-kernel void test_function() {
- float3 val = 0.0f;
- float3 const tint_symbol = tint_radians(val);
- return;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Radians_Scalar_f16) {
- Enable(wgsl::Extension::kF16);
-
- auto* val = Var("val", ty.f16());
- auto* call = Call("radians", val);
- WrapInFunction(val, call);
-
- ASTPrinter& gen = SanitizeAndBuild();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-
-half tint_radians(half param_0) {
- return param_0 * 0.01745329251994329547;
-}
-
-kernel void test_function() {
- half val = 0.0h;
- half const tint_symbol = tint_radians(val);
- return;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Radians_Vector_f16) {
- Enable(wgsl::Extension::kF16);
-
- auto* val = Var("val", ty.vec3<f16>());
- auto* call = Call("radians", val);
- WrapInFunction(val, call);
-
- ASTPrinter& gen = SanitizeAndBuild();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-
-half3 tint_radians(half3 param_0) {
- return param_0 * 0.01745329251994329547;
-}
-
-kernel void test_function() {
- half3 val = 0.0h;
- half3 const tint_symbol = tint_radians(val);
- return;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Pack2x16Float) {
- auto* call = Call("pack2x16float", "p1");
- GlobalVar("p1", ty.vec2<f32>(), core::AddressSpace::kPrivate);
- WrapInFunction(Decl(Var("r", call)));
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "as_type<uint>(half2(p1))");
-}
-
-TEST_F(MslASTPrinterTest, Unpack2x16Float) {
- auto* call = Call("unpack2x16float", "p1");
- GlobalVar("p1", ty.u32(), core::AddressSpace::kPrivate);
- WrapInFunction(Decl(Var("r", call)));
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "float2(as_type<half2>(p1))");
-}
-
-TEST_F(MslASTPrinterTest, DotI32) {
- GlobalVar("v", ty.vec3<i32>(), core::AddressSpace::kPrivate);
- WrapInFunction(Decl(Var("r", Call("dot", "v", "v"))));
-
- ASTPrinter& gen = SanitizeAndBuild();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-
-template<typename T>
-T tint_dot3(vec<T,3> a, vec<T,3> b) {
- return a[0]*b[0] + a[1]*b[1] + a[2]*b[2];
-}
-struct tint_private_vars_struct {
- int3 v;
-};
-
-kernel void test_function() {
- thread tint_private_vars_struct tint_private_vars = {};
- int r = tint_dot3(tint_private_vars.v, tint_private_vars.v);
- return;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Ignore) {
- Func("f", Vector{Param("a", ty.i32()), Param("b", ty.i32()), Param("c", ty.i32())}, ty.i32(),
- Vector{Return(Mul(Add("a", "b"), "c"))});
-
- Func("func", tint::Empty, ty.void_(), Vector{CallStmt(Call("f", 1_i, 2_i, 3_i))},
- Vector{
- Stage(ast::PipelineStage::kCompute),
- WorkgroupSize(1_i),
- });
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-int f(int a, int b, int c) {
- return as_type<int>((as_type<uint>(as_type<int>((as_type<uint>(a) + as_type<uint>(b)))) * as_type<uint>(c)));
-}
-
-kernel void func() {
- f(1, 2, 3);
- return;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, PolyfillDot4I8Packed) {
- WrapInFunction(Decl(Let("zero", Expr(0_u))), //
- Decl(Let("v", Call("dot4I8Packed", "zero", Expr(1_u)))));
-
- ASTPrinter& gen = SanitizeAndBuild();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-
-template<typename T>
-T tint_dot4(vec<T,4> a, vec<T,4> b) {
- return a[0]*b[0] + a[1]*b[1] + a[2]*b[2] + a[3]*b[3];
-}
-int tint_dot4_i8_packed(uint a, uint b) {
- int4 const a_i8 = (as_type<int4>((uint4(a) << uint4(24u, 16u, 8u, 0u))) >> uint4(24u));
- int4 const b_i8 = (as_type<int4>((uint4(b) << uint4(24u, 16u, 8u, 0u))) >> uint4(24u));
- return tint_dot4(a_i8, b_i8);
-}
-
-kernel void test_function() {
- uint const zero = 0u;
- int const v = tint_dot4_i8_packed(zero, 1u);
- return;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, PolyfillDot4U8Packed) {
- WrapInFunction(Decl(Let("zero", Expr(0_u))), //
- Decl(Let("v", Call("dot4U8Packed", "zero", Expr(1_u)))));
-
- ASTPrinter& gen = SanitizeAndBuild();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-
-template<typename T>
-T tint_dot4(vec<T,4> a, vec<T,4> b) {
- return a[0]*b[0] + a[1]*b[1] + a[2]*b[2] + a[3]*b[3];
-}
-uint tint_dot4_u8_packed(uint a, uint b) {
- uint4 const a_u8 = ((uint4(a) >> uint4(24u, 16u, 8u, 0u)) & uint4(255u));
- uint4 const b_u8 = ((uint4(b) >> uint4(24u, 16u, 8u, 0u)) & uint4(255u));
- return tint_dot4(a_u8, b_u8);
-}
-
-kernel void test_function() {
- uint const zero = 0u;
- uint const v = tint_dot4_u8_packed(zero, 1u);
- return;
-}
-
-)");
-}
-
-} // namespace
-} // namespace tint::msl::writer
diff --git a/src/tint/lang/msl/writer/ast_printer/builtin_texture_test.cc b/src/tint/lang/msl/writer/ast_printer/builtin_texture_test.cc
deleted file mode 100644
index 8213b90..0000000
--- a/src/tint/lang/msl/writer/ast_printer/builtin_texture_test.cc
+++ /dev/null
@@ -1,313 +0,0 @@
-// Copyright 2020 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/tint/lang/msl/writer/ast_printer/helper_test.h"
-#include "src/tint/lang/wgsl/ast/builtin_texture_helper_test.h"
-#include "src/tint/lang/wgsl/ast/call_statement.h"
-#include "src/tint/utils/text/string_stream.h"
-
-namespace tint::msl::writer {
-namespace {
-
-std::string expected_texture_overload(ast::test::ValidTextureOverload overload) {
- using ValidTextureOverload = ast::test::ValidTextureOverload;
- switch (overload) {
- case ValidTextureOverload::kDimensions1d:
- case ValidTextureOverload::kDimensionsStorageWO1d:
- return R"(Texture.get_width(0))";
- case ValidTextureOverload::kDimensions2d:
- case ValidTextureOverload::kDimensions2dArray:
- case ValidTextureOverload::kDimensionsCube:
- case ValidTextureOverload::kDimensionsCubeArray:
- case ValidTextureOverload::kDimensionsMultisampled2d:
- case ValidTextureOverload::kDimensionsDepth2d:
- case ValidTextureOverload::kDimensionsDepth2dArray:
- case ValidTextureOverload::kDimensionsDepthCube:
- case ValidTextureOverload::kDimensionsDepthCubeArray:
- case ValidTextureOverload::kDimensionsDepthMultisampled2d:
- case ValidTextureOverload::kDimensionsStorageWO2d:
- case ValidTextureOverload::kDimensionsStorageWO2dArray:
- return R"(uint2(Texture.get_width(), Texture.get_height()))";
- case ValidTextureOverload::kDimensions3d:
- case ValidTextureOverload::kDimensionsStorageWO3d:
- return R"(uint3(Texture.get_width(), Texture.get_height(), Texture.get_depth()))";
- case ValidTextureOverload::kDimensions2dLevel:
- case ValidTextureOverload::kDimensionsCubeLevel:
- case ValidTextureOverload::kDimensionsCubeArrayLevel:
- case ValidTextureOverload::kDimensions2dArrayLevel:
- case ValidTextureOverload::kDimensionsDepth2dLevel:
- case ValidTextureOverload::kDimensionsDepth2dArrayLevel:
- case ValidTextureOverload::kDimensionsDepthCubeLevel:
- case ValidTextureOverload::kDimensionsDepthCubeArrayLevel:
- return R"(uint2(Texture.get_width(1), Texture.get_height(1)))";
- case ValidTextureOverload::kDimensions3dLevel:
- return R"(uint3(Texture.get_width(1), Texture.get_height(1), Texture.get_depth(1)))";
- case ValidTextureOverload::kGather2dF32:
- return R"(Texture.gather(Sampler, float2(1.0f, 2.0f), int2(0), component::x))";
- case ValidTextureOverload::kGather2dOffsetF32:
- return R"(Texture.gather(Sampler, float2(1.0f, 2.0f), int2(3, 4), component::x))";
- case ValidTextureOverload::kGather2dArrayF32:
- return R"(Texture.gather(Sampler, float2(1.0f, 2.0f), max(0, 3), int2(0), component::x))";
- case ValidTextureOverload::kGather2dArrayOffsetF32:
- return R"(Texture.gather(Sampler, float2(1.0f, 2.0f), 3u, int2(4, 5), component::x))";
- case ValidTextureOverload::kGatherCubeF32:
- return R"(Texture.gather(Sampler, float3(1.0f, 2.0f, 3.0f), component::x))";
- case ValidTextureOverload::kGatherCubeArrayF32:
- return R"(Texture.gather(Sampler, float3(1.0f, 2.0f, 3.0f), 4u, component::x))";
- case ValidTextureOverload::kGatherDepth2dF32:
- return R"(Texture.gather(Sampler, float2(1.0f, 2.0f)))";
- case ValidTextureOverload::kGatherDepth2dOffsetF32:
- return R"(Texture.gather(Sampler, float2(1.0f, 2.0f), int2(3, 4)))";
- case ValidTextureOverload::kGatherDepth2dArrayF32:
- return R"(Texture.gather(Sampler, float2(1.0f, 2.0f), 3u))";
- case ValidTextureOverload::kGatherDepth2dArrayOffsetF32:
- return R"(Texture.gather(Sampler, float2(1.0f, 2.0f), max(0, 3), int2(4, 5)))";
- case ValidTextureOverload::kGatherDepthCubeF32:
- return R"(Texture.gather(Sampler, float3(1.0f, 2.0f, 3.0f)))";
- case ValidTextureOverload::kGatherDepthCubeArrayF32:
- return R"(Texture.gather(Sampler, float3(1.0f, 2.0f, 3.0f), 4u))";
- case ValidTextureOverload::kGatherCompareDepth2dF32:
- return R"(Texture.gather_compare(Sampler, float2(1.0f, 2.0f), 3.0f))";
- case ValidTextureOverload::kGatherCompareDepth2dOffsetF32:
- return R"(Texture.gather_compare(Sampler, float2(1.0f, 2.0f), 3.0f, int2(4, 5)))";
- case ValidTextureOverload::kGatherCompareDepth2dArrayF32:
- return R"(Texture.gather_compare(Sampler, float2(1.0f, 2.0f), max(0, 3), 4.0f))";
- case ValidTextureOverload::kGatherCompareDepth2dArrayOffsetF32:
- return R"(Texture.gather_compare(Sampler, float2(1.0f, 2.0f), max(0, 3), 4.0f, int2(5, 6)))";
- case ValidTextureOverload::kGatherCompareDepthCubeF32:
- return R"(Texture.gather_compare(Sampler, float3(1.0f, 2.0f, 3.0f), 4.0f))";
- case ValidTextureOverload::kGatherCompareDepthCubeArrayF32:
- return R"(Texture.gather_compare(Sampler, float3(1.0f, 2.0f, 3.0f), 4u, 5.0f))";
- case ValidTextureOverload::kNumLayers2dArray:
- case ValidTextureOverload::kNumLayersCubeArray:
- case ValidTextureOverload::kNumLayersDepth2dArray:
- case ValidTextureOverload::kNumLayersDepthCubeArray:
- case ValidTextureOverload::kNumLayersStorageWO2dArray:
- return R"(Texture.get_array_size())";
- case ValidTextureOverload::kNumLevels2d:
- case ValidTextureOverload::kNumLevels2dArray:
- case ValidTextureOverload::kNumLevels3d:
- case ValidTextureOverload::kNumLevelsCube:
- case ValidTextureOverload::kNumLevelsCubeArray:
- case ValidTextureOverload::kNumLevelsDepth2d:
- case ValidTextureOverload::kNumLevelsDepth2dArray:
- case ValidTextureOverload::kNumLevelsDepthCube:
- case ValidTextureOverload::kNumLevelsDepthCubeArray:
- return R"(Texture.get_num_mip_levels())";
- case ValidTextureOverload::kNumSamplesDepthMultisampled2d:
- case ValidTextureOverload::kNumSamplesMultisampled2d:
- return R"(Texture.get_num_samples())";
- case ValidTextureOverload::kSample1dF32:
- return R"(Texture.sample(Sampler, 1.0f))";
- case ValidTextureOverload::kSample2dF32:
- return R"(Texture.sample(Sampler, float2(1.0f, 2.0f)))";
- case ValidTextureOverload::kSample2dOffsetF32:
- return R"(Texture.sample(Sampler, float2(1.0f, 2.0f), int2(3, 4)))";
- case ValidTextureOverload::kSample2dArrayF32:
- return R"(Texture.sample(Sampler, float2(1.0f, 2.0f), max(0, 3)))";
- case ValidTextureOverload::kSample2dArrayOffsetF32:
- return R"(Texture.sample(Sampler, float2(1.0f, 2.0f), 3u, int2(4, 5)))";
- case ValidTextureOverload::kSample3dF32:
- return R"(Texture.sample(Sampler, float3(1.0f, 2.0f, 3.0f)))";
- case ValidTextureOverload::kSample3dOffsetF32:
- return R"(Texture.sample(Sampler, float3(1.0f, 2.0f, 3.0f), int3(4, 5, 6)))";
- case ValidTextureOverload::kSampleCubeF32:
- return R"(Texture.sample(Sampler, float3(1.0f, 2.0f, 3.0f)))";
- case ValidTextureOverload::kSampleCubeArrayF32:
- return R"(Texture.sample(Sampler, float3(1.0f, 2.0f, 3.0f), max(0, 4)))";
- case ValidTextureOverload::kSampleDepth2dF32:
- return R"(Texture.sample(Sampler, float2(1.0f, 2.0f)))";
- case ValidTextureOverload::kSampleDepth2dOffsetF32:
- return R"(Texture.sample(Sampler, float2(1.0f, 2.0f), int2(3, 4)))";
- case ValidTextureOverload::kSampleDepth2dArrayF32:
- return R"(Texture.sample(Sampler, float2(1.0f, 2.0f), max(0, 3)))";
- case ValidTextureOverload::kSampleDepth2dArrayOffsetF32:
- return R"(Texture.sample(Sampler, float2(1.0f, 2.0f), max(0, 3), int2(4, 5)))";
- case ValidTextureOverload::kSampleDepthCubeF32:
- return R"(Texture.sample(Sampler, float3(1.0f, 2.0f, 3.0f)))";
- case ValidTextureOverload::kSampleDepthCubeArrayF32:
- return R"(Texture.sample(Sampler, float3(1.0f, 2.0f, 3.0f), 4u))";
- case ValidTextureOverload::kSampleBias2dF32:
- return R"(Texture.sample(Sampler, float2(1.0f, 2.0f), bias(3.0f)))";
- case ValidTextureOverload::kSampleBias2dOffsetF32:
- return R"(Texture.sample(Sampler, float2(1.0f, 2.0f), bias(3.0f), int2(4, 5)))";
- case ValidTextureOverload::kSampleBias2dArrayF32:
- return R"(Texture.sample(Sampler, float2(1.0f, 2.0f), 4u, bias(3.0f)))";
- case ValidTextureOverload::kSampleBias2dArrayOffsetF32:
- return R"(Texture.sample(Sampler, float2(1.0f, 2.0f), max(0, 3), bias(4.0f), int2(5, 6)))";
- case ValidTextureOverload::kSampleBias3dF32:
- return R"(Texture.sample(Sampler, float3(1.0f, 2.0f, 3.0f), bias(4.0f)))";
- case ValidTextureOverload::kSampleBias3dOffsetF32:
- return R"(Texture.sample(Sampler, float3(1.0f, 2.0f, 3.0f), bias(4.0f), int3(5, 6, 7)))";
- case ValidTextureOverload::kSampleBiasCubeF32:
- return R"(Texture.sample(Sampler, float3(1.0f, 2.0f, 3.0f), bias(4.0f)))";
- case ValidTextureOverload::kSampleBiasCubeArrayF32:
- return R"(Texture.sample(Sampler, float3(1.0f, 2.0f, 3.0f), max(0, 3), bias(4.0f)))";
- case ValidTextureOverload::kSampleLevel2dF32:
- return R"(Texture.sample(Sampler, float2(1.0f, 2.0f), level(3.0f)))";
- case ValidTextureOverload::kSampleLevel2dOffsetF32:
- return R"(Texture.sample(Sampler, float2(1.0f, 2.0f), level(3.0f), int2(4, 5)))";
- case ValidTextureOverload::kSampleLevel2dArrayF32:
- return R"(Texture.sample(Sampler, float2(1.0f, 2.0f), max(0, 3), level(4.0f)))";
- case ValidTextureOverload::kSampleLevel2dArrayOffsetF32:
- return R"(Texture.sample(Sampler, float2(1.0f, 2.0f), max(0, 3), level(4.0f), int2(5, 6)))";
- case ValidTextureOverload::kSampleLevel3dF32:
- return R"(Texture.sample(Sampler, float3(1.0f, 2.0f, 3.0f), level(4.0f)))";
- case ValidTextureOverload::kSampleLevel3dOffsetF32:
- return R"(Texture.sample(Sampler, float3(1.0f, 2.0f, 3.0f), level(4.0f), int3(5, 6, 7)))";
- case ValidTextureOverload::kSampleLevelCubeF32:
- return R"(Texture.sample(Sampler, float3(1.0f, 2.0f, 3.0f), level(4.0f)))";
- case ValidTextureOverload::kSampleLevelCubeArrayF32:
- return R"(Texture.sample(Sampler, float3(1.0f, 2.0f, 3.0f), max(0, 4), level(5.0f)))";
- case ValidTextureOverload::kSampleLevelDepth2dF32:
- return R"(Texture.sample(Sampler, float2(1.0f, 2.0f), level(3u)))";
- case ValidTextureOverload::kSampleLevelDepth2dOffsetF32:
- return R"(Texture.sample(Sampler, float2(1.0f, 2.0f), level(3), int2(4, 5)))";
- case ValidTextureOverload::kSampleLevelDepth2dArrayF32:
- return R"(Texture.sample(Sampler, float2(1.0f, 2.0f), 3u, level(4u)))";
- case ValidTextureOverload::kSampleLevelDepth2dArrayOffsetF32:
- return R"(Texture.sample(Sampler, float2(1.0f, 2.0f), 3u, level(4u), int2(5, 6)))";
- case ValidTextureOverload::kSampleLevelDepthCubeF32:
- return R"(Texture.sample(Sampler, float3(1.0f, 2.0f, 3.0f), level(4)))";
- case ValidTextureOverload::kSampleLevelDepthCubeArrayF32:
- return R"(Texture.sample(Sampler, float3(1.0f, 2.0f, 3.0f), max(0, 4), level(5)))";
- case ValidTextureOverload::kSampleGrad2dF32:
- return R"(Texture.sample(Sampler, float2(1.0f, 2.0f), gradient2d(float2(3.0f, 4.0f), float2(5.0f, 6.0f))))";
- case ValidTextureOverload::kSampleGrad2dOffsetF32:
- return R"(Texture.sample(Sampler, float2(1.0f, 2.0f), gradient2d(float2(3.0f, 4.0f), float2(5.0f, 6.0f)), int2(7)))";
- case ValidTextureOverload::kSampleGrad2dArrayF32:
- return R"(Texture.sample(Sampler, float2(1.0f, 2.0f), max(0, 3), gradient2d(float2(4.0f, 5.0f), float2(6.0f, 7.0f))))";
- case ValidTextureOverload::kSampleGrad2dArrayOffsetF32:
- return R"(Texture.sample(Sampler, float2(1.0f, 2.0f), 3u, gradient2d(float2(4.0f, 5.0f), float2(6.0f, 7.0f)), int2(6, 7)))";
- case ValidTextureOverload::kSampleGrad3dF32:
- return R"(Texture.sample(Sampler, float3(1.0f, 2.0f, 3.0f), gradient3d(float3(4.0f, 5.0f, 6.0f), float3(7.0f, 8.0f, 9.0f))))";
- case ValidTextureOverload::kSampleGrad3dOffsetF32:
- return R"(Texture.sample(Sampler, float3(1.0f, 2.0f, 3.0f), gradient3d(float3(4.0f, 5.0f, 6.0f), float3(7.0f, 8.0f, 9.0f)), int3(0, 1, 2)))";
- case ValidTextureOverload::kSampleGradCubeF32:
- return R"(Texture.sample(Sampler, float3(1.0f, 2.0f, 3.0f), gradientcube(float3(4.0f, 5.0f, 6.0f), float3(7.0f, 8.0f, 9.0f))))";
- case ValidTextureOverload::kSampleGradCubeArrayF32:
- return R"(Texture.sample(Sampler, float3(1.0f, 2.0f, 3.0f), 4u, gradientcube(float3(5.0f, 6.0f, 7.0f), float3(8.0f, 9.0f, 10.0f))))";
- case ValidTextureOverload::kSampleCompareDepth2dF32:
- return R"(Texture.sample_compare(Sampler, float2(1.0f, 2.0f), 3.0f))";
- case ValidTextureOverload::kSampleCompareDepth2dOffsetF32:
- return R"(Texture.sample_compare(Sampler, float2(1.0f, 2.0f), 3.0f, int2(4, 5)))";
- case ValidTextureOverload::kSampleCompareDepth2dArrayF32:
- return R"(Texture.sample_compare(Sampler, float2(1.0f, 2.0f), max(0, 4), 3.0f))";
- case ValidTextureOverload::kSampleCompareDepth2dArrayOffsetF32:
- return R"(Texture.sample_compare(Sampler, float2(1.0f, 2.0f), 4u, 3.0f, int2(5, 6)))";
- case ValidTextureOverload::kSampleCompareDepthCubeF32:
- return R"(Texture.sample_compare(Sampler, float3(1.0f, 2.0f, 3.0f), 4.0f))";
- case ValidTextureOverload::kSampleCompareDepthCubeArrayF32:
- return R"(Texture.sample_compare(Sampler, float3(1.0f, 2.0f, 3.0f), max(0, 4), 5.0f))";
- case ValidTextureOverload::kSampleCompareLevelDepth2dF32:
- return R"(Texture.sample_compare(Sampler, float2(1.0f, 2.0f), 3.0f, level(0)))";
- case ValidTextureOverload::kSampleCompareLevelDepth2dOffsetF32:
- return R"(Texture.sample_compare(Sampler, float2(1.0f, 2.0f), 3.0f, level(0), int2(4, 5)))";
- case ValidTextureOverload::kSampleCompareLevelDepth2dArrayF32:
- return R"(Texture.sample_compare(Sampler, float2(1.0f, 2.0f), max(0, 3), 4.0f, level(0)))";
- case ValidTextureOverload::kSampleCompareLevelDepth2dArrayOffsetF32:
- return R"(Texture.sample_compare(Sampler, float2(1.0f, 2.0f), max(0, 3), 4.0f, level(0), int2(5, 6)))";
- case ValidTextureOverload::kSampleCompareLevelDepthCubeF32:
- return R"(Texture.sample_compare(Sampler, float3(1.0f, 2.0f, 3.0f), 4.0f, level(0)))";
- case ValidTextureOverload::kSampleCompareLevelDepthCubeArrayF32:
- return R"(Texture.sample_compare(Sampler, float3(1.0f, 2.0f, 3.0f), max(0, 4), 5.0f, level(0)))";
- case ValidTextureOverload::kLoad1dLevelF32:
- return R"(Texture.read(uint(1u), 0))";
- case ValidTextureOverload::kLoad1dLevelU32:
- return R"(Texture.read(uint(1), 0))";
- case ValidTextureOverload::kLoad1dLevelI32:
- return R"(Texture.read(uint(1), 0))";
- case ValidTextureOverload::kLoad2dLevelF32:
- return R"(Texture.read(uint2(uint2(1u, 2u)), 3u))";
- case ValidTextureOverload::kLoad2dLevelU32:
- return R"(Texture.read(uint2(int2(1, 2)), 3))";
- case ValidTextureOverload::kLoad2dArrayLevelF32:
- return R"(Texture.read(uint2(int2(1, 2)), 3, 4))";
- case ValidTextureOverload::kLoad2dArrayLevelU32:
- return R"(Texture.read(uint2(int2(1, 2)), 3, 4))";
- case ValidTextureOverload::kLoad2dArrayLevelI32:
- return R"(Texture.read(uint2(uint2(1u, 2u)), 3u, 4u))";
- case ValidTextureOverload::kLoad3dLevelF32:
- return R"(Texture.read(uint3(int3(1, 2, 3)), 4))";
- case ValidTextureOverload::kLoad3dLevelU32:
- return R"(Texture.read(uint3(int3(1, 2, 3)), 4))";
- case ValidTextureOverload::kLoad3dLevelI32:
- return R"(Texture.read(uint3(uint3(1u, 2u, 3u)), 4u))";
- case ValidTextureOverload::kLoadMultisampled2dF32:
- case ValidTextureOverload::kLoadMultisampled2dU32:
- return R"(Texture.read(uint2(int2(1, 2)), 3))";
- case ValidTextureOverload::kLoad2dLevelI32:
- case ValidTextureOverload::kLoadMultisampled2dI32:
- return R"(Texture.read(uint2(uint2(1u, 2u)), 3u))";
- case ValidTextureOverload::kLoadDepth2dLevelF32:
- return R"(Texture.read(uint2(int2(1, 2)), 3))";
- case ValidTextureOverload::kLoadDepth2dArrayLevelF32:
- return R"(Texture.read(uint2(uint2(1u, 2u)), 3u, 4u))";
- case ValidTextureOverload::kLoadDepthMultisampled2dF32:
- return R"(Texture.read(uint2(uint2(1u, 2u)), 3u))";
- case ValidTextureOverload::kStoreWO1dRgba32float:
- return R"(Texture.write(float4(2.0f, 3.0f, 4.0f, 5.0f), uint(1)))";
- case ValidTextureOverload::kStoreWO2dRgba32float:
- return R"(Texture.write(float4(3.0f, 4.0f, 5.0f, 6.0f), uint2(int2(1, 2))))";
- case ValidTextureOverload::kStoreWO2dArrayRgba32float:
- return R"(Texture.write(float4(4.0f, 5.0f, 6.0f, 7.0f), uint2(uint2(1u, 2u)), 3u))";
- case ValidTextureOverload::kStoreWO3dRgba32float:
- return R"(Texture.write(float4(4.0f, 5.0f, 6.0f, 7.0f), uint3(uint3(1u, 2u, 3u))))";
- }
- return "<unmatched texture overload>";
-} // NOLINT - Ignore the length of this function
-
-class MslGeneratorBuiltinTextureTest : public TestParamHelper<ast::test::TextureOverloadCase> {};
-
-TEST_P(MslGeneratorBuiltinTextureTest, Call) {
- auto param = GetParam();
-
- param.BuildTextureVariable(this);
- param.BuildSamplerVariable(this);
-
- auto* call = Call(param.function, param.args(this));
- auto* stmt = param.returns_value ? static_cast<const ast::Statement*>(Assign(Phony(), call))
- : static_cast<const ast::Statement*>(CallStmt(call));
-
- Func("main", tint::Empty, ty.void_(), Vector{stmt},
- Vector{Stage(ast::PipelineStage::kFragment)});
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.Diagnostics();
-
- auto expected = expected_texture_overload(param.overload);
- EXPECT_EQ(expected, out.str());
-}
-
-INSTANTIATE_TEST_SUITE_P(MslGeneratorBuiltinTextureTest,
- MslGeneratorBuiltinTextureTest,
- testing::ValuesIn(ast::test::TextureOverloadCase::ValidCases()));
-
-} // namespace
-} // namespace tint::msl::writer
diff --git a/src/tint/lang/msl/writer/ast_printer/call_test.cc b/src/tint/lang/msl/writer/ast_printer/call_test.cc
deleted file mode 100644
index 9865f9f..0000000
--- a/src/tint/lang/msl/writer/ast_printer/call_test.cc
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright 2020 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/tint/lang/msl/writer/ast_printer/helper_test.h"
-#include "src/tint/lang/wgsl/ast/call_statement.h"
-#include "src/tint/utils/text/string_stream.h"
-
-using namespace tint::core::number_suffixes; // NOLINT
-
-namespace tint::msl::writer {
-namespace {
-
-using MslASTPrinterTest = TestHelper;
-
-TEST_F(MslASTPrinterTest, EmitExpression_Call_WithoutParams) {
- Func("my_func", tint::Empty, ty.f32(), Vector{Return(1.23_f)});
-
- auto* call = Call("my_func");
- WrapInFunction(call);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "my_func()");
-}
-
-TEST_F(MslASTPrinterTest, EmitExpression_Call_WithParams) {
- Func("my_func",
- Vector{
- Param(Sym(), ty.f32()),
- Param(Sym(), ty.f32()),
- },
- ty.f32(),
- Vector{
- Return(1.23_f),
- });
- GlobalVar("param1", ty.f32(), core::AddressSpace::kPrivate);
- GlobalVar("param2", ty.f32(), core::AddressSpace::kPrivate);
-
- auto* call = Call("my_func", "param1", "param2");
- WrapInFunction(call);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitExpression(out, call)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "my_func(param1, param2)");
-}
-
-TEST_F(MslASTPrinterTest, EmitStatement_Call) {
- Func("my_func",
- Vector{
- Param(Sym(), ty.f32()),
- Param(Sym(), ty.f32()),
- },
- ty.void_(), tint::Empty, tint::Empty);
- GlobalVar("param1", ty.f32(), core::AddressSpace::kPrivate);
- GlobalVar("param2", ty.f32(), core::AddressSpace::kPrivate);
-
- auto* call = Call("my_func", "param1", "param2");
- auto* stmt = CallStmt(call);
- WrapInFunction(stmt);
-
- ASTPrinter& gen = Build();
-
- gen.IncrementIndent();
- ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), " my_func(param1, param2);\n");
-}
-
-} // namespace
-} // namespace tint::msl::writer
diff --git a/src/tint/lang/msl/writer/ast_printer/case_test.cc b/src/tint/lang/msl/writer/ast_printer/case_test.cc
deleted file mode 100644
index fa3d56b..0000000
--- a/src/tint/lang/msl/writer/ast_printer/case_test.cc
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright 2020 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/tint/lang/msl/writer/ast_printer/helper_test.h"
-
-using namespace tint::core::number_suffixes; // NOLINT
-
-namespace tint::msl::writer {
-namespace {
-
-using MslASTPrinterTest = TestHelper;
-
-TEST_F(MslASTPrinterTest, Emit_Case) {
- auto* s =
- Switch(1_i, Case(CaseSelector(5_i), Block(create<ast::BreakStatement>())), DefaultCase());
- WrapInFunction(s);
-
- ASTPrinter& gen = Build();
-
- gen.IncrementIndent();
-
- ASSERT_TRUE(gen.EmitCase(s->body[0])) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"( case 5: {
- break;
- }
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_Case_BreaksByDefault) {
- auto* s = Switch(1_i, Case(CaseSelector(5_i), Block()), DefaultCase());
- WrapInFunction(s);
-
- ASTPrinter& gen = Build();
-
- gen.IncrementIndent();
-
- ASSERT_TRUE(gen.EmitCase(s->body[0])) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"( case 5: {
- break;
- }
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_Case_MultipleSelectors) {
- auto* s = Switch(1_i,
- Case(
- Vector{
- CaseSelector(5_i),
- CaseSelector(6_i),
- },
- Block(create<ast::BreakStatement>())),
- DefaultCase());
- WrapInFunction(s);
-
- ASTPrinter& gen = Build();
-
- gen.IncrementIndent();
-
- ASSERT_TRUE(gen.EmitCase(s->body[0])) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"( case 5:
- case 6: {
- break;
- }
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_Case_Default) {
- auto* s = Switch(1_i, DefaultCase(Block(create<ast::BreakStatement>())));
- WrapInFunction(s);
-
- ASTPrinter& gen = Build();
-
- gen.IncrementIndent();
-
- ASSERT_TRUE(gen.EmitCase(s->body[0])) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"( default: {
- break;
- }
-)");
-}
-
-} // namespace
-} // namespace tint::msl::writer
diff --git a/src/tint/lang/msl/writer/ast_printer/cast_test.cc b/src/tint/lang/msl/writer/ast_printer/cast_test.cc
deleted file mode 100644
index 14cf4ea..0000000
--- a/src/tint/lang/msl/writer/ast_printer/cast_test.cc
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2020 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/tint/lang/msl/writer/ast_printer/helper_test.h"
-#include "src/tint/utils/text/string_stream.h"
-
-namespace tint::msl::writer {
-namespace {
-
-using namespace tint::core::fluent_types; // NOLINT
-using namespace tint::core::number_suffixes; // NOLINT
-
-using MslASTPrinterTest = TestHelper;
-
-TEST_F(MslASTPrinterTest, EmitExpression_Cast_Scalar) {
- auto* cast = Call<f32>(1_i);
- WrapInFunction(cast);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitExpression(out, cast)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "1.0f");
-}
-
-TEST_F(MslASTPrinterTest, EmitExpression_Cast_Vector) {
- auto* cast = Call<vec3<f32>>(Call<vec3<i32>>(1_i, 2_i, 3_i));
- WrapInFunction(cast);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitExpression(out, cast)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "float3(1.0f, 2.0f, 3.0f)");
-}
-
-TEST_F(MslASTPrinterTest, EmitExpression_Cast_IntMin) {
- auto* cast = Call<u32>(i32(std::numeric_limits<int32_t>::min()));
- WrapInFunction(cast);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitExpression(out, cast)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "2147483648u");
-}
-
-} // namespace
-} // namespace tint::msl::writer
diff --git a/src/tint/lang/msl/writer/ast_printer/const_assert_test.cc b/src/tint/lang/msl/writer/ast_printer/const_assert_test.cc
deleted file mode 100644
index 12c14d7..0000000
--- a/src/tint/lang/msl/writer/ast_printer/const_assert_test.cc
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2022 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/tint/lang/msl/writer/ast_printer/helper_test.h"
-
-using namespace tint::core::number_suffixes; // NOLINT
-
-namespace tint::msl::writer {
-namespace {
-
-using MslASTPrinterTest = TestHelper;
-
-TEST_F(MslASTPrinterTest, Emit_GlobalConstAssert) {
- GlobalConstAssert(true);
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- // const asserts are not emitted
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_FunctionConstAssert) {
- Func("f", tint::Empty, ty.void_(), Vector{ConstAssert(true)});
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- // const asserts are not emitted
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-void f() {
-}
-
-)");
-}
-
-} // namespace
-} // namespace tint::msl::writer
diff --git a/src/tint/lang/msl/writer/ast_printer/constructor_test.cc b/src/tint/lang/msl/writer/ast_printer/constructor_test.cc
deleted file mode 100644
index 682666d..0000000
--- a/src/tint/lang/msl/writer/ast_printer/constructor_test.cc
+++ /dev/null
@@ -1,435 +0,0 @@
-// Copyright 2020 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "gmock/gmock.h"
-#include "src/tint/lang/msl/writer/ast_printer/helper_test.h"
-
-namespace tint::msl::writer {
-namespace {
-
-using ::testing::HasSubstr;
-using namespace tint::core::fluent_types; // NOLINT
-using namespace tint::core::number_suffixes; // NOLINT
-
-using MslASTPrinterTest_Constructor = TestHelper;
-
-TEST_F(MslASTPrinterTest_Constructor, Bool) {
- WrapInFunction(Expr(false));
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_THAT(gen.Result(), HasSubstr("false"));
-}
-
-TEST_F(MslASTPrinterTest_Constructor, Int) {
- WrapInFunction(Expr(-12345_i));
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_THAT(gen.Result(), HasSubstr("-12345"));
-}
-
-TEST_F(MslASTPrinterTest_Constructor, UInt) {
- WrapInFunction(Expr(56779_u));
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_THAT(gen.Result(), HasSubstr("56779u"));
-}
-
-TEST_F(MslASTPrinterTest_Constructor, Float) {
- // Use a number close to 1<<30 but whose decimal representation ends in 0.
- WrapInFunction(Expr(f32((1 << 30) - 4)));
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_THAT(gen.Result(), HasSubstr("1073741824.0f"));
-}
-
-TEST_F(MslASTPrinterTest_Constructor, F16) {
- Enable(wgsl::Extension::kF16);
-
- // Use a number close to 1<<16 but whose decimal representation ends in 0.
- WrapInFunction(Expr(f16((1 << 15) - 8)));
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_THAT(gen.Result(), HasSubstr("32752.0h"));
-}
-
-TEST_F(MslASTPrinterTest_Constructor, Type_Float) {
- WrapInFunction(Call<f32>(-1.2e-5_f));
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_THAT(gen.Result(), HasSubstr("-0.00001200000042445026f"));
-}
-
-TEST_F(MslASTPrinterTest_Constructor, Type_F16) {
- Enable(wgsl::Extension::kF16);
-
- WrapInFunction(Call<f16>(-1.2e-3_h));
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_THAT(gen.Result(), HasSubstr("-0.0011997222900390625h"));
-}
-
-TEST_F(MslASTPrinterTest_Constructor, Type_Bool) {
- WrapInFunction(Call<bool>(true));
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_THAT(gen.Result(), HasSubstr("true"));
-}
-
-TEST_F(MslASTPrinterTest_Constructor, Type_Int) {
- WrapInFunction(Call<i32>(-12345_i));
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_THAT(gen.Result(), HasSubstr("-12345"));
-}
-
-TEST_F(MslASTPrinterTest_Constructor, Type_Uint) {
- WrapInFunction(Call<u32>(12345_u));
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_THAT(gen.Result(), HasSubstr("12345u"));
-}
-
-TEST_F(MslASTPrinterTest_Constructor, Type_Vec_F32) {
- WrapInFunction(Call<vec3<f32>>(1_f, 2_f, 3_f));
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_THAT(gen.Result(), HasSubstr("float3(1.0f, 2.0f, 3.0f)"));
-}
-
-TEST_F(MslASTPrinterTest_Constructor, Type_Vec_F16) {
- Enable(wgsl::Extension::kF16);
-
- WrapInFunction(Call<vec3<f16>>(1_h, 2_h, 3_h));
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_THAT(gen.Result(), HasSubstr("half3(1.0h, 2.0h, 3.0h)"));
-}
-
-TEST_F(MslASTPrinterTest_Constructor, Type_Vec_Empty_F32) {
- WrapInFunction(Call<vec3<f32>>());
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_THAT(gen.Result(), HasSubstr("float3(0.0f)"));
-}
-
-TEST_F(MslASTPrinterTest_Constructor, Type_Vec_Empty_F16) {
- Enable(wgsl::Extension::kF16);
-
- WrapInFunction(Call<vec3<f16>>());
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_THAT(gen.Result(), HasSubstr("half3(0.0h)"));
-}
-
-TEST_F(MslASTPrinterTest_Constructor, Type_Vec_SingleScalar_F32_Literal) {
- WrapInFunction(Call<vec3<f32>>(2_f));
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_THAT(gen.Result(), HasSubstr("float3(2.0f)"));
-}
-
-TEST_F(MslASTPrinterTest_Constructor, Type_Vec_SingleScalar_F16_Literal) {
- Enable(wgsl::Extension::kF16);
-
- WrapInFunction(Call<vec3<f16>>(2_h));
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_THAT(gen.Result(), HasSubstr("half3(2.0h)"));
-}
-
-TEST_F(MslASTPrinterTest_Constructor, Type_Vec_SingleScalar_F32_Var) {
- auto* var = Var("v", Expr(2_f));
- auto* cast = Call<vec3<f32>>(var);
- WrapInFunction(var, cast);
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_THAT(gen.Result(), HasSubstr(R"(float v = 2.0f;
- float3 const tint_symbol = float3(v);)"));
-}
-
-TEST_F(MslASTPrinterTest_Constructor, Type_Vec_SingleScalar_F16_Var) {
- Enable(wgsl::Extension::kF16);
-
- auto* var = Var("v", Expr(2_h));
- auto* cast = Call<vec3<f16>>(var);
- WrapInFunction(var, cast);
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_THAT(gen.Result(), HasSubstr(R"(half v = 2.0h;
- half3 const tint_symbol = half3(v);)"));
-}
-
-TEST_F(MslASTPrinterTest_Constructor, Type_Vec_SingleScalar_Bool) {
- WrapInFunction(Call<vec3<bool>>(true));
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_THAT(gen.Result(), HasSubstr("bool3(true)"));
-}
-
-TEST_F(MslASTPrinterTest_Constructor, Type_Vec_SingleScalar_Int) {
- WrapInFunction(Call<vec3<i32>>(2_i));
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_THAT(gen.Result(), HasSubstr("int3(2)"));
-}
-
-TEST_F(MslASTPrinterTest_Constructor, Type_Vec_SingleScalar_UInt) {
- WrapInFunction(Call<vec3<u32>>(2_u));
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_THAT(gen.Result(), HasSubstr("uint3(2u)"));
-}
-
-TEST_F(MslASTPrinterTest_Constructor, Type_Mat_F32) {
- WrapInFunction(
- Call<mat2x3<f32>>(Call<vec3<f32>>(1_f, 2_f, 3_f), Call<vec3<f32>>(3_f, 4_f, 5_f)));
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-
- EXPECT_THAT(gen.Result(),
- HasSubstr("float2x3(float3(1.0f, 2.0f, 3.0f), float3(3.0f, 4.0f, 5.0f))"));
-}
-
-TEST_F(MslASTPrinterTest_Constructor, Type_Mat_F16) {
- Enable(wgsl::Extension::kF16);
-
- WrapInFunction(
- Call<mat2x3<f16>>(Call<vec3<f16>>(1_h, 2_h, 3_h), Call<vec3<f16>>(3_h, 4_h, 5_h)));
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-
- EXPECT_THAT(gen.Result(),
- HasSubstr("half2x3(half3(1.0h, 2.0h, 3.0h), half3(3.0h, 4.0h, 5.0h))"));
-}
-
-TEST_F(MslASTPrinterTest_Constructor, Type_Mat_Complex_F32) {
- // mat4x4<f32>(
- // vec4<f32>(2.0f, 3.0f, 4.0f, 8.0f),
- // vec4<f32>(),
- // vec4<f32>(7.0f),
- // vec4<f32>(vec4<f32>(42.0f, 21.0f, 6.0f, -5.0f)),
- // );
- auto* vector_literal = Call<vec4<f32>>(f32(2.0), f32(3.0), f32(4.0), f32(8.0));
- auto* vector_zero_init = Call<vec4<f32>>();
- auto* vector_single_scalar_init = Call<vec4<f32>>(f32(7.0));
- auto* vector_identical_init =
- Call<vec4<f32>>(Call<vec4<f32>>(f32(42.0), f32(21.0), f32(6.0), f32(-5.0)));
-
- auto* constructor = Call<mat4x4<f32>>(vector_literal, vector_zero_init,
- vector_single_scalar_init, vector_identical_init);
-
- WrapInFunction(constructor);
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-
- EXPECT_THAT(gen.Result(), HasSubstr("float4x4(float4(2.0f, 3.0f, 4.0f, 8.0f), float4(0.0f), "
- "float4(7.0f), float4(42.0f, 21.0f, 6.0f, -5.0f))"));
-}
-
-TEST_F(MslASTPrinterTest_Constructor, Type_Mat_Complex_F16) {
- // mat4x4<f16>(
- // vec4<f16>(2.0h, 3.0h, 4.0h, 8.0h),
- // vec4<f16>(),
- // vec4<f16>(7.0h),
- // vec4<f16>(vec4<f16>(42.0h, 21.0h, 6.0h, -5.0h)),
- // );
- Enable(wgsl::Extension::kF16);
-
- auto* vector_literal = Call<vec4<f16>>(f16(2.0), f16(3.0), f16(4.0), f16(8.0));
- auto* vector_zero_init = Call<vec4<f16>>();
- auto* vector_single_scalar_init = Call<vec4<f16>>(f16(7.0));
- auto* vector_identical_init =
- Call<vec4<f16>>(Call<vec4<f16>>(f16(42.0), f16(21.0), f16(6.0), f16(-5.0)));
-
- auto* constructor = Call<mat4x4<f16>>(vector_literal, vector_zero_init,
- vector_single_scalar_init, vector_identical_init);
-
- WrapInFunction(constructor);
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-
- EXPECT_THAT(gen.Result(), HasSubstr("half4x4(half4(2.0h, 3.0h, 4.0h, 8.0h), half4(0.0h), "
- "half4(7.0h), half4(42.0h, 21.0h, 6.0h, -5.0h))"));
-}
-
-TEST_F(MslASTPrinterTest_Constructor, Type_Mat_Empty_F32) {
- WrapInFunction(Call<mat2x3<f32>>());
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-
- EXPECT_THAT(gen.Result(),
- HasSubstr("float2x3 const tint_symbol = float2x3(float3(0.0f), float3(0.0f))"));
-}
-
-TEST_F(MslASTPrinterTest_Constructor, Type_Mat_Empty_F16) {
- Enable(wgsl::Extension::kF16);
-
- WrapInFunction(Call<mat2x3<f16>>());
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-
- EXPECT_THAT(gen.Result(),
- HasSubstr("half2x3 const tint_symbol = half2x3(half3(0.0h), half3(0.0h))"));
-}
-
-TEST_F(MslASTPrinterTest_Constructor, Type_Mat_Identity_F32) {
- // fn f() {
- // var m_1: mat4x4<f32> = mat4x4<f32>();
- // var m_2: mat4x4<f32> = mat4x4<f32>(m_1);
- // }
-
- auto* m_1 = Var("m_1", ty.mat4x4(ty.f32()), Call<mat4x4<f32>>());
- auto* m_2 = Var("m_2", ty.mat4x4(ty.f32()), Call<mat4x4<f32>>(m_1));
-
- WrapInFunction(m_1, m_2);
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-
- EXPECT_THAT(gen.Result(), HasSubstr("float4x4 m_2 = float4x4(m_1);"));
-}
-
-TEST_F(MslASTPrinterTest_Constructor, Type_Mat_Identity_F16) {
- // fn f() {
- // var m_1: mat4x4<f16> = mat4x4<f16>();
- // var m_2: mat4x4<f16> = mat4x4<f16>(m_1);
- // }
-
- Enable(wgsl::Extension::kF16);
-
- auto* m_1 = Var("m_1", ty.mat4x4(ty.f16()), Call<mat4x4<f16>>());
- auto* m_2 = Var("m_2", ty.mat4x4(ty.f16()), Call<mat4x4<f16>>(m_1));
-
- WrapInFunction(m_1, m_2);
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-
- EXPECT_THAT(gen.Result(), HasSubstr("half4x4 m_2 = half4x4(m_1);"));
-}
-
-TEST_F(MslASTPrinterTest_Constructor, Type_Array) {
- WrapInFunction(Call<array<vec3<f32>, 3>>(Call<vec3<f32>>(1_f, 2_f, 3_f),
- Call<vec3<f32>>(4_f, 5_f, 6_f),
- Call<vec3<f32>>(7_f, 8_f, 9_f)));
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_THAT(gen.Result(), HasSubstr("{float3(1.0f, 2.0f, 3.0f), float3(4.0f, 5.0f, 6.0f), "
- "float3(7.0f, 8.0f, 9.0f)}"));
-}
-
-TEST_F(MslASTPrinterTest_Constructor, Type_Struct) {
- auto* str = Structure("S", Vector{
- Member("a", ty.i32()),
- Member("b", ty.f32()),
- Member("c", ty.vec3<i32>()),
- });
-
- WrapInFunction(Call(ty.Of(str), 1_i, 2_f, Call<vec3<i32>>(3_i, 4_i, 5_i)));
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_THAT(gen.Result(), HasSubstr("{.a=1, .b=2.0f, .c=int3(3, 4, 5)}"));
-}
-
-TEST_F(MslASTPrinterTest_Constructor, Type_Struct_Empty) {
- auto* str = Structure("S", Vector{
- Member("a", ty.i32()),
- Member("b", ty.f32()),
- Member("c", ty.vec3<i32>()),
- });
-
- WrapInFunction(Call(ty.Of(str)));
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_THAT(gen.Result(), HasSubstr("{}"));
- EXPECT_THAT(gen.Result(), testing::Not(HasSubstr("{{}}")));
-}
-
-} // namespace
-} // namespace tint::msl::writer
diff --git a/src/tint/lang/msl/writer/ast_printer/continue_test.cc b/src/tint/lang/msl/writer/ast_printer/continue_test.cc
deleted file mode 100644
index 266daaf..0000000
--- a/src/tint/lang/msl/writer/ast_printer/continue_test.cc
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright 2020 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/tint/lang/msl/writer/ast_printer/helper_test.h"
-
-namespace tint::msl::writer {
-namespace {
-
-using MslASTPrinterTest = TestHelper;
-
-TEST_F(MslASTPrinterTest, Emit_Continue) {
- auto* loop = Loop(Block(If(false, Block(Break())), //
- Continue()));
- WrapInFunction(loop);
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-
-#define TINT_ISOLATE_UB(VOLATILE_NAME) \
- {volatile bool VOLATILE_NAME = false; if (VOLATILE_NAME) break;}
-
-kernel void test_function() {
- while(true) {
- TINT_ISOLATE_UB(tint_volatile_false);
- if (false) {
- break;
- }
- continue;
- }
- return;
-}
-
-)");
-}
-
-} // namespace
-} // namespace tint::msl::writer
diff --git a/src/tint/lang/msl/writer/ast_printer/discard_test.cc b/src/tint/lang/msl/writer/ast_printer/discard_test.cc
deleted file mode 100644
index d1fdd53..0000000
--- a/src/tint/lang/msl/writer/ast_printer/discard_test.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2020 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/tint/lang/msl/writer/ast_printer/helper_test.h"
-
-namespace tint::msl::writer {
-namespace {
-
-using MslASTPrinterTest = TestHelper;
-
-// MslPrinterTest.Discard
-TEST_F(MslASTPrinterTest, Emit_Discard) {
- auto* stmt = Discard();
-
- Func("F", tint::Empty, ty.void_(), Vector{stmt}, Vector{Stage(ast::PipelineStage::kFragment)});
-
- ASTPrinter& gen = Build();
-
- gen.IncrementIndent();
-
- ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), " discard_fragment();\n");
-}
-
-} // namespace
-} // namespace tint::msl::writer
diff --git a/src/tint/lang/msl/writer/ast_printer/helper_test.h b/src/tint/lang/msl/writer/ast_printer/helper_test.h
deleted file mode 100644
index cdadbfb..0000000
--- a/src/tint/lang/msl/writer/ast_printer/helper_test.h
+++ /dev/null
@@ -1,120 +0,0 @@
-// Copyright 2020 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef SRC_TINT_LANG_MSL_WRITER_AST_PRINTER_HELPER_TEST_H_
-#define SRC_TINT_LANG_MSL_WRITER_AST_PRINTER_HELPER_TEST_H_
-
-#include <memory>
-#include <string>
-#include <utility>
-
-#include "gtest/gtest.h"
-#include "src/tint/lang/msl/writer/ast_printer/ast_printer.h"
-#include "src/tint/lang/wgsl/program/program_builder.h"
-#include "src/tint/lang/wgsl/resolver/resolve.h"
-
-namespace tint::msl::writer {
-
-/// Helper class for testing
-template <typename BASE>
-class TestHelperBase : public BASE, public ProgramBuilder {
- public:
- TestHelperBase() = default;
- ~TestHelperBase() override = default;
-
- /// @returns the default generator options for SanitizeAndBuild(), if no explicit options are
- /// provided.
- static Options DefaultOptions() {
- Options opts;
- opts.disable_robustness = true;
- return opts;
- }
-
- /// Builds and returns a ASTPrinter from the program.
- /// @note The generator is only built once. Multiple calls to Build() will
- /// return the same ASTPrinter without rebuilding.
- /// @return the built generator
- ASTPrinter& Build(const Options& options = {}) {
- if (gen_) {
- return *gen_;
- }
- if (!IsValid()) {
- ADD_FAILURE() << "ProgramBuilder is not valid: " << Diagnostics();
- }
- program = std::make_unique<Program>(resolver::Resolve(*this));
- if (!program->IsValid()) {
- ADD_FAILURE() << program->Diagnostics();
- }
- gen_ = std::make_unique<ASTPrinter>(*program, options);
- return *gen_;
- }
-
- /// Builds the program, runs the program through the transform::Msl sanitizer
- /// and returns a ASTPrinter from the sanitized program.
- /// @param options The MSL generator options.
- /// @note The generator is only built once. Multiple calls to Build() will
- /// return the same ASTPrinter without rebuilding.
- /// @return the built generator
- ASTPrinter& SanitizeAndBuild(const Options& options = DefaultOptions()) {
- if (gen_) {
- return *gen_;
- }
- if (!IsValid()) {
- ADD_FAILURE() << "ProgramBuilder is not valid: " << Diagnostics();
- }
- program = std::make_unique<Program>(resolver::Resolve(*this));
- if (!program->IsValid()) {
- ADD_FAILURE() << program->Diagnostics();
- }
-
- auto result = Sanitize(*program, options);
- if (!result.program.IsValid()) {
- ADD_FAILURE() << result.program.Diagnostics();
- }
- *program = std::move(result.program);
- gen_ = std::make_unique<ASTPrinter>(*program, options);
- return *gen_;
- }
-
- /// The program built with a call to Build()
- std::unique_ptr<Program> program;
-
- private:
- std::unique_ptr<ASTPrinter> gen_;
- std::unique_ptr<ASTPrinter> gen_with_options_;
-};
-
-/// Test helper
-using TestHelper = TestHelperBase<testing::Test>;
-
-/// Param test helper
-template <typename T>
-using TestParamHelper = TestHelperBase<testing::TestWithParam<T>>;
-
-} // namespace tint::msl::writer
-
-#endif // SRC_TINT_LANG_MSL_WRITER_AST_PRINTER_HELPER_TEST_H_
diff --git a/src/tint/lang/msl/writer/ast_printer/identifier_test.cc b/src/tint/lang/msl/writer/ast_printer/identifier_test.cc
deleted file mode 100644
index 57c0561..0000000
--- a/src/tint/lang/msl/writer/ast_printer/identifier_test.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2020 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/tint/lang/msl/writer/ast_printer/helper_test.h"
-#include "src/tint/utils/text/string_stream.h"
-
-namespace tint::msl::writer {
-namespace {
-
-using MslASTPrinterTest = TestHelper;
-
-TEST_F(MslASTPrinterTest, EmitIdentifierExpression) {
- auto* foo = Var("foo", ty.i32());
-
- auto* i = Expr("foo");
- WrapInFunction(foo, i);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitExpression(out, i)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "foo");
-}
-
-} // namespace
-} // namespace tint::msl::writer
diff --git a/src/tint/lang/msl/writer/ast_printer/if_test.cc b/src/tint/lang/msl/writer/ast_printer/if_test.cc
deleted file mode 100644
index 1f4a8f0..0000000
--- a/src/tint/lang/msl/writer/ast_printer/if_test.cc
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright 2020 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/tint/lang/msl/writer/ast_printer/helper_test.h"
-
-namespace tint::msl::writer {
-namespace {
-
-using MslASTPrinterTest = TestHelper;
-
-// MSLPrinterTest.If
-TEST_F(MslASTPrinterTest, Emit_If) {
- auto* cond = Var("cond", ty.bool_());
- auto* i = If(cond, Block(Return()));
- WrapInFunction(cond, i);
-
- ASTPrinter& gen = Build();
-
- gen.IncrementIndent();
-
- ASSERT_TRUE(gen.EmitStatement(i)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"( if (cond) {
- return;
- }
-)");
-}
-
-// MSLPrinterTest.IfWithElseIf
-TEST_F(MslASTPrinterTest, Emit_IfWithElseIf) {
- auto* cond = Var("cond", ty.bool_());
- auto* else_cond = Var("else_cond", ty.bool_());
- auto* i = If(cond, Block(Return()), Else(If(else_cond, Block(Return()))));
- WrapInFunction(cond, else_cond, i);
-
- ASTPrinter& gen = Build();
-
- gen.IncrementIndent();
-
- ASSERT_TRUE(gen.EmitStatement(i)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"( if (cond) {
- return;
- } else {
- if (else_cond) {
- return;
- }
- }
-)");
-}
-
-// MSLPrinterTest.IfWithElse
-TEST_F(MslASTPrinterTest, Emit_IfWithElse) {
- auto* cond = Var("cond", ty.bool_());
- auto* i = If(cond, Block(Return()), Else(Block(Return())));
- WrapInFunction(cond, i);
-
- ASTPrinter& gen = Build();
-
- gen.IncrementIndent();
-
- ASSERT_TRUE(gen.EmitStatement(i)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"( if (cond) {
- return;
- } else {
- return;
- }
-)");
-}
-
-// TODO(dj2): Port to MSLPrinterTest
-TEST_F(MslASTPrinterTest, Emit_IfWithMultiple) {
- auto* cond = Var("cond", ty.bool_());
- auto* else_cond = Var("else_cond", ty.bool_());
- auto* i =
- If(cond, Block(Return()), Else(If(else_cond, Block(Return()), Else(Block(Return())))));
- WrapInFunction(cond, else_cond, i);
-
- ASTPrinter& gen = Build();
-
- gen.IncrementIndent();
-
- ASSERT_TRUE(gen.EmitStatement(i)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"( if (cond) {
- return;
- } else {
- if (else_cond) {
- return;
- } else {
- return;
- }
- }
-)");
-}
-
-} // namespace
-} // namespace tint::msl::writer
diff --git a/src/tint/lang/msl/writer/ast_printer/import_test.cc b/src/tint/lang/msl/writer/ast_printer/import_test.cc
deleted file mode 100644
index 4ada591..0000000
--- a/src/tint/lang/msl/writer/ast_printer/import_test.cc
+++ /dev/null
@@ -1,292 +0,0 @@
-// Copyright 2020 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/tint/lang/msl/writer/ast_printer/helper_test.h"
-#include "src/tint/lang/wgsl/sem/call.h"
-#include "src/tint/utils/text/string_stream.h"
-
-namespace tint::msl::writer {
-namespace {
-
-using namespace tint::core::fluent_types; // NOLINT
-using namespace tint::core::number_suffixes; // NOLINT
-
-using MslASTPrinterTest = TestHelper;
-
-struct MslImportData {
- const char* name;
- const char* msl_name;
-};
-inline std::ostream& operator<<(std::ostream& out, MslImportData data) {
- out << data.name;
- return out;
-}
-using MslImportData_SingleParamTest = TestParamHelper<MslImportData>;
-TEST_P(MslImportData_SingleParamTest, FloatScalar) {
- auto param = GetParam();
- auto* call = Call(param.name, 1_f);
-
- // The resolver will set the builtin data for the ident
- WrapInFunction(call);
-
- ASTPrinter& gen = Build();
-
- auto* sem = program->Sem().Get<sem::Call>(call);
- ASSERT_NE(sem, nullptr);
- auto* target = sem->Target();
- ASSERT_NE(target, nullptr);
- auto* builtin = target->As<sem::BuiltinFn>();
- ASSERT_NE(builtin, nullptr);
-
- ASSERT_EQ(gen.generate_builtin_name(builtin), param.msl_name);
-}
-INSTANTIATE_TEST_SUITE_P(MslASTPrinterTest,
- MslImportData_SingleParamTest,
- testing::Values(MslImportData{"abs", "fabs"},
- MslImportData{"acos", "acos"},
- MslImportData{"asin", "asin"},
- MslImportData{"atan", "atan"},
- MslImportData{"ceil", "ceil"},
- MslImportData{"cos", "cos"},
- MslImportData{"cosh", "cosh"},
- MslImportData{"exp", "exp"},
- MslImportData{"exp2", "exp2"},
- MslImportData{"floor", "floor"},
- MslImportData{"fract", "fract"},
- MslImportData{"inverseSqrt", "rsqrt"},
- MslImportData{"length", "length"},
- MslImportData{"log", "log"},
- MslImportData{"log2", "log2"},
- MslImportData{"round", "rint"},
- MslImportData{"sign", "sign"},
- MslImportData{"sin", "sin"},
- MslImportData{"sinh", "sinh"},
- MslImportData{"sqrt", "sqrt"},
- MslImportData{"tan", "tan"},
- MslImportData{"tanh", "tanh"},
- MslImportData{"trunc", "trunc"}));
-
-TEST_F(MslASTPrinterTest, MslImportData_SingleParamTest_IntScalar) {
- auto* expr = Call("abs", 1_i);
- WrapInFunction(expr);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), R"(abs(1))");
-}
-
-TEST_F(MslASTPrinterTest, MslImportData_SingleParamTest_ScalarLength) {
- auto* expr = Call("length", 2_f);
- WrapInFunction(expr);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), R"(fabs(2.0f))");
-}
-
-using MslImportData_DualParam_ScalarTest = TestParamHelper<MslImportData>;
-TEST_P(MslImportData_DualParam_ScalarTest, Float) {
- auto param = GetParam();
- auto* expr = Call(param.name, 1_f, 2_f);
-
- WrapInFunction(expr);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), std::string(param.msl_name) + "(1.0f, 2.0f)");
-}
-INSTANTIATE_TEST_SUITE_P(MslASTPrinterTest,
- MslImportData_DualParam_ScalarTest,
- testing::Values(MslImportData{"atan2", "atan2"},
- MslImportData{"max", "fmax"},
- MslImportData{"min", "fmin"},
- MslImportData{"pow", "powr"},
- MslImportData{"step", "step"}));
-
-TEST_F(MslASTPrinterTest, MslImportData_DualParam_ScalarDistance) {
- auto* expr = Call("distance", 2_f, 3_f);
- WrapInFunction(expr);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), R"(fabs(2.0f - 3.0f))");
-}
-
-using MslImportData_DualParam_VectorTest = TestParamHelper<MslImportData>;
-TEST_P(MslImportData_DualParam_VectorTest, Float) {
- auto param = GetParam();
-
- auto* expr = Call(param.name, Call<vec3<f32>>(1_f, 2_f, 3_f), Call<vec3<f32>>(4_f, 5_f, 6_f));
- WrapInFunction(expr);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), std::string(param.msl_name) +
- R"((float3(1.0f, 2.0f, 3.0f), float3(4.0f, 5.0f, 6.0f)))");
-}
-INSTANTIATE_TEST_SUITE_P(MslASTPrinterTest,
- MslImportData_DualParam_VectorTest,
- testing::Values(MslImportData{"atan2", "atan2"},
- MslImportData{"cross", "cross"},
- MslImportData{"distance", "distance"},
- MslImportData{"max", "fmax"},
- MslImportData{"min", "fmin"},
- MslImportData{"pow", "powr"},
- MslImportData{"reflect", "reflect"},
- MslImportData{"step", "step"}));
-
-using MslImportData_DualParam_Int_Test = TestParamHelper<MslImportData>;
-TEST_P(MslImportData_DualParam_Int_Test, IntScalar) {
- auto param = GetParam();
-
- auto* expr = Call(param.name, 1_i, 2_i);
- WrapInFunction(expr);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), std::string(param.msl_name) + "(1, 2)");
-}
-INSTANTIATE_TEST_SUITE_P(MslASTPrinterTest,
- MslImportData_DualParam_Int_Test,
- testing::Values(MslImportData{"max", "max"}, MslImportData{"min", "min"}));
-
-using MslImportData_TripleParam_ScalarTest = TestParamHelper<MslImportData>;
-TEST_P(MslImportData_TripleParam_ScalarTest, Float) {
- auto param = GetParam();
-
- auto* expr = Call(param.name, 1_f, 2_f, 3_f);
- WrapInFunction(expr);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), std::string(param.msl_name) + "(1.0f, 2.0f, 3.0f)");
-}
-INSTANTIATE_TEST_SUITE_P(MslASTPrinterTest,
- MslImportData_TripleParam_ScalarTest,
- testing::Values(MslImportData{"fma", "fma"},
- MslImportData{"mix", "mix"},
- MslImportData{"clamp", "clamp"},
- MslImportData{"smoothstep", "smoothstep"}));
-
-using MslImportData_TripleParam_VectorTest = TestParamHelper<MslImportData>;
-TEST_P(MslImportData_TripleParam_VectorTest, Float) {
- auto param = GetParam();
-
- auto* expr = Call(param.name, Call<vec3<f32>>(1_f, 2_f, 3_f), Call<vec3<f32>>(4_f, 5_f, 6_f),
- Call<vec3<f32>>(7_f, 8_f, 9_f));
- WrapInFunction(expr);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.Diagnostics();
- EXPECT_EQ(
- out.str(),
- std::string(param.msl_name) +
- R"((float3(1.0f, 2.0f, 3.0f), float3(4.0f, 5.0f, 6.0f), float3(7.0f, 8.0f, 9.0f)))");
-}
-INSTANTIATE_TEST_SUITE_P(MslASTPrinterTest,
- MslImportData_TripleParam_VectorTest,
- testing::Values(MslImportData{"faceForward", "faceforward"},
- MslImportData{"fma", "fma"},
- MslImportData{"clamp", "clamp"},
- MslImportData{"smoothstep", "smoothstep"}));
-
-using MslImportData_TripleParam_Int_Test = TestParamHelper<MslImportData>;
-TEST_P(MslImportData_TripleParam_Int_Test, IntScalar) {
- auto param = GetParam();
-
- auto* expr = Call(param.name, 1_i, 2_i, 3_i);
- WrapInFunction(expr);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), std::string(param.msl_name) + "(1, 2, 3)");
-}
-INSTANTIATE_TEST_SUITE_P(MslASTPrinterTest,
- MslImportData_TripleParam_Int_Test,
- testing::Values(MslImportData{"clamp", "clamp"},
- MslImportData{"clamp", "clamp"}));
-
-TEST_F(MslASTPrinterTest, MslImportData_Determinant) {
- GlobalVar("var", ty.mat3x3<f32>(), core::AddressSpace::kPrivate);
-
- auto* expr = Call("determinant", "var");
-
- WrapInFunction(expr);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), std::string("determinant(var)"));
-}
-
-TEST_F(MslASTPrinterTest, MslImportData_QuantizeToF16_Scalar) {
- GlobalVar("v", Expr(2_f), core::AddressSpace::kPrivate);
-
- auto* expr = Call("quantizeToF16", "v");
- WrapInFunction(expr);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "float(half(v))");
-}
-
-TEST_F(MslASTPrinterTest, MslImportData_QuantizeToF16_Vector) {
- GlobalVar("v", Call<vec3<f32>>(2_f), core::AddressSpace::kPrivate);
-
- auto* expr = Call("quantizeToF16", "v");
- WrapInFunction(expr);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitCall(out, expr)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "float3(half3(v))");
-}
-
-} // namespace
-} // namespace tint::msl::writer
diff --git a/src/tint/lang/msl/writer/ast_printer/loop_test.cc b/src/tint/lang/msl/writer/ast_printer/loop_test.cc
deleted file mode 100644
index 9914e7e..0000000
--- a/src/tint/lang/msl/writer/ast_printer/loop_test.cc
+++ /dev/null
@@ -1,886 +0,0 @@
-// Copyright 2020 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/tint/lang/core/fluent_types.h"
-#include "src/tint/lang/msl/writer/ast_printer/helper_test.h"
-#include "src/tint/lang/wgsl/ast/variable_decl_statement.h"
-
-using namespace tint::core::number_suffixes; // NOLINT
-using namespace tint::core::fluent_types; // NOLINT
-
-namespace tint::msl::writer {
-namespace {
-
-using MslASTPrinterTest = TestHelper;
-
-Options NoRobustness() {
- Options o;
- o.disable_robustness = true;
- return o;
-}
-
-TEST_F(MslASTPrinterTest, Emit_Loop) {
- auto* body = Block(Break());
- auto* continuing = Block();
- auto* l = Loop(body, continuing);
-
- Func("F", tint::Empty, ty.void_(), Vector{l}, Vector{Stage(ast::PipelineStage::kFragment)});
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-
-#define TINT_ISOLATE_UB(VOLATILE_NAME) \
- {volatile bool VOLATILE_NAME = false; if (VOLATILE_NAME) break;}
-
-fragment void F() {
- while(true) {
- TINT_ISOLATE_UB(tint_volatile_false);
- break;
- }
- return;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_Loop_WithoutRobustness) {
- auto* body = Block(Break());
- auto* continuing = Block();
- auto* l = Loop(body, continuing);
-
- Func("F", tint::Empty, ty.void_(), Vector{l}, Vector{Stage(ast::PipelineStage::kFragment)});
-
- ASTPrinter& gen = Build(NoRobustness());
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-fragment void F() {
- while(true) {
- break;
- }
- return;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_LoopWithContinuing) {
- Func("a_statement", {}, ty.void_(), tint::Empty);
-
- auto* body = Block(Break());
- auto* continuing = Block(CallStmt(Call("a_statement")));
- auto* l = Loop(body, continuing);
-
- Func("F", tint::Empty, ty.void_(), Vector{l}, Vector{Stage(ast::PipelineStage::kFragment)});
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-
-#define TINT_ISOLATE_UB(VOLATILE_NAME) \
- {volatile bool VOLATILE_NAME = false; if (VOLATILE_NAME) break;}
-
-void a_statement() {
-}
-
-fragment void F() {
- while(true) {
- TINT_ISOLATE_UB(tint_volatile_false);
- break;
- {
- a_statement();
- }
- }
- return;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_LoopWithContinuing_WithoutRobustness) {
- Func("a_statement", {}, ty.void_(), tint::Empty);
-
- auto* body = Block(Break());
- auto* continuing = Block(CallStmt(Call("a_statement")));
- auto* l = Loop(body, continuing);
-
- Func("F", tint::Empty, ty.void_(), Vector{l}, Vector{Stage(ast::PipelineStage::kFragment)});
-
- ASTPrinter& gen = Build(NoRobustness());
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-void a_statement() {
-}
-
-fragment void F() {
- while(true) {
- break;
- {
- a_statement();
- }
- }
- return;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_LoopWithContinuing_BreakIf) {
- Func("a_statement", {}, ty.void_(), {});
-
- auto* body = Block(Break());
- auto* continuing = Block(CallStmt(Call("a_statement")), BreakIf(true));
- auto* l = Loop(body, continuing);
-
- Func("F", tint::Empty, ty.void_(), Vector{l}, Vector{Stage(ast::PipelineStage::kFragment)});
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-
-#define TINT_ISOLATE_UB(VOLATILE_NAME) \
- {volatile bool VOLATILE_NAME = false; if (VOLATILE_NAME) break;}
-
-void a_statement() {
-}
-
-fragment void F() {
- while(true) {
- TINT_ISOLATE_UB(tint_volatile_false);
- break;
- {
- a_statement();
- if (true) { break; }
- }
- }
- return;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_LoopWithContinuing_BreakIf_WithoutRobustness) {
- Func("a_statement", {}, ty.void_(), {});
-
- auto* body = Block(Break());
- auto* continuing = Block(CallStmt(Call("a_statement")), BreakIf(true));
- auto* l = Loop(body, continuing);
-
- Func("F", tint::Empty, ty.void_(), Vector{l}, Vector{Stage(ast::PipelineStage::kFragment)});
-
- ASTPrinter& gen = Build(NoRobustness());
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-void a_statement() {
-}
-
-fragment void F() {
- while(true) {
- break;
- {
- a_statement();
- if (true) { break; }
- }
- }
- return;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_LoopNestedWithContinuing) {
- Func("a_statement", {}, ty.void_(), tint::Empty);
-
- GlobalVar("lhs", ty.f32(), core::AddressSpace::kPrivate);
- GlobalVar("rhs", ty.f32(), core::AddressSpace::kPrivate);
-
- auto* body = Block(Break());
- auto* continuing = Block(CallStmt(Call("a_statement")));
- auto* inner = Loop(body, continuing);
-
- body = Block(inner);
-
- continuing = Block(Assign("lhs", "rhs"), BreakIf(true));
-
- auto* outer = Loop(body, continuing);
-
- Func("F", tint::Empty, ty.void_(), Vector{outer}, Vector{Stage(ast::PipelineStage::kFragment)});
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.EmitStatement(outer)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(while(true) {
- TINT_ISOLATE_UB(tint_volatile_false);
- while(true) {
- TINT_ISOLATE_UB(tint_volatile_false_1);
- break;
- {
- a_statement();
- }
- }
- {
- lhs = rhs;
- if (true) { break; }
- }
-}
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_LoopNestedWithContinuing_WithoutRobustness) {
- Func("a_statement", {}, ty.void_(), tint::Empty);
-
- GlobalVar("lhs", ty.f32(), core::AddressSpace::kPrivate);
- GlobalVar("rhs", ty.f32(), core::AddressSpace::kPrivate);
-
- auto* body = Block(Break());
- auto* continuing = Block(CallStmt(Call("a_statement")));
- auto* inner = Loop(body, continuing);
-
- body = Block(inner);
-
- continuing = Block(Assign("lhs", "rhs"), BreakIf(true));
-
- auto* outer = Loop(body, continuing);
-
- Func("F", tint::Empty, ty.void_(), Vector{outer}, Vector{Stage(ast::PipelineStage::kFragment)});
-
- ASTPrinter& gen = Build(NoRobustness());
-
- ASSERT_TRUE(gen.EmitStatement(outer)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(while(true) {
- while(true) {
- break;
- {
- a_statement();
- }
- }
- {
- lhs = rhs;
- if (true) { break; }
- }
-}
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_LoopWithVarUsedInContinuing) {
- // loop {
- // var lhs : f32 = 2.5;
- // var other : f32;
- // continuing {
- // lhs = rhs
- // }
- // }
- //
-
- GlobalVar("rhs", ty.f32(), core::AddressSpace::kPrivate);
-
- auto* body = Block(Decl(Var("lhs", ty.f32(), Expr(2.5_f))), //
- Decl(Var("other", ty.f32())), //
- Break());
-
- auto* continuing = Block(Assign("lhs", "rhs"));
- auto* outer = Loop(body, continuing);
- WrapInFunction(outer);
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.EmitStatement(outer)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(while(true) {
- TINT_ISOLATE_UB(tint_volatile_false);
- float lhs = 2.5f;
- float other = 0.0f;
- break;
- {
- lhs = rhs;
- }
-}
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_LoopWithVarUsedInContinuing_WithoutRobustness) {
- // loop {
- // var lhs : f32 = 2.5;
- // var other : f32;
- // continuing {
- // lhs = rhs
- // }
- // }
- //
-
- GlobalVar("rhs", ty.f32(), core::AddressSpace::kPrivate);
-
- auto* body = Block(Decl(Var("lhs", ty.f32(), Expr(2.5_f))), //
- Decl(Var("other", ty.f32())), //
- Break());
-
- auto* continuing = Block(Assign("lhs", "rhs"));
- auto* outer = Loop(body, continuing);
- WrapInFunction(outer);
-
- ASTPrinter& gen = Build(NoRobustness());
-
- ASSERT_TRUE(gen.EmitStatement(outer)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(while(true) {
- float lhs = 2.5f;
- float other = 0.0f;
- break;
- {
- lhs = rhs;
- }
-}
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_ForLoop) {
- // for(; ; ) {
- // return;
- // }
-
- auto* f = For(nullptr, nullptr, nullptr, //
- Block(Return()));
- WrapInFunction(f);
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(for(; ; ) {
- TINT_ISOLATE_UB(tint_volatile_false);
- return;
-}
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_ForLoop_WithoutRobustness) {
- // for(; ; ) {
- // return;
- // }
-
- auto* f = For(nullptr, nullptr, nullptr, //
- Block(Return()));
- WrapInFunction(f);
-
- ASTPrinter& gen = Build(NoRobustness());
-
- ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(for(; ; ) {
- return;
-}
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_ForLoopWithSimpleInit) {
- // for(var i : i32; ; ) {
- // return;
- // }
-
- auto* f = For(Decl(Var("i", ty.i32())), nullptr, nullptr, //
- Block(Return()));
- WrapInFunction(f);
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(for(int i = 0; ; ) {
- TINT_ISOLATE_UB(tint_volatile_false);
- return;
-}
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_ForLoopWithSimpleInit_WithoutRobustness) {
- // for(var i : i32; ; ) {
- // return;
- // }
-
- auto* f = For(Decl(Var("i", ty.i32())), nullptr, nullptr, //
- Block(Return()));
- WrapInFunction(f);
-
- ASTPrinter& gen = Build(NoRobustness());
-
- ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(for(int i = 0; ; ) {
- return;
-}
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_ForLoopWithMultiStmtInit) {
- // fn f(i : i32) {}
- //
- // var<workgroup> a : atomic<i32>;
- // for({f(1i); f(2i);}; ; ) {
- // return;
- // }
-
- Func("f", Vector{Param("i", ty.i32())}, ty.void_(), tint::Empty);
- auto f = [&](auto&& expr) { return CallStmt(Call("f", expr)); };
-
- GlobalVar("a", ty.atomic<i32>(), core::AddressSpace::kWorkgroup);
- auto* multi_stmt = Block(f(1_i), f(2_i));
- auto* loop = For(multi_stmt, nullptr, nullptr, //
- Block(Return()));
- WrapInFunction(loop);
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.EmitStatement(loop)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"({
- {
- f(1);
- f(2);
- }
- for(; ; ) {
- TINT_ISOLATE_UB(tint_volatile_false);
- return;
- }
-}
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_ForLoopWithMultiStmtInit_WithoutRobustness) {
- // fn f(i : i32) {}
- //
- // var<workgroup> a : atomic<i32>;
- // for({f(1i); f(2i);}; ; ) {
- // return;
- // }
-
- Func("f", Vector{Param("i", ty.i32())}, ty.void_(), tint::Empty);
- auto f = [&](auto&& expr) { return CallStmt(Call("f", expr)); };
-
- GlobalVar("a", ty.atomic<i32>(), core::AddressSpace::kWorkgroup);
- auto* multi_stmt = Block(f(1_i), f(2_i));
- auto* loop = For(multi_stmt, nullptr, nullptr, //
- Block(Return()));
- WrapInFunction(loop);
-
- ASTPrinter& gen = Build(NoRobustness());
-
- ASSERT_TRUE(gen.EmitStatement(loop)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"({
- {
- f(1);
- f(2);
- }
- for(; ; ) {
- return;
- }
-}
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_ForLoopWithSimpleCond) {
- // for(; true; ) {
- // return;
- // }
-
- auto* f = For(nullptr, true, nullptr, //
- Block(Return()));
- WrapInFunction(f);
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(for(; true; ) {
- TINT_ISOLATE_UB(tint_volatile_false);
- return;
-}
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_ForLoopWithSimpleCond_WithoutRobustness) {
- // for(; true; ) {
- // return;
- // }
-
- auto* f = For(nullptr, true, nullptr, //
- Block(Return()));
- WrapInFunction(f);
-
- ASTPrinter& gen = Build(NoRobustness());
-
- ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(for(; true; ) {
- return;
-}
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_ForLoopWithSimpleCont) {
- // for(; ; i = i + 1) {
- // return;
- // }
-
- auto* v = Decl(Var("i", ty.i32()));
- auto* f = For(nullptr, nullptr, Assign("i", Add("i", 1_i)), //
- Block(Return()));
- WrapInFunction(v, f);
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(),
- R"(for(; ; i = as_type<int>((as_type<uint>(i) + as_type<uint>(1)))) {
- TINT_ISOLATE_UB(tint_volatile_false);
- return;
-}
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_ForLoopWithSimpleCont_WithoutRobustness) {
- // for(; ; i = i + 1) {
- // return;
- // }
-
- auto* v = Decl(Var("i", ty.i32()));
- auto* f = For(nullptr, nullptr, Assign("i", Add("i", 1_i)), //
- Block(Return()));
- WrapInFunction(v, f);
-
- ASTPrinter& gen = Build(NoRobustness());
-
- ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(),
- R"(for(; ; i = as_type<int>((as_type<uint>(i) + as_type<uint>(1)))) {
- return;
-}
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_ForLoopWithMultiStmtCont) {
- // fn f(i : i32) {}
- //
- // var<workgroup> a : atomic<i32>;
- // for(; ; { f(1i); f(2i); }) {
- // return;
- // }
-
- Func("f", Vector{Param("i", ty.i32())}, ty.void_(), tint::Empty);
- auto f = [&](auto&& expr) { return CallStmt(Call("f", expr)); };
-
- GlobalVar("a", ty.atomic<i32>(), core::AddressSpace::kWorkgroup);
- auto* multi_stmt = Block(f(1_i), f(2_i));
- auto* loop = For(nullptr, nullptr, multi_stmt, //
- Block(Return()));
- WrapInFunction(loop);
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.EmitStatement(loop)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(while(true) {
- TINT_ISOLATE_UB(tint_volatile_false);
- return;
- {
- f(1);
- f(2);
- }
-}
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_ForLoopWithMultiStmtCont_WithoutRobustness) {
- // fn f(i : i32) {}
- //
- // var<workgroup> a : atomic<i32>;
- // for(; ; { f(1i); f(2i); }) {
- // return;
- // }
-
- Func("f", Vector{Param("i", ty.i32())}, ty.void_(), tint::Empty);
- auto f = [&](auto&& expr) { return CallStmt(Call("f", expr)); };
-
- GlobalVar("a", ty.atomic<i32>(), core::AddressSpace::kWorkgroup);
- auto* multi_stmt = Block(f(1_i), f(2_i));
- auto* loop = For(nullptr, nullptr, multi_stmt, //
- Block(Return()));
- WrapInFunction(loop);
-
- ASTPrinter& gen = Build(NoRobustness());
-
- ASSERT_TRUE(gen.EmitStatement(loop)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(while(true) {
- return;
- {
- f(1);
- f(2);
- }
-}
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_ForLoopWithSimpleInitCondCont) {
- // for(var i : i32; true; i = i + 1) {
- // return;
- // }
-
- Func("a_statement", {}, ty.void_(), tint::Empty);
-
- auto* f = For(Decl(Var("i", ty.i32())), true, Assign("i", Add("i", 1_i)),
- Block(CallStmt(Call("a_statement"))));
- WrapInFunction(f);
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(),
- R"(for(int i = 0; true; i = as_type<int>((as_type<uint>(i) + as_type<uint>(1)))) {
- TINT_ISOLATE_UB(tint_volatile_false);
- a_statement();
-}
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_ForLoopWithSimpleInitCondCont_WithoutRobustness) {
- // for(var i : i32; true; i = i + 1) {
- // return;
- // }
-
- Func("a_statement", {}, ty.void_(), tint::Empty);
-
- auto* f = For(Decl(Var("i", ty.i32())), true, Assign("i", Add("i", 1_i)),
- Block(CallStmt(Call("a_statement"))));
- WrapInFunction(f);
-
- ASTPrinter& gen = Build(NoRobustness());
-
- ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(),
- R"(for(int i = 0; true; i = as_type<int>((as_type<uint>(i) + as_type<uint>(1)))) {
- a_statement();
-}
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_ForLoopWithMultiStmtInitCondCont) {
- // fn f(i : i32) {}
- //
- // var<workgroup> a : atomic<i32>;
- // for({ f(1i); f(2i); }; true; { f(3i); f(4i); }) {
- // return;
- // }
-
- Func("f", Vector{Param("i", ty.i32())}, ty.void_(), tint::Empty);
- auto f = [&](auto&& expr) { return CallStmt(Call("f", expr)); };
-
- GlobalVar("a", ty.atomic<i32>(), core::AddressSpace::kWorkgroup);
- auto* multi_stmt_a = Block(f(1_i), f(2_i));
- auto* multi_stmt_b = Block(f(3_i), f(4_i));
- auto* loop = For(multi_stmt_a, Expr(true), multi_stmt_b, //
- Block(Return()));
- WrapInFunction(loop);
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.EmitStatement(loop)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"({
- {
- f(1);
- f(2);
- }
- while(true) {
- TINT_ISOLATE_UB(tint_volatile_false);
- if (!(true)) { break; }
- return;
- {
- f(3);
- f(4);
- }
- }
-}
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_ForLoopWithMultiStmtInitCondCont_WithoutRobustness) {
- // fn f(i : i32) {}
- //
- // var<workgroup> a : atomic<i32>;
- // for({ f(1i); f(2i); }; true; { f(3i); f(4i); }) {
- // return;
- // }
-
- Func("f", Vector{Param("i", ty.i32())}, ty.void_(), tint::Empty);
- auto f = [&](auto&& expr) { return CallStmt(Call("f", expr)); };
-
- GlobalVar("a", ty.atomic<i32>(), core::AddressSpace::kWorkgroup);
- auto* multi_stmt_a = Block(f(1_i), f(2_i));
- auto* multi_stmt_b = Block(f(3_i), f(4_i));
- auto* loop = For(multi_stmt_a, Expr(true), multi_stmt_b, //
- Block(Return()));
- WrapInFunction(loop);
-
- ASTPrinter& gen = Build(NoRobustness());
-
- ASSERT_TRUE(gen.EmitStatement(loop)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"({
- {
- f(1);
- f(2);
- }
- while(true) {
- if (!(true)) { break; }
- return;
- {
- f(3);
- f(4);
- }
- }
-}
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_While) {
- // while(true) {
- // return;
- // }
-
- auto* f = While(Expr(true), Block(Return()));
- WrapInFunction(f);
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(while(true) {
- TINT_ISOLATE_UB(tint_volatile_false);
- return;
-}
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_While_WithoutRobustness) {
- // while(true) {
- // return;
- // }
-
- auto* f = While(Expr(true), Block(Return()));
- WrapInFunction(f);
-
- ASTPrinter& gen = Build(NoRobustness());
-
- ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(while(true) {
- return;
-}
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_While_WithContinue) {
- // while(true) {
- // continue;
- // }
-
- auto* f = While(Expr(true), Block(Continue()));
- WrapInFunction(f);
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(while(true) {
- TINT_ISOLATE_UB(tint_volatile_false);
- continue;
-}
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_While_WithContinue_WithoutRobustness) {
- // while(true) {
- // continue;
- // }
-
- auto* f = While(Expr(true), Block(Continue()));
- WrapInFunction(f);
-
- ASTPrinter& gen = Build(NoRobustness());
-
- ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(while(true) {
- continue;
-}
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_WhileWithMultiCond) {
- // while(true && false) {
- // return;
- // }
-
- auto* t = Let("t", Expr(true));
- auto* multi_stmt = LogicalAnd(t, false);
- // create<ast::BinaryExpression>(core::BinaryOp::kLogicalAnd, Expr(t), Expr(false));
- auto* f = While(multi_stmt, Block(Return()));
- WrapInFunction(t, f);
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(while((t && false)) {
- TINT_ISOLATE_UB(tint_volatile_false);
- return;
-}
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_WhileWithMultiCond_WithoutRobustness) {
- // while(true && false) {
- // return;
- // }
-
- auto* t = Let("t", Expr(true));
- auto* multi_stmt = LogicalAnd(t, false);
- // create<ast::BinaryExpression>(core::BinaryOp::kLogicalAnd, Expr(t), Expr(false));
- auto* f = While(multi_stmt, Block(Return()));
- WrapInFunction(t, f);
-
- ASTPrinter& gen = Build(NoRobustness());
-
- ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(while((t && false)) {
- return;
-}
-)");
-}
-
-} // namespace
-} // namespace tint::msl::writer
diff --git a/src/tint/lang/msl/writer/ast_printer/member_accessor_test.cc b/src/tint/lang/msl/writer/ast_printer/member_accessor_test.cc
deleted file mode 100644
index 18e3af1..0000000
--- a/src/tint/lang/msl/writer/ast_printer/member_accessor_test.cc
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2020 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/tint/lang/core/fluent_types.h"
-#include "src/tint/lang/msl/writer/ast_printer/helper_test.h"
-#include "src/tint/utils/text/string_stream.h"
-
-using namespace tint::core::fluent_types; // NOLINT
-
-namespace tint::msl::writer {
-namespace {
-
-using MslASTPrinterTest = TestHelper;
-
-TEST_F(MslASTPrinterTest, EmitExpression_MemberAccessor) {
- GlobalVar("str", ty.Of(Structure("my_str", Vector{Member("mem", ty.f32())})),
- core::AddressSpace::kPrivate);
- auto* expr = MemberAccessor("str", "mem");
- WrapInFunction(expr);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "str.mem");
-}
-
-TEST_F(MslASTPrinterTest, EmitExpression_MemberAccessor_Swizzle_xyz) {
- GlobalVar("my_vec", ty.vec4<f32>(), core::AddressSpace::kPrivate);
-
- auto* expr = MemberAccessor("my_vec", "xyz");
- WrapInFunction(expr);
-
- ASTPrinter& gen = Build();
- StringStream out;
- ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "my_vec.xyz");
-}
-
-TEST_F(MslASTPrinterTest, EmitExpression_MemberAccessor_Swizzle_gbr) {
- GlobalVar("my_vec", ty.vec4<f32>(), core::AddressSpace::kPrivate);
-
- auto* expr = MemberAccessor("my_vec", "gbr");
- WrapInFunction(expr);
-
- ASTPrinter& gen = Build();
- StringStream out;
- ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "my_vec.gbr");
-}
-
-} // namespace
-} // namespace tint::msl::writer
diff --git a/src/tint/lang/msl/writer/ast_printer/module_constant_test.cc b/src/tint/lang/msl/writer/ast_printer/module_constant_test.cc
deleted file mode 100644
index f357199..0000000
--- a/src/tint/lang/msl/writer/ast_printer/module_constant_test.cc
+++ /dev/null
@@ -1,344 +0,0 @@
-// Copyright 2020 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/tint/lang/msl/writer/ast_printer/helper_test.h"
-#include "src/tint/lang/wgsl/ast/id_attribute.h"
-
-namespace tint::msl::writer {
-namespace {
-
-using namespace tint::core::fluent_types; // NOLINT
-using namespace tint::core::number_suffixes; // NOLINT
-
-using MslASTPrinterTest = TestHelper;
-
-TEST_F(MslASTPrinterTest, Emit_GlobalConst_AInt) {
- auto* var = GlobalConst("G", Expr(1_a));
- Func("f", tint::Empty, ty.void_(), Vector{Decl(Let("l", Expr(var)))});
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-void f() {
- int const l = 1;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_GlobalConst_AFloat) {
- auto* var = GlobalConst("G", Expr(1._a));
- Func("f", tint::Empty, ty.void_(), Vector{Decl(Let("l", Expr(var)))});
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-void f() {
- float const l = 1.0f;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_GlobalConst_i32) {
- auto* var = GlobalConst("G", Expr(1_i));
- Func("f", tint::Empty, ty.void_(), Vector{Decl(Let("l", Expr(var)))});
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-void f() {
- int const l = 1;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_GlobalConst_u32) {
- auto* var = GlobalConst("G", Expr(1_u));
- Func("f", tint::Empty, ty.void_(), Vector{Decl(Let("l", Expr(var)))});
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-void f() {
- uint const l = 1u;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_GlobalConst_f32) {
- auto* var = GlobalConst("G", Expr(1_f));
- Func("f", tint::Empty, ty.void_(), Vector{Decl(Let("l", Expr(var)))});
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-void f() {
- float const l = 1.0f;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_GlobalConst_f16) {
- Enable(wgsl::Extension::kF16);
-
- auto* var = GlobalConst("G", Expr(1_h));
- Func("f", tint::Empty, ty.void_(), Vector{Decl(Let("l", Expr(var)))});
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-void f() {
- half const l = 1.0h;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_GlobalConst_vec3_AInt) {
- auto* var = GlobalConst("G", Call<vec3<Infer>>(1_a, 2_a, 3_a));
- Func("f", tint::Empty, ty.void_(), Vector{Decl(Let("l", Expr(var)))});
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-void f() {
- int3 const l = int3(1, 2, 3);
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_GlobalConst_vec3_AFloat) {
- auto* var = GlobalConst("G", Call<vec3<Infer>>(1._a, 2._a, 3._a));
- Func("f", tint::Empty, ty.void_(), Vector{Decl(Let("l", Expr(var)))});
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-void f() {
- float3 const l = float3(1.0f, 2.0f, 3.0f);
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_GlobalConst_vec3_f32) {
- auto* var = GlobalConst("G", Call<vec3<f32>>(1_f, 2_f, 3_f));
- Func("f", tint::Empty, ty.void_(), Vector{Decl(Let("l", Expr(var)))});
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-void f() {
- float3 const l = float3(1.0f, 2.0f, 3.0f);
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_GlobalConst_vec3_f16) {
- Enable(wgsl::Extension::kF16);
-
- auto* var = GlobalConst("G", Call<vec3<f16>>(1_h, 2_h, 3_h));
- Func("f", tint::Empty, ty.void_(), Vector{Decl(Let("l", Expr(var)))});
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-void f() {
- half3 const l = half3(1.0h, 2.0h, 3.0h);
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_GlobalConst_mat2x3_AFloat) {
- auto* var = GlobalConst("G", Call<mat2x3<Infer>>(1._a, 2._a, 3._a, 4._a, 5._a, 6._a));
- Func("f", tint::Empty, ty.void_(), Vector{Decl(Let("l", Expr(var)))});
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-void f() {
- float2x3 const l = float2x3(float3(1.0f, 2.0f, 3.0f), float3(4.0f, 5.0f, 6.0f));
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_GlobalConst_mat2x3_f32) {
- auto* var = GlobalConst("G", Call<mat2x3<f32>>(1_f, 2_f, 3_f, 4_f, 5_f, 6_f));
- Func("f", tint::Empty, ty.void_(), Vector{Decl(Let("l", Expr(var)))});
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-void f() {
- float2x3 const l = float2x3(float3(1.0f, 2.0f, 3.0f), float3(4.0f, 5.0f, 6.0f));
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_GlobalConst_mat2x3_f16) {
- Enable(wgsl::Extension::kF16);
-
- auto* var = GlobalConst("G", Call<mat2x3<f16>>(1_h, 2_h, 3_h, 4_h, 5_h, 6_h));
- Func("f", tint::Empty, ty.void_(), Vector{Decl(Let("l", Expr(var)))});
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-void f() {
- half2x3 const l = half2x3(half3(1.0h, 2.0h, 3.0h), half3(4.0h, 5.0h, 6.0h));
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_GlobalConst_arr_f32) {
- auto* var = GlobalConst("G", Call(ty.array<f32, 3>(), 1_f, 2_f, 3_f));
- Func("f", tint::Empty, ty.void_(), Vector{Decl(Let("l", Expr(var)))});
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-
-template<typename T, size_t N>
-struct tint_array {
- const constant T& operator[](size_t i) const constant { return elements[i]; }
- device T& operator[](size_t i) device { return elements[i]; }
- const device T& operator[](size_t i) const device { return elements[i]; }
- thread T& operator[](size_t i) thread { return elements[i]; }
- const thread T& operator[](size_t i) const thread { return elements[i]; }
- threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
- const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
- T elements[N];
-};
-
-void f() {
- tint_array<float, 3> const l = tint_array<float, 3>{1.0f, 2.0f, 3.0f};
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_GlobalConst_arr_vec2_bool) {
- auto* var = GlobalConst("G", Call<array<vec2<bool>, 3>>(Call<vec2<bool>>(true, false), //
- Call<vec2<bool>>(false, true), //
- Call<vec2<bool>>(true, true)));
- Func("f", tint::Empty, ty.void_(), Vector{Decl(Let("l", Expr(var)))});
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-
-template<typename T, size_t N>
-struct tint_array {
- const constant T& operator[](size_t i) const constant { return elements[i]; }
- device T& operator[](size_t i) device { return elements[i]; }
- const device T& operator[](size_t i) const device { return elements[i]; }
- thread T& operator[](size_t i) thread { return elements[i]; }
- const thread T& operator[](size_t i) const thread { return elements[i]; }
- threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
- const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
- T elements[N];
-};
-
-void f() {
- tint_array<bool2, 3> const l = tint_array<bool2, 3>{bool2(true, false), bool2(false, true), bool2(true)};
-}
-
-)");
-}
-
-} // namespace
-} // namespace tint::msl::writer
diff --git a/src/tint/lang/msl/writer/ast_printer/return_test.cc b/src/tint/lang/msl/writer/ast_printer/return_test.cc
deleted file mode 100644
index 4ea89a6..0000000
--- a/src/tint/lang/msl/writer/ast_printer/return_test.cc
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 2020 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/tint/lang/msl/writer/ast_printer/helper_test.h"
-
-using namespace tint::core::number_suffixes; // NOLINT
-
-namespace tint::msl::writer {
-namespace {
-
-// All ported to IR tests
-
-using MslASTPrinterTest = TestHelper;
-
-// MslPrinterTest.Return
-TEST_F(MslASTPrinterTest, Emit_Return) {
- auto* r = Return();
- WrapInFunction(r);
-
- ASTPrinter& gen = Build();
-
- gen.IncrementIndent();
-
- ASSERT_TRUE(gen.EmitStatement(r)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), " return;\n");
-}
-
-// MslPrinterTest.ReturnWithValue
-TEST_F(MslASTPrinterTest, Emit_ReturnWithValue) {
- auto* r = Return(123_i);
- Func("f", tint::Empty, ty.i32(), Vector{r});
-
- ASTPrinter& gen = Build();
-
- gen.IncrementIndent();
-
- ASSERT_TRUE(gen.EmitStatement(r)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), " return 123;\n");
-}
-
-} // namespace
-} // namespace tint::msl::writer
diff --git a/src/tint/lang/msl/writer/ast_printer/sanitizer_test.cc b/src/tint/lang/msl/writer/ast_printer/sanitizer_test.cc
deleted file mode 100644
index 901ddd2..0000000
--- a/src/tint/lang/msl/writer/ast_printer/sanitizer_test.cc
+++ /dev/null
@@ -1,303 +0,0 @@
-// Copyright 2021 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "gmock/gmock.h"
-#include "src/tint/lang/core/fluent_types.h"
-#include "src/tint/lang/msl/writer/ast_printer/helper_test.h"
-#include "src/tint/lang/wgsl/ast/call_statement.h"
-#include "src/tint/lang/wgsl/ast/stage_attribute.h"
-#include "src/tint/lang/wgsl/ast/variable_decl_statement.h"
-
-using namespace tint::core::number_suffixes; // NOLINT
-using namespace tint::core::fluent_types; // NOLINT
-
-namespace tint::msl::writer {
-namespace {
-
-using ::testing::HasSubstr;
-using MslSanitizerTest = TestHelper;
-
-TEST_F(MslSanitizerTest, Call_ArrayLength) {
- auto* s = Structure("my_struct", Vector{Member(0, "a", ty.array<f32>())});
- GlobalVar("b", ty.Of(s), core::AddressSpace::kStorage, core::Access::kRead, Binding(1_a),
- Group(2_a));
-
- Func("a_func", tint::Empty, ty.void_(),
- Vector{
- Decl(Var("len", ty.u32(), Call("arrayLength", AddressOf(MemberAccessor("b", "a"))))),
- },
- Vector{
- Stage(ast::PipelineStage::kFragment),
- });
-
- Options opts = DefaultOptions();
- opts.array_length_from_uniform.ubo_binding = 30;
- opts.array_length_from_uniform.bindpoint_to_size_index.emplace(BindingPoint{2, 1}, 1);
- ASTPrinter& gen = SanitizeAndBuild(opts);
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-
- auto got = gen.Result();
- auto* expect = R"(#include <metal_stdlib>
-
-using namespace metal;
-
-template<typename T, size_t N>
-struct tint_array {
- const constant T& operator[](size_t i) const constant { return elements[i]; }
- device T& operator[](size_t i) device { return elements[i]; }
- const device T& operator[](size_t i) const device { return elements[i]; }
- thread T& operator[](size_t i) thread { return elements[i]; }
- const thread T& operator[](size_t i) const thread { return elements[i]; }
- threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
- const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
- T elements[N];
-};
-
-struct TintArrayLengths {
- /* 0x0000 */ tint_array<uint4, 1> array_lengths;
-};
-
-struct my_struct {
- tint_array<float, 1> a;
-};
-
-fragment void a_func(const constant TintArrayLengths* tint_symbol [[buffer(30)]]) {
- uint len = (((*(tint_symbol)).array_lengths[0u][1u] - 0u) / 4u);
- return;
-}
-
-)";
- EXPECT_EQ(expect, got);
-}
-
-TEST_F(MslSanitizerTest, Call_ArrayLength_OtherMembersInStruct) {
- auto* s = Structure("my_struct", Vector{
- Member(0, "z", ty.f32()),
- Member(4, "a", ty.array<f32>()),
- });
- GlobalVar("b", ty.Of(s), core::AddressSpace::kStorage, core::Access::kRead, Binding(1_a),
- Group(2_a));
-
- Func("a_func", tint::Empty, ty.void_(),
- Vector{
- Decl(Var("len", ty.u32(), Call("arrayLength", AddressOf(MemberAccessor("b", "a"))))),
- },
- Vector{
- Stage(ast::PipelineStage::kFragment),
- });
-
- Options opts = DefaultOptions();
- opts.array_length_from_uniform.ubo_binding = 30;
- opts.array_length_from_uniform.bindpoint_to_size_index.emplace(BindingPoint{2, 1}, 1);
- ASTPrinter& gen = SanitizeAndBuild(opts);
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-
- auto got = gen.Result();
- auto* expect = R"(#include <metal_stdlib>
-
-using namespace metal;
-
-template<typename T, size_t N>
-struct tint_array {
- const constant T& operator[](size_t i) const constant { return elements[i]; }
- device T& operator[](size_t i) device { return elements[i]; }
- const device T& operator[](size_t i) const device { return elements[i]; }
- thread T& operator[](size_t i) thread { return elements[i]; }
- const thread T& operator[](size_t i) const thread { return elements[i]; }
- threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
- const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
- T elements[N];
-};
-
-struct TintArrayLengths {
- /* 0x0000 */ tint_array<uint4, 1> array_lengths;
-};
-
-struct my_struct {
- float z;
- tint_array<float, 1> a;
-};
-
-fragment void a_func(const constant TintArrayLengths* tint_symbol [[buffer(30)]]) {
- uint len = (((*(tint_symbol)).array_lengths[0u][1u] - 4u) / 4u);
- return;
-}
-
-)";
-
- EXPECT_EQ(expect, got);
-}
-
-TEST_F(MslSanitizerTest, Call_ArrayLength_ViaLets) {
- auto* s = Structure("my_struct", Vector{Member(0, "a", ty.array<f32>())});
- GlobalVar("b", ty.Of(s), core::AddressSpace::kStorage, core::Access::kRead, Binding(1_a),
- Group(2_a));
-
- auto* p = Let("p", AddressOf("b"));
- auto* p2 = Let("p2", AddressOf(MemberAccessor(Deref(p), "a")));
-
- Func("a_func", tint::Empty, ty.void_(),
- Vector{
- Decl(p),
- Decl(p2),
- Decl(Var("len", ty.u32(), Call("arrayLength", p2))),
- },
- Vector{
- Stage(ast::PipelineStage::kFragment),
- });
-
- Options opts = DefaultOptions();
- opts.array_length_from_uniform.ubo_binding = 30;
- opts.array_length_from_uniform.bindpoint_to_size_index.emplace(BindingPoint{2, 1}, 1);
- ASTPrinter& gen = SanitizeAndBuild(opts);
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-
- auto got = gen.Result();
- auto* expect = R"(#include <metal_stdlib>
-
-using namespace metal;
-
-template<typename T, size_t N>
-struct tint_array {
- const constant T& operator[](size_t i) const constant { return elements[i]; }
- device T& operator[](size_t i) device { return elements[i]; }
- const device T& operator[](size_t i) const device { return elements[i]; }
- thread T& operator[](size_t i) thread { return elements[i]; }
- const thread T& operator[](size_t i) const thread { return elements[i]; }
- threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
- const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
- T elements[N];
-};
-
-struct TintArrayLengths {
- /* 0x0000 */ tint_array<uint4, 1> array_lengths;
-};
-
-struct my_struct {
- tint_array<float, 1> a;
-};
-
-fragment void a_func(const constant TintArrayLengths* tint_symbol [[buffer(30)]]) {
- uint len = (((*(tint_symbol)).array_lengths[0u][1u] - 0u) / 4u);
- return;
-}
-
-)";
-
- EXPECT_EQ(expect, got);
-}
-
-TEST_F(MslSanitizerTest, Call_ArrayLength_ArrayLengthFromUniform) {
- auto* s = Structure("my_struct", Vector{Member(0, "a", ty.array<f32>())});
- GlobalVar("b", ty.Of(s), core::AddressSpace::kStorage, core::Access::kRead, Binding(1_a),
- Group(0_a));
- GlobalVar("c", ty.Of(s), core::AddressSpace::kStorage, core::Access::kRead, Binding(2_a),
- Group(0_a));
-
- Func("a_func", tint::Empty, ty.void_(),
- Vector{
- Decl(Var("len", ty.u32(),
- Add(Call("arrayLength", AddressOf(MemberAccessor("b", "a"))),
- Call("arrayLength", AddressOf(MemberAccessor("c", "a")))))),
- },
- Vector{
- Stage(ast::PipelineStage::kFragment),
- });
-
- Options options;
- options.array_length_from_uniform.ubo_binding = 29;
- options.array_length_from_uniform.bindpoint_to_size_index.emplace(BindingPoint{0, 1}, 7u);
- options.array_length_from_uniform.bindpoint_to_size_index.emplace(BindingPoint{0, 2}, 2u);
- ASTPrinter& gen = SanitizeAndBuild(options);
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-
- auto got = gen.Result();
- auto* expect = R"(#include <metal_stdlib>
-
-using namespace metal;
-
-template<typename T, size_t N>
-struct tint_array {
- const constant T& operator[](size_t i) const constant { return elements[i]; }
- device T& operator[](size_t i) device { return elements[i]; }
- const device T& operator[](size_t i) const device { return elements[i]; }
- thread T& operator[](size_t i) thread { return elements[i]; }
- const thread T& operator[](size_t i) const thread { return elements[i]; }
- threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
- const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
- T elements[N];
-};
-
-struct TintArrayLengths {
- /* 0x0000 */ tint_array<uint4, 2> array_lengths;
-};
-
-struct my_struct {
- tint_array<float, 1> a;
-};
-
-fragment void a_func(const constant TintArrayLengths* tint_symbol [[buffer(29)]]) {
- uint len = ((((*(tint_symbol)).array_lengths[1u][3u] - 0u) / 4u) + (((*(tint_symbol)).array_lengths[0u][2u] - 0u) / 4u));
- return;
-}
-
-)";
- EXPECT_EQ(expect, got);
-}
-
-TEST_F(MslSanitizerTest, Call_ArrayLength_ArrayLengthFromUniformMissingBinding) {
- auto* s = Structure("my_struct", Vector{Member(0, "a", ty.array<f32>())});
- GlobalVar("b", ty.Of(s), core::AddressSpace::kStorage, core::Access::kRead, Binding(1_a),
- Group(0_a));
- GlobalVar("c", ty.Of(s), core::AddressSpace::kStorage, core::Access::kRead, Binding(2_a),
- Group(0_a));
-
- Func("a_func", tint::Empty, ty.void_(),
- Vector{
- Decl(Var("len", ty.u32(),
- Add(Call("arrayLength", AddressOf(MemberAccessor("b", "a"))),
- Call("arrayLength", AddressOf(MemberAccessor("c", "a")))))),
- },
- Vector{
- Stage(ast::PipelineStage::kFragment),
- });
-
- Options options;
- options.array_length_from_uniform.ubo_binding = 29;
- options.array_length_from_uniform.bindpoint_to_size_index.emplace(BindingPoint{0, 2}, 2u);
- ASTPrinter& gen = SanitizeAndBuild(options);
-
- ASSERT_FALSE(gen.Generate());
- EXPECT_THAT(gen.Diagnostics().Str(), HasSubstr("Unable to translate builtin: arrayLength"));
-}
-
-} // namespace
-} // namespace tint::msl::writer
diff --git a/src/tint/lang/msl/writer/ast_printer/switch_test.cc b/src/tint/lang/msl/writer/ast_printer/switch_test.cc
deleted file mode 100644
index 78a74f4..0000000
--- a/src/tint/lang/msl/writer/ast_printer/switch_test.cc
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright 2020 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/tint/lang/msl/writer/ast_printer/helper_test.h"
-
-using namespace tint::core::number_suffixes; // NOLINT
-
-namespace tint::msl::writer {
-namespace {
-
-using MslASTPrinterTest = TestHelper;
-
-TEST_F(MslASTPrinterTest, Emit_Switch) {
- auto* cond = Var("cond", ty.i32());
-
- auto* def_body = Block(create<ast::BreakStatement>());
- auto* def = Case(DefaultCaseSelector(), def_body);
-
- auto* case_body = Block(create<ast::BreakStatement>());
- auto* case_stmt = Case(CaseSelector(5_i), case_body);
-
- Vector body{case_stmt, def};
- auto* s = Switch(cond, body);
- WrapInFunction(cond, s);
- ASTPrinter& gen = Build();
-
- gen.IncrementIndent();
-
- ASSERT_TRUE(gen.EmitStatement(s)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"( switch(cond) {
- case 5: {
- break;
- }
- default: {
- break;
- }
- }
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_Switch_MixedDefault) {
- auto* cond = Var("cond", ty.i32());
-
- auto* def_body = Block(create<ast::BreakStatement>());
- auto* def = Case(Vector{CaseSelector(5_i), DefaultCaseSelector()}, def_body);
-
- auto* s = Switch(cond, def);
- WrapInFunction(cond, s);
- ASTPrinter& gen = Build();
-
- gen.IncrementIndent();
-
- ASSERT_TRUE(gen.EmitStatement(s)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"( switch(cond) {
- case 5:
- default: {
- break;
- }
- }
-)");
-}
-
-} // namespace
-} // namespace tint::msl::writer
diff --git a/src/tint/lang/msl/writer/ast_printer/unary_op_test.cc b/src/tint/lang/msl/writer/ast_printer/unary_op_test.cc
deleted file mode 100644
index 629653b..0000000
--- a/src/tint/lang/msl/writer/ast_printer/unary_op_test.cc
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright 2020 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/tint/lang/core/fluent_types.h"
-#include "src/tint/lang/msl/writer/ast_printer/helper_test.h"
-#include "src/tint/utils/text/string_stream.h"
-
-using namespace tint::core::fluent_types; // NOLINT
-
-namespace tint::msl::writer {
-namespace {
-
-using MslUnaryOpTest = TestHelper;
-
-TEST_F(MslUnaryOpTest, AddressOf) {
- GlobalVar("expr", ty.f32(), core::AddressSpace::kPrivate);
- auto* op = create<ast::UnaryOpExpression>(core::UnaryOp::kAddressOf, Expr("expr"));
- WrapInFunction(op);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitExpression(out, op)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "&(expr)");
-}
-
-TEST_F(MslUnaryOpTest, Complement) {
- GlobalVar("expr", ty.i32(), core::AddressSpace::kPrivate);
- auto* op = create<ast::UnaryOpExpression>(core::UnaryOp::kComplement, Expr("expr"));
- WrapInFunction(op);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitExpression(out, op)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "~(expr)");
-}
-
-TEST_F(MslUnaryOpTest, Indirection) {
- GlobalVar("G", ty.f32(), core::AddressSpace::kPrivate);
- auto* p = Let("expr", create<ast::UnaryOpExpression>(core::UnaryOp::kAddressOf, Expr("G")));
- auto* op = create<ast::UnaryOpExpression>(core::UnaryOp::kIndirection, Expr("expr"));
- WrapInFunction(p, op);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitExpression(out, op)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "*(expr)");
-}
-
-TEST_F(MslUnaryOpTest, Not) {
- GlobalVar("expr", ty.bool_(), core::AddressSpace::kPrivate);
- auto* op = create<ast::UnaryOpExpression>(core::UnaryOp::kNot, Expr("expr"));
- WrapInFunction(op);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitExpression(out, op)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "!(expr)");
-}
-
-TEST_F(MslUnaryOpTest, Negation) {
- GlobalVar("expr", ty.i32(), core::AddressSpace::kPrivate);
- auto* op = create<ast::UnaryOpExpression>(core::UnaryOp::kNegation, Expr("expr"));
- WrapInFunction(op);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitExpression(out, op)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "tint_unary_minus(expr)");
-}
-
-TEST_F(MslUnaryOpTest, IntMin) {
- auto* op = Expr(i32(std::numeric_limits<int32_t>::min()));
- WrapInFunction(op);
-
- ASTPrinter& gen = Build();
-
- StringStream out;
- ASSERT_TRUE(gen.EmitExpression(out, op)) << gen.Diagnostics();
- EXPECT_EQ(out.str(), "(-2147483647 - 1)");
-}
-
-} // namespace
-} // namespace tint::msl::writer
diff --git a/src/tint/lang/msl/writer/ast_printer/variable_decl_statement_test.cc b/src/tint/lang/msl/writer/ast_printer/variable_decl_statement_test.cc
deleted file mode 100644
index ba3a4f2..0000000
--- a/src/tint/lang/msl/writer/ast_printer/variable_decl_statement_test.cc
+++ /dev/null
@@ -1,563 +0,0 @@
-// Copyright 2020 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/tint/lang/wgsl/ast/variable_decl_statement.h"
-#include "gmock/gmock.h"
-#include "src/tint/lang/msl/writer/ast_printer/helper_test.h"
-
-namespace tint::msl::writer {
-namespace {
-
-using ::testing::HasSubstr;
-using namespace tint::core::fluent_types; // NOLINT
-using namespace tint::core::number_suffixes; // NOLINT
-
-using MslASTPrinterTest = TestHelper;
-
-TEST_F(MslASTPrinterTest, Emit_VariableDeclStatement) {
- auto* var = Var("a", ty.f32());
- auto* stmt = Decl(var);
- WrapInFunction(stmt);
-
- ASTPrinter& gen = Build();
-
- gen.IncrementIndent();
-
- ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), " float a = 0.0f;\n");
-}
-
-TEST_F(MslASTPrinterTest, Emit_VariableDeclStatement_Let) {
- auto* var = Let("a", ty.f32(), Call<f32>());
- auto* stmt = Decl(var);
- WrapInFunction(stmt);
-
- ASTPrinter& gen = Build();
-
- gen.IncrementIndent();
-
- ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), " float const a = 0.0f;\n");
-}
-
-TEST_F(MslASTPrinterTest, Emit_VariableDeclStatement_Const) {
- auto* var = Const("a", ty.f32(), Call<f32>());
- auto* stmt = Decl(var);
- WrapInFunction(stmt);
-
- ASTPrinter& gen = Build();
-
- gen.IncrementIndent();
-
- ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), ""); // Not a mistake - 'const' is inlined
-}
-
-TEST_F(MslASTPrinterTest, Emit_VariableDeclStatement_Const_AInt) {
- auto* C = Const("C", Expr(1_a));
- Func("f", tint::Empty, ty.void_(), Vector{Decl(C), Decl(Let("l", Expr(C)))});
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-void f() {
- int const l = 1;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_VariableDeclStatement_Const_AFloat) {
- auto* C = Const("C", Expr(1._a));
- Func("f", tint::Empty, ty.void_(), Vector{Decl(C), Decl(Let("l", Expr(C)))});
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-void f() {
- float const l = 1.0f;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_VariableDeclStatement_Const_i32) {
- auto* C = Const("C", Expr(1_i));
- Func("f", tint::Empty, ty.void_(), Vector{Decl(C), Decl(Let("l", Expr(C)))});
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-void f() {
- int const l = 1;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_VariableDeclStatement_Const_u32) {
- auto* C = Const("C", Expr(1_u));
- Func("f", tint::Empty, ty.void_(), Vector{Decl(C), Decl(Let("l", Expr(C)))});
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-void f() {
- uint const l = 1u;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_VariableDeclStatement_Const_f32) {
- auto* C = Const("C", Expr(1_f));
- Func("f", tint::Empty, ty.void_(), Vector{Decl(C), Decl(Let("l", Expr(C)))});
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-void f() {
- float const l = 1.0f;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_VariableDeclStatement_Const_f16) {
- Enable(wgsl::Extension::kF16);
-
- auto* C = Const("C", Expr(1_h));
- Func("f", tint::Empty, ty.void_(), Vector{Decl(C), Decl(Let("l", Expr(C)))});
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-void f() {
- half const l = 1.0h;
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_VariableDeclStatement_Const_vec3_AInt) {
- auto* C = Const("C", Call<vec3<Infer>>(1_a, 2_a, 3_a));
- Func("f", tint::Empty, ty.void_(), Vector{Decl(C), Decl(Let("l", Expr(C)))});
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-void f() {
- int3 const l = int3(1, 2, 3);
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_VariableDeclStatement_Const_vec3_AFloat) {
- auto* C = Const("C", Call<vec3<Infer>>(1._a, 2._a, 3._a));
- Func("f", tint::Empty, ty.void_(), Vector{Decl(C), Decl(Let("l", Expr(C)))});
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-void f() {
- float3 const l = float3(1.0f, 2.0f, 3.0f);
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_VariableDeclStatement_Const_vec3_f32) {
- auto* C = Const("C", Call<vec3<f32>>(1_f, 2_f, 3_f));
- Func("f", tint::Empty, ty.void_(), Vector{Decl(C), Decl(Let("l", Expr(C)))});
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-void f() {
- float3 const l = float3(1.0f, 2.0f, 3.0f);
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_VariableDeclStatement_Const_vec3_f16) {
- Enable(wgsl::Extension::kF16);
-
- auto* C = Const("C", Call<vec3<f16>>(1_h, 2_h, 3_h));
- Func("f", tint::Empty, ty.void_(), Vector{Decl(C), Decl(Let("l", Expr(C)))});
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-void f() {
- half3 const l = half3(1.0h, 2.0h, 3.0h);
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_VariableDeclStatement_Const_mat2x3_AFloat) {
- auto* C = Const("C", Call<mat2x3<Infer>>(1._a, 2._a, 3._a, 4._a, 5._a, 6._a));
- Func("f", tint::Empty, ty.void_(), Vector{Decl(C), Decl(Let("l", Expr(C)))});
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-void f() {
- float2x3 const l = float2x3(float3(1.0f, 2.0f, 3.0f), float3(4.0f, 5.0f, 6.0f));
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_VariableDeclStatement_Const_mat2x3_f32) {
- auto* C = Const("C", Call<mat2x3<f32>>(1_f, 2_f, 3_f, 4_f, 5_f, 6_f));
- Func("f", tint::Empty, ty.void_(), Vector{Decl(C), Decl(Let("l", Expr(C)))});
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-void f() {
- float2x3 const l = float2x3(float3(1.0f, 2.0f, 3.0f), float3(4.0f, 5.0f, 6.0f));
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_VariableDeclStatement_Const_mat2x3_f16) {
- Enable(wgsl::Extension::kF16);
-
- auto* C = Const("C", Call<mat2x3<f16>>(1_h, 2_h, 3_h, 4_h, 5_h, 6_h));
- Func("f", tint::Empty, ty.void_(), Vector{Decl(C), Decl(Let("l", Expr(C)))});
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-void f() {
- half2x3 const l = half2x3(half3(1.0h, 2.0h, 3.0h), half3(4.0h, 5.0h, 6.0h));
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_VariableDeclStatement_Const_arr_f32) {
- auto* C = Const("C", Call<array<f32, 3>>(1_f, 2_f, 3_f));
- Func("f", tint::Empty, ty.void_(), Vector{Decl(C), Decl(Let("l", Expr(C)))});
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-
-template<typename T, size_t N>
-struct tint_array {
- const constant T& operator[](size_t i) const constant { return elements[i]; }
- device T& operator[](size_t i) device { return elements[i]; }
- const device T& operator[](size_t i) const device { return elements[i]; }
- thread T& operator[](size_t i) thread { return elements[i]; }
- const thread T& operator[](size_t i) const thread { return elements[i]; }
- threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
- const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
- T elements[N];
-};
-
-void f() {
- tint_array<float, 3> const l = tint_array<float, 3>{1.0f, 2.0f, 3.0f};
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_VariableDeclStatement_Const_arr_vec2_bool) {
- auto* C = Const("C", Call<array<vec2<bool>, 3>>( //
- Call<vec2<bool>>(true, false), //
- Call<vec2<bool>>(false, true), //
- Call<vec2<bool>>(true, true)));
- Func("f", tint::Empty, ty.void_(), Vector{Decl(C), Decl(Let("l", Expr(C)))});
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
-
- EXPECT_EQ(gen.Result(), R"(#include <metal_stdlib>
-
-using namespace metal;
-
-template<typename T, size_t N>
-struct tint_array {
- const constant T& operator[](size_t i) const constant { return elements[i]; }
- device T& operator[](size_t i) device { return elements[i]; }
- const device T& operator[](size_t i) const device { return elements[i]; }
- thread T& operator[](size_t i) thread { return elements[i]; }
- const thread T& operator[](size_t i) const thread { return elements[i]; }
- threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
- const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
- T elements[N];
-};
-
-void f() {
- tint_array<bool2, 3> const l = tint_array<bool2, 3>{bool2(true, false), bool2(false, true), bool2(true)};
-}
-
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_VariableDeclStatement_Array) {
- auto* var = Var("a", ty.array<f32, 5>());
- auto* stmt = Decl(var);
- WrapInFunction(stmt);
-
- ASTPrinter& gen = Build();
-
- gen.IncrementIndent();
-
- ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), " tint_array<float, 5> a = {};\n");
-}
-
-TEST_F(MslASTPrinterTest, Emit_VariableDeclStatement_Struct) {
- auto* s = Structure("S", Vector{
- Member("a", ty.f32()),
- Member("b", ty.f32()),
- });
-
- auto* var = Var("a", ty.Of(s));
- auto* stmt = Decl(var);
- WrapInFunction(stmt);
-
- ASTPrinter& gen = Build();
-
- gen.IncrementIndent();
-
- ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"( S a = {};
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_VariableDeclStatement_Vector_f32) {
- auto* var = Var("a", ty.vec2<f32>());
- auto* stmt = Decl(var);
- WrapInFunction(stmt);
-
- ASTPrinter& gen = Build();
-
- gen.IncrementIndent();
-
- ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), " float2 a = 0.0f;\n");
-}
-
-TEST_F(MslASTPrinterTest, Emit_VariableDeclStatement_Vector_f16) {
- Enable(wgsl::Extension::kF16);
-
- auto* var = Var("a", ty.vec2<f16>());
- auto* stmt = Decl(var);
- WrapInFunction(stmt);
-
- ASTPrinter& gen = Build();
-
- gen.IncrementIndent();
-
- ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), " half2 a = 0.0h;\n");
-}
-
-TEST_F(MslASTPrinterTest, Emit_VariableDeclStatement_Matrix_f32) {
- auto* var = Var("a", ty.mat3x2<f32>());
-
- auto* stmt = Decl(var);
- WrapInFunction(stmt);
-
- ASTPrinter& gen = Build();
-
- gen.IncrementIndent();
-
- ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), " float3x2 a = float3x2(0.0f);\n");
-}
-
-TEST_F(MslASTPrinterTest, Emit_VariableDeclStatement_Matrix_f16) {
- Enable(wgsl::Extension::kF16);
-
- auto* var = Var("a", ty.mat3x2<f16>());
-
- auto* stmt = Decl(var);
- WrapInFunction(stmt);
-
- ASTPrinter& gen = Build();
-
- gen.IncrementIndent();
-
- ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), " half3x2 a = half3x2(0.0h);\n");
-}
-
-TEST_F(MslASTPrinterTest, Emit_VariableDeclStatement_Initializer_ZeroVec_f32) {
- auto* var = Var("a", ty.vec3<f32>(), Call<vec3<f32>>());
-
- auto* stmt = Decl(var);
- WrapInFunction(stmt);
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(float3 a = float3(0.0f);
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_VariableDeclStatement_Initializer_ZeroVec_f16) {
- Enable(wgsl::Extension::kF16);
-
- auto* var = Var("a", ty.vec3<f16>(), Call<vec3<f16>>());
-
- auto* stmt = Decl(var);
- WrapInFunction(stmt);
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(half3 a = half3(0.0h);
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_VariableDeclStatement_Initializer_ZeroMat_f32) {
- auto* var = Var("a", ty.mat2x3<f32>(), Call<mat2x3<f32>>());
-
- auto* stmt = Decl(var);
- WrapInFunction(stmt);
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(),
- R"(float2x3 a = float2x3(float3(0.0f), float3(0.0f));
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_VariableDeclStatement_Initializer_ZeroMat_f16) {
- Enable(wgsl::Extension::kF16);
-
- auto* var = Var("a", ty.mat2x3<f16>(), Call<mat2x3<f16>>());
-
- auto* stmt = Decl(var);
- WrapInFunction(stmt);
-
- ASTPrinter& gen = Build();
-
- ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(),
- R"(half2x3 a = half2x3(half3(0.0h), half3(0.0h));
-)");
-}
-
-TEST_F(MslASTPrinterTest, Emit_VariableDeclStatement_Private) {
- GlobalVar("a", ty.f32(), core::AddressSpace::kPrivate);
-
- WrapInFunction(Expr("a"));
-
- ASTPrinter& gen = SanitizeAndBuild();
-
- gen.IncrementIndent();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_THAT(gen.Result(), HasSubstr(R"(thread tint_private_vars_struct tint_private_vars = {};
- float const tint_symbol = tint_private_vars.a;
- return;
-)"));
-}
-
-TEST_F(MslASTPrinterTest, Emit_VariableDeclStatement_Workgroup) {
- GlobalVar("a", ty.f32(), core::AddressSpace::kWorkgroup);
-
- WrapInFunction(Expr("a"));
-
- ASTPrinter& gen = SanitizeAndBuild();
-
- gen.IncrementIndent();
-
- ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
- EXPECT_THAT(gen.Result(), HasSubstr("threadgroup float tint_symbol_"));
-}
-
-} // namespace
-} // namespace tint::msl::writer
diff --git a/src/tint/lang/msl/writer/ast_raise/BUILD.bazel b/src/tint/lang/msl/writer/ast_raise/BUILD.bazel
deleted file mode 100644
index f832b43..0000000
--- a/src/tint/lang/msl/writer/ast_raise/BUILD.bazel
+++ /dev/null
@@ -1,177 +0,0 @@
-# Copyright 2023 The Dawn & Tint Authors
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#
-# 1. Redistributions of source code must retain the above copyright notice, this
-# list of conditions and the following disclaimer.
-#
-# 2. Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# 3. Neither the name of the copyright holder nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-################################################################################
-# File generated by 'tools/src/cmd/gen' using the template:
-# tools/src/cmd/gen/build/BUILD.bazel.tmpl
-#
-# To regenerate run: './tools/run gen'
-#
-# Do not modify this file directly
-################################################################################
-
-load("//src/tint:flags.bzl", "COPTS")
-load("@bazel_skylib//lib:selects.bzl", "selects")
-cc_library(
- name = "ast_raise",
- srcs = [
- "module_scope_var_to_entry_point_param.cc",
- "packed_vec3.cc",
- "pixel_local.cc",
- "quad_swap.cc",
- "subgroup_ballot.cc",
- ],
- hdrs = [
- "module_scope_var_to_entry_point_param.h",
- "packed_vec3.h",
- "pixel_local.h",
- "quad_swap.h",
- "subgroup_ballot.h",
- ],
- deps = [
- "//src/tint/api/common",
- "//src/tint/lang/core",
- "//src/tint/lang/core/constant",
- "//src/tint/lang/core/type",
- "//src/tint/lang/wgsl",
- "//src/tint/lang/wgsl/ast",
- "//src/tint/lang/wgsl/ast/transform",
- "//src/tint/lang/wgsl/common",
- "//src/tint/lang/wgsl/features",
- "//src/tint/lang/wgsl/program",
- "//src/tint/lang/wgsl/resolver",
- "//src/tint/lang/wgsl/sem",
- "//src/tint/utils",
- "//src/tint/utils/containers",
- "//src/tint/utils/diagnostic",
- "//src/tint/utils/ice",
- "//src/tint/utils/macros",
- "//src/tint/utils/math",
- "//src/tint/utils/memory",
- "//src/tint/utils/result",
- "//src/tint/utils/rtti",
- "//src/tint/utils/symbol",
- "//src/tint/utils/text",
- "//src/utils",
- ],
- copts = COPTS,
- visibility = ["//visibility:public"],
-)
-cc_library(
- name = "test",
- alwayslink = True,
- srcs = [
- "module_scope_var_to_entry_point_param_test.cc",
- "packed_vec3_test.cc",
- "pixel_local_test.cc",
- "quad_swap_test.cc",
- "subgroup_ballot_test.cc",
- ],
- deps = [
- "//src/tint/api/common",
- "//src/tint/lang/core",
- "//src/tint/lang/core/constant",
- "//src/tint/lang/core/ir",
- "//src/tint/lang/core/type",
- "//src/tint/lang/wgsl",
- "//src/tint/lang/wgsl/ast",
- "//src/tint/lang/wgsl/ast/transform",
- "//src/tint/lang/wgsl/common",
- "//src/tint/lang/wgsl/features",
- "//src/tint/lang/wgsl/program",
- "//src/tint/lang/wgsl/resolver",
- "//src/tint/lang/wgsl/sem",
- "//src/tint/lang/wgsl/writer/ir_to_program",
- "//src/tint/utils",
- "//src/tint/utils/containers",
- "//src/tint/utils/diagnostic",
- "//src/tint/utils/ice",
- "//src/tint/utils/macros",
- "//src/tint/utils/math",
- "//src/tint/utils/memory",
- "//src/tint/utils/result",
- "//src/tint/utils/rtti",
- "//src/tint/utils/symbol",
- "//src/tint/utils/text",
- "@gtest",
- "//src/utils",
- ] + select({
- ":tint_build_msl_writer": [
- "//src/tint/lang/msl/writer/ast_raise",
- ],
- "//conditions:default": [],
- }) + select({
- ":tint_build_wgsl_reader": [
- "//src/tint/lang/wgsl/reader",
- ],
- "//conditions:default": [],
- }) + select({
- ":tint_build_wgsl_reader_and_tint_build_wgsl_writer": [
- "//src/tint/lang/wgsl/ast/transform:test",
- ],
- "//conditions:default": [],
- }) + select({
- ":tint_build_wgsl_writer": [
- "//src/tint/lang/wgsl/writer",
- ],
- "//conditions:default": [],
- }),
- copts = COPTS,
- visibility = ["//visibility:public"],
-)
-
-alias(
- name = "tint_build_msl_writer",
- actual = "//src/tint:tint_build_msl_writer_true",
-)
-
-alias(
- name = "tint_build_wgsl_reader",
- actual = "//src/tint:tint_build_wgsl_reader_true",
-)
-
-alias(
- name = "tint_build_wgsl_writer",
- actual = "//src/tint:tint_build_wgsl_writer_true",
-)
-
-selects.config_setting_group(
- name = "tint_build_msl_writer_and_tint_build_wgsl_reader_and_tint_build_wgsl_writer",
- match_all = [
- ":tint_build_msl_writer",
- ":tint_build_wgsl_reader",
- ":tint_build_wgsl_writer",
- ],
-)
-selects.config_setting_group(
- name = "tint_build_wgsl_reader_and_tint_build_wgsl_writer",
- match_all = [
- ":tint_build_wgsl_reader",
- ":tint_build_wgsl_writer",
- ],
-)
-
diff --git a/src/tint/lang/msl/writer/ast_raise/BUILD.cfg b/src/tint/lang/msl/writer/ast_raise/BUILD.cfg
deleted file mode 100644
index 98cff52..0000000
--- a/src/tint/lang/msl/writer/ast_raise/BUILD.cfg
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "condition": "tint_build_msl_writer",
- "test": {
- "condition": "tint_build_wgsl_reader && tint_build_wgsl_writer",
- }
-}
diff --git a/src/tint/lang/msl/writer/ast_raise/BUILD.cmake b/src/tint/lang/msl/writer/ast_raise/BUILD.cmake
deleted file mode 100644
index 266c257..0000000
--- a/src/tint/lang/msl/writer/ast_raise/BUILD.cmake
+++ /dev/null
@@ -1,158 +0,0 @@
-# Copyright 2023 The Dawn & Tint Authors
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#
-# 1. Redistributions of source code must retain the above copyright notice, this
-# list of conditions and the following disclaimer.
-#
-# 2. Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# 3. Neither the name of the copyright holder nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-################################################################################
-# File generated by 'tools/src/cmd/gen' using the template:
-# tools/src/cmd/gen/build/BUILD.cmake.tmpl
-#
-# To regenerate run: './tools/run gen'
-#
-# Do not modify this file directly
-################################################################################
-
-if(TINT_BUILD_MSL_WRITER)
-################################################################################
-# Target: tint_lang_msl_writer_ast_raise
-# Kind: lib
-# Condition: TINT_BUILD_MSL_WRITER
-################################################################################
-tint_add_target(tint_lang_msl_writer_ast_raise lib
- lang/msl/writer/ast_raise/module_scope_var_to_entry_point_param.cc
- lang/msl/writer/ast_raise/module_scope_var_to_entry_point_param.h
- lang/msl/writer/ast_raise/packed_vec3.cc
- lang/msl/writer/ast_raise/packed_vec3.h
- lang/msl/writer/ast_raise/pixel_local.cc
- lang/msl/writer/ast_raise/pixel_local.h
- lang/msl/writer/ast_raise/quad_swap.cc
- lang/msl/writer/ast_raise/quad_swap.h
- lang/msl/writer/ast_raise/subgroup_ballot.cc
- lang/msl/writer/ast_raise/subgroup_ballot.h
-)
-
-tint_target_add_dependencies(tint_lang_msl_writer_ast_raise lib
- tint_api_common
- tint_lang_core
- tint_lang_core_constant
- tint_lang_core_type
- tint_lang_wgsl
- tint_lang_wgsl_ast
- tint_lang_wgsl_ast_transform
- tint_lang_wgsl_common
- tint_lang_wgsl_features
- tint_lang_wgsl_program
- tint_lang_wgsl_resolver
- tint_lang_wgsl_sem
- tint_utils
- tint_utils_containers
- tint_utils_diagnostic
- tint_utils_ice
- tint_utils_macros
- tint_utils_math
- tint_utils_memory
- tint_utils_result
- tint_utils_rtti
- tint_utils_symbol
- tint_utils_text
-)
-
-tint_target_add_external_dependencies(tint_lang_msl_writer_ast_raise lib
- "src_utils"
-)
-
-endif(TINT_BUILD_MSL_WRITER)
-if(TINT_BUILD_MSL_WRITER AND TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
-################################################################################
-# Target: tint_lang_msl_writer_ast_raise_test
-# Kind: test
-# Condition: TINT_BUILD_MSL_WRITER AND TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER
-################################################################################
-tint_add_target(tint_lang_msl_writer_ast_raise_test test
- lang/msl/writer/ast_raise/module_scope_var_to_entry_point_param_test.cc
- lang/msl/writer/ast_raise/packed_vec3_test.cc
- lang/msl/writer/ast_raise/pixel_local_test.cc
- lang/msl/writer/ast_raise/quad_swap_test.cc
- lang/msl/writer/ast_raise/subgroup_ballot_test.cc
-)
-
-tint_target_add_dependencies(tint_lang_msl_writer_ast_raise_test test
- tint_api_common
- tint_lang_core
- tint_lang_core_constant
- tint_lang_core_ir
- tint_lang_core_type
- tint_lang_wgsl
- tint_lang_wgsl_ast
- tint_lang_wgsl_ast_transform
- tint_lang_wgsl_common
- tint_lang_wgsl_features
- tint_lang_wgsl_program
- tint_lang_wgsl_resolver
- tint_lang_wgsl_sem
- tint_lang_wgsl_writer_ir_to_program
- tint_utils
- tint_utils_containers
- tint_utils_diagnostic
- tint_utils_ice
- tint_utils_macros
- tint_utils_math
- tint_utils_memory
- tint_utils_result
- tint_utils_rtti
- tint_utils_symbol
- tint_utils_text
-)
-
-tint_target_add_external_dependencies(tint_lang_msl_writer_ast_raise_test test
- "gtest"
- "src_utils"
-)
-
-if(TINT_BUILD_MSL_WRITER)
- tint_target_add_dependencies(tint_lang_msl_writer_ast_raise_test test
- tint_lang_msl_writer_ast_raise
- )
-endif(TINT_BUILD_MSL_WRITER)
-
-if(TINT_BUILD_WGSL_READER)
- tint_target_add_dependencies(tint_lang_msl_writer_ast_raise_test test
- tint_lang_wgsl_reader
- )
-endif(TINT_BUILD_WGSL_READER)
-
-if(TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
- tint_target_add_dependencies(tint_lang_msl_writer_ast_raise_test test
- tint_lang_wgsl_ast_transform_test
- )
-endif(TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
-
-if(TINT_BUILD_WGSL_WRITER)
- tint_target_add_dependencies(tint_lang_msl_writer_ast_raise_test test
- tint_lang_wgsl_writer
- )
-endif(TINT_BUILD_WGSL_WRITER)
-
-endif(TINT_BUILD_MSL_WRITER AND TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER)
\ No newline at end of file
diff --git a/src/tint/lang/msl/writer/ast_raise/BUILD.gn b/src/tint/lang/msl/writer/ast_raise/BUILD.gn
deleted file mode 100644
index 6be3773..0000000
--- a/src/tint/lang/msl/writer/ast_raise/BUILD.gn
+++ /dev/null
@@ -1,145 +0,0 @@
-# Copyright 2023 The Dawn & Tint Authors
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#
-# 1. Redistributions of source code must retain the above copyright notice, this
-# list of conditions and the following disclaimer.
-#
-# 2. Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# 3. Neither the name of the copyright holder nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-################################################################################
-# File generated by 'tools/src/cmd/gen' using the template:
-# tools/src/cmd/gen/build/BUILD.gn.tmpl
-#
-# To regenerate run: './tools/run gen'
-#
-# Do not modify this file directly
-################################################################################
-
-import("../../../../../../scripts/dawn_overrides_with_defaults.gni")
-import("../../../../../../scripts/tint_overrides_with_defaults.gni")
-
-import("${tint_src_dir}/tint.gni")
-
-if (tint_build_unittests || tint_build_benchmarks) {
- import("//testing/test.gni")
-}
-if (tint_build_msl_writer) {
- libtint_source_set("ast_raise") {
- sources = [
- "module_scope_var_to_entry_point_param.cc",
- "module_scope_var_to_entry_point_param.h",
- "packed_vec3.cc",
- "packed_vec3.h",
- "pixel_local.cc",
- "pixel_local.h",
- "quad_swap.cc",
- "quad_swap.h",
- "subgroup_ballot.cc",
- "subgroup_ballot.h",
- ]
- deps = [
- "${dawn_root}/src/utils:utils",
- "${tint_src_dir}/api/common",
- "${tint_src_dir}/lang/core",
- "${tint_src_dir}/lang/core/constant",
- "${tint_src_dir}/lang/core/type",
- "${tint_src_dir}/lang/wgsl",
- "${tint_src_dir}/lang/wgsl/ast",
- "${tint_src_dir}/lang/wgsl/ast/transform",
- "${tint_src_dir}/lang/wgsl/common",
- "${tint_src_dir}/lang/wgsl/features",
- "${tint_src_dir}/lang/wgsl/program",
- "${tint_src_dir}/lang/wgsl/resolver",
- "${tint_src_dir}/lang/wgsl/sem",
- "${tint_src_dir}/utils",
- "${tint_src_dir}/utils/containers",
- "${tint_src_dir}/utils/diagnostic",
- "${tint_src_dir}/utils/ice",
- "${tint_src_dir}/utils/macros",
- "${tint_src_dir}/utils/math",
- "${tint_src_dir}/utils/memory",
- "${tint_src_dir}/utils/result",
- "${tint_src_dir}/utils/rtti",
- "${tint_src_dir}/utils/symbol",
- "${tint_src_dir}/utils/text",
- ]
- }
-}
-if (tint_build_unittests) {
- if (tint_build_msl_writer && tint_build_wgsl_reader &&
- tint_build_wgsl_writer) {
- tint_unittests_source_set("unittests") {
- sources = [
- "module_scope_var_to_entry_point_param_test.cc",
- "packed_vec3_test.cc",
- "pixel_local_test.cc",
- "quad_swap_test.cc",
- "subgroup_ballot_test.cc",
- ]
- deps = [
- "${dawn_root}/src/utils:utils",
- "${tint_src_dir}:gmock_and_gtest",
- "${tint_src_dir}/api/common",
- "${tint_src_dir}/lang/core",
- "${tint_src_dir}/lang/core/constant",
- "${tint_src_dir}/lang/core/ir",
- "${tint_src_dir}/lang/core/type",
- "${tint_src_dir}/lang/wgsl",
- "${tint_src_dir}/lang/wgsl/ast",
- "${tint_src_dir}/lang/wgsl/ast/transform",
- "${tint_src_dir}/lang/wgsl/common",
- "${tint_src_dir}/lang/wgsl/features",
- "${tint_src_dir}/lang/wgsl/program",
- "${tint_src_dir}/lang/wgsl/resolver",
- "${tint_src_dir}/lang/wgsl/sem",
- "${tint_src_dir}/lang/wgsl/writer/ir_to_program",
- "${tint_src_dir}/utils",
- "${tint_src_dir}/utils/containers",
- "${tint_src_dir}/utils/diagnostic",
- "${tint_src_dir}/utils/ice",
- "${tint_src_dir}/utils/macros",
- "${tint_src_dir}/utils/math",
- "${tint_src_dir}/utils/memory",
- "${tint_src_dir}/utils/result",
- "${tint_src_dir}/utils/rtti",
- "${tint_src_dir}/utils/symbol",
- "${tint_src_dir}/utils/text",
- ]
-
- if (tint_build_msl_writer) {
- deps += [ "${tint_src_dir}/lang/msl/writer/ast_raise" ]
- }
-
- if (tint_build_wgsl_reader) {
- deps += [ "${tint_src_dir}/lang/wgsl/reader" ]
- }
-
- if (tint_build_wgsl_reader && tint_build_wgsl_writer) {
- deps += [ "${tint_src_dir}/lang/wgsl/ast/transform:unittests" ]
- }
-
- if (tint_build_wgsl_writer) {
- deps += [ "${tint_src_dir}/lang/wgsl/writer" ]
- }
- }
- }
-}
diff --git a/src/tint/lang/msl/writer/ast_raise/module_scope_var_to_entry_point_param.cc b/src/tint/lang/msl/writer/ast_raise/module_scope_var_to_entry_point_param.cc
deleted file mode 100644
index c1bde6c..0000000
--- a/src/tint/lang/msl/writer/ast_raise/module_scope_var_to_entry_point_param.cc
+++ /dev/null
@@ -1,612 +0,0 @@
-// Copyright 2021 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/tint/lang/msl/writer/ast_raise/module_scope_var_to_entry_point_param.h"
-
-#include <unordered_map>
-#include <unordered_set>
-#include <utility>
-
-#include "src/tint/lang/wgsl/ast/disable_validation_attribute.h"
-#include "src/tint/lang/wgsl/program/clone_context.h"
-#include "src/tint/lang/wgsl/program/program_builder.h"
-#include "src/tint/lang/wgsl/resolver/resolve.h"
-#include "src/tint/lang/wgsl/sem/call.h"
-#include "src/tint/lang/wgsl/sem/function.h"
-#include "src/tint/lang/wgsl/sem/module.h"
-#include "src/tint/lang/wgsl/sem/statement.h"
-#include "src/tint/lang/wgsl/sem/struct.h"
-#include "src/tint/lang/wgsl/sem/variable.h"
-#include "src/tint/utils/text/string.h"
-
-TINT_INSTANTIATE_TYPEINFO(tint::msl::writer::ModuleScopeVarToEntryPointParam);
-
-using namespace tint::core::fluent_types; // NOLINT
-
-namespace tint::msl::writer {
-namespace {
-
-using StructMemberList = tint::Vector<const ast::StructMember*, 8>;
-
-// The name of the struct member for arrays that are wrapped in structures.
-const char* kWrappedArrayMemberName = "arr";
-
-bool ShouldRun(const Program& program) {
- for (auto* decl : program.AST().GlobalDeclarations()) {
- if (decl->Is<ast::Variable>()) {
- return true;
- }
- }
- return false;
-}
-
-// Returns `true` if `type` is or contains a matrix type.
-bool ContainsMatrix(const core::type::Type* type) {
- type = type->UnwrapRef();
- if (type->Is<core::type::Matrix>()) {
- return true;
- } else if (auto* ary = type->As<core::type::Array>()) {
- return ContainsMatrix(ary->ElemType());
- } else if (auto* str = type->As<core::type::Struct>()) {
- for (auto* member : str->Members()) {
- if (ContainsMatrix(member->Type())) {
- return true;
- }
- }
- }
- return false;
-}
-} // namespace
-
-/// PIMPL state for the transform
-struct ModuleScopeVarToEntryPointParam::State {
- /// The clone context.
- program::CloneContext& ctx;
-
- /// Constructor
- /// @param context the clone context
- explicit State(program::CloneContext& context) : ctx(context) {}
-
- /// Clone any struct types that are contained in `ty` (including `ty` itself),
- /// and add it to the global declarations now, so that they precede new global
- /// declarations that need to reference them.
- /// @param ty the type to clone
- void CloneStructTypes(const core::type::Type* ty) {
- if (auto* str = ty->As<sem::Struct>()) {
- if (!cloned_structs_.emplace(str).second) {
- // The struct has already been cloned.
- return;
- }
-
- // Recurse into members.
- for (auto* member : str->Members()) {
- CloneStructTypes(member->Type());
- }
-
- // Clone the struct and add it to the global declaration list.
- // Remove the old declaration.
- auto* ast_str = str->Declaration();
- ctx.dst->AST().AddTypeDecl(ctx.Clone(ast_str));
- ctx.Remove(ctx.src->AST().GlobalDeclarations(), ast_str);
- } else if (auto* arr = ty->As<core::type::Array>()) {
- CloneStructTypes(arr->ElemType());
- }
- }
-
- /// Process a variable `var` that is referenced in the entry point function `func`.
- /// This will redeclare the variable as a function parameter, possibly as a pointer.
- /// Some workgroup variables will be redeclared as a member inside a workgroup structure.
- /// @param func the entry point function
- /// @param var the variable
- /// @param new_var_symbol the symbol to use for the replacement
- /// @param workgroup_param helper function to get a symbol to a workgroup struct parameter
- /// @param workgroup_parameter_members reference to a list of a workgroup struct members
- /// @param is_pointer output signalling whether the replacement is a pointer
- /// @param is_wrapped output signalling whether the replacement is wrapped in a struct
- void ProcessVariableInEntryPoint(const ast::Function* func,
- const sem::Variable* var,
- Symbol new_var_symbol,
- std::function<Symbol()> workgroup_param,
- StructMemberList& workgroup_parameter_members,
- bool& is_pointer,
- bool& is_wrapped) {
- auto* ty = var->Type()->UnwrapRef();
-
- // Helper to create an AST node for the store type of the variable.
- auto store_type = [&] { return CreateASTTypeFor(ctx, ty); };
-
- core::AddressSpace sc = var->AddressSpace();
- switch (sc) {
- case core::AddressSpace::kHandle: {
- // For a texture or sampler variable, redeclare it as an entry point parameter.
- // Disable entry point parameter validation.
- auto* disable_validation =
- ctx.dst->Disable(ast::DisabledValidation::kEntryPointParameter);
- auto attrs = ctx.Clone(var->Declaration()->attributes);
- attrs.Push(disable_validation);
- auto* param = ctx.dst->Param(new_var_symbol, store_type(), attrs);
- ctx.InsertFront(func->params, param);
-
- break;
- }
- case core::AddressSpace::kStorage:
- case core::AddressSpace::kUniform: {
- // Variables into the Storage and Uniform address spaces are redeclared as entry
- // point parameters with a pointer type.
- auto attributes = ctx.Clone(var->Declaration()->attributes);
- attributes.Push(ctx.dst->Disable(ast::DisabledValidation::kEntryPointParameter));
- attributes.Push(ctx.dst->Disable(ast::DisabledValidation::kIgnoreAddressSpace));
-
- auto param_type = store_type();
- if (auto* arr = ty->As<core::type::Array>();
- arr && arr->Count()->Is<core::type::RuntimeArrayCount>()) {
- // Wrap runtime-sized arrays in structures, so that we can declare pointers to
- // them. Ideally we'd just emit the array itself as a pointer, but this is not
- // representable in Tint's AST.
- CloneStructTypes(ty);
- auto* wrapper = ctx.dst->Structure(
- ctx.dst->Sym(), tint::Vector{
- ctx.dst->Member(kWrappedArrayMemberName, param_type),
- });
- param_type = ctx.dst->ty.Of(wrapper);
- is_wrapped = true;
- }
-
- param_type = sc == core::AddressSpace::kStorage
- ? ctx.dst->ty.ptr(sc, param_type, var->Access())
- : ctx.dst->ty.ptr(sc, param_type);
- auto* param = ctx.dst->Param(new_var_symbol, param_type, attributes);
- ctx.InsertFront(func->params, param);
- is_pointer = true;
-
- break;
- }
- case core::AddressSpace::kWorkgroup: {
- if (ContainsMatrix(var->Type())) {
- // Due to a bug in the MSL compiler, we use a threadgroup memory argument for
- // any workgroup allocation that contains a matrix. See crbug.com/tint/938.
- // TODO(jrprice): Do this for all other workgroup variables too.
-
- // Create a member in the workgroup parameter struct.
- auto member = ctx.Clone(var->Declaration()->name->symbol);
- workgroup_parameter_members.Push(ctx.dst->Member(member, store_type()));
- CloneStructTypes(var->Type()->UnwrapRef());
-
- // Create a function-scope variable that is a pointer to the member.
- auto* member_ptr = ctx.dst->AddressOf(
- ctx.dst->MemberAccessor(ctx.dst->Deref(workgroup_param()), member));
- auto* local_var = ctx.dst->Let(new_var_symbol, member_ptr);
- ctx.InsertFront(func->body->statements, ctx.dst->Decl(local_var));
- is_pointer = true;
- } else {
- auto* disable_validation =
- ctx.dst->Disable(ast::DisabledValidation::kIgnoreAddressSpace);
- auto* initializer = ctx.Clone(var->Declaration()->initializer);
- auto* local_var = ctx.dst->Var(new_var_symbol, store_type(), sc, initializer,
- tint::Vector{disable_validation});
- ctx.InsertFront(func->body->statements, ctx.dst->Decl(local_var));
- }
- break;
- }
- case core::AddressSpace::kPixelLocal:
- break; // Ignore
- default: {
- TINT_ICE() << "unhandled module-scope address space (" << sc << ")";
- }
- }
- }
-
- /// Process a variable `var` that is referenced in the user-defined function `func`.
- /// This will redeclare the variable as a function parameter, possibly as a pointer.
- /// @param func the user-defined function
- /// @param var the variable
- /// @param new_var_symbol the symbol to use for the replacement
- /// @param is_pointer output signalling whether the replacement is a pointer or not
- void ProcessVariableInUserFunction(const ast::Function* func,
- const sem::Variable* var,
- Symbol new_var_symbol,
- bool& is_pointer) {
- auto* ty = var->Type()->UnwrapRef();
- auto param_type = CreateASTTypeFor(ctx, ty);
- auto sc = var->AddressSpace();
- switch (sc) {
- case core::AddressSpace::kPrivate:
- // Private variables are passed all together in a struct.
- return;
- case core::AddressSpace::kStorage:
- case core::AddressSpace::kUniform:
- case core::AddressSpace::kHandle:
- case core::AddressSpace::kWorkgroup:
- break;
- case core::AddressSpace::kPushConstant: {
- ctx.dst->Diagnostics().AddError(Source{})
- << "unhandled module-scope address space (" << sc << ")";
- break;
- }
- default: {
- TINT_ICE() << "unhandled module-scope address space (" << sc << ")";
- }
- }
-
- // Use a pointer for non-handle types.
- tint::Vector<const ast::Attribute*, 2> attributes;
- if (!ty->IsHandle()) {
- param_type = sc == core::AddressSpace::kStorage
- ? ctx.dst->ty.ptr(sc, param_type, var->Access())
- : ctx.dst->ty.ptr(sc, param_type);
- is_pointer = true;
-
- // Disable validation of the parameter's address space and of arguments passed to it.
- attributes.Push(ctx.dst->Disable(ast::DisabledValidation::kIgnoreAddressSpace));
- attributes.Push(
- ctx.dst->Disable(ast::DisabledValidation::kIgnoreInvalidPointerArgument));
- }
-
- // Redeclare the variable as a parameter.
- ctx.InsertBack(func->params,
- ctx.dst->Param(new_var_symbol, param_type, std::move(attributes)));
- }
-
- /// Replace all uses of `var` in `func` with references to `new_var`.
- /// @param func the function
- /// @param var the variable to replace
- /// @param new_var the symbol to use for replacement
- /// @param is_pointer true if `new_var` is a pointer to the new variable
- /// @param member_name if valid, the name of the struct member that holds this variable
- void ReplaceUsesInFunction(const ast::Function* func,
- const sem::Variable* var,
- Symbol new_var,
- bool is_pointer,
- Symbol member_name) {
- for (auto* user : var->Users()) {
- if (user->Stmt()->Function()->Declaration() == func) {
- const ast::Expression* expr = ctx.dst->Expr(new_var);
- if (is_pointer) {
- // If this identifier is used by an address-of operator, just remove the
- // address-of instead of adding a deref, since we already have a pointer.
- auto* ident = user->Declaration()->As<ast::IdentifierExpression>();
- if (ident_to_address_of_.count(ident) && !member_name.IsValid()) {
- ctx.Replace(ident_to_address_of_[ident], expr);
- continue;
- }
-
- expr = ctx.dst->Deref(expr);
- }
- if (member_name.IsValid()) {
- // Get the member from the containing structure.
- expr = ctx.dst->MemberAccessor(expr, member_name);
- }
- ctx.Replace(user->Declaration(), expr);
- }
- }
- }
-
- /// Process the module.
- void Process() {
- // Predetermine the list of function calls that need to be replaced.
- using CallList = tint::Vector<const ast::CallExpression*, 8>;
- std::unordered_map<const ast::Function*, CallList> calls_to_replace;
-
- tint::Vector<const ast::Function*, 8> functions_to_process;
-
- // Collect private variables into a single structure.
- StructMemberList private_struct_members;
- tint::Vector<std::function<const ast::AssignmentStatement*()>, 4> private_initializers;
- std::unordered_set<const ast::Function*> uses_privates;
-
- // Build a list of functions that transitively reference any module-scope variables.
- for (auto* decl : ctx.src->Sem().Module()->DependencyOrderedDeclarations()) {
- if (auto* var = decl->As<ast::Var>()) {
- auto* sem_var = ctx.src->Sem().Get(var);
- if (sem_var->AddressSpace() == core::AddressSpace::kPrivate) {
- // Create a member in the private variable struct.
- auto* ty = sem_var->Type()->UnwrapRef();
- auto name = ctx.Clone(var->name->symbol);
- private_struct_members.Push(ctx.dst->Member(name, CreateASTTypeFor(ctx, ty)));
- CloneStructTypes(ty);
-
- // Create a statement to assign the initializer if present.
- if (var->initializer) {
- private_initializers.Push([&, name, var] {
- return ctx.dst->Assign(
- ctx.dst->MemberAccessor(PrivateStructVariableName(), name),
- ctx.Clone(var->initializer));
- });
- }
- }
- continue;
- }
-
- auto* func_ast = decl->As<ast::Function>();
- if (!func_ast) {
- continue;
- }
-
- auto* func_sem = ctx.src->Sem().Get(func_ast);
-
- bool needs_processing = false;
- for (auto* var : func_sem->TransitivelyReferencedGlobals()) {
- if (var->AddressSpace() != core::AddressSpace::kUndefined) {
- if (var->AddressSpace() == core::AddressSpace::kPrivate) {
- uses_privates.insert(func_ast);
- }
- needs_processing = true;
- }
- }
- if (needs_processing) {
- functions_to_process.Push(func_ast);
-
- // Find all of the calls to this function that will need to be replaced.
- for (auto* call : func_sem->CallSites()) {
- calls_to_replace[call->Stmt()->Function()->Declaration()].Push(
- call->Declaration());
- }
- }
- }
-
- if (!private_struct_members.IsEmpty()) {
- // Create the private variable struct.
- ctx.dst->Structure(PrivateStructName(), std::move(private_struct_members));
- }
-
- // Build a list of `&ident` expressions. We'll use this later to avoid generating
- // expressions of the form `&*ident`, which break WGSL validation rules when this expression
- // is passed to a function.
- // TODO(jrprice): We should add support for bidirectional SEM tree traversal so that we can
- // do this on the fly instead.
- for (auto* node : ctx.src->ASTNodes().Objects()) {
- auto* address_of = node->As<ast::UnaryOpExpression>();
- if (!address_of || address_of->op != core::UnaryOp::kAddressOf) {
- continue;
- }
- if (auto* ident = address_of->expr->As<ast::IdentifierExpression>()) {
- ident_to_address_of_[ident] = address_of;
- }
- }
-
- for (auto* func_ast : functions_to_process) {
- auto* func_sem = ctx.src->Sem().Get(func_ast);
- bool is_entry_point = func_ast->IsEntryPoint();
- bool needs_pointer_aliasing = false;
-
- // Map module-scope variables onto their replacement.
- struct NewVar {
- Symbol symbol;
- bool is_pointer;
- bool is_wrapped;
- };
- std::unordered_map<const sem::Variable*, NewVar> var_to_newvar;
-
- // We aggregate all workgroup variables into a struct to avoid hitting MSL's limit for
- // threadgroup memory arguments.
- Symbol workgroup_parameter_symbol;
- StructMemberList workgroup_parameter_members;
- auto workgroup_param = [&] {
- if (!workgroup_parameter_symbol.IsValid()) {
- workgroup_parameter_symbol = ctx.dst->Sym();
- }
- return workgroup_parameter_symbol;
- };
-
- // If this function references any private variables, it needs to take the private
- // variable struct as a parameter (or declare it, if it is an entry point function).
- if (uses_privates.count(func_ast)) {
- if (is_entry_point) {
- // Create a local declaration for the private variable struct.
- auto* var = ctx.dst->Var(
- PrivateStructVariableName(), ctx.dst->ty(PrivateStructName()),
- core::AddressSpace::kPrivate,
- tint::Vector{
- ctx.dst->Disable(ast::DisabledValidation::kIgnoreAddressSpace),
- });
- ctx.InsertFront(func_ast->body->statements, ctx.dst->Decl(var));
-
- // Initialize the members of that struct with the original initializers.
- for (auto init : private_initializers) {
- ctx.InsertFront(func_ast->body->statements, init());
- }
- } else {
- // Create a parameter that is a pointer to the private variable struct.
- auto ptr = ctx.dst->ty.ptr<private_>(ctx.dst->ty(PrivateStructName()));
- auto* param = ctx.dst->Param(PrivateStructVariableName(), ptr);
- ctx.InsertBack(func_ast->params, param);
- }
- }
-
- // Process and redeclare all variables referenced by the function.
- for (auto* var : func_sem->TransitivelyReferencedGlobals()) {
- if (var->AddressSpace() == core::AddressSpace::kUndefined) {
- continue;
- }
- if (var->AddressSpace() == core::AddressSpace::kPrivate) {
- // Private variable are collected into a single struct that is passed by
- // pointer (handled above), so we just need to replace the uses here.
- ReplaceUsesInFunction(func_ast, var, PrivateStructVariableName(),
- /* is_pointer */ !is_entry_point,
- ctx.Clone(var->Declaration()->name->symbol));
- continue;
- }
-
- // This is the symbol for the variable that replaces the module-scope var.
- auto new_var_symbol = ctx.dst->Sym();
-
- // Track whether the new variable is a pointer or not.
- bool is_pointer = false;
-
- // Track whether the new variable was wrapped in a struct or not.
- bool is_wrapped = false;
-
- // Process the variable to redeclare it as a parameter or local variable.
- if (is_entry_point) {
- ProcessVariableInEntryPoint(func_ast, var, new_var_symbol, workgroup_param,
- workgroup_parameter_members, is_pointer,
- is_wrapped);
- } else {
- ProcessVariableInUserFunction(func_ast, var, new_var_symbol, is_pointer);
- if (var->AddressSpace() == core::AddressSpace::kWorkgroup) {
- needs_pointer_aliasing = true;
- }
- }
-
- // Record the replacement symbol.
- var_to_newvar[var] = {new_var_symbol, is_pointer, is_wrapped};
-
- // Replace all uses of the module-scope variable.
- ReplaceUsesInFunction(
- func_ast, var, new_var_symbol, is_pointer,
- is_wrapped ? ctx.dst->Sym(kWrappedArrayMemberName) : Symbol());
- }
-
- // Allow pointer aliasing if needed.
- if (needs_pointer_aliasing) {
- ctx.InsertBack(func_ast->attributes,
- ctx.dst->Disable(ast::DisabledValidation::kIgnorePointerAliasing));
- }
-
- if (!workgroup_parameter_members.IsEmpty()) {
- // Create the workgroup memory parameter.
- // The parameter is a struct that contains members for each workgroup variable.
- auto* str =
- ctx.dst->Structure(ctx.dst->Sym(), std::move(workgroup_parameter_members));
- auto param_type = ctx.dst->ty.ptr(workgroup, ctx.dst->ty.Of(str));
- auto* param = ctx.dst->Param(
- workgroup_param(), param_type,
- tint::Vector{
- ctx.dst->Disable(ast::DisabledValidation::kEntryPointParameter),
- ctx.dst->Disable(ast::DisabledValidation::kIgnoreAddressSpace),
- });
- ctx.InsertFront(func_ast->params, param);
- }
-
- // Pass the variables as pointers to any functions that need them.
- for (auto* call : calls_to_replace[func_ast]) {
- auto* call_sem = ctx.src->Sem().Get(call)->Unwrap()->As<sem::Call>();
- auto* target_sem = call_sem->Target()->As<sem::Function>();
-
- // Pass the private variable struct pointer if needed.
- if (uses_privates.count(target_sem->Declaration())) {
- const ast::Expression* arg = ctx.dst->Expr(PrivateStructVariableName());
- if (is_entry_point) {
- arg = ctx.dst->AddressOf(arg);
- }
- ctx.InsertBack(call->args, arg);
- }
-
- // Add new arguments for any variables that are needed by the callee.
- // For entry points, pass non-handle types as pointers.
- for (auto* target_var : target_sem->TransitivelyReferencedGlobals()) {
- auto sc = target_var->AddressSpace();
- if (sc == core::AddressSpace::kUndefined) {
- continue;
- }
-
- auto it = var_to_newvar.find(target_var);
- if (it == var_to_newvar.end()) {
- // No replacement was created for this function.
- continue;
- }
-
- auto new_var = it->second;
- bool IsHandle = target_var->Type()->UnwrapRef()->IsHandle();
- const ast::Expression* arg = ctx.dst->Expr(new_var.symbol);
- if (new_var.is_wrapped) {
- // The variable is wrapped in a struct, so we need to pass a pointer to the
- // struct member instead.
- arg = ctx.dst->AddressOf(
- ctx.dst->MemberAccessor(ctx.dst->Deref(arg), kWrappedArrayMemberName));
- } else if (is_entry_point && !IsHandle && !new_var.is_pointer) {
- // We need to pass a pointer and we don't already have one, so take
- // the address of the new variable.
- arg = ctx.dst->AddressOf(arg);
- }
- ctx.InsertBack(call->args, arg);
- }
- }
- }
-
- // Now remove all module-scope variables with these address spaces.
- for (auto* var_ast : ctx.src->AST().GlobalVariables()) {
- auto* var_sem = ctx.src->Sem().Get(var_ast);
- if (var_sem->AddressSpace() != core::AddressSpace::kUndefined) {
- ctx.Remove(ctx.src->AST().GlobalDeclarations(), var_ast);
- }
- }
- }
-
- /// @returns the name of the structure that contains all of the module-scope private variables
- Symbol PrivateStructName() {
- if (!private_struct_name.IsValid()) {
- private_struct_name = ctx.dst->Symbols().New("tint_private_vars_struct");
- }
- return private_struct_name;
- }
-
- /// @returns the name of the variable that contains all of the module-scope private variables
- Symbol PrivateStructVariableName() {
- if (!private_struct_variable_name.IsValid()) {
- private_struct_variable_name = ctx.dst->Symbols().New("tint_private_vars");
- }
- return private_struct_variable_name;
- }
-
- private:
- // The structures that have already been cloned by this transform.
- std::unordered_set<const sem::Struct*> cloned_structs_;
-
- // Map from identifier expression to the address-of expression that uses it.
- std::unordered_map<const ast::IdentifierExpression*, const ast::UnaryOpExpression*>
- ident_to_address_of_;
-
- // The name of the structure that contains all the module-scope private variables.
- Symbol private_struct_name;
-
- // The name of the structure variable that contains all the module-scope private variables.
- Symbol private_struct_variable_name;
-};
-
-ModuleScopeVarToEntryPointParam::ModuleScopeVarToEntryPointParam() = default;
-
-ModuleScopeVarToEntryPointParam::~ModuleScopeVarToEntryPointParam() = default;
-
-ast::transform::Transform::ApplyResult ModuleScopeVarToEntryPointParam::Apply(
- const Program& src,
- const ast::transform::DataMap&,
- ast::transform::DataMap&) const {
- if (!ShouldRun(src)) {
- return SkipTransform;
- }
-
- ProgramBuilder b;
- program::CloneContext ctx{&b, &src, /* auto_clone_symbols */ true};
- State state{ctx};
- state.Process();
-
- ctx.Clone();
- return resolver::Resolve(b);
-}
-
-} // namespace tint::msl::writer
diff --git a/src/tint/lang/msl/writer/ast_raise/module_scope_var_to_entry_point_param.h b/src/tint/lang/msl/writer/ast_raise/module_scope_var_to_entry_point_param.h
deleted file mode 100644
index 44cfc33..0000000
--- a/src/tint/lang/msl/writer/ast_raise/module_scope_var_to_entry_point_param.h
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright 2021 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef SRC_TINT_LANG_MSL_WRITER_AST_RAISE_MODULE_SCOPE_VAR_TO_ENTRY_POINT_PARAM_H_
-#define SRC_TINT_LANG_MSL_WRITER_AST_RAISE_MODULE_SCOPE_VAR_TO_ENTRY_POINT_PARAM_H_
-
-#include "src/tint/lang/wgsl/ast/transform/transform.h"
-
-namespace tint::msl::writer {
-
-/// Move module-scope variables into the entry point as parameters.
-///
-/// MSL does not allow module-scope variables to have any address space other
-/// than `constant`. This transform moves all module-scope declarations into the
-/// entry point function (either as parameters or function-scope variables) and
-/// then passes them as pointer parameters to any function that references them.
-///
-/// Since WGSL does not allow entry point parameters or function-scope variables
-/// to have these address spaces, we annotate the new variable declarations
-/// with an attribute that bypasses that validation rule.
-///
-/// Before:
-/// ```
-/// struct S {
-/// f : f32;
-/// };
-/// @binding(0) @group(0)
-/// var<storage, read> s : S;
-/// var<private> p : f32 = 2.0;
-///
-/// fn foo() {
-/// p = p + f;
-/// }
-///
-/// @compute @workgroup_size(1)
-/// fn main() {
-/// foo();
-/// }
-/// ```
-///
-/// After:
-/// ```
-/// fn foo(p : ptr<private, f32>, sptr : ptr<storage, S, read>) {
-/// *p = *p + (*sptr).f;
-/// }
-///
-/// @compute @workgroup_size(1)
-/// fn main(sptr : ptr<storage, S, read>) {
-/// var<private> p : f32 = 2.0;
-/// foo(&p, sptr);
-/// }
-/// ```
-class ModuleScopeVarToEntryPointParam final
- : public Castable<ModuleScopeVarToEntryPointParam, ast::transform::Transform> {
- public:
- /// Constructor
- ModuleScopeVarToEntryPointParam();
- /// Destructor
- ~ModuleScopeVarToEntryPointParam() override;
-
- /// @copydoc ast::transform::Transform::Apply
- ApplyResult Apply(const Program& program,
- const ast::transform::DataMap& inputs,
- ast::transform::DataMap& outputs) const override;
-
- private:
- struct State;
-};
-
-} // namespace tint::msl::writer
-
-#endif // SRC_TINT_LANG_MSL_WRITER_AST_RAISE_MODULE_SCOPE_VAR_TO_ENTRY_POINT_PARAM_H_
diff --git a/src/tint/lang/msl/writer/ast_raise/module_scope_var_to_entry_point_param_test.cc b/src/tint/lang/msl/writer/ast_raise/module_scope_var_to_entry_point_param_test.cc
deleted file mode 100644
index 8a24325..0000000
--- a/src/tint/lang/msl/writer/ast_raise/module_scope_var_to_entry_point_param_test.cc
+++ /dev/null
@@ -1,1363 +0,0 @@
-// Copyright 2021 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/tint/lang/msl/writer/ast_raise/module_scope_var_to_entry_point_param.h"
-
-#include <utility>
-
-#include "src/tint/lang/wgsl/ast/transform/helper_test.h"
-
-namespace tint::msl::writer {
-namespace {
-
-using ModuleScopeVarToEntryPointParamTest = ast::transform::TransformTest;
-
-TEST_F(ModuleScopeVarToEntryPointParamTest, ShouldRunEmptyModule) {
- auto* src = R"()";
-
- EXPECT_FALSE(ShouldRun<ModuleScopeVarToEntryPointParam>(src));
-}
-
-TEST_F(ModuleScopeVarToEntryPointParamTest, ShouldRunHasGlobal) {
- auto* src = R"(
-var<private> v : i32;
-)";
-
- EXPECT_TRUE(ShouldRun<ModuleScopeVarToEntryPointParam>(src));
-}
-
-TEST_F(ModuleScopeVarToEntryPointParamTest, Basic) {
- auto* src = R"(
-var<private> p : f32;
-var<workgroup> w : f32;
-
-@compute @workgroup_size(1)
-fn main() {
- w = p;
-}
-)";
-
- auto* expect = R"(
-struct tint_private_vars_struct {
- p : f32,
-}
-
-@compute @workgroup_size(1)
-fn main() {
- @internal(disable_validation__ignore_address_space) var<private> tint_private_vars : tint_private_vars_struct;
- @internal(disable_validation__ignore_address_space) var<workgroup> tint_symbol : f32;
- tint_symbol = tint_private_vars.p;
-}
-)";
-
- auto got = Run<ModuleScopeVarToEntryPointParam>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(ModuleScopeVarToEntryPointParamTest, Basic_OutOfOrder) {
- auto* src = R"(
-@compute @workgroup_size(1)
-fn main() {
- w = p;
-}
-
-var<workgroup> w : f32;
-var<private> p : f32;
-)";
-
- auto* expect = R"(
-struct tint_private_vars_struct {
- p : f32,
-}
-
-@compute @workgroup_size(1)
-fn main() {
- @internal(disable_validation__ignore_address_space) var<private> tint_private_vars : tint_private_vars_struct;
- @internal(disable_validation__ignore_address_space) var<workgroup> tint_symbol : f32;
- tint_symbol = tint_private_vars.p;
-}
-)";
-
- auto got = Run<ModuleScopeVarToEntryPointParam>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(ModuleScopeVarToEntryPointParamTest, FunctionCalls) {
- auto* src = R"(
-var<private> p : f32;
-var<workgroup> w : f32;
-
-fn no_uses() {
-}
-
-fn zoo() {
- p = p * 2.0;
-}
-
-fn bar(a : f32, b : f32) {
- p = a;
- w = b;
- zoo();
-}
-
-fn foo(a : f32) {
- let b : f32 = 2.0;
- bar(a, b);
- no_uses();
-}
-
-@compute @workgroup_size(1)
-fn main() {
- foo(1.0);
-}
-)";
-
- auto* expect = R"(
-struct tint_private_vars_struct {
- p : f32,
-}
-
-fn no_uses() {
-}
-
-fn zoo(tint_private_vars : ptr<private, tint_private_vars_struct>) {
- (*(tint_private_vars)).p = ((*(tint_private_vars)).p * 2.0);
-}
-
-@internal(disable_validation__ignore_pointer_aliasing)
-fn bar(a : f32, b : f32, tint_private_vars : ptr<private, tint_private_vars_struct>, @internal(disable_validation__ignore_address_space) @internal(disable_validation__ignore_invalid_pointer_argument) tint_symbol : ptr<workgroup, f32>) {
- (*(tint_private_vars)).p = a;
- *(tint_symbol) = b;
- zoo(tint_private_vars);
-}
-
-@internal(disable_validation__ignore_pointer_aliasing)
-fn foo(a : f32, tint_private_vars : ptr<private, tint_private_vars_struct>, @internal(disable_validation__ignore_address_space) @internal(disable_validation__ignore_invalid_pointer_argument) tint_symbol_1 : ptr<workgroup, f32>) {
- let b : f32 = 2.0;
- bar(a, b, tint_private_vars, tint_symbol_1);
- no_uses();
-}
-
-@compute @workgroup_size(1)
-fn main() {
- @internal(disable_validation__ignore_address_space) var<private> tint_private_vars : tint_private_vars_struct;
- @internal(disable_validation__ignore_address_space) var<workgroup> tint_symbol_2 : f32;
- foo(1.0, &(tint_private_vars), &(tint_symbol_2));
-}
-)";
-
- auto got = Run<ModuleScopeVarToEntryPointParam>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(ModuleScopeVarToEntryPointParamTest, FunctionCalls_OutOfOrder) {
- auto* src = R"(
-@compute @workgroup_size(1)
-fn main() {
- foo(1.0);
-}
-
-fn foo(a : f32) {
- let b : f32 = 2.0;
- bar(a, b);
- no_uses();
-}
-
-fn no_uses() {
-}
-
-fn bar(a : f32, b : f32) {
- p = a;
- w = b;
- zoo();
-}
-
-fn zoo() {
- p = p * 2.0;
-}
-
-var<private> p : f32;
-var<workgroup> w : f32;
-)";
-
- auto* expect = R"(
-struct tint_private_vars_struct {
- p : f32,
-}
-
-@compute @workgroup_size(1)
-fn main() {
- @internal(disable_validation__ignore_address_space) var<private> tint_private_vars : tint_private_vars_struct;
- @internal(disable_validation__ignore_address_space) var<workgroup> tint_symbol_2 : f32;
- foo(1.0, &(tint_private_vars), &(tint_symbol_2));
-}
-
-@internal(disable_validation__ignore_pointer_aliasing)
-fn foo(a : f32, tint_private_vars : ptr<private, tint_private_vars_struct>, @internal(disable_validation__ignore_address_space) @internal(disable_validation__ignore_invalid_pointer_argument) tint_symbol_1 : ptr<workgroup, f32>) {
- let b : f32 = 2.0;
- bar(a, b, tint_private_vars, tint_symbol_1);
- no_uses();
-}
-
-fn no_uses() {
-}
-
-@internal(disable_validation__ignore_pointer_aliasing)
-fn bar(a : f32, b : f32, tint_private_vars : ptr<private, tint_private_vars_struct>, @internal(disable_validation__ignore_address_space) @internal(disable_validation__ignore_invalid_pointer_argument) tint_symbol : ptr<workgroup, f32>) {
- (*(tint_private_vars)).p = a;
- *(tint_symbol) = b;
- zoo(tint_private_vars);
-}
-
-fn zoo(tint_private_vars : ptr<private, tint_private_vars_struct>) {
- (*(tint_private_vars)).p = ((*(tint_private_vars)).p * 2.0);
-}
-)";
-
- auto got = Run<ModuleScopeVarToEntryPointParam>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(ModuleScopeVarToEntryPointParamTest, Initializers) {
- auto* src = R"(
-var<private> a : f32 = 1.0;
-var<private> b : f32 = f32();
-
-@compute @workgroup_size(1)
-fn main() {
- let x : f32 = a + b;
-}
-)";
-
- auto* expect = R"(
-struct tint_private_vars_struct {
- a : f32,
- b : f32,
-}
-
-@compute @workgroup_size(1)
-fn main() {
- @internal(disable_validation__ignore_address_space) var<private> tint_private_vars : tint_private_vars_struct;
- tint_private_vars.a = 1.0;
- tint_private_vars.b = f32();
- let x : f32 = (tint_private_vars.a + tint_private_vars.b);
-}
-)";
-
- auto got = Run<ModuleScopeVarToEntryPointParam>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(ModuleScopeVarToEntryPointParamTest, Initializers_OutOfOrder) {
- auto* src = R"(
-@compute @workgroup_size(1)
-fn main() {
- let x : f32 = a + b;
-}
-
-var<private> b : f32 = f32();
-var<private> a : f32 = 1.0;
-)";
-
- auto* expect = R"(
-struct tint_private_vars_struct {
- a : f32,
- b : f32,
-}
-
-@compute @workgroup_size(1)
-fn main() {
- @internal(disable_validation__ignore_address_space) var<private> tint_private_vars : tint_private_vars_struct;
- tint_private_vars.a = 1.0;
- tint_private_vars.b = f32();
- let x : f32 = (tint_private_vars.a + tint_private_vars.b);
-}
-)";
-
- auto got = Run<ModuleScopeVarToEntryPointParam>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(ModuleScopeVarToEntryPointParamTest, Pointers) {
- auto* src = R"(
-var<private> p : f32;
-var<workgroup> w : f32;
-
-@compute @workgroup_size(1)
-fn main() {
- let p_ptr : ptr<private, f32> = &p;
- let w_ptr : ptr<workgroup, f32> = &w;
- let x : f32 = *p_ptr + *w_ptr;
- *p_ptr = x;
-}
-)";
-
- auto* expect = R"(
-struct tint_private_vars_struct {
- p : f32,
-}
-
-@compute @workgroup_size(1)
-fn main() {
- @internal(disable_validation__ignore_address_space) var<private> tint_private_vars : tint_private_vars_struct;
- @internal(disable_validation__ignore_address_space) var<workgroup> tint_symbol : f32;
- let p_ptr : ptr<private, f32> = &(tint_private_vars.p);
- let w_ptr : ptr<workgroup, f32> = &(tint_symbol);
- let x : f32 = (*(p_ptr) + *(w_ptr));
- *(p_ptr) = x;
-}
-)";
-
- auto got = Run<ModuleScopeVarToEntryPointParam>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(ModuleScopeVarToEntryPointParamTest, Pointers_OutOfOrder) {
- auto* src = R"(
-@compute @workgroup_size(1)
-fn main() {
- let p_ptr : ptr<private, f32> = &p;
- let w_ptr : ptr<workgroup, f32> = &w;
- let x : f32 = *p_ptr + *w_ptr;
- *p_ptr = x;
-}
-
-var<workgroup> w : f32;
-var<private> p : f32;
-)";
-
- auto* expect = R"(
-struct tint_private_vars_struct {
- p : f32,
-}
-
-@compute @workgroup_size(1)
-fn main() {
- @internal(disable_validation__ignore_address_space) var<private> tint_private_vars : tint_private_vars_struct;
- @internal(disable_validation__ignore_address_space) var<workgroup> tint_symbol : f32;
- let p_ptr : ptr<private, f32> = &(tint_private_vars.p);
- let w_ptr : ptr<workgroup, f32> = &(tint_symbol);
- let x : f32 = (*(p_ptr) + *(w_ptr));
- *(p_ptr) = x;
-}
-)";
-
- auto got = Run<ModuleScopeVarToEntryPointParam>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-// TODO(crbug.com/tint/1758): Requires support for workgroup pointer parameters, which is
-// unsupported until WGSL 1.1
-TEST_F(ModuleScopeVarToEntryPointParamTest, DISABLED_FoldAddressOfDeref) {
- auto* src = R"(
-var<workgroup> v : f32;
-
-fn bar(p : ptr<workgroup, f32>) {
- (*p) = 0.0;
-}
-
-fn foo() {
- bar(&v);
-}
-
-@compute @workgroup_size(1)
-fn main() {
- foo();
-}
-)";
-
- auto* expect = R"(
-fn bar(p : ptr<workgroup, f32>) {
- *(p) = 0.0;
-}
-
-fn foo(@internal(disable_validation__ignore_address_space) @internal(disable_validation__ignore_invalid_pointer_argument) tint_symbol : ptr<workgroup, f32>) {
- bar(tint_symbol);
-}
-
-@compute @workgroup_size(1)
-fn main() {
- @internal(disable_validation__ignore_address_space) var<workgroup> tint_symbol_1 : f32;
- foo(&(tint_symbol_1));
-}
-)";
-
- auto got = Run<ModuleScopeVarToEntryPointParam>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-// TODO(crbug.com/tint/1758): Requires support for workgroup pointer parameters, which is
-// unsupported until WGSL 1.1
-TEST_F(ModuleScopeVarToEntryPointParamTest, DISABLED_FoldAddressOfDeref_OutOfOrder) {
- auto* src = R"(
-@compute @workgroup_size(1)
-fn main() {
- foo();
-}
-
-fn foo() {
- bar(&v);
-}
-
-fn bar(p : ptr<workgroup, f32>) {
- (*p) = 0.0;
-}
-
-var<workgroup> v : f32;
-)";
-
- auto* expect = R"(
-@compute @workgroup_size(1)
-fn main() {
- @internal(disable_validation__ignore_address_space) var<workgroup> tint_symbol_1 : f32;
- foo(&(tint_symbol_1));
-}
-
-fn foo(@internal(disable_validation__ignore_address_space) @internal(disable_validation__ignore_invalid_pointer_argument) tint_symbol : ptr<workgroup, f32>) {
- bar(tint_symbol);
-}
-
-fn bar(p : ptr<workgroup, f32>) {
- *(p) = 0.0;
-}
-)";
-
- auto got = Run<ModuleScopeVarToEntryPointParam>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(ModuleScopeVarToEntryPointParamTest, Buffers_Basic) {
- auto* src = R"(
-struct S {
- a : f32,
-};
-
-@group(0) @binding(0)
-var<uniform> u : S;
-@group(0) @binding(1)
-var<storage> s : S;
-
-@compute @workgroup_size(1)
-fn main() {
- _ = u;
- _ = s;
-}
-)";
-
- auto* expect = R"(
-struct S {
- a : f32,
-}
-
-@compute @workgroup_size(1)
-fn main(@group(0) @binding(0) @internal(disable_validation__entry_point_parameter) @internal(disable_validation__ignore_address_space) tint_symbol : ptr<uniform, S>, @group(0) @binding(1) @internal(disable_validation__entry_point_parameter) @internal(disable_validation__ignore_address_space) tint_symbol_1 : ptr<storage, S, read>) {
- _ = *(tint_symbol);
- _ = *(tint_symbol_1);
-}
-)";
-
- auto got = Run<ModuleScopeVarToEntryPointParam>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(ModuleScopeVarToEntryPointParamTest, Buffers_Basic_OutOfOrder) {
- auto* src = R"(
-@compute @workgroup_size(1)
-fn main() {
- _ = u;
- _ = s;
-}
-
-@group(0) @binding(0) var<uniform> u : S;
-@group(0) @binding(1) var<storage> s : S;
-
-struct S {
- a : f32,
-};
-
-)";
-
- auto* expect = R"(
-@compute @workgroup_size(1)
-fn main(@group(0) @binding(0) @internal(disable_validation__entry_point_parameter) @internal(disable_validation__ignore_address_space) tint_symbol : ptr<uniform, S>, @group(0) @binding(1) @internal(disable_validation__entry_point_parameter) @internal(disable_validation__ignore_address_space) tint_symbol_1 : ptr<storage, S, read>) {
- _ = *(tint_symbol);
- _ = *(tint_symbol_1);
-}
-
-struct S {
- a : f32,
-}
-)";
-
- auto got = Run<ModuleScopeVarToEntryPointParam>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(ModuleScopeVarToEntryPointParamTest, Buffer_RuntimeArray) {
- auto* src = R"(
-@group(0) @binding(0)
-var<storage> buffer : array<f32>;
-
-@compute @workgroup_size(1)
-fn main() {
- _ = buffer[0];
-}
-)";
-
- auto* expect = R"(
-struct tint_symbol_1 {
- arr : array<f32>,
-}
-
-@compute @workgroup_size(1)
-fn main(@group(0) @binding(0) @internal(disable_validation__entry_point_parameter) @internal(disable_validation__ignore_address_space) tint_symbol : ptr<storage, tint_symbol_1, read>) {
- _ = (*(tint_symbol)).arr[0];
-}
-)";
-
- auto got = Run<ModuleScopeVarToEntryPointParam>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(ModuleScopeVarToEntryPointParamTest, Buffer_RuntimeArray_OutOfOrder) {
- auto* src = R"(
-@compute @workgroup_size(1)
-fn main() {
- _ = buffer[0];
-}
-
-@group(0) @binding(0)
-var<storage> buffer : array<f32>;
-)";
-
- auto* expect = R"(
-struct tint_symbol_1 {
- arr : array<f32>,
-}
-
-@compute @workgroup_size(1)
-fn main(@group(0) @binding(0) @internal(disable_validation__entry_point_parameter) @internal(disable_validation__ignore_address_space) tint_symbol : ptr<storage, tint_symbol_1, read>) {
- _ = (*(tint_symbol)).arr[0];
-}
-)";
-
- auto got = Run<ModuleScopeVarToEntryPointParam>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(ModuleScopeVarToEntryPointParamTest, Buffer_RuntimeArrayInsideFunction) {
- auto* src = R"(
-@group(0) @binding(0)
-var<storage> buffer : array<f32>;
-
-fn foo() {
- _ = buffer[0];
-}
-
-@compute @workgroup_size(1)
-fn main() {
- foo();
-}
-)";
-
- auto* expect = R"(
-struct tint_symbol_2 {
- arr : array<f32>,
-}
-
-fn foo(@internal(disable_validation__ignore_address_space) @internal(disable_validation__ignore_invalid_pointer_argument) tint_symbol : ptr<storage, array<f32>, read>) {
- _ = (*(tint_symbol))[0];
-}
-
-@compute @workgroup_size(1)
-fn main(@group(0) @binding(0) @internal(disable_validation__entry_point_parameter) @internal(disable_validation__ignore_address_space) tint_symbol_1 : ptr<storage, tint_symbol_2, read>) {
- foo(&((*(tint_symbol_1)).arr));
-}
-)";
-
- auto got = Run<ModuleScopeVarToEntryPointParam>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(ModuleScopeVarToEntryPointParamTest, Buffer_RuntimeArrayInsideFunction_OutOfOrder) {
- auto* src = R"(
-@compute @workgroup_size(1)
-fn main() {
- foo();
-}
-
-fn foo() {
- _ = buffer[0];
-}
-
-@group(0) @binding(0) var<storage> buffer : array<f32>;
-)";
-
- auto* expect = R"(
-struct tint_symbol_2 {
- arr : array<f32>,
-}
-
-@compute @workgroup_size(1)
-fn main(@group(0) @binding(0) @internal(disable_validation__entry_point_parameter) @internal(disable_validation__ignore_address_space) tint_symbol_1 : ptr<storage, tint_symbol_2, read>) {
- foo(&((*(tint_symbol_1)).arr));
-}
-
-fn foo(@internal(disable_validation__ignore_address_space) @internal(disable_validation__ignore_invalid_pointer_argument) tint_symbol : ptr<storage, array<f32>, read>) {
- _ = (*(tint_symbol))[0];
-}
-)";
-
- auto got = Run<ModuleScopeVarToEntryPointParam>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(ModuleScopeVarToEntryPointParamTest, Buffer_RuntimeArray_Alias) {
- auto* src = R"(
-alias myarray = array<f32>;
-
-@group(0) @binding(0)
-var<storage> buffer : myarray;
-
-@compute @workgroup_size(1)
-fn main() {
- _ = buffer[0];
-}
-)";
-
- auto* expect = R"(
-struct tint_symbol_1 {
- arr : array<f32>,
-}
-
-alias myarray = array<f32>;
-
-@compute @workgroup_size(1)
-fn main(@group(0) @binding(0) @internal(disable_validation__entry_point_parameter) @internal(disable_validation__ignore_address_space) tint_symbol : ptr<storage, tint_symbol_1, read>) {
- _ = (*(tint_symbol)).arr[0];
-}
-)";
-
- auto got = Run<ModuleScopeVarToEntryPointParam>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(ModuleScopeVarToEntryPointParamTest, Buffer_RuntimeArray_Alias_OutOfOrder) {
- auto* src = R"(
-@compute @workgroup_size(1)
-fn main() {
- _ = buffer[0];
-}
-
-@group(0) @binding(0) var<storage> buffer : myarray;
-
-alias myarray = array<f32>;
-)";
-
- auto* expect = R"(
-struct tint_symbol_1 {
- arr : array<f32>,
-}
-
-@compute @workgroup_size(1)
-fn main(@group(0) @binding(0) @internal(disable_validation__entry_point_parameter) @internal(disable_validation__ignore_address_space) tint_symbol : ptr<storage, tint_symbol_1, read>) {
- _ = (*(tint_symbol)).arr[0];
-}
-
-alias myarray = array<f32>;
-)";
-
- auto got = Run<ModuleScopeVarToEntryPointParam>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(ModuleScopeVarToEntryPointParamTest, Buffer_ArrayOfStruct) {
- auto* src = R"(
-struct S {
- f : f32,
-};
-
-@group(0) @binding(0)
-var<storage> buffer : array<S>;
-
-@compute @workgroup_size(1)
-fn main() {
- _ = buffer[0];
-}
-)";
-
- auto* expect = R"(
-struct S {
- f : f32,
-}
-
-struct tint_symbol_1 {
- arr : array<S>,
-}
-
-@compute @workgroup_size(1)
-fn main(@group(0) @binding(0) @internal(disable_validation__entry_point_parameter) @internal(disable_validation__ignore_address_space) tint_symbol : ptr<storage, tint_symbol_1, read>) {
- _ = (*(tint_symbol)).arr[0];
-}
-)";
-
- auto got = Run<ModuleScopeVarToEntryPointParam>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(ModuleScopeVarToEntryPointParamTest, Buffer_ArrayOfStruct_OutOfOrder) {
- auto* src = R"(
-@compute @workgroup_size(1)
-fn main() {
- _ = buffer[0];
-}
-
-@group(0) @binding(0) var<storage> buffer : array<S>;
-
-struct S {
- f : f32,
-};
-)";
-
- auto* expect = R"(
-struct S {
- f : f32,
-}
-
-struct tint_symbol_1 {
- arr : array<S>,
-}
-
-@compute @workgroup_size(1)
-fn main(@group(0) @binding(0) @internal(disable_validation__entry_point_parameter) @internal(disable_validation__ignore_address_space) tint_symbol : ptr<storage, tint_symbol_1, read>) {
- _ = (*(tint_symbol)).arr[0];
-}
-)";
-
- auto got = Run<ModuleScopeVarToEntryPointParam>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(ModuleScopeVarToEntryPointParamTest, Buffers_FunctionCalls) {
- auto* src = R"(
-struct S {
- a : f32,
-};
-
-@group(0) @binding(0)
-var<uniform> u : S;
-@group(0) @binding(1)
-var<storage> s : S;
-
-fn no_uses() {
-}
-
-fn bar(a : f32, b : f32) {
- _ = u;
- _ = s;
-}
-
-fn foo(a : f32) {
- let b : f32 = 2.0;
- _ = u;
- bar(a, b);
- no_uses();
-}
-
-@compute @workgroup_size(1)
-fn main() {
- foo(1.0);
-}
-)";
-
- auto* expect = R"(
-struct S {
- a : f32,
-}
-
-fn no_uses() {
-}
-
-fn bar(a : f32, b : f32, @internal(disable_validation__ignore_address_space) @internal(disable_validation__ignore_invalid_pointer_argument) tint_symbol : ptr<uniform, S>, @internal(disable_validation__ignore_address_space) @internal(disable_validation__ignore_invalid_pointer_argument) tint_symbol_1 : ptr<storage, S, read>) {
- _ = *(tint_symbol);
- _ = *(tint_symbol_1);
-}
-
-fn foo(a : f32, @internal(disable_validation__ignore_address_space) @internal(disable_validation__ignore_invalid_pointer_argument) tint_symbol_2 : ptr<uniform, S>, @internal(disable_validation__ignore_address_space) @internal(disable_validation__ignore_invalid_pointer_argument) tint_symbol_3 : ptr<storage, S, read>) {
- let b : f32 = 2.0;
- _ = *(tint_symbol_2);
- bar(a, b, tint_symbol_2, tint_symbol_3);
- no_uses();
-}
-
-@compute @workgroup_size(1)
-fn main(@group(0) @binding(0) @internal(disable_validation__entry_point_parameter) @internal(disable_validation__ignore_address_space) tint_symbol_4 : ptr<uniform, S>, @group(0) @binding(1) @internal(disable_validation__entry_point_parameter) @internal(disable_validation__ignore_address_space) tint_symbol_5 : ptr<storage, S, read>) {
- foo(1.0, tint_symbol_4, tint_symbol_5);
-}
-)";
-
- auto got = Run<ModuleScopeVarToEntryPointParam>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(ModuleScopeVarToEntryPointParamTest, Buffers_FunctionCalls_OutOfOrder) {
- auto* src = R"(
-@compute @workgroup_size(1)
-fn main() {
- foo(1.0);
-}
-
-fn foo(a : f32) {
- let b : f32 = 2.0;
- _ = u;
- bar(a, b);
- no_uses();
-}
-
-fn no_uses() {
-}
-
-fn bar(a : f32, b : f32) {
- _ = u;
- _ = s;
-}
-
-struct S {
- a : f32,
-};
-
-@group(0) @binding(0)
-var<uniform> u : S;
-@group(0) @binding(1)
-var<storage> s : S;
-)";
-
- auto* expect = R"(
-@compute @workgroup_size(1)
-fn main(@group(0) @binding(0) @internal(disable_validation__entry_point_parameter) @internal(disable_validation__ignore_address_space) tint_symbol_4 : ptr<uniform, S>, @group(0) @binding(1) @internal(disable_validation__entry_point_parameter) @internal(disable_validation__ignore_address_space) tint_symbol_5 : ptr<storage, S, read>) {
- foo(1.0, tint_symbol_4, tint_symbol_5);
-}
-
-fn foo(a : f32, @internal(disable_validation__ignore_address_space) @internal(disable_validation__ignore_invalid_pointer_argument) tint_symbol_2 : ptr<uniform, S>, @internal(disable_validation__ignore_address_space) @internal(disable_validation__ignore_invalid_pointer_argument) tint_symbol_3 : ptr<storage, S, read>) {
- let b : f32 = 2.0;
- _ = *(tint_symbol_2);
- bar(a, b, tint_symbol_2, tint_symbol_3);
- no_uses();
-}
-
-fn no_uses() {
-}
-
-fn bar(a : f32, b : f32, @internal(disable_validation__ignore_address_space) @internal(disable_validation__ignore_invalid_pointer_argument) tint_symbol : ptr<uniform, S>, @internal(disable_validation__ignore_address_space) @internal(disable_validation__ignore_invalid_pointer_argument) tint_symbol_1 : ptr<storage, S, read>) {
- _ = *(tint_symbol);
- _ = *(tint_symbol_1);
-}
-
-struct S {
- a : f32,
-}
-)";
-
- auto got = Run<ModuleScopeVarToEntryPointParam>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(ModuleScopeVarToEntryPointParamTest, HandleTypes_Basic) {
- auto* src = R"(
-@group(0) @binding(0) var t : texture_2d<f32>;
-@group(0) @binding(1) var s : sampler;
-
-@compute @workgroup_size(1)
-fn main() {
- _ = t;
- _ = s;
-}
-)";
-
- auto* expect = R"(
-@compute @workgroup_size(1)
-fn main(@group(0) @binding(0) @internal(disable_validation__entry_point_parameter) tint_symbol : texture_2d<f32>, @group(0) @binding(1) @internal(disable_validation__entry_point_parameter) tint_symbol_1 : sampler) {
- _ = tint_symbol;
- _ = tint_symbol_1;
-}
-)";
-
- auto got = Run<ModuleScopeVarToEntryPointParam>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(ModuleScopeVarToEntryPointParamTest, HandleTypes_FunctionCalls) {
- auto* src = R"(
-@group(0) @binding(0) var t : texture_2d<f32>;
-@group(0) @binding(1) var s : sampler;
-
-fn no_uses() {
-}
-
-fn bar(a : f32, b : f32) {
- _ = t;
- _ = s;
-}
-
-fn foo(a : f32) {
- let b : f32 = 2.0;
- _ = t;
- bar(a, b);
- no_uses();
-}
-
-@compute @workgroup_size(1)
-fn main() {
- foo(1.0);
-}
-)";
-
- auto* expect = R"(
-fn no_uses() {
-}
-
-fn bar(a : f32, b : f32, tint_symbol : texture_2d<f32>, tint_symbol_1 : sampler) {
- _ = tint_symbol;
- _ = tint_symbol_1;
-}
-
-fn foo(a : f32, tint_symbol_2 : texture_2d<f32>, tint_symbol_3 : sampler) {
- let b : f32 = 2.0;
- _ = tint_symbol_2;
- bar(a, b, tint_symbol_2, tint_symbol_3);
- no_uses();
-}
-
-@compute @workgroup_size(1)
-fn main(@group(0) @binding(0) @internal(disable_validation__entry_point_parameter) tint_symbol_4 : texture_2d<f32>, @group(0) @binding(1) @internal(disable_validation__entry_point_parameter) tint_symbol_5 : sampler) {
- foo(1.0, tint_symbol_4, tint_symbol_5);
-}
-)";
-
- auto got = Run<ModuleScopeVarToEntryPointParam>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(ModuleScopeVarToEntryPointParamTest, HandleTypes_FunctionCalls_OutOfOrder) {
- auto* src = R"(
-@compute @workgroup_size(1)
-fn main() {
- foo(1.0);
-}
-
-fn foo(a : f32) {
- let b : f32 = 2.0;
- _ = t;
- bar(a, b);
- no_uses();
-}
-
-fn no_uses() {
-}
-
-fn bar(a : f32, b : f32) {
- _ = t;
- _ = s;
-}
-
-@group(0) @binding(0) var t : texture_2d<f32>;
-@group(0) @binding(1) var s : sampler;
-)";
-
- auto* expect = R"(
-@compute @workgroup_size(1)
-fn main(@group(0) @binding(0) @internal(disable_validation__entry_point_parameter) tint_symbol_4 : texture_2d<f32>, @group(0) @binding(1) @internal(disable_validation__entry_point_parameter) tint_symbol_5 : sampler) {
- foo(1.0, tint_symbol_4, tint_symbol_5);
-}
-
-fn foo(a : f32, tint_symbol_2 : texture_2d<f32>, tint_symbol_3 : sampler) {
- let b : f32 = 2.0;
- _ = tint_symbol_2;
- bar(a, b, tint_symbol_2, tint_symbol_3);
- no_uses();
-}
-
-fn no_uses() {
-}
-
-fn bar(a : f32, b : f32, tint_symbol : texture_2d<f32>, tint_symbol_1 : sampler) {
- _ = tint_symbol;
- _ = tint_symbol_1;
-}
-)";
-
- auto got = Run<ModuleScopeVarToEntryPointParam>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(ModuleScopeVarToEntryPointParamTest, Matrix) {
- auto* src = R"(
-var<workgroup> m : mat2x2<f32>;
-
-@compute @workgroup_size(1)
-fn main() {
- let x = m;
-}
-)";
-
- auto* expect = R"(
-struct tint_symbol_2 {
- m : mat2x2<f32>,
-}
-
-@compute @workgroup_size(1)
-fn main(@internal(disable_validation__entry_point_parameter) @internal(disable_validation__ignore_address_space) tint_symbol_1 : ptr<workgroup, tint_symbol_2>) {
- let tint_symbol = &((*(tint_symbol_1)).m);
- let x = *(tint_symbol);
-}
-)";
-
- auto got = Run<ModuleScopeVarToEntryPointParam>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(ModuleScopeVarToEntryPointParamTest, NestedMatrix) {
- auto* src = R"(
-struct S1 {
- m : mat2x2<f32>,
-};
-struct S2 {
- s : S1,
-};
-var<workgroup> m : array<S2, 4>;
-
-@compute @workgroup_size(1)
-fn main() {
- let x = m;
-}
-)";
-
- auto* expect = R"(
-struct S1 {
- m : mat2x2<f32>,
-}
-
-struct S2 {
- s : S1,
-}
-
-struct tint_symbol_2 {
- m : array<S2, 4u>,
-}
-
-@compute @workgroup_size(1)
-fn main(@internal(disable_validation__entry_point_parameter) @internal(disable_validation__ignore_address_space) tint_symbol_1 : ptr<workgroup, tint_symbol_2>) {
- let tint_symbol = &((*(tint_symbol_1)).m);
- let x = *(tint_symbol);
-}
-)";
-
- auto got = Run<ModuleScopeVarToEntryPointParam>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-// Test that we do not duplicate a struct type used by multiple workgroup
-// variables that are promoted to threadgroup memory arguments.
-TEST_F(ModuleScopeVarToEntryPointParamTest, DuplicateThreadgroupArgumentTypes) {
- auto* src = R"(
-struct S {
- m : mat2x2<f32>,
-};
-
-var<workgroup> a : S;
-
-var<workgroup> b : S;
-
-@compute @workgroup_size(1)
-fn main() {
- let x = a;
- let y = b;
-}
-)";
-
- auto* expect = R"(
-struct S {
- m : mat2x2<f32>,
-}
-
-struct tint_symbol_3 {
- a : S,
- b : S,
-}
-
-@compute @workgroup_size(1)
-fn main(@internal(disable_validation__entry_point_parameter) @internal(disable_validation__ignore_address_space) tint_symbol_1 : ptr<workgroup, tint_symbol_3>) {
- let tint_symbol = &((*(tint_symbol_1)).a);
- let tint_symbol_2 = &((*(tint_symbol_1)).b);
- let x = *(tint_symbol);
- let y = *(tint_symbol_2);
-}
-)";
-
- auto got = Run<ModuleScopeVarToEntryPointParam>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-// Test that we do not duplicate a struct type used by multiple workgroup
-// variables that are promoted to threadgroup memory arguments.
-TEST_F(ModuleScopeVarToEntryPointParamTest, DuplicateThreadgroupArgumentTypes_OutOfOrder) {
- auto* src = R"(
-@compute @workgroup_size(1)
-fn main() {
- let x = a;
- let y = b;
-}
-
-var<workgroup> a : S;
-var<workgroup> b : S;
-
-struct S {
- m : mat2x2<f32>,
-};
-)";
-
- auto* expect = R"(
-struct S {
- m : mat2x2<f32>,
-}
-
-struct tint_symbol_3 {
- a : S,
- b : S,
-}
-
-@compute @workgroup_size(1)
-fn main(@internal(disable_validation__entry_point_parameter) @internal(disable_validation__ignore_address_space) tint_symbol_1 : ptr<workgroup, tint_symbol_3>) {
- let tint_symbol = &((*(tint_symbol_1)).a);
- let tint_symbol_2 = &((*(tint_symbol_1)).b);
- let x = *(tint_symbol);
- let y = *(tint_symbol_2);
-}
-)";
-
- auto got = Run<ModuleScopeVarToEntryPointParam>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(ModuleScopeVarToEntryPointParamTest, UnusedVariables) {
- auto* src = R"(
-struct S {
- a : f32,
-};
-
-var<private> p : f32;
-var<workgroup> w : f32;
-var<private> p_with_init : f32 = 42;
-
-@group(0) @binding(0)
-var<uniform> ub : S;
-@group(0) @binding(1)
-var<storage> sb : S;
-
-@group(0) @binding(2) var t : texture_2d<f32>;
-@group(0) @binding(3) var s : sampler;
-
-@compute @workgroup_size(1)
-fn main() {
-}
-)";
-
- auto* expect = R"(
-struct tint_private_vars_struct {
- p : f32,
- p_with_init : f32,
-}
-
-struct S {
- a : f32,
-}
-
-@compute @workgroup_size(1)
-fn main() {
-}
-)";
-
- auto got = Run<ModuleScopeVarToEntryPointParam>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(ModuleScopeVarToEntryPointParamTest, MultiplePrivateVariables) {
- auto* src = R"(
-struct S {
- a : f32,
- b : f32,
- c : f32,
-}
-
-var<private> a : f32;
-var<private> b : f32 = 42;
-var<private> c : S = S(1, 2, 3);
-var<private> d : S;
-var<private> unused : f32;
-
-fn foo(x : f32) -> f32 {
- return (a + b + c.a + d.c) * x;
-}
-
-@compute @workgroup_size(1)
-fn main() {
- _ = foo(1.0);
-}
-)";
-
- auto* expect = R"(
-struct S {
- a : f32,
- b : f32,
- c : f32,
-}
-
-struct tint_private_vars_struct {
- a : f32,
- b : f32,
- c : S,
- d : S,
- unused : f32,
-}
-
-fn foo(x : f32, tint_private_vars : ptr<private, tint_private_vars_struct>) -> f32 {
- return (((((*(tint_private_vars)).a + (*(tint_private_vars)).b) + (*(tint_private_vars)).c.a) + (*(tint_private_vars)).d.c) * x);
-}
-
-@compute @workgroup_size(1)
-fn main() {
- @internal(disable_validation__ignore_address_space) var<private> tint_private_vars : tint_private_vars_struct;
- tint_private_vars.b = 42;
- tint_private_vars.c = S(1, 2, 3);
- _ = foo(1.0, &(tint_private_vars));
-}
-)";
-
- auto got = Run<ModuleScopeVarToEntryPointParam>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(ModuleScopeVarToEntryPointParamTest, MultiplePrivateVariables_OutOfOrder) {
- auto* src = R"(
-var<private> a : f32;
-var<private> c : S = S(1, 2, 3);
-var<private> unused : f32;
-
-@compute @workgroup_size(1)
-fn main() {
- _ = foo(1.0);
-}
-
-fn foo(x : f32) -> f32 {
- return (a + b + c.a + d.c) * x;
-}
-
-var<private> b : f32 = 42;
-
-struct S {
- a : f32,
- b : f32,
- c : f32,
-}
-
-var<private> d : S;
-)";
-
- auto* expect = R"(
-struct S {
- a : f32,
- b : f32,
- c : f32,
-}
-
-struct tint_private_vars_struct {
- a : f32,
- c : S,
- unused : f32,
- b : f32,
- d : S,
-}
-
-@compute @workgroup_size(1)
-fn main() {
- @internal(disable_validation__ignore_address_space) var<private> tint_private_vars : tint_private_vars_struct;
- tint_private_vars.c = S(1, 2, 3);
- tint_private_vars.b = 42;
- _ = foo(1.0, &(tint_private_vars));
-}
-
-fn foo(x : f32, tint_private_vars : ptr<private, tint_private_vars_struct>) -> f32 {
- return (((((*(tint_private_vars)).a + (*(tint_private_vars)).b) + (*(tint_private_vars)).c.a) + (*(tint_private_vars)).d.c) * x);
-}
-)";
-
- auto got = Run<ModuleScopeVarToEntryPointParam>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(ModuleScopeVarToEntryPointParamTest, EmtpyModule) {
- auto* src = "";
-
- auto got = Run<ModuleScopeVarToEntryPointParam>(src);
-
- EXPECT_EQ(src, str(got));
-}
-
-} // namespace
-} // namespace tint::msl::writer
diff --git a/src/tint/lang/msl/writer/ast_raise/packed_vec3.cc b/src/tint/lang/msl/writer/ast_raise/packed_vec3.cc
deleted file mode 100644
index 4081fac..0000000
--- a/src/tint/lang/msl/writer/ast_raise/packed_vec3.cc
+++ /dev/null
@@ -1,566 +0,0 @@
-// Copyright 2022 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/tint/lang/msl/writer/ast_raise/packed_vec3.h"
-
-#include <algorithm>
-#include <string>
-#include <utility>
-
-#include "src/tint/lang/core/builtin_type.h"
-#include "src/tint/lang/core/fluent_types.h"
-#include "src/tint/lang/core/type/array.h"
-#include "src/tint/lang/core/type/reference.h"
-#include "src/tint/lang/core/type/vector.h"
-#include "src/tint/lang/wgsl/ast/assignment_statement.h"
-#include "src/tint/lang/wgsl/program/clone_context.h"
-#include "src/tint/lang/wgsl/program/program_builder.h"
-#include "src/tint/lang/wgsl/resolver/resolve.h"
-#include "src/tint/lang/wgsl/sem/array_count.h"
-#include "src/tint/lang/wgsl/sem/index_accessor_expression.h"
-#include "src/tint/lang/wgsl/sem/load.h"
-#include "src/tint/lang/wgsl/sem/statement.h"
-#include "src/tint/lang/wgsl/sem/type_expression.h"
-#include "src/tint/lang/wgsl/sem/variable.h"
-#include "src/tint/utils/containers/hashmap.h"
-#include "src/tint/utils/containers/hashset.h"
-#include "src/tint/utils/containers/vector.h"
-#include "src/tint/utils/rtti/switch.h"
-
-TINT_INSTANTIATE_TYPEINFO(tint::msl::writer::PackedVec3);
-
-using namespace tint::core::number_suffixes; // NOLINT
-using namespace tint::core::fluent_types; // NOLINT
-
-namespace tint::msl::writer {
-
-/// Arrays larger than this will be packed/unpacked with a for loop.
-/// Arrays up to this size will be packed/unpacked with a sequence of statements.
-static constexpr uint32_t kMaxSeriallyUnpackedArraySize = 8;
-
-/// PIMPL state for the transform
-struct PackedVec3::State {
- /// Constructor
- /// @param program the source program
- explicit State(const Program& program) : src(program) {}
-
- /// The name of the struct member used when wrapping packed vec3 types.
- static constexpr const char* kStructMemberName = "elements";
-
- /// The names of the structures used to wrap packed vec3 types.
- Hashmap<const core::type::Type*, Symbol, 4> packed_vec3_wrapper_struct_names;
-
- /// A cache of host-shareable structures that have been rewritten.
- Hashmap<const core::type::Type*, Symbol, 4> rewritten_structs;
-
- /// A map from type to the name of a helper function used to pack that type.
- Hashmap<const core::type::Type*, Symbol, 4> pack_helpers;
-
- /// A map from type to the name of a helper function used to unpack that type.
- Hashmap<const core::type::Type*, Symbol, 4> unpack_helpers;
-
- /// @returns true if @p addrspace requires vec3 types to be packed
- bool AddressSpaceNeedsPacking(core::AddressSpace addrspace) {
- // Host-shareable address spaces need to be packed to match the memory layout on the host.
- // The workgroup address space needs to be packed so that the size of generated threadgroup
- // variables matches the size of the original WGSL declarations.
- return core::IsHostShareable(addrspace) || addrspace == core::AddressSpace::kWorkgroup;
- }
-
- /// @param ty the type to test
- /// @returns true if `ty` is a vec3, false otherwise
- bool IsVec3(const core::type::Type* ty) {
- if (auto* vec = ty->As<core::type::Vector>()) {
- if (vec->Width() == 3) {
- return true;
- }
- }
- return false;
- }
-
- /// @param ty the type to test
- /// @returns true if `ty` is or contains a vec3, false otherwise
- bool ContainsVec3(const core::type::Type* ty) {
- return Switch(
- ty, //
- [&](const core::type::Vector* vec) { return IsVec3(vec); },
- [&](const core::type::Matrix* mat) { return ContainsVec3(mat->ColumnType()); },
- [&](const core::type::Array* arr) { return ContainsVec3(arr->ElemType()); },
- [&](const core::type::Struct* str) {
- for (auto* member : str->Members()) {
- if (ContainsVec3(member->Type())) {
- return true;
- }
- }
- return false;
- });
- }
-
- /// Create a `__packed_vec3` type with the same element type as `ty`.
- /// @param ty a three-element vector type
- /// @returns the new AST type
- ast::Type MakePackedVec3(const core::type::Type* ty) {
- auto* vec = ty->As<core::type::Vector>();
- TINT_ASSERT(vec != nullptr && vec->Width() == 3);
- return b.ty(core::BuiltinType::kPackedVec3, CreateASTTypeFor(ctx, vec->Type()));
- }
-
- /// Recursively rewrite a type using `__packed_vec3`, if needed.
- /// When used as an array element type, the `__packed_vec3` type will be wrapped in a structure
- /// and given an `@align()` attribute to give it alignment it needs to yield the correct array
- /// element stride. For vec3 types used in structures directly, the `@align()` attribute is
- /// placed on the containing structure instead. Matrices with three rows become arrays of
- /// columns, and used the aligned wrapper struct for the column type.
- /// @param ty the type to rewrite
- /// @param array_element `true` if this is being called for the element of an array
- /// @returns the new AST type, or nullptr if rewriting was not necessary
- ast::Type RewriteType(const core::type::Type* ty, bool array_element = false) {
- return Switch(
- ty,
- [&](const core::type::Vector* vec) -> ast::Type {
- if (IsVec3(vec)) {
- if (array_element) {
- // Create a struct with a single `__packed_vec3` member.
- // Give the struct member the same alignment as the original unpacked vec3
- // type, to avoid changing the array element stride.
- return b.ty(packed_vec3_wrapper_struct_names.GetOrAdd(vec, [&] {
- auto name = b.Symbols().New(
- "tint_packed_vec3_" + vec->Type()->FriendlyName() +
- (array_element ? "_array_element" : "_struct_member"));
- auto* member =
- b.Member(kStructMemberName, MakePackedVec3(vec),
- tint::Vector{b.MemberAlign(AInt(vec->Align()))});
- b.Structure(b.Ident(name), tint::Vector{member}, tint::Empty);
- return name;
- }));
- } else {
- return MakePackedVec3(vec);
- }
- }
- return {};
- },
- [&](const core::type::Matrix* mat) -> ast::Type {
- // Rewrite the matrix as an array of columns that use the aligned wrapper struct.
- auto new_col_type = RewriteType(mat->ColumnType(), /* array_element */ true);
- if (new_col_type) {
- return b.ty.array(new_col_type, u32(mat->Columns()));
- }
- return {};
- },
- [&](const core::type::Array* arr) -> ast::Type {
- // Rewrite the array with the modified element type.
- auto new_type = RewriteType(arr->ElemType(), /* array_element */ true);
- if (new_type) {
- tint::Vector<const ast::Attribute*, 1> attrs;
- if (arr->Count()->Is<core::type::RuntimeArrayCount>()) {
- return b.ty.array(new_type, std::move(attrs));
- } else if (auto count = arr->ConstantCount()) {
- return b.ty.array(new_type, u32(count.value()), std::move(attrs));
- } else {
- TINT_ICE() << core::type::Array::kErrExpectedConstantCount;
- }
- }
- return {};
- },
- [&](const core::type::Struct* str) -> ast::Type {
- if (ContainsVec3(str)) {
- auto name = rewritten_structs.GetOrAdd(str, [&] {
- tint::Vector<const ast::StructMember*, 4> members;
- for (auto* member : str->Members()) {
- // If the member type contains a vec3, rewrite it.
- auto new_type = RewriteType(member->Type());
- if (new_type) {
- // Copy the member attributes.
- bool needs_align = true;
- tint::Vector<const ast::Attribute*, 4> attributes;
- if (auto* sem_mem = member->As<sem::StructMember>()) {
- for (auto* attr : sem_mem->Declaration()->attributes) {
- if (attr->IsAnyOf<ast::StructMemberAlignAttribute,
- ast::StructMemberOffsetAttribute>()) {
- needs_align = false;
- }
- attributes.Push(ctx.Clone(attr));
- }
- }
- // If the alignment wasn't already specified, add an attribute to
- // make sure that we don't alter the alignment when using the packed
- // vector type.
- if (needs_align) {
- attributes.Push(b.MemberAlign(AInt(member->Align())));
- }
- members.Push(b.Member(ctx.Clone(member->Name()), new_type,
- std::move(attributes)));
- } else {
- // No vec3s, just clone the member as is.
- if (auto* sem_mem = member->As<sem::StructMember>()) {
- members.Push(ctx.Clone(sem_mem->Declaration()));
- } else {
- members.Push(
- b.Member(ctx.Clone(member->Name()), new_type, tint::Empty));
- }
- }
- }
- // Create the new structure.
- auto struct_name =
- b.Symbols().New(str->Name().Name() + "_tint_packed_vec3");
- b.Structure(struct_name, std::move(members));
- return struct_name;
- });
- return b.ty(name);
- }
- return {};
- });
- }
-
- /// Create a helper function to recursively pack or unpack a composite that contains vec3 types.
- /// @param name_prefix the name of the helper function
- /// @param ty the composite type to pack or unpack
- /// @param pack_or_unpack_element a function that packs or unpacks an element with a given type
- /// @param in_type a function that create an AST type for the input type
- /// @param out_type a function that create an AST type for the output type
- /// @returns the name of the helper function
- Symbol MakePackUnpackHelper(
- const char* name_prefix,
- const core::type::Type* ty,
- const std::function<const ast::Expression*(const ast::Expression*,
- const core::type::Type*)>&
- pack_or_unpack_element,
- const std::function<ast::Type()>& in_type,
- const std::function<ast::Type()>& out_type) {
- // Allocate a variable to hold the return value of the function.
- tint::Vector<const ast::Statement*, 4> statements;
-
- // Helper that generates a loop to copy and pack/unpack elements of an array to the result:
- // for (var i = 0u; i < num_elements; i = i + 1) {
- // result[i] = pack_or_unpack_element(in[i]);
- // }
- auto copy_array_elements = [&](uint32_t num_elements,
- const core::type::Type* element_type) {
- // Generate code for unpacking the array.
- if (num_elements <= kMaxSeriallyUnpackedArraySize) {
- // Generate a variable with an explicit initializer.
- tint::Vector<const ast::Expression*, 8> elements;
- for (uint32_t i = 0; i < num_elements; i++) {
- elements.Push(pack_or_unpack_element(
- b.IndexAccessor("in", b.Expr(core::AInt(i))), element_type));
- }
- statements.Push(b.Decl(b.Var("result", b.Call(out_type(), b.ExprList(elements)))));
- } else {
- statements.Push(b.Decl(b.Var("result", out_type())));
- // Generate a for loop.
- // Generate an expression for packing or unpacking an element of the array.
- auto* element = pack_or_unpack_element(b.IndexAccessor("in", "i"), element_type);
- statements.Push(b.For( //
- b.Decl(b.Var("i", b.ty.u32())), //
- b.LessThan("i", u32(num_elements)), //
- b.Assign("i", b.Add("i", 1_a)), //
- b.Block(tint::Vector{
- b.Assign(b.IndexAccessor("result", "i"), element),
- })));
- }
- };
-
- // Copy the elements of the value over to the result.
- Switch(
- ty,
- [&](const core::type::Array* arr) {
- TINT_ASSERT(arr->ConstantCount());
- copy_array_elements(arr->ConstantCount().value(), arr->ElemType());
- },
- [&](const core::type::Matrix* mat) {
- copy_array_elements(mat->Columns(), mat->ColumnType());
- },
- [&](const core::type::Struct* str) {
- statements.Push(b.Decl(b.Var("result", out_type())));
- // Copy the struct members over one at a time, packing/unpacking as necessary.
- for (auto* member : str->Members()) {
- const ast::Expression* element =
- b.MemberAccessor("in", b.Ident(ctx.Clone(member->Name())));
- if (ContainsVec3(member->Type())) {
- element = pack_or_unpack_element(element, member->Type());
- }
- statements.Push(b.Assign(
- b.MemberAccessor("result", b.Ident(ctx.Clone(member->Name()))), element));
- }
- });
-
- // Return the result.
- statements.Push(b.Return("result"));
-
- // Create the function and return its name.
- auto name = b.Symbols().New(name_prefix);
- b.Func(name, tint::Vector{b.Param("in", in_type())}, out_type(), std::move(statements));
- return name;
- }
-
- /// Unpack the composite value `expr` to the unpacked type `ty`. If `ty` is a matrix, this will
- /// produce a regular matNx3 value from an array of packed column vectors.
- /// @param expr the composite value expression to unpack
- /// @param ty the unpacked type
- /// @returns an expression that holds the unpacked value
- const ast::Expression* UnpackComposite(const ast::Expression* expr,
- const core::type::Type* ty) {
- auto helper = unpack_helpers.GetOrAdd(ty, [&] {
- return MakePackUnpackHelper(
- "tint_unpack_vec3_in_composite", ty,
- [&](const ast::Expression* element,
- const core::type::Type* element_type) -> const ast::Expression* {
- if (element_type->Is<core::type::Vector>()) {
- // Unpack a `__packed_vec3` by casting it to a regular vec3.
- // If it is an array element, extract the vector from the wrapper struct.
- if (element->Is<ast::IndexAccessorExpression>()) {
- element = b.MemberAccessor(element, kStructMemberName);
- }
- return b.Call(CreateASTTypeFor(ctx, element_type), element);
- } else {
- return UnpackComposite(element, element_type);
- }
- },
- [&] { return RewriteType(ty); }, //
- [&] { return CreateASTTypeFor(ctx, ty); });
- });
- return b.Call(helper, expr);
- }
-
- /// Pack the composite value `expr` from the unpacked type `ty`. If `ty` is a matrix, this will
- /// produce an array of packed column vectors.
- /// @param expr the composite value expression to pack
- /// @param ty the unpacked type
- /// @returns an expression that holds the packed value
- const ast::Expression* PackComposite(const ast::Expression* expr, const core::type::Type* ty) {
- auto helper = pack_helpers.GetOrAdd(ty, [&] {
- return MakePackUnpackHelper(
- "tint_pack_vec3_in_composite", ty,
- [&](const ast::Expression* element,
- const core::type::Type* element_type) -> const ast::Expression* {
- if (element_type->Is<core::type::Vector>()) {
- // Pack a vector element by casting it to a packed_vec3.
- // If it is an array element, construct a wrapper struct.
- auto* packed = b.Call(MakePackedVec3(element_type), element);
- if (element->Is<ast::IndexAccessorExpression>()) {
- packed = b.Call(RewriteType(element_type, true), packed);
- }
- return packed;
- } else {
- return PackComposite(element, element_type);
- }
- },
- [&] { return CreateASTTypeFor(ctx, ty); }, //
- [&] { return RewriteType(ty); });
- });
- return b.Call(helper, expr);
- }
-
- /// @returns true if there are host-shareable vec3's that need transforming
- bool ShouldRun() {
- // Check for vec3s in the types of all uniform and storage buffer variables to determine
- // if the transform is necessary.
- for (auto* decl : src.AST().GlobalVariables()) {
- auto* var = sem.Get<sem::GlobalVariable>(decl);
- if (var && AddressSpaceNeedsPacking(var->AddressSpace()) &&
- ContainsVec3(var->Type()->UnwrapRef())) {
- return true;
- }
- }
- return false;
- }
-
- /// Runs the transform
- /// @returns the new program or SkipTransform if the transform is not required
- ApplyResult Run() {
- if (!ShouldRun()) {
- return SkipTransform;
- }
-
- // Changing the types of certain structure members can trigger stricter layout validation
- // rules for the uniform address space. In particular, replacing 16-bit matrices with arrays
- // violates the requirement that the array element stride is a multiple of 16 bytes, and
- // replacing vec3s with a structure violates the requirement that there must be at least 16
- // bytes from the start of a structure to the start of the next member.
- // Disable these validation rules using an internal extension, as MSL does not have these
- // restrictions.
- b.Enable(wgsl::Extension::kChromiumInternalRelaxedUniformLayout);
-
- // Track expressions that need to be packed or unpacked.
- Hashset<const sem::ValueExpression*, 8> to_pack;
- Hashset<const sem::ValueExpression*, 8> to_unpack;
-
- // Replace vec3 types in host-shareable address spaces with `__packed_vec3` types, and
- // collect expressions that need to be converted to or from values that use the
- // `__packed_vec3` type.
- for (auto* node : src.ASTNodes().Objects()) {
- Switch(
- sem.Get(node),
- [&](const sem::TypeExpression* type) {
- // Rewrite pointers to types that contain vec3s.
- auto* ptr = type->Type()->As<core::type::Pointer>();
- if (ptr && AddressSpaceNeedsPacking(ptr->AddressSpace())) {
- auto new_store_type = RewriteType(ptr->StoreType());
- if (new_store_type) {
- auto access = ptr->AddressSpace() == core::AddressSpace::kStorage
- ? ptr->Access()
- : core::Access::kUndefined;
- auto new_ptr_type =
- b.ty.ptr(ptr->AddressSpace(), new_store_type, access);
- ctx.Replace(node, new_ptr_type.expr);
- }
- }
- },
- [&](const sem::Variable* var) {
- if (!AddressSpaceNeedsPacking(var->AddressSpace())) {
- return;
- }
-
- // Rewrite the var type, if it contains vec3s.
- auto new_store_type = RewriteType(var->Type()->UnwrapRef());
- if (new_store_type) {
- ctx.Replace(var->Declaration()->type.expr, new_store_type.expr);
- }
- },
- [&](const sem::Statement* stmt) {
- // Pack the RHS of assignment statements that are writing to packed types.
- if (auto* assign = stmt->Declaration()->As<ast::AssignmentStatement>()) {
- auto* lhs = sem.GetVal(assign->lhs);
- auto* rhs = sem.GetVal(assign->rhs);
- if (!ContainsVec3(rhs->Type()) ||
- !AddressSpaceNeedsPacking(
- lhs->Type()->As<core::type::Reference>()->AddressSpace())) {
- // Skip assignments to address spaces that are not host-shareable, or
- // that do not contain vec3 types.
- return;
- }
-
- // Pack the RHS expression.
- if (to_unpack.Contains(rhs)) {
- // The expression will already be packed, so skip the pending unpack.
- to_unpack.Remove(rhs);
-
- // If the expression produces a vec3 from an array element, extract
- // the packed vector from the wrapper struct.
- if (IsVec3(rhs->Type()) &&
- rhs->UnwrapLoad()->Is<sem::IndexAccessorExpression>()) {
- ctx.Replace(rhs->Declaration(),
- b.MemberAccessor(ctx.Clone(rhs->Declaration()),
- kStructMemberName));
- }
- } else if (rhs) {
- to_pack.Add(rhs);
- }
- }
- },
- [&](const sem::Load* load) {
- // Unpack loads of types that contain vec3s in host-shareable address spaces.
- if (ContainsVec3(load->Type()) &&
- AddressSpaceNeedsPacking(load->MemoryView()->AddressSpace())) {
- to_unpack.Add(load);
- }
- },
- [&](const sem::IndexAccessorExpression* accessor) {
- // If the expression produces a reference to a vec3 in a host-shareable address
- // space from an array element, extract the packed vector from the wrapper
- // struct.
- if (auto* ref = accessor->Type()->As<core::type::Reference>()) {
- if (IsVec3(ref->StoreType()) &&
- AddressSpaceNeedsPacking(ref->AddressSpace())) {
- ctx.Replace(node, b.MemberAccessor(ctx.Clone(accessor->Declaration()),
- kStructMemberName));
- }
- }
- });
- }
-
- // Sort the pending pack/unpack operations by AST node ID to make the order deterministic.
- auto to_unpack_sorted = to_unpack.Vector();
- auto to_pack_sorted = to_pack.Vector();
- auto pred = [&](auto* expr_a, auto* expr_b) {
- return expr_a->Declaration()->node_id < expr_b->Declaration()->node_id;
- };
- to_unpack_sorted.Sort(pred);
- to_pack_sorted.Sort(pred);
-
- // Apply all of the pending unpack operations that we have collected.
- for (auto* expr : to_unpack_sorted) {
- TINT_ASSERT(ContainsVec3(expr->Type()));
- auto* packed = ctx.Clone(expr->Declaration());
- const ast::Expression* unpacked = nullptr;
- if (IsVec3(expr->Type())) {
- if (expr->UnwrapLoad()->Is<sem::IndexAccessorExpression>()) {
- // If we are unpacking a vec3 from an array element, extract the vector from the
- // wrapper struct.
- packed = b.MemberAccessor(packed, kStructMemberName);
- }
- // Cast the packed vector to a regular vec3.
- unpacked = b.Call(CreateASTTypeFor(ctx, expr->Type()), packed);
- } else {
- // Use a helper function to unpack an array or matrix.
- unpacked = UnpackComposite(packed, expr->Type());
- }
- TINT_ASSERT(unpacked != nullptr);
- ctx.Replace(expr->Declaration(), unpacked);
- }
-
- // Apply all of the pending pack operations that we have collected.
- for (auto* expr : to_pack_sorted) {
- TINT_ASSERT(ContainsVec3(expr->Type()));
- auto* unpacked = ctx.Clone(expr->Declaration());
- const ast::Expression* packed = nullptr;
- if (IsVec3(expr->Type())) {
- // Cast the regular vec3 to a packed vector type.
- packed = b.Call(MakePackedVec3(expr->Type()), unpacked);
- } else {
- // Use a helper function to pack an array or matrix.
- packed = PackComposite(unpacked, expr->Type());
- }
- TINT_ASSERT(packed != nullptr);
- ctx.Replace(expr->Declaration(), packed);
- }
-
- ctx.Clone();
- return resolver::Resolve(b);
- }
-
- private:
- /// The source program
- const Program& src;
- /// The target program builder
- ProgramBuilder b;
- /// The clone context
- program::CloneContext ctx = {&b, &src, /* auto_clone_symbols */ true};
- /// Alias to the semantic info in ctx.src
- const sem::Info& sem = src.Sem();
-};
-
-PackedVec3::PackedVec3() = default;
-PackedVec3::~PackedVec3() = default;
-
-ast::transform::Transform::ApplyResult PackedVec3::Apply(const Program& src,
- const ast::transform::DataMap&,
- ast::transform::DataMap&) const {
- return State{src}.Run();
-}
-
-} // namespace tint::msl::writer
diff --git a/src/tint/lang/msl/writer/ast_raise/packed_vec3.h b/src/tint/lang/msl/writer/ast_raise/packed_vec3.h
deleted file mode 100644
index 9e19dc2..0000000
--- a/src/tint/lang/msl/writer/ast_raise/packed_vec3.h
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright 2022 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef SRC_TINT_LANG_MSL_WRITER_AST_RAISE_PACKED_VEC3_H_
-#define SRC_TINT_LANG_MSL_WRITER_AST_RAISE_PACKED_VEC3_H_
-
-#include "src/tint/lang/wgsl/ast/transform/transform.h"
-
-namespace tint::msl::writer {
-
-/// A transform to be used by the MSL backend which will:
-/// * Replace `vec3<T>` types with an internal `__packed_vec3` type when they are used in
-/// host-shareable address spaces.
-/// * Wrap generated `__packed_vec3` types in a structure when they are used in arrays, so that we
-/// ensure that the array has the correct element stride.
-/// * Multi-version structures that contain `vec3<T>` types when they are used in host-shareable
-/// memory, to avoid modifying uses in other address spaces.
-/// * Rewrite matrix types that have three rows into arrays of column vectors.
-/// * Insert calls to helper functions to convert expressions that use these types to or from the
-/// regular vec3 types when accessing host-shareable memory.
-/// * Cast all direct (not sub-accessed) loads of these packed vectors to the 'unpacked' vec3<T>
-/// type before usage.
-///
-/// This transform is necessary in order to emit vec3 types with the correct size (so that scalars
-/// can follow them in structures), and also to ensure that padding bytes are preserved when writing
-/// to a vec3, an array of vec3 elements, or a matrix with vec3 column type.
-///
-/// @note Depends on the following transforms to have been run first:
-/// * ExpandCompoundAssignment
-class PackedVec3 final : public Castable<PackedVec3, ast::transform::Transform> {
- public:
- /// Constructor
- PackedVec3();
- /// Destructor
- ~PackedVec3() override;
-
- /// @copydoc ast::transform::Transform::Apply
- ApplyResult Apply(const Program& program,
- const ast::transform::DataMap& inputs,
- ast::transform::DataMap& outputs) const override;
-
- private:
- struct State;
-};
-
-} // namespace tint::msl::writer
-
-#endif // SRC_TINT_LANG_MSL_WRITER_AST_RAISE_PACKED_VEC3_H_
diff --git a/src/tint/lang/msl/writer/ast_raise/packed_vec3_test.cc b/src/tint/lang/msl/writer/ast_raise/packed_vec3_test.cc
deleted file mode 100644
index 9fab6df..0000000
--- a/src/tint/lang/msl/writer/ast_raise/packed_vec3_test.cc
+++ /dev/null
@@ -1,8768 +0,0 @@
-// Copyright 2022 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/tint/lang/msl/writer/ast_raise/packed_vec3.h"
-
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "src/tint/lang/core/fluent_types.h"
-#include "src/tint/lang/core/type/array.h"
-#include "src/tint/lang/wgsl/ast/module.h"
-#include "src/tint/lang/wgsl/ast/transform/helper_test.h"
-#include "src/tint/lang/wgsl/program/program_builder.h"
-#include "src/tint/lang/wgsl/resolver/resolve.h"
-#include "src/tint/lang/wgsl/sem/struct.h"
-#include "src/tint/lang/wgsl/sem/variable.h"
-#include "src/tint/utils/text/string.h"
-
-using namespace tint::core::fluent_types; // NOLINT
-
-namespace tint::msl::writer {
-namespace {
-
-using PackedVec3Test = ast::transform::TransformTest;
-
-TEST_F(PackedVec3Test, ShouldRun_EmptyModule) {
- auto* src = R"()";
-
- EXPECT_FALSE(ShouldRun<PackedVec3>(src));
-}
-
-TEST_F(PackedVec3Test, ShouldRun_NoHostShareableVec3s) {
- auto* src = R"(
-struct S {
- v : vec3<f32>,
- m : mat3x3<f32>,
- a : array<vec3<f32>, 4>,
-}
-
-var<private> p_s : S;
-var<private> p_v : vec3<f32>;
-var<private> p_m : mat3x3<f32>;
-var<private> p_a : array<vec3<f32>, 4>;
-
-fn f() {
- var f_s : S;
- var f_v : vec3<f32>;
- var f_m : mat3x3<f32>;
- var f_a : array<vec3<f32>, 4>;
-}
-)";
-
- EXPECT_FALSE(ShouldRun<PackedVec3>(src));
-}
-
-TEST_F(PackedVec3Test, ShouldRun_Vec4Vec2) {
- auto* src = R"(
-struct S {
- v4 : vec4<f32>,
- v2 : vec2<f32>,
-}
-
-@group(0) @binding(0) var<uniform> Ps : S; // Host sharable
-@group(0) @binding(1) var<uniform> Pv4 : vec4<f32>; // Host sharable
-@group(0) @binding(2) var<uniform> Pv2 : vec2<f32>; // Host sharable
-)";
-
- EXPECT_FALSE(ShouldRun<PackedVec3>(src));
-}
-
-TEST_F(PackedVec3Test, ShouldRun_OtherMatrices) {
- auto* src = R"(
-struct S {
- m2x2 : mat2x2<f32>,
- m2x4 : mat2x4<f32>,
- m3x2 : mat3x2<f32>,
- m3x4 : mat3x4<f32>,
- m4x2 : mat4x2<f32>,
- m4x4 : mat4x4<f32>,
-}
-
-@group(0) @binding(0) var<uniform> Ps : S; // Host sharable
-@group(0) @binding(1) var<uniform> Pm2x2 : mat2x2<f32>; // Host sharable
-@group(0) @binding(2) var<uniform> Pm2x4 : mat2x4<f32>; // Host sharable
-@group(0) @binding(3) var<uniform> Pm3x2 : mat3x2<f32>; // Host sharable
-@group(0) @binding(4) var<uniform> Pm3x4 : mat3x4<f32>; // Host sharable
-@group(0) @binding(5) var<uniform> Pm4x2 : mat4x2<f32>; // Host sharable
-@group(0) @binding(6) var<uniform> Pm4x4 : mat4x4<f32>; // Host sharable
-)";
-
- EXPECT_FALSE(ShouldRun<PackedVec3>(src));
-}
-
-TEST_F(PackedVec3Test, ShouldRun_ArrayOfNonVec3) {
- auto* src = R"(
-struct S {
- arr_v : array<vec2<f32>, 4>,
- arr_m : array<mat3x2<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage> Ps : S; // Host sharable
-@group(0) @binding(1) var<storage> Parr_v : array<vec2<f32>, 4>; // Host sharable
-@group(0) @binding(2) var<storage> Parr_m : array<mat3x2<f32>, 4>; // Host sharable
-)";
-
- EXPECT_FALSE(ShouldRun<PackedVec3>(src));
-}
-
-TEST_F(PackedVec3Test, ShouldRun_HostSharable_Vec3) {
- auto* src = R"(
-@group(0) @binding(0) var<uniform> P : vec3<f32>; // Host sharable
-)";
-
- EXPECT_TRUE(ShouldRun<PackedVec3>(src));
-}
-
-TEST_F(PackedVec3Test, ShouldRun_HostSharable_Mat3x3) {
- auto* src = R"(
-@group(0) @binding(0) var<uniform> P : mat3x3<f32>; // Host sharable
-)";
-
- EXPECT_TRUE(ShouldRun<PackedVec3>(src));
-}
-
-TEST_F(PackedVec3Test, ShouldRun_HostSharable_ArrayOfVec3) {
- auto* src = R"(
-@group(0) @binding(0) var<storage> P : array<vec3<f32>>; // Host sharable
-)";
-
- EXPECT_TRUE(ShouldRun<PackedVec3>(src));
-}
-
-TEST_F(PackedVec3Test, ShouldRun_HostSharable_ArrayOfMat3x3) {
- auto* src = R"(
-@group(0) @binding(0) var<storage> P : array<mat3x3<f32>>; // Host sharable
-)";
-
- EXPECT_TRUE(ShouldRun<PackedVec3>(src));
-}
-
-TEST_F(PackedVec3Test, ShouldRun_HostSharableStruct_Vec3) {
- auto* src = R"(
-struct S {
- v : vec3<f32>,
-}
-
-@group(0) @binding(0) var<uniform> P : S; // Host sharable
-)";
-
- EXPECT_TRUE(ShouldRun<PackedVec3>(src));
-}
-
-TEST_F(PackedVec3Test, ShouldRun_HostSharableStruct_Mat3x3) {
- auto* src = R"(
-struct S {
- m : mat3x3<f32>,
-}
-
-@group(0) @binding(0) var<uniform> P : S; // Host sharable
-)";
-
- EXPECT_TRUE(ShouldRun<PackedVec3>(src));
-}
-
-TEST_F(PackedVec3Test, ShouldRun_HostSharableStruct_ArrayOfVec3) {
- auto* src = R"(
-struct S {
- a : array<vec3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<uniform> P : S; // Host sharable
-)";
-
- EXPECT_TRUE(ShouldRun<PackedVec3>(src));
-}
-
-TEST_F(PackedVec3Test, ShouldRun_HostSharableStruct_ArrayOfMat3x3) {
- auto* src = R"(
-struct S {
- a : array<mat3x3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<uniform> P : S; // Host sharable
-)";
-
- EXPECT_TRUE(ShouldRun<PackedVec3>(src));
-}
-
-TEST_F(PackedVec3Test, Vec3_ReadVector) {
- auto* src = R"(
-@group(0) @binding(0) var<storage> v : vec3<f32>;
-
-fn f() {
- let x = v;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-@group(0) @binding(0) var<storage> v : __packed_vec3<f32>;
-
-fn f() {
- let x = vec3<f32>(v);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, Vec3_ReadComponent_MemberAccessChain) {
- auto* src = R"(
-@group(0) @binding(0) var<storage> v : vec3<f32>;
-
-fn f() {
- let x = v.yz.x;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-@group(0) @binding(0) var<storage> v : __packed_vec3<f32>;
-
-fn f() {
- let x = vec3<f32>(v).yz.x;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, Vec3_ReadComponent_IndexAccessor) {
- auto* src = R"(
-@group(0) @binding(0) var<storage> v : vec3<f32>;
-
-fn f() {
- let x = v[1];
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-@group(0) @binding(0) var<storage> v : __packed_vec3<f32>;
-
-fn f() {
- let x = v[1];
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, Vec3_ReadComponent_IndexAccessor_ViaDerefPointerIndex) {
- auto* src = R"(
-@group(0) @binding(0) var<storage> v : vec3<f32>;
-
-fn f() {
- let p = &v;
- let x = (*p)[1];
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-@group(0) @binding(0) var<storage> v : __packed_vec3<f32>;
-
-fn f() {
- let p = &(v);
- let x = (*(p))[1];
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, Vec3_ReadComponent_IndexAccessor_ViaPointerIndex) {
- auto* src = R"(
-@group(0) @binding(0) var<storage> v : vec3<f32>;
-
-fn f() {
- let p = &v;
- let x = p[1];
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-@group(0) @binding(0) var<storage> v : __packed_vec3<f32>;
-
-fn f() {
- let p = &(v);
- let x = p[1];
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, Vec3_WriteVector_ValueRHS) {
- auto* src = R"(
-@group(0) @binding(0) var<storage, read_write> v : vec3<f32>;
-
-fn f() {
- v = vec3(1.23);
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-@group(0) @binding(0) var<storage, read_write> v : __packed_vec3<f32>;
-
-fn f() {
- v = __packed_vec3<f32>(vec3(1.22999999999999998224));
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, Vec3_WriteVector_RefRHS) {
- auto* src = R"(
-@group(0) @binding(0) var<storage, read_write> v : vec3<f32>;
-@group(0) @binding(1) var<uniform> in : vec3<f32>;
-
-fn f() {
- v = in;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-@group(0) @binding(0) var<storage, read_write> v : __packed_vec3<f32>;
-
-@group(0) @binding(1) var<uniform> in : __packed_vec3<f32>;
-
-fn f() {
- v = in;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, Vec3_WriteComponent_MemberAccessor) {
- auto* src = R"(
-@group(0) @binding(0) var<storage, read_write> v : vec3<f32>;
-
-fn f() {
- v.y = 1.23;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-@group(0) @binding(0) var<storage, read_write> v : __packed_vec3<f32>;
-
-fn f() {
- v.y = 1.22999999999999998224;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, Vec3_WriteComponent_MemberAccessor_ViaDerefPointerDot) {
- auto* src = R"(
-@group(0) @binding(0) var<storage, read_write> v : vec3<f32>;
-
-fn f() {
- let p = &v;
- (*p).y = 1.23;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-@group(0) @binding(0) var<storage, read_write> v : __packed_vec3<f32>;
-
-fn f() {
- let p = &(v);
- (*(p)).y = 1.22999999999999998224;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, Vec3_WriteComponent_MemberAccessor_ViaPointerDot) {
- auto* src = R"(
-@group(0) @binding(0) var<storage, read_write> v : vec3<f32>;
-
-fn f() {
- let p = &v;
- p.y = 1.23;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-@group(0) @binding(0) var<storage, read_write> v : __packed_vec3<f32>;
-
-fn f() {
- let p = &(v);
- p.y = 1.22999999999999998224;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, Vec3_WriteComponent_IndexAccessor) {
- auto* src = R"(
-@group(0) @binding(0) var<storage, read_write> v : vec3<f32>;
-
-fn f() {
- v[1] = 1.23;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-@group(0) @binding(0) var<storage, read_write> v : __packed_vec3<f32>;
-
-fn f() {
- v[1] = 1.22999999999999998224;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ArrayOfVec3_ReadArray_Small) {
- auto* src = R"(
-@group(0) @binding(0) var<storage> arr : array<vec3<f32>, 4>;
-
-fn f() {
- let x = arr;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 4u>) -> array<vec3<f32>, 4u> {
- var result = array<vec3<f32>, 4u>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements), vec3<f32>(in[3].elements));
- return result;
-}
-
-@group(0) @binding(0) var<storage> arr : array<tint_packed_vec3_f32_array_element, 4u>;
-
-fn f() {
- let x = tint_unpack_vec3_in_composite(arr);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ArrayOfVec3_ReadArray_Large) {
- auto* src = R"(
-@group(0) @binding(0) var<storage> arr : array<vec3<f32>, 9>;
-
-fn f() {
- let x = arr;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 9u>) -> array<vec3<f32>, 9u> {
- var result : array<vec3<f32>, 9u>;
- for(var i : u32; (i < 9u); i = (i + 1)) {
- result[i] = vec3<f32>(in[i].elements);
- }
- return result;
-}
-
-@group(0) @binding(0) var<storage> arr : array<tint_packed_vec3_f32_array_element, 9u>;
-
-fn f() {
- let x = tint_unpack_vec3_in_composite(arr);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ArrayOfVec3_ReadVector) {
- auto* src = R"(
-@group(0) @binding(0) var<storage> arr : array<vec3<f32>, 4>;
-
-fn f() {
- let x = arr[0];
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage> arr : array<tint_packed_vec3_f32_array_element, 4u>;
-
-fn f() {
- let x = vec3<f32>(arr[0].elements);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ArrayOfVec3_ReadComponent_MemberAccessor) {
- auto* src = R"(
-@group(0) @binding(0) var<storage> arr : array<vec3<f32>, 4>;
-
-fn f() {
- let x = arr[0].y;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage> arr : array<tint_packed_vec3_f32_array_element, 4u>;
-
-fn f() {
- let x = arr[0].elements.y;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ArrayOfVec3_ReadComponent_IndexAccessor) {
- auto* src = R"(
-@group(0) @binding(0) var<storage> arr : array<vec3<f32>, 4>;
-
-fn f() {
- let x = arr[0][1];
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage> arr : array<tint_packed_vec3_f32_array_element, 4u>;
-
-fn f() {
- let x = arr[0].elements[1];
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ArrayOfVec3_WriteArray_ValueRHS_Small) {
- auto* src = R"(
-@group(0) @binding(0) var<storage, read_write> arr : array<vec3<f32>, 2>;
-
-fn f() {
- arr = array(vec3(1.5, 2.5, 3.5), vec3(4.5, 5.5, 6.5));
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-fn tint_pack_vec3_in_composite(in : array<vec3<f32>, 2u>) -> array<tint_packed_vec3_f32_array_element, 2u> {
- var result = array<tint_packed_vec3_f32_array_element, 2u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])));
- return result;
-}
-
-@group(0) @binding(0) var<storage, read_write> arr : array<tint_packed_vec3_f32_array_element, 2u>;
-
-fn f() {
- arr = tint_pack_vec3_in_composite(array(vec3(1.5, 2.5, 3.5), vec3(4.5, 5.5, 6.5)));
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ArrayOfVec3_WriteArray_ValueRHS_Large) {
- auto* src = R"(
-@group(0) @binding(0) var<storage, read_write> arr : array<vec3<f32>, 9>;
-
-fn f() {
- arr = array(vec3(1.5, 2.5, 3.5),
- vec3(4.5, 5.5, 6.5),
- vec3(7.5, 8.5, 9.5),
- vec3(7.5, 8.5, 9.5),
- vec3(7.5, 8.5, 9.5),
- vec3(7.5, 8.5, 9.5),
- vec3(7.5, 8.5, 9.5),
- vec3(7.5, 8.5, 9.5),
- vec3(7.5, 8.5, 9.5));
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-fn tint_pack_vec3_in_composite(in : array<vec3<f32>, 9u>) -> array<tint_packed_vec3_f32_array_element, 9u> {
- var result : array<tint_packed_vec3_f32_array_element, 9u>;
- for(var i : u32; (i < 9u); i = (i + 1)) {
- result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
- }
- return result;
-}
-
-@group(0) @binding(0) var<storage, read_write> arr : array<tint_packed_vec3_f32_array_element, 9u>;
-
-fn f() {
- arr = tint_pack_vec3_in_composite(array(vec3(1.5, 2.5, 3.5), vec3(4.5, 5.5, 6.5), vec3(7.5, 8.5, 9.5), vec3(7.5, 8.5, 9.5), vec3(7.5, 8.5, 9.5), vec3(7.5, 8.5, 9.5), vec3(7.5, 8.5, 9.5), vec3(7.5, 8.5, 9.5), vec3(7.5, 8.5, 9.5)));
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ArrayOfVec3_WriteArray_RefRHS) {
- auto* src = R"(
-@group(0) @binding(0) var<storage, read_write> arr : array<vec3<f32>, 2>;
-@group(0) @binding(1) var<uniform> in : array<vec3<f32>, 2>;
-
-fn f() {
- arr = in;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> arr : array<tint_packed_vec3_f32_array_element, 2u>;
-
-@group(0) @binding(1) var<uniform> in : array<tint_packed_vec3_f32_array_element, 2u>;
-
-fn f() {
- arr = in;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ArrayOfVec3_WriteVector_ValueRHS) {
- auto* src = R"(
-@group(0) @binding(0) var<storage, read_write> arr : array<vec3<f32>, 4>;
-
-fn f() {
- arr[0] = vec3(1.23);
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> arr : array<tint_packed_vec3_f32_array_element, 4u>;
-
-fn f() {
- arr[0].elements = __packed_vec3<f32>(vec3(1.22999999999999998224));
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ArrayOfVec3_WriteVector_RefRHS_Small) {
- auto* src = R"(
-@group(0) @binding(0) var<storage, read_write> arr : array<vec3<f32>, 4>;
-@group(0) @binding(1) var<uniform> in_arr : array<vec3<f32>, 4>;
-@group(0) @binding(2) var<uniform> in_vec : vec3<f32>;
-
-fn f() {
- arr[0] = in_arr[0];
- arr[1] = in_vec;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> arr : array<tint_packed_vec3_f32_array_element, 4u>;
-
-@group(0) @binding(1) var<uniform> in_arr : array<tint_packed_vec3_f32_array_element, 4u>;
-
-@group(0) @binding(2) var<uniform> in_vec : __packed_vec3<f32>;
-
-fn f() {
- arr[0].elements = in_arr[0].elements;
- arr[1].elements = in_vec;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ArrayOfVec3_WriteVector_RefRHS_Large) {
- auto* src = R"(
-@group(0) @binding(0) var<storage, read_write> arr : array<vec3<f32>, 9>;
-@group(0) @binding(1) var<uniform> in_arr : array<vec3<f32>, 9>;
-@group(0) @binding(2) var<uniform> in_vec : vec3<f32>;
-
-fn f() {
- arr[0] = in_arr[0];
- arr[1] = in_vec;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> arr : array<tint_packed_vec3_f32_array_element, 9u>;
-
-@group(0) @binding(1) var<uniform> in_arr : array<tint_packed_vec3_f32_array_element, 9u>;
-
-@group(0) @binding(2) var<uniform> in_vec : __packed_vec3<f32>;
-
-fn f() {
- arr[0].elements = in_arr[0].elements;
- arr[1].elements = in_vec;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ArrayOfVec3_WriteComponent_MemberAccessor) {
- auto* src = R"(
-@group(0) @binding(0) var<storage, read_write> arr : array<vec3<f32>, 4>;
-
-fn f() {
- arr[0].y = 1.23;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> arr : array<tint_packed_vec3_f32_array_element, 4u>;
-
-fn f() {
- arr[0].elements.y = 1.22999999999999998224;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ArrayOfVec3_WriteComponent_IndexAccessor) {
- auto* src = R"(
-@group(0) @binding(0) var<storage, read_write> arr : array<vec3<f32>, 4>;
-
-fn f() {
- arr[0][1] = 1.23;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> arr : array<tint_packed_vec3_f32_array_element, 4u>;
-
-fn f() {
- arr[0].elements[1] = 1.22999999999999998224;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, Matrix_ReadMatrix) {
- auto* src = R"(
-@group(0) @binding(0) var<storage> m : mat3x3<f32>;
-
-fn f() {
- let x = m;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
- return result;
-}
-
-@group(0) @binding(0) var<storage> m : array<tint_packed_vec3_f32_array_element, 3u>;
-
-fn f() {
- let x = tint_unpack_vec3_in_composite(m);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, Matrix_ReadColumn) {
- auto* src = R"(
-@group(0) @binding(0) var<storage> m : mat3x3<f32>;
-
-fn f() {
- let x = m[1];
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage> m : array<tint_packed_vec3_f32_array_element, 3u>;
-
-fn f() {
- let x = vec3<f32>(m[1].elements);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, Matrix_ReadComponent_MemberAccessChain) {
- auto* src = R"(
-@group(0) @binding(0) var<storage> m : mat3x3<f32>;
-
-fn f() {
- let x = m[1].yz.x;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage> m : array<tint_packed_vec3_f32_array_element, 3u>;
-
-fn f() {
- let x = vec3<f32>(m[1].elements).yz.x;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, Matrix_ReadComponent_IndexAccessor) {
- auto* src = R"(
-@group(0) @binding(0) var<storage> m : mat3x3<f32>;
-
-fn f() {
- let x = m[2][1];
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage> m : array<tint_packed_vec3_f32_array_element, 3u>;
-
-fn f() {
- let x = m[2].elements[1];
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, Matrix_WriteMatrix_ValueRHS) {
- auto* src = R"(
-@group(0) @binding(0) var<storage, read_write> m : mat3x3<f32>;
-
-fn f() {
- m = mat3x3(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5);
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
- var result = array<tint_packed_vec3_f32_array_element, 3u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])));
- return result;
-}
-
-@group(0) @binding(0) var<storage, read_write> m : array<tint_packed_vec3_f32_array_element, 3u>;
-
-fn f() {
- m = tint_pack_vec3_in_composite(mat3x3(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5));
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, Matrix_WriteMatrix_RefRHS) {
- auto* src = R"(
-@group(0) @binding(0) var<storage, read_write> m : mat3x3<f32>;
-@group(0) @binding(1) var<uniform> in : mat3x3<f32>;
-
-fn f() {
- m = in;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> m : array<tint_packed_vec3_f32_array_element, 3u>;
-
-@group(0) @binding(1) var<uniform> in : array<tint_packed_vec3_f32_array_element, 3u>;
-
-fn f() {
- m = in;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, Matrix_WriteColumn_ValueRHS) {
- auto* src = R"(
-@group(0) @binding(0) var<storage, read_write> m : mat3x3<f32>;
-
-fn f() {
- m[1] = vec3(1.23);
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> m : array<tint_packed_vec3_f32_array_element, 3u>;
-
-fn f() {
- m[1].elements = __packed_vec3<f32>(vec3(1.22999999999999998224));
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, Matrix_WriteColumn_RefRHS) {
- auto* src = R"(
-@group(0) @binding(0) var<storage, read_write> m : mat3x3<f32>;
-@group(0) @binding(1) var<uniform> in_mat : mat3x3<f32>;
-@group(0) @binding(1) var<uniform> in_vec : vec3<f32>;
-
-fn f() {
- m[0] = in_mat[0];
- m[1] = in_vec;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> m : array<tint_packed_vec3_f32_array_element, 3u>;
-
-@group(0) @binding(1) var<uniform> in_mat : array<tint_packed_vec3_f32_array_element, 3u>;
-
-@group(0) @binding(1) var<uniform> in_vec : __packed_vec3<f32>;
-
-fn f() {
- m[0].elements = in_mat[0].elements;
- m[1].elements = in_vec;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, Matrix_WriteComponent_MemberAccessor) {
- auto* src = R"(
-@group(0) @binding(0) var<storage, read_write> m : mat3x3<f32>;
-
-fn f() {
- m[1].y = 1.23;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> m : array<tint_packed_vec3_f32_array_element, 3u>;
-
-fn f() {
- m[1].elements.y = 1.22999999999999998224;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, Matrix_WriteComponent_IndexAccessor) {
- auto* src = R"(
-@group(0) @binding(0) var<storage, read_write> m : mat3x3<f32>;
-
-fn f() {
- m[1][2] = 1.23;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> m : array<tint_packed_vec3_f32_array_element, 3u>;
-
-fn f() {
- m[1].elements[2] = 1.22999999999999998224;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ArrayOfMatrix_ReadArray_Small) {
- auto* src = R"(
-@group(0) @binding(0) var<storage> arr : array<mat3x3<f32>, 4>;
-
-fn f() {
- let x = arr;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_1(in : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>) -> array<mat3x3<f32>, 4u> {
- var result = array<mat3x3<f32>, 4u>(tint_unpack_vec3_in_composite(in[0]), tint_unpack_vec3_in_composite(in[1]), tint_unpack_vec3_in_composite(in[2]), tint_unpack_vec3_in_composite(in[3]));
- return result;
-}
-
-@group(0) @binding(0) var<storage> arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
-
-fn f() {
- let x = tint_unpack_vec3_in_composite_1(arr);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ArrayOfMatrix_ReadArray_Large) {
- auto* src = R"(
-@group(0) @binding(0) var<storage> arr : array<mat3x3<f32>, 9>;
-
-fn f() {
- let x = arr;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_1(in : array<array<tint_packed_vec3_f32_array_element, 3u>, 9u>) -> array<mat3x3<f32>, 9u> {
- var result : array<mat3x3<f32>, 9u>;
- for(var i : u32; (i < 9u); i = (i + 1)) {
- result[i] = tint_unpack_vec3_in_composite(in[i]);
- }
- return result;
-}
-
-@group(0) @binding(0) var<storage> arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 9u>;
-
-fn f() {
- let x = tint_unpack_vec3_in_composite_1(arr);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ArrayOfMatrix_ReadMatrix) {
- auto* src = R"(
-@group(0) @binding(0) var<storage> arr : array<mat3x3<f32>, 4>;
-
-fn f() {
- let x = arr[0];
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
- return result;
-}
-
-@group(0) @binding(0) var<storage> arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
-
-fn f() {
- let x = tint_unpack_vec3_in_composite(arr[0]);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ArrayOfMatrix_ReadColumn) {
- auto* src = R"(
-@group(0) @binding(0) var<storage> arr : array<mat3x3<f32>, 4>;
-
-fn f() {
- let x = arr[0][1];
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage> arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
-
-fn f() {
- let x = vec3<f32>(arr[0][1].elements);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ArrayOfMatrix_ReadComponent_MemberAccessor) {
- auto* src = R"(
-@group(0) @binding(0) var<storage> arr : array<mat3x3<f32>, 4>;
-
-fn f() {
- let x = arr[0][1].y;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage> arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
-
-fn f() {
- let x = arr[0][1].elements.y;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ArrayOfMatrix_ReadComponent_IndexAccessor) {
- auto* src = R"(
-@group(0) @binding(0) var<storage> arr : array<mat3x3<f32>, 4>;
-
-fn f() {
- let x = arr[0][1][2];
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage> arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
-
-fn f() {
- let x = arr[0][1].elements[2];
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ArrayOfMatrix_WriteArray_ValueRHS_Small) {
- auto* src = R"(
-@group(0) @binding(0) var<storage, read_write> arr : array<mat3x3<f32>, 2>;
-
-fn f() {
- arr = array(mat3x3<f32>(), mat3x3(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5));
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
- var result = array<tint_packed_vec3_f32_array_element, 3u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])));
- return result;
-}
-
-fn tint_pack_vec3_in_composite_1(in : array<mat3x3<f32>, 2u>) -> array<array<tint_packed_vec3_f32_array_element, 3u>, 2u> {
- var result = array<array<tint_packed_vec3_f32_array_element, 3u>, 2u>(tint_pack_vec3_in_composite(in[0]), tint_pack_vec3_in_composite(in[1]));
- return result;
-}
-
-@group(0) @binding(0) var<storage, read_write> arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 2u>;
-
-fn f() {
- arr = tint_pack_vec3_in_composite_1(array(mat3x3<f32>(), mat3x3(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5)));
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ArrayOfMatrix_WriteArray_ValueRHS_Large) {
- auto* src = R"(
-@group(0) @binding(0) var<storage, read_write> arr : array<mat3x3<f32>, 9>;
-
-fn f() {
- arr = array(mat3x3<f32>(),
- mat3x3(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5),
- mat3x3f(),
- mat3x3f(),
- mat3x3f(),
- mat3x3f(),
- mat3x3f(),
- mat3x3f(),
- mat3x3f());
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
- var result = array<tint_packed_vec3_f32_array_element, 3u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])));
- return result;
-}
-
-fn tint_pack_vec3_in_composite_1(in : array<mat3x3<f32>, 9u>) -> array<array<tint_packed_vec3_f32_array_element, 3u>, 9u> {
- var result : array<array<tint_packed_vec3_f32_array_element, 3u>, 9u>;
- for(var i : u32; (i < 9u); i = (i + 1)) {
- result[i] = tint_pack_vec3_in_composite(in[i]);
- }
- return result;
-}
-
-@group(0) @binding(0) var<storage, read_write> arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 9u>;
-
-fn f() {
- arr = tint_pack_vec3_in_composite_1(array(mat3x3<f32>(), mat3x3(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5), mat3x3f(), mat3x3f(), mat3x3f(), mat3x3f(), mat3x3f(), mat3x3f(), mat3x3f()));
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ArrayOfMatrix_WriteArray_RefRHS) {
- auto* src = R"(
-@group(0) @binding(0) var<storage, read_write> arr : array<mat3x3<f32>, 2>;
-@group(0) @binding(1) var<uniform> in : array<mat3x3<f32>, 2>;
-
-fn f() {
- arr = in;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 2u>;
-
-@group(0) @binding(1) var<uniform> in : array<array<tint_packed_vec3_f32_array_element, 3u>, 2u>;
-
-fn f() {
- arr = in;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ArrayOfMatrix_WriteMatrix_ValueRHS) {
- auto* src = R"(
-@group(0) @binding(0) var<storage, read_write> arr : array<mat3x3<f32>, 4>;
-
-fn f() {
- arr[0] = mat3x3(1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9);
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
- var result = array<tint_packed_vec3_f32_array_element, 3u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])));
- return result;
-}
-
-@group(0) @binding(0) var<storage, read_write> arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
-
-fn f() {
- arr[0] = tint_pack_vec3_in_composite(mat3x3(1.10000000000000008882, 2.20000000000000017764, 3.29999999999999982236, 4.40000000000000035527, 5.5, 6.59999999999999964473, 7.70000000000000017764, 8.80000000000000071054, 9.90000000000000035527));
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ArrayOfMatrix_WriteMatrix_RefRHS) {
- auto* src = R"(
-@group(0) @binding(0) var<storage, read_write> arr : array<mat3x3<f32>, 4>;
-@group(0) @binding(1) var<uniform> in_arr : array<mat3x3<f32>, 4>;
-@group(0) @binding(2) var<uniform> in_mat : mat3x3<f32>;
-
-fn f() {
- arr[0] = in_arr[0];
- arr[1] = in_mat;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
-
-@group(0) @binding(1) var<uniform> in_arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
-
-@group(0) @binding(2) var<uniform> in_mat : array<tint_packed_vec3_f32_array_element, 3u>;
-
-fn f() {
- arr[0] = in_arr[0];
- arr[1] = in_mat;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ArrayOfMatrix_WriteVector_ValueRHS) {
- auto* src = R"(
-@group(0) @binding(0) var<storage, read_write> arr : array<mat3x3<f32>, 4>;
-
-fn f() {
- arr[0][1] = vec3(1.23);
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
-
-fn f() {
- arr[0][1].elements = __packed_vec3<f32>(vec3(1.22999999999999998224));
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ArrayOfMatrix_WriteVector_RefRHS) {
- auto* src = R"(
-@group(0) @binding(0) var<storage, read_write> arr : array<mat3x3<f32>, 4>;
-@group(0) @binding(1) var<uniform> in_arr : array<mat3x3<f32>, 4>;
-@group(0) @binding(2) var<uniform> in_mat : mat3x3<f32>;
-@group(0) @binding(3) var<uniform> in_vec : vec3<f32>;
-
-fn f() {
- arr[0][0] = arr[0][1];
- arr[0][1] = in_mat[2];
- arr[0][2] = in_vec;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
-
-@group(0) @binding(1) var<uniform> in_arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
-
-@group(0) @binding(2) var<uniform> in_mat : array<tint_packed_vec3_f32_array_element, 3u>;
-
-@group(0) @binding(3) var<uniform> in_vec : __packed_vec3<f32>;
-
-fn f() {
- arr[0][0].elements = arr[0][1].elements;
- arr[0][1].elements = in_mat[2].elements;
- arr[0][2].elements = in_vec;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ArrayOfMatrix_WriteComponent_MemberAccessor) {
- auto* src = R"(
-@group(0) @binding(0) var<storage, read_write> arr : array<mat3x3<f32>, 4>;
-
-fn f() {
- arr[0][1].y = 1.23;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
-
-fn f() {
- arr[0][1].elements.y = 1.22999999999999998224;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ArrayOfMatrix_WriteComponent_IndexAccessor) {
- auto* src = R"(
-@group(0) @binding(0) var<storage, read_write> arr : array<mat3x3<f32>, 4>;
-
-fn f() {
- arr[0][1][2] = 1.23;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
-
-fn f() {
- arr[0][1].elements[2] = 1.22999999999999998224;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_Vec3_ReadStruct) {
- auto* src = R"(
-struct S {
- v : vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
- let x = P;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct S_tint_packed_vec3 {
- @align(16)
- v : __packed_vec3<f32>,
-}
-
-fn tint_unpack_vec3_in_composite(in : S_tint_packed_vec3) -> S {
- var result : S;
- result.v = vec3<f32>(in.v);
- return result;
-}
-
-struct S {
- v : vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
-
-fn f() {
- let x = tint_unpack_vec3_in_composite(P);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_Vec3_ReadVector) {
- auto* src = R"(
-struct S {
- v : vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
- let x = P.v;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct S_tint_packed_vec3 {
- @align(16)
- v : __packed_vec3<f32>,
-}
-
-struct S {
- v : vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
-
-fn f() {
- let x = vec3<f32>(P.v);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_Vec3_ReadComponent_MemberAccessChain) {
- auto* src = R"(
-struct S {
- v : vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
- let x = P.v.yz.x;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct S_tint_packed_vec3 {
- @align(16)
- v : __packed_vec3<f32>,
-}
-
-struct S {
- v : vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
-
-fn f() {
- let x = vec3<f32>(P.v).yz.x;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_Vec3_ReadComponent_IndexAccessor) {
- auto* src = R"(
-struct S {
- v : vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
- let x = P.v[1];
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct S_tint_packed_vec3 {
- @align(16)
- v : __packed_vec3<f32>,
-}
-
-struct S {
- v : vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
-
-fn f() {
- let x = P.v[1];
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_Vec3_WriteStruct_ValueRHS) {
- auto* src = R"(
-struct S {
- v : vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S;
-
-fn f() {
- P = S(vec3(1.23));
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct S_tint_packed_vec3 {
- @align(16)
- v : __packed_vec3<f32>,
-}
-
-fn tint_pack_vec3_in_composite(in : S) -> S_tint_packed_vec3 {
- var result : S_tint_packed_vec3;
- result.v = __packed_vec3<f32>(in.v);
- return result;
-}
-
-struct S {
- v : vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
-
-fn f() {
- P = tint_pack_vec3_in_composite(S(vec3(1.22999999999999998224)));
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_Vec3_WriteStruct_RefRHS) {
- auto* src = R"(
-struct S {
- v : vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S;
-@group(0) @binding(1) var<uniform> in : S;
-
-fn f() {
- P = in;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct S_tint_packed_vec3 {
- @align(16)
- v : __packed_vec3<f32>,
-}
-
-struct S {
- v : vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
-
-@group(0) @binding(1) var<uniform> in : S_tint_packed_vec3;
-
-fn f() {
- P = in;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_Vec3_WriteVector_ValueRHS) {
- auto* src = R"(
-struct S {
- v : vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S;
-
-fn f() {
- P.v = vec3(1.23);
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct S_tint_packed_vec3 {
- @align(16)
- v : __packed_vec3<f32>,
-}
-
-struct S {
- v : vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
-
-fn f() {
- P.v = __packed_vec3<f32>(vec3(1.22999999999999998224));
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_Vec3_WriteVector_RefRHS) {
- auto* src = R"(
-struct S {
- v1 : vec3<f32>,
- v2 : vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S;
-@group(0) @binding(1) var<uniform> in_str : S;
-@group(0) @binding(2) var<uniform> in_vec : vec3<f32>;
-
-fn f() {
- P.v1 = in_str.v1;
- P.v2 = in_vec;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct S_tint_packed_vec3 {
- @align(16)
- v1 : __packed_vec3<f32>,
- @align(16)
- v2 : __packed_vec3<f32>,
-}
-
-struct S {
- v1 : vec3<f32>,
- v2 : vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
-
-@group(0) @binding(1) var<uniform> in_str : S_tint_packed_vec3;
-
-@group(0) @binding(2) var<uniform> in_vec : __packed_vec3<f32>;
-
-fn f() {
- P.v1 = in_str.v1;
- P.v2 = in_vec;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_Vec3_WriteComponent_MemberAccessor) {
- auto* src = R"(
-struct S {
- v : vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S;
-
-fn f() {
- P.v.y = 1.23;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct S_tint_packed_vec3 {
- @align(16)
- v : __packed_vec3<f32>,
-}
-
-struct S {
- v : vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
-
-fn f() {
- P.v.y = 1.22999999999999998224;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_Vec3_WriteComponent_IndexAccessor) {
- auto* src = R"(
-struct S {
- v : vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S;
-
-fn f() {
- P.v[1] = 1.23;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct S_tint_packed_vec3 {
- @align(16)
- v : __packed_vec3<f32>,
-}
-
-struct S {
- v : vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
-
-fn f() {
- P.v[1] = 1.22999999999999998224;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_ReadStruct_Small) {
- auto* src = R"(
-struct S {
- arr : array<vec3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
- let x = P;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr : array<tint_packed_vec3_f32_array_element, 4u>,
-}
-
-fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 4u>) -> array<vec3<f32>, 4u> {
- var result = array<vec3<f32>, 4u>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements), vec3<f32>(in[3].elements));
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_1(in : S_tint_packed_vec3) -> S {
- var result : S;
- result.arr = tint_unpack_vec3_in_composite(in.arr);
- return result;
-}
-
-struct S {
- arr : array<vec3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
-
-fn f() {
- let x = tint_unpack_vec3_in_composite_1(P);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_ReadStruct_Large) {
- auto* src = R"(
-struct S {
- arr : array<vec3<f32>, 9>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
- let x = P;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr : array<tint_packed_vec3_f32_array_element, 9u>,
-}
-
-fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 9u>) -> array<vec3<f32>, 9u> {
- var result : array<vec3<f32>, 9u>;
- for(var i : u32; (i < 9u); i = (i + 1)) {
- result[i] = vec3<f32>(in[i].elements);
- }
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_1(in : S_tint_packed_vec3) -> S {
- var result : S;
- result.arr = tint_unpack_vec3_in_composite(in.arr);
- return result;
-}
-
-struct S {
- arr : array<vec3<f32>, 9>,
-}
-
-@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
-
-fn f() {
- let x = tint_unpack_vec3_in_composite_1(P);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_ReadArray_Small) {
- auto* src = R"(
-struct S {
- arr : array<vec3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
- let x = P.arr;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr : array<tint_packed_vec3_f32_array_element, 4u>,
-}
-
-fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 4u>) -> array<vec3<f32>, 4u> {
- var result = array<vec3<f32>, 4u>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements), vec3<f32>(in[3].elements));
- return result;
-}
-
-struct S {
- arr : array<vec3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
-
-fn f() {
- let x = tint_unpack_vec3_in_composite(P.arr);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_ReadArray_Large) {
- auto* src = R"(
-struct S {
- arr : array<vec3<f32>, 9>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
- let x = P.arr;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr : array<tint_packed_vec3_f32_array_element, 9u>,
-}
-
-fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 9u>) -> array<vec3<f32>, 9u> {
- var result : array<vec3<f32>, 9u>;
- for(var i : u32; (i < 9u); i = (i + 1)) {
- result[i] = vec3<f32>(in[i].elements);
- }
- return result;
-}
-
-struct S {
- arr : array<vec3<f32>, 9>,
-}
-
-@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
-
-fn f() {
- let x = tint_unpack_vec3_in_composite(P.arr);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_ReadVector) {
- auto* src = R"(
-struct S {
- arr : array<vec3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
- let x = P.arr[0];
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr : array<tint_packed_vec3_f32_array_element, 4u>,
-}
-
-struct S {
- arr : array<vec3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
-
-fn f() {
- let x = vec3<f32>(P.arr[0].elements);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_ReadComponent_MemberAccessor) {
- auto* src = R"(
-struct S {
- arr : array<vec3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
- let x = P.arr[0].y;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr : array<tint_packed_vec3_f32_array_element, 4u>,
-}
-
-struct S {
- arr : array<vec3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
-
-fn f() {
- let x = P.arr[0].elements.y;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_ReadComponent_IndexAccessor) {
- auto* src = R"(
-struct S {
- arr : array<vec3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
- let x = P.arr[0][1];
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr : array<tint_packed_vec3_f32_array_element, 4u>,
-}
-
-struct S {
- arr : array<vec3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
-
-fn f() {
- let x = P.arr[0].elements[1];
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_WriteStruct_ValueRHS_Small) {
- auto* src = R"(
-struct S {
- arr : array<vec3<f32>, 2>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S;
-
-fn f() {
- P = S(array(vec3(1.5, 4.5, 7.5), vec3(9.5, 6.5, 3.5)));
-}
-)";
-
- auto* expect =
- R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr : array<tint_packed_vec3_f32_array_element, 2u>,
-}
-
-fn tint_pack_vec3_in_composite(in : array<vec3<f32>, 2u>) -> array<tint_packed_vec3_f32_array_element, 2u> {
- var result = array<tint_packed_vec3_f32_array_element, 2u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])));
- return result;
-}
-
-fn tint_pack_vec3_in_composite_1(in : S) -> S_tint_packed_vec3 {
- var result : S_tint_packed_vec3;
- result.arr = tint_pack_vec3_in_composite(in.arr);
- return result;
-}
-
-struct S {
- arr : array<vec3<f32>, 2>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
-
-fn f() {
- P = tint_pack_vec3_in_composite_1(S(array(vec3(1.5, 4.5, 7.5), vec3(9.5, 6.5, 3.5))));
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_WriteStruct_ValueRHS_Large) {
- auto* src = R"(
-struct S {
- arr : array<vec3<f32>, 9>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S;
-
-fn f() {
- P = S(array(vec3(1.5, 4.5, 7.5),
- vec3(9.5, 6.5, 3.5),
- vec3(9.5, 6.5, 3.5),
- vec3(9.5, 6.5, 3.5),
- vec3(9.5, 6.5, 3.5),
- vec3(9.5, 6.5, 3.5),
- vec3(9.5, 6.5, 3.5),
- vec3(9.5, 6.5, 3.5),
- vec3(9.5, 6.5, 3.5)));
-}
-)";
-
- auto* expect =
- R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr : array<tint_packed_vec3_f32_array_element, 9u>,
-}
-
-fn tint_pack_vec3_in_composite(in : array<vec3<f32>, 9u>) -> array<tint_packed_vec3_f32_array_element, 9u> {
- var result : array<tint_packed_vec3_f32_array_element, 9u>;
- for(var i : u32; (i < 9u); i = (i + 1)) {
- result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
- }
- return result;
-}
-
-fn tint_pack_vec3_in_composite_1(in : S) -> S_tint_packed_vec3 {
- var result : S_tint_packed_vec3;
- result.arr = tint_pack_vec3_in_composite(in.arr);
- return result;
-}
-
-struct S {
- arr : array<vec3<f32>, 9>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
-
-fn f() {
- P = tint_pack_vec3_in_composite_1(S(array(vec3(1.5, 4.5, 7.5), vec3(9.5, 6.5, 3.5), vec3(9.5, 6.5, 3.5), vec3(9.5, 6.5, 3.5), vec3(9.5, 6.5, 3.5), vec3(9.5, 6.5, 3.5), vec3(9.5, 6.5, 3.5), vec3(9.5, 6.5, 3.5), vec3(9.5, 6.5, 3.5))));
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_WriteStruct_RefRHS) {
- auto* src = R"(
-struct S {
- arr : array<vec3<f32>, 2>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S;
-@group(0) @binding(1) var<uniform> in : S;
-
-fn f() {
- P = in;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr : array<tint_packed_vec3_f32_array_element, 2u>,
-}
-
-struct S {
- arr : array<vec3<f32>, 2>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
-
-@group(0) @binding(1) var<uniform> in : S_tint_packed_vec3;
-
-fn f() {
- P = in;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_WriteArray_ValueRHS_Small) {
- auto* src = R"(
-struct S {
- arr : array<vec3<f32>, 2>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S;
-
-fn f() {
- P.arr = array(vec3(1.5, 4.5, 7.5), vec3(9.5, 6.5, 3.5));
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr : array<tint_packed_vec3_f32_array_element, 2u>,
-}
-
-fn tint_pack_vec3_in_composite(in : array<vec3<f32>, 2u>) -> array<tint_packed_vec3_f32_array_element, 2u> {
- var result = array<tint_packed_vec3_f32_array_element, 2u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])));
- return result;
-}
-
-struct S {
- arr : array<vec3<f32>, 2>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
-
-fn f() {
- P.arr = tint_pack_vec3_in_composite(array(vec3(1.5, 4.5, 7.5), vec3(9.5, 6.5, 3.5)));
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_WriteArray_ValueRHS_Large) {
- auto* src = R"(
-struct S {
- arr : array<vec3<f32>, 9>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S;
-
-fn f() {
- P.arr = array(vec3(1.5, 4.5, 7.5),
- vec3(9.5, 6.5, 3.5),
- vec3(9.5, 6.5, 3.5),
- vec3(9.5, 6.5, 3.5),
- vec3(9.5, 6.5, 3.5),
- vec3(9.5, 6.5, 3.5),
- vec3(9.5, 6.5, 3.5),
- vec3(9.5, 6.5, 3.5),
- vec3(9.5, 6.5, 3.5));
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr : array<tint_packed_vec3_f32_array_element, 9u>,
-}
-
-fn tint_pack_vec3_in_composite(in : array<vec3<f32>, 9u>) -> array<tint_packed_vec3_f32_array_element, 9u> {
- var result : array<tint_packed_vec3_f32_array_element, 9u>;
- for(var i : u32; (i < 9u); i = (i + 1)) {
- result[i] = tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[i]));
- }
- return result;
-}
-
-struct S {
- arr : array<vec3<f32>, 9>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
-
-fn f() {
- P.arr = tint_pack_vec3_in_composite(array(vec3(1.5, 4.5, 7.5), vec3(9.5, 6.5, 3.5), vec3(9.5, 6.5, 3.5), vec3(9.5, 6.5, 3.5), vec3(9.5, 6.5, 3.5), vec3(9.5, 6.5, 3.5), vec3(9.5, 6.5, 3.5), vec3(9.5, 6.5, 3.5), vec3(9.5, 6.5, 3.5)));
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_WriteArray_RefRHS) {
- auto* src = R"(
-struct S {
- arr1 : array<vec3<f32>, 2>,
- arr2 : array<vec3<f32>, 2>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S;
-@group(0) @binding(1) var<uniform> in_str : S;
-@group(0) @binding(2) var<uniform> in_arr : array<vec3<f32>, 2>;
-
-fn f() {
- P.arr1 = in_str.arr1;
- P.arr2 = in_arr;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr1 : array<tint_packed_vec3_f32_array_element, 2u>,
- @align(16)
- arr2 : array<tint_packed_vec3_f32_array_element, 2u>,
-}
-
-struct S {
- arr1 : array<vec3<f32>, 2>,
- arr2 : array<vec3<f32>, 2>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
-
-@group(0) @binding(1) var<uniform> in_str : S_tint_packed_vec3;
-
-@group(0) @binding(2) var<uniform> in_arr : array<tint_packed_vec3_f32_array_element, 2u>;
-
-fn f() {
- P.arr1 = in_str.arr1;
- P.arr2 = in_arr;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_WriteVector_ValueRHS) {
- auto* src = R"(
-struct S {
- arr : array<vec3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S;
-
-fn f() {
- P.arr[0] = vec3(1.23);
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr : array<tint_packed_vec3_f32_array_element, 4u>,
-}
-
-struct S {
- arr : array<vec3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
-
-fn f() {
- P.arr[0].elements = __packed_vec3<f32>(vec3(1.22999999999999998224));
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_WriteVector_RefRHS) {
- auto* src = R"(
-struct S {
- arr : array<vec3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S;
-@group(0) @binding(1) var<uniform> in_str : S;
-@group(0) @binding(2) var<uniform> in_arr : array<vec3<f32>, 4>;
-@group(0) @binding(3) var<uniform> in_vec : vec3<f32>;
-
-fn f() {
- P.arr[0] = in_str.arr[0];
- P.arr[1] = in_arr[1];
- P.arr[2] = in_vec;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr : array<tint_packed_vec3_f32_array_element, 4u>,
-}
-
-struct S {
- arr : array<vec3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
-
-@group(0) @binding(1) var<uniform> in_str : S_tint_packed_vec3;
-
-@group(0) @binding(2) var<uniform> in_arr : array<tint_packed_vec3_f32_array_element, 4u>;
-
-@group(0) @binding(3) var<uniform> in_vec : __packed_vec3<f32>;
-
-fn f() {
- P.arr[0].elements = in_str.arr[0].elements;
- P.arr[1].elements = in_arr[1].elements;
- P.arr[2].elements = in_vec;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_WriteComponent_MemberAccessor) {
- auto* src = R"(
-struct S {
- arr : array<vec3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S;
-
-fn f() {
- P.arr[0].y = 1.23;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr : array<tint_packed_vec3_f32_array_element, 4u>,
-}
-
-struct S {
- arr : array<vec3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
-
-fn f() {
- P.arr[0].elements.y = 1.22999999999999998224;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_ArrayOfVec3_WriteComponent_IndexAccessor) {
- auto* src = R"(
-struct S {
- arr : array<vec3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S;
-
-fn f() {
- P.arr[0][1] = 1.23;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr : array<tint_packed_vec3_f32_array_element, 4u>,
-}
-
-struct S {
- arr : array<vec3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
-
-fn f() {
- P.arr[0].elements[1] = 1.22999999999999998224;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_Matrix_ReadStruct) {
- auto* src = R"(
-struct S {
- m : mat3x3<f32>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
- let x = P;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- m : array<tint_packed_vec3_f32_array_element, 3u>,
-}
-
-fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_1(in : S_tint_packed_vec3) -> S {
- var result : S;
- result.m = tint_unpack_vec3_in_composite(in.m);
- return result;
-}
-
-struct S {
- m : mat3x3<f32>,
-}
-
-@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
-
-fn f() {
- let x = tint_unpack_vec3_in_composite_1(P);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_Matrix_ReadMatrix) {
- auto* src = R"(
-struct S {
- m : mat3x3<f32>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
- let x = P.m;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- m : array<tint_packed_vec3_f32_array_element, 3u>,
-}
-
-fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
- return result;
-}
-
-struct S {
- m : mat3x3<f32>,
-}
-
-@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
-
-fn f() {
- let x = tint_unpack_vec3_in_composite(P.m);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_Matrix_ReadColumn) {
- auto* src = R"(
-struct S {
- m : mat3x3<f32>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
- let x = P.m[1];
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- m : array<tint_packed_vec3_f32_array_element, 3u>,
-}
-
-struct S {
- m : mat3x3<f32>,
-}
-
-@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
-
-fn f() {
- let x = vec3<f32>(P.m[1].elements);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_Matrix_ReadComponent_MemberAccessChain) {
- auto* src = R"(
-struct S {
- m : mat3x3<f32>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
- let x = P.m[1].yz.x;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- m : array<tint_packed_vec3_f32_array_element, 3u>,
-}
-
-struct S {
- m : mat3x3<f32>,
-}
-
-@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
-
-fn f() {
- let x = vec3<f32>(P.m[1].elements).yz.x;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_Matrix_ReadComponent_IndexAccessor) {
- auto* src = R"(
-struct S {
- m : mat3x3<f32>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
- let x = P.m[2][1];
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- m : array<tint_packed_vec3_f32_array_element, 3u>,
-}
-
-struct S {
- m : mat3x3<f32>,
-}
-
-@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
-
-fn f() {
- let x = P.m[2].elements[1];
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_Matrix_WriteStruct_ValueRHS) {
- auto* src = R"(
-struct S {
- m : mat3x3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S;
-
-fn f() {
- P = S(mat3x3(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5));
-}
-)";
-
- auto* expect =
- R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- m : array<tint_packed_vec3_f32_array_element, 3u>,
-}
-
-fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
- var result = array<tint_packed_vec3_f32_array_element, 3u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])));
- return result;
-}
-
-fn tint_pack_vec3_in_composite_1(in : S) -> S_tint_packed_vec3 {
- var result : S_tint_packed_vec3;
- result.m = tint_pack_vec3_in_composite(in.m);
- return result;
-}
-
-struct S {
- m : mat3x3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
-
-fn f() {
- P = tint_pack_vec3_in_composite_1(S(mat3x3(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5)));
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_Matrix_WriteStruct_RefRHS) {
- auto* src = R"(
-struct S {
- m : mat3x3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S;
-@group(0) @binding(1) var<uniform> in : S;
-
-fn f() {
- P = in;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- m : array<tint_packed_vec3_f32_array_element, 3u>,
-}
-
-struct S {
- m : mat3x3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
-
-@group(0) @binding(1) var<uniform> in : S_tint_packed_vec3;
-
-fn f() {
- P = in;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_Matrix_WriteMatrix_ValueRHS) {
- auto* src = R"(
-struct S {
- m : mat3x3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S;
-
-fn f() {
- P.m = mat3x3(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5);
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- m : array<tint_packed_vec3_f32_array_element, 3u>,
-}
-
-fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
- var result = array<tint_packed_vec3_f32_array_element, 3u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])));
- return result;
-}
-
-struct S {
- m : mat3x3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
-
-fn f() {
- P.m = tint_pack_vec3_in_composite(mat3x3(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5));
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_Matrix_WriteMatrix_RefRHS) {
- auto* src = R"(
-struct S {
- m1 : mat3x3<f32>,
- m2 : mat3x3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S;
-@group(0) @binding(1) var<uniform> in_str : S;
-@group(0) @binding(2) var<uniform> in_mat : mat3x3<f32>;
-
-fn f() {
- P.m1 = in_str.m1;
- P.m2 = in_mat;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- m1 : array<tint_packed_vec3_f32_array_element, 3u>,
- @align(16)
- m2 : array<tint_packed_vec3_f32_array_element, 3u>,
-}
-
-struct S {
- m1 : mat3x3<f32>,
- m2 : mat3x3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
-
-@group(0) @binding(1) var<uniform> in_str : S_tint_packed_vec3;
-
-@group(0) @binding(2) var<uniform> in_mat : array<tint_packed_vec3_f32_array_element, 3u>;
-
-fn f() {
- P.m1 = in_str.m1;
- P.m2 = in_mat;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_Matrix_WriteColumn_ValueRHS) {
- auto* src = R"(
-struct S {
- m : mat3x3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S;
-
-fn f() {
- P.m[1] = vec3(1.23);
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- m : array<tint_packed_vec3_f32_array_element, 3u>,
-}
-
-struct S {
- m : mat3x3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
-
-fn f() {
- P.m[1].elements = __packed_vec3<f32>(vec3(1.22999999999999998224));
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_Matrix_WriteColumn_RefRHS) {
- auto* src = R"(
-struct S {
- m : mat3x3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S;
-@group(0) @binding(1) var<uniform> in_str : S;
-@group(0) @binding(2) var<uniform> in_mat : mat3x3<f32>;
-@group(0) @binding(3) var<uniform> in_vec : vec3<f32>;
-
-fn f() {
- P.m[0] = in_str.m[0];
- P.m[1] = in_mat[1];
- P.m[2] = in_vec;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- m : array<tint_packed_vec3_f32_array_element, 3u>,
-}
-
-struct S {
- m : mat3x3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
-
-@group(0) @binding(1) var<uniform> in_str : S_tint_packed_vec3;
-
-@group(0) @binding(2) var<uniform> in_mat : array<tint_packed_vec3_f32_array_element, 3u>;
-
-@group(0) @binding(3) var<uniform> in_vec : __packed_vec3<f32>;
-
-fn f() {
- P.m[0].elements = in_str.m[0].elements;
- P.m[1].elements = in_mat[1].elements;
- P.m[2].elements = in_vec;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_Matrix_WriteComponent_MemberAccessor) {
- auto* src = R"(
-struct S {
- m : mat3x3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S;
-
-fn f() {
- P.m[1].y = 1.23;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- m : array<tint_packed_vec3_f32_array_element, 3u>,
-}
-
-struct S {
- m : mat3x3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
-
-fn f() {
- P.m[1].elements.y = 1.22999999999999998224;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_Matrix_WriteComponent_IndexAccessor) {
- auto* src = R"(
-struct S {
- m : mat3x3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S;
-
-fn f() {
- P.m[1][2] = 1.23;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- m : array<tint_packed_vec3_f32_array_element, 3u>,
-}
-
-struct S {
- m : mat3x3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
-
-fn f() {
- P.m[1].elements[2] = 1.22999999999999998224;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_ReadStruct_Small) {
- auto* src = R"(
-struct S {
- arr : array<mat3x3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
- let x = P;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
-}
-
-fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_1(in : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>) -> array<mat3x3<f32>, 4u> {
- var result = array<mat3x3<f32>, 4u>(tint_unpack_vec3_in_composite(in[0]), tint_unpack_vec3_in_composite(in[1]), tint_unpack_vec3_in_composite(in[2]), tint_unpack_vec3_in_composite(in[3]));
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_2(in : S_tint_packed_vec3) -> S {
- var result : S;
- result.arr = tint_unpack_vec3_in_composite_1(in.arr);
- return result;
-}
-
-struct S {
- arr : array<mat3x3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
-
-fn f() {
- let x = tint_unpack_vec3_in_composite_2(P);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_ReadStruct_Large) {
- auto* src = R"(
-struct S {
- arr : array<mat3x3<f32>, 9>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
- let x = P;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 9u>,
-}
-
-fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_1(in : array<array<tint_packed_vec3_f32_array_element, 3u>, 9u>) -> array<mat3x3<f32>, 9u> {
- var result : array<mat3x3<f32>, 9u>;
- for(var i : u32; (i < 9u); i = (i + 1)) {
- result[i] = tint_unpack_vec3_in_composite(in[i]);
- }
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_2(in : S_tint_packed_vec3) -> S {
- var result : S;
- result.arr = tint_unpack_vec3_in_composite_1(in.arr);
- return result;
-}
-
-struct S {
- arr : array<mat3x3<f32>, 9>,
-}
-
-@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
-
-fn f() {
- let x = tint_unpack_vec3_in_composite_2(P);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_ReadArray) {
- auto* src = R"(
-struct S {
- arr : array<mat3x3<f32>, 9>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
- let x = P.arr;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 9u>,
-}
-
-fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_1(in : array<array<tint_packed_vec3_f32_array_element, 3u>, 9u>) -> array<mat3x3<f32>, 9u> {
- var result : array<mat3x3<f32>, 9u>;
- for(var i : u32; (i < 9u); i = (i + 1)) {
- result[i] = tint_unpack_vec3_in_composite(in[i]);
- }
- return result;
-}
-
-struct S {
- arr : array<mat3x3<f32>, 9>,
-}
-
-@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
-
-fn f() {
- let x = tint_unpack_vec3_in_composite_1(P.arr);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_ReadMatrix) {
- auto* src = R"(
-struct S {
- arr : array<mat3x3<f32>, 4u>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
- let x = P.arr[0];
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
-}
-
-fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
- return result;
-}
-
-struct S {
- arr : array<mat3x3<f32>, 4u>,
-}
-
-@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
-
-fn f() {
- let x = tint_unpack_vec3_in_composite(P.arr[0]);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_ReadColumn) {
- auto* src = R"(
-struct S {
- arr : array<mat3x3<f32>, 4u>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
- let x = P.arr[0][1];
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
-}
-
-struct S {
- arr : array<mat3x3<f32>, 4u>,
-}
-
-@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
-
-fn f() {
- let x = vec3<f32>(P.arr[0][1].elements);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_ReadComponent_MemberAccessor) {
- auto* src = R"(
-struct S {
- arr : array<mat3x3<f32>, 4u>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
- let x = P.arr[0][1].y;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
-}
-
-struct S {
- arr : array<mat3x3<f32>, 4u>,
-}
-
-@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
-
-fn f() {
- let x = P.arr[0][1].elements.y;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_ReadComponent_IndexAccessor) {
- auto* src = R"(
-struct S {
- arr : array<mat3x3<f32>, 4u>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
- let x = P.arr[0][1][2];
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
-}
-
-struct S {
- arr : array<mat3x3<f32>, 4u>,
-}
-
-@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
-
-fn f() {
- let x = P.arr[0][1].elements[2];
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_WriteStruct_ValueRHS) {
- auto* src = R"(
-struct S {
- arr : array<mat3x3<f32>, 2>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S;
-
-fn f() {
- P = S(array(mat3x3<f32>(), mat3x3(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5)));
-}
-)";
-
- auto* expect =
- R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 2u>,
-}
-
-fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
- var result = array<tint_packed_vec3_f32_array_element, 3u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])));
- return result;
-}
-
-fn tint_pack_vec3_in_composite_1(in : array<mat3x3<f32>, 2u>) -> array<array<tint_packed_vec3_f32_array_element, 3u>, 2u> {
- var result = array<array<tint_packed_vec3_f32_array_element, 3u>, 2u>(tint_pack_vec3_in_composite(in[0]), tint_pack_vec3_in_composite(in[1]));
- return result;
-}
-
-fn tint_pack_vec3_in_composite_2(in : S) -> S_tint_packed_vec3 {
- var result : S_tint_packed_vec3;
- result.arr = tint_pack_vec3_in_composite_1(in.arr);
- return result;
-}
-
-struct S {
- arr : array<mat3x3<f32>, 2>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
-
-fn f() {
- P = tint_pack_vec3_in_composite_2(S(array(mat3x3<f32>(), mat3x3(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5))));
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_WriteStruct_RefRHS) {
- auto* src = R"(
-struct S {
- arr : array<mat3x3<f32>, 2>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S;
-@group(0) @binding(1) var<uniform> in : S;
-
-fn f() {
- P = in;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 2u>,
-}
-
-struct S {
- arr : array<mat3x3<f32>, 2>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
-
-@group(0) @binding(1) var<uniform> in : S_tint_packed_vec3;
-
-fn f() {
- P = in;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_WriteArray_ValueRHS) {
- auto* src = R"(
-struct S {
- arr : array<mat3x3<f32>, 2>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S;
-
-fn f() {
- P.arr = array(mat3x3<f32>(), mat3x3(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5));
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 2u>,
-}
-
-fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
- var result = array<tint_packed_vec3_f32_array_element, 3u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])));
- return result;
-}
-
-fn tint_pack_vec3_in_composite_1(in : array<mat3x3<f32>, 2u>) -> array<array<tint_packed_vec3_f32_array_element, 3u>, 2u> {
- var result = array<array<tint_packed_vec3_f32_array_element, 3u>, 2u>(tint_pack_vec3_in_composite(in[0]), tint_pack_vec3_in_composite(in[1]));
- return result;
-}
-
-struct S {
- arr : array<mat3x3<f32>, 2>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
-
-fn f() {
- P.arr = tint_pack_vec3_in_composite_1(array(mat3x3<f32>(), mat3x3(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5)));
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_WriteArray_RefRHS) {
- auto* src = R"(
-struct S {
- arr1 : array<mat3x3<f32>, 2>,
- arr2 : array<mat3x3<f32>, 2>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S;
-@group(0) @binding(1) var<uniform> in_str : S;
-@group(0) @binding(2) var<uniform> in_arr : array<mat3x3<f32>, 2>;
-
-fn f() {
- P.arr1 = in_str.arr1;
- P.arr2 = in_arr;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr1 : array<array<tint_packed_vec3_f32_array_element, 3u>, 2u>,
- @align(16)
- arr2 : array<array<tint_packed_vec3_f32_array_element, 3u>, 2u>,
-}
-
-struct S {
- arr1 : array<mat3x3<f32>, 2>,
- arr2 : array<mat3x3<f32>, 2>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
-
-@group(0) @binding(1) var<uniform> in_str : S_tint_packed_vec3;
-
-@group(0) @binding(2) var<uniform> in_arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 2u>;
-
-fn f() {
- P.arr1 = in_str.arr1;
- P.arr2 = in_arr;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_WriteMatrix_ValueRHS) {
- auto* src = R"(
-struct S {
- arr : array<mat3x3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S;
-
-fn f() {
- P.arr[0] = mat3x3(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5);
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
-}
-
-fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
- var result = array<tint_packed_vec3_f32_array_element, 3u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])));
- return result;
-}
-
-struct S {
- arr : array<mat3x3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
-
-fn f() {
- P.arr[0] = tint_pack_vec3_in_composite(mat3x3(1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5));
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_WriteMatrix_RefRHS) {
- auto* src = R"(
-struct S {
- arr : array<mat3x3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S;
-@group(0) @binding(1) var<uniform> in_str : S;
-@group(0) @binding(2) var<uniform> in_arr : array<mat3x3<f32>, 4>;
-@group(0) @binding(3) var<uniform> in_mat : mat3x3<f32>;
-
-fn f() {
- P.arr[0] = in_str.arr[0];
- P.arr[1] = in_arr[1];
- P.arr[2] = in_mat;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
-}
-
-struct S {
- arr : array<mat3x3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
-
-@group(0) @binding(1) var<uniform> in_str : S_tint_packed_vec3;
-
-@group(0) @binding(2) var<uniform> in_arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
-
-@group(0) @binding(3) var<uniform> in_mat : array<tint_packed_vec3_f32_array_element, 3u>;
-
-fn f() {
- P.arr[0] = in_str.arr[0];
- P.arr[1] = in_arr[1];
- P.arr[2] = in_mat;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_WriteVector_ValueRHS) {
- auto* src = R"(
-struct S {
- arr : array<mat3x3<f32>, 4u>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S;
-
-fn f() {
- P.arr[0][1] = vec3(1.23);
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
-}
-
-struct S {
- arr : array<mat3x3<f32>, 4u>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
-
-fn f() {
- P.arr[0][1].elements = __packed_vec3<f32>(vec3(1.22999999999999998224));
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_WriteVector_RefRHS) {
- auto* src = R"(
-struct S {
- arr : array<mat3x3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S;
-@group(0) @binding(1) var<uniform> in_str : S;
-@group(0) @binding(2) var<uniform> in_arr : array<mat3x3<f32>, 4>;
-@group(0) @binding(3) var<uniform> in_mat : mat3x3<f32>;
-@group(0) @binding(4) var<uniform> in_vec : vec3<f32>;
-
-fn f() {
- P.arr[0][0] = in_str.arr[0][1];
- P.arr[1][1] = in_arr[3][2];
- P.arr[2][2] = in_mat[1];
- P.arr[3][0] = in_vec;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
-}
-
-struct S {
- arr : array<mat3x3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
-
-@group(0) @binding(1) var<uniform> in_str : S_tint_packed_vec3;
-
-@group(0) @binding(2) var<uniform> in_arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
-
-@group(0) @binding(3) var<uniform> in_mat : array<tint_packed_vec3_f32_array_element, 3u>;
-
-@group(0) @binding(4) var<uniform> in_vec : __packed_vec3<f32>;
-
-fn f() {
- P.arr[0][0].elements = in_str.arr[0][1].elements;
- P.arr[1][1].elements = in_arr[3][2].elements;
- P.arr[2][2].elements = in_mat[1].elements;
- P.arr[3][0].elements = in_vec;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_WriteComponent_MemberAccessor) {
- auto* src = R"(
-struct S {
- arr : array<mat3x3<f32>, 4u>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S;
-
-fn f() {
- P.arr[0][1].y = 1.23;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
-}
-
-struct S {
- arr : array<mat3x3<f32>, 4u>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
-
-fn f() {
- P.arr[0][1].elements.y = 1.22999999999999998224;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_ArrayOfMatrix_WriteComponent_IndexAccessor) {
- auto* src = R"(
-struct S {
- arr : array<mat3x3<f32>, 4u>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S;
-
-fn f() {
- P.arr[0][1][2] = 1.23;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
-}
-
-struct S {
- arr : array<mat3x3<f32>, 4u>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
-
-fn f() {
- P.arr[0][1].elements[2] = 1.22999999999999998224;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_ExistingMemberAttributes) {
- auto* src = R"(
-struct S {
- @align(32) @size(32) v : vec3<f32>,
- @align(64) @size(64) arr : array<vec3<f32>, 4>,
- @align(128) @size(128) x : u32,
-}
-
-@group(0) @binding(0) var<uniform> P : S;
-
-fn f() {
- let x = P.v[0];
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(32) @size(32)
- v : __packed_vec3<f32>,
- @align(64) @size(64)
- arr : array<tint_packed_vec3_f32_array_element, 4u>,
- @align(128) @size(128)
- x : u32,
-}
-
-struct S {
- @align(32) @size(32)
- v : vec3<f32>,
- @align(64) @size(64)
- arr : array<vec3<f32>, 4>,
- @align(128) @size(128)
- x : u32,
-}
-
-@group(0) @binding(0) var<uniform> P : S_tint_packed_vec3;
-
-fn f() {
- let x = P.v[0];
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_ExistingMemberAttributes_SizeMatchesUnpackedVec3) {
- // Test that the type we replace a vec3 with is not larger than it should be.
- auto* src = R"(
-struct S {
- @size(12) v : vec3<f32>,
- @size(64) arr : array<vec3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<uniform> P : S;
-
-fn f() {
- let x = P.v[0];
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @size(12) @align(16)
- v : __packed_vec3<f32>,
- @size(64) @align(16)
- arr : array<tint_packed_vec3_f32_array_element, 4u>,
-}
-
-struct S {
- @size(12)
- v : vec3<f32>,
- @size(64)
- arr : array<vec3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<uniform> P : S_tint_packed_vec3;
-
-fn f() {
- let x = P.v[0];
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_ExistingMemberAttributes_AlignTooSmall) {
- // Test that we add an @align() attribute when the new alignment of the packed vec3 struct would
- // be too small.
- auto* src = R"(
-struct S {
- a : u32,
- v : vec3<f32>,
- b : u32,
- arr : array<vec3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<uniform> P : S;
-
-fn f() {
- let x = P.v[0];
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- a : u32,
- @align(16)
- v : __packed_vec3<f32>,
- b : u32,
- @align(16)
- arr : array<tint_packed_vec3_f32_array_element, 4u>,
-}
-
-struct S {
- a : u32,
- v : vec3<f32>,
- b : u32,
- arr : array<vec3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<uniform> P : S_tint_packed_vec3;
-
-fn f() {
- let x = P.v[0];
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructMember_ExistingMemberAttributes_ExplicitOffset) {
- // Test that the we do not add an @align attribute if @offset is present.
-
- // struct S {
- // a : u32,
- // @offset(32) v : vec3<f32>,
- // b : u32,
- // @offset(128) arr : array<vec3<f32>, 4>,
- // }
- //
- // @group(0) @binding(0) var<uniform> P : S;
- ProgramBuilder b;
- b.Structure("S", tint::Vector{
- b.Member("a", b.ty.u32()),
- b.Member("v", b.ty.vec3<f32>(), tint::Vector{b.MemberOffset(AInt(32))}),
- b.Member("b", b.ty.u32()),
- b.Member("arr", b.ty.array(b.ty.vec3<f32>(), b.Expr(AInt(4))),
- tint::Vector{b.MemberOffset(AInt(128))}),
- });
- b.GlobalVar("P", core::AddressSpace::kStorage, b.ty("S"),
- tint::Vector{b.Group(AInt(0)), b.Binding(AInt(0))});
- Program src(resolver::Resolve(b));
-
- auto* expect =
- R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- a : u32,
- @size(28)
- padding_0 : u32,
- /* @offset(32) */
- v : __packed_vec3<f32>,
- b : u32,
- @size(80)
- padding_1 : u32,
- /* @offset(128) */
- arr : array<tint_packed_vec3_f32_array_element, 4u>,
-}
-
-struct S {
- a : u32,
- @size(16)
- padding_0 : u32,
- /* @offset(32) */
- v : vec3<f32>,
- b : u32,
- @size(80)
- padding_1 : u32,
- /* @offset(128) */
- arr : array<vec3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(std::move(src), data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructValueConstructor_ViaIndexAccessor) {
- auto* src = R"(
-struct S {
- a : vec3<f32>,
- b : vec3<f32>,
- arr : array<vec3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage> s : S;
-
-fn f() {
- let value_arr : array<vec3<f32>, 4> = array<vec3<f32>, 4>();
- let x = S(value_arr[0], s.arr[0], value_arr);
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- a : __packed_vec3<f32>,
- @align(16)
- b : __packed_vec3<f32>,
- @align(16)
- arr : array<tint_packed_vec3_f32_array_element, 4u>,
-}
-
-struct S {
- a : vec3<f32>,
- b : vec3<f32>,
- arr : array<vec3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage> s : S_tint_packed_vec3;
-
-fn f() {
- let value_arr : array<vec3<f32>, 4> = array<vec3<f32>, 4>();
- let x = S(value_arr[0], vec3<f32>(s.arr[0].elements), value_arr);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, WrapperStructLayout_MixedUsage) {
- // Test the layout of the generated wrapper struct(s) when vec3s are used in both structures and
- // arrays.
- auto* src = R"(
-struct S {
- v : vec3<f32>,
- a : u32,
-}
-
-@group(0) @binding(0) var<storage, read_write> str : S;
-@group(0) @binding(1) var<storage, read_write> arr : array<vec3<f32>, 4>;
-
-fn main() {
- str.v = arr[0];
- arr[1] = str.v;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct S_tint_packed_vec3 {
- @align(16)
- v : __packed_vec3<f32>,
- a : u32,
-}
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S {
- v : vec3<f32>,
- a : u32,
-}
-
-@group(0) @binding(0) var<storage, read_write> str : S_tint_packed_vec3;
-
-@group(0) @binding(1) var<storage, read_write> arr : array<tint_packed_vec3_f32_array_element, 4u>;
-
-fn main() {
- str.v = arr[0].elements;
- arr[1].elements = str.v;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- auto& vars = got.program.AST().GlobalVariables();
- ASSERT_EQ(vars.Length(), 2u);
-
- {
- // Check the layout of the struct type of "str".
- // The first member should have an alignment of 16 bytes, a size of 12 bytes, and the second
- // member should have an offset of 12 bytes.
- auto* sem_str = got.program.Sem().Get(vars[0]);
- auto* str_ty = sem_str->Type()->UnwrapRef()->As<core::type::Struct>();
- ASSERT_NE(str_ty, nullptr);
- ASSERT_EQ(str_ty->Members().Length(), 2u);
- EXPECT_EQ(str_ty->Members()[0]->Align(), 16u);
- EXPECT_EQ(str_ty->Members()[0]->Size(), 12u);
- EXPECT_EQ(str_ty->Members()[1]->Offset(), 12u);
- }
-
- {
- // Check the layout of the array type of "arr".
- // The element stride should be 16 bytes.
- auto* sem_arr = got.program.Sem().Get(vars[1]);
- auto* arr_ty = sem_arr->Type()->UnwrapRef()->As<core::type::Array>();
- ASSERT_NE(arr_ty, nullptr);
- EXPECT_EQ(arr_ty->Stride(), 16u);
- }
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, PackUnpackStructWithNonVec3Members) {
- auto* src = R"(
-struct S {
- v : vec3<f32>,
- arr : array<vec3<f32>, 4>,
- a : u32,
- b : vec4<f32>,
- c : array<vec4<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S;
-
-fn f() {
- let x = P;
- P = x;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- v : __packed_vec3<f32>,
- @align(16)
- arr : array<tint_packed_vec3_f32_array_element, 4u>,
- a : u32,
- b : vec4<f32>,
- c : array<vec4<f32>, 4>,
-}
-
-fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 4u>) -> array<vec3<f32>, 4u> {
- var result = array<vec3<f32>, 4u>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements), vec3<f32>(in[3].elements));
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_1(in : S_tint_packed_vec3) -> S {
- var result : S;
- result.v = vec3<f32>(in.v);
- result.arr = tint_unpack_vec3_in_composite(in.arr);
- result.a = in.a;
- result.b = in.b;
- result.c = in.c;
- return result;
-}
-
-fn tint_pack_vec3_in_composite(in : array<vec3<f32>, 4u>) -> array<tint_packed_vec3_f32_array_element, 4u> {
- var result = array<tint_packed_vec3_f32_array_element, 4u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[3])));
- return result;
-}
-
-fn tint_pack_vec3_in_composite_1(in : S) -> S_tint_packed_vec3 {
- var result : S_tint_packed_vec3;
- result.v = __packed_vec3<f32>(in.v);
- result.arr = tint_pack_vec3_in_composite(in.arr);
- result.a = in.a;
- result.b = in.b;
- result.c = in.c;
- return result;
-}
-
-struct S {
- v : vec3<f32>,
- arr : array<vec3<f32>, 4>,
- a : u32,
- b : vec4<f32>,
- c : array<vec4<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
-
-fn f() {
- let x = tint_unpack_vec3_in_composite_1(P);
- P = tint_pack_vec3_in_composite_1(x);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, Struct_ShaderIO) {
- // Test that we do not modify structures that are used for shader IO.
- auto* src = R"(
-struct S1 {
- @location(0) v : vec3<f32>,
-}
-
-struct S2 {
- @location(0) v : vec3<f32>,
- @builtin(position) pos : vec4<f32>,
-}
-
-@vertex
-fn main(s1 : S1) -> S2 {
- let v : vec3<f32> = s1.v;
- var s2 : S2;
- s2.v = v;
- return s2;
-}
-)";
-
- auto* expect = R"(
-struct S1 {
- @location(0)
- v : vec3<f32>,
-}
-
-struct S2 {
- @location(0)
- v : vec3<f32>,
- @builtin(position)
- pos : vec4<f32>,
-}
-
-@vertex
-fn main(s1 : S1) -> S2 {
- let v : vec3<f32> = s1.v;
- var s2 : S2;
- s2.v = v;
- return s2;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ModfReturnStruct) {
- // Test that we do not try to modify accessors on the anonymous structure returned by modf.
- auto* src = R"(
-@group(0) @binding(0) var<storage, read_write> output : vec3<f32>;
-
-const values = array(modf(vec3(1.0, 2.0, 3.0)).fract);
-
-@compute @workgroup_size(1)
-fn main() {
- output = values[0];
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-@group(0) @binding(0) var<storage, read_write> output : __packed_vec3<f32>;
-
-const values = array(modf(vec3(1.0, 2.0, 3.0)).fract);
-
-@compute @workgroup_size(1)
-fn main() {
- output = __packed_vec3<f32>(values[0]);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ModfReturnStruct_PointerToMember) {
- // Test that we can pass a pointer to the vec3 member of the modf return struct to a function
- // parameter to which we also pass a pointer to a vec3 member on a host-shareable struct.
- auto* src = R"(
-struct S {
- v : vec3<f32>
-}
-
-@group(0) @binding(0) var<storage, read_write> output : S;
-
-fn foo(p : ptr<function, vec3<f32>>) {
- (*p) = vec3(1, 2, 3);
-}
-
-@compute @workgroup_size(1)
-fn main() {
- var f : S;
- var modf_ret = modf(vec3(1.0, 2.0, 3.0));
- foo(&f.v);
- foo(&modf_ret.fract);
- output.v = modf_ret.fract;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct S_tint_packed_vec3 {
- @align(16)
- v : __packed_vec3<f32>,
-}
-
-struct S {
- v : vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> output : S_tint_packed_vec3;
-
-fn foo(p : ptr<function, vec3<f32>>) {
- *(p) = vec3(1, 2, 3);
-}
-
-@compute @workgroup_size(1)
-fn main() {
- var f : S;
- var modf_ret = modf(vec3(1.0, 2.0, 3.0));
- foo(&(f.v));
- foo(&(modf_ret.fract));
- output.v = __packed_vec3<f32>(modf_ret.fract);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, MultipleStructMembers) {
- auto* src = R"(
-struct S {
- v2_a : vec2<f32>,
- v3_a : vec3<f32>,
- v4_a : vec4<f32>,
- v2_b : vec2<f32>,
- v3_b : vec3<f32>,
- v4_b : vec4<f32>,
- v2_arr : array<vec2<f32>, 4>,
- v3_arr : array<vec3<f32>, 4>,
- v4_arr : array<vec4<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
- let v2_a = P.v2_a;
- let v3_a = P.v3_a;
- let v4_a = P.v4_a;
- let v2_b = P.v2_b;
- let v3_b = P.v3_b;
- let v4_b = P.v4_b;
- let v2_arr : array<vec2<f32>, 4> = P.v2_arr;
- let v3_arr : array<vec3<f32>, 4> = P.v3_arr;
- let v4_arr : array<vec4<f32>, 4> = P.v4_arr;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- v2_a : vec2<f32>,
- @align(16)
- v3_a : __packed_vec3<f32>,
- v4_a : vec4<f32>,
- v2_b : vec2<f32>,
- @align(16)
- v3_b : __packed_vec3<f32>,
- v4_b : vec4<f32>,
- v2_arr : array<vec2<f32>, 4>,
- @align(16)
- v3_arr : array<tint_packed_vec3_f32_array_element, 4u>,
- v4_arr : array<vec4<f32>, 4>,
-}
-
-fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 4u>) -> array<vec3<f32>, 4u> {
- var result = array<vec3<f32>, 4u>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements), vec3<f32>(in[3].elements));
- return result;
-}
-
-struct S {
- v2_a : vec2<f32>,
- v3_a : vec3<f32>,
- v4_a : vec4<f32>,
- v2_b : vec2<f32>,
- v3_b : vec3<f32>,
- v4_b : vec4<f32>,
- v2_arr : array<vec2<f32>, 4>,
- v3_arr : array<vec3<f32>, 4>,
- v4_arr : array<vec4<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
-
-fn f() {
- let v2_a = P.v2_a;
- let v3_a = vec3<f32>(P.v3_a);
- let v4_a = P.v4_a;
- let v2_b = P.v2_b;
- let v3_b = vec3<f32>(P.v3_b);
- let v4_b = P.v4_b;
- let v2_arr : array<vec2<f32>, 4> = P.v2_arr;
- let v3_arr : array<vec3<f32>, 4> = tint_unpack_vec3_in_composite(P.v3_arr);
- let v4_arr : array<vec4<f32>, 4> = P.v4_arr;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, Vec3Pointers) {
- auto* src = R"(
-struct S {
- v : vec3<f32>,
- m : mat3x3<f32>,
- arr_v : array<vec3<f32>, 4>,
- arr_m : array<mat3x3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> v : vec3<f32>;
-@group(0) @binding(1) var<storage, read_write> arr_v : array<vec3<f32>, 4>;
-@group(0) @binding(2) var<storage, read_write> m : mat3x3<f32>;
-@group(0) @binding(3) var<storage, read_write> arr_m : array<mat3x3<f32>, 4>;
-@group(0) @binding(4) var<storage, read_write> str : S;
-
-fn f() {
- let p_v = &v;
- let v = *p_v;
- *p_v = v;
-
- let p_arr_v = &arr_v[0];
- let arr_v = *p_arr_v;
- *p_arr_v = arr_v;
-
- let p_m = &m[0];
- let m = *p_m;
- *p_m = m;
-
- let p_arr_m = &arr_m[0][1];
- let arr_m = *p_arr_m;
- *p_arr_m = arr_m;
-
- let p_str_v = &str.v;
- let str_v = *p_str_v;
- *p_str_v = str_v;
-
- let p_str_arr_v = &str.arr_v[0];
- let str_arr_v = *p_str_arr_v;
- *p_str_arr_v = str_arr_v;
-
- let p_str_m = &str.m[0];
- let str_m = *p_str_m;
- *p_str_m = str_m;
-
- let p_str_arr_m = &str.arr_m[0][1];
- let str_arr_m = *p_str_arr_m;
- *p_str_arr_m = str_arr_m;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- v : __packed_vec3<f32>,
- @align(16)
- m : array<tint_packed_vec3_f32_array_element, 3u>,
- @align(16)
- arr_v : array<tint_packed_vec3_f32_array_element, 4u>,
- @align(16)
- arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
-}
-
-struct S {
- v : vec3<f32>,
- m : mat3x3<f32>,
- arr_v : array<vec3<f32>, 4>,
- arr_m : array<mat3x3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> v : __packed_vec3<f32>;
-
-@group(0) @binding(1) var<storage, read_write> arr_v : array<tint_packed_vec3_f32_array_element, 4u>;
-
-@group(0) @binding(2) var<storage, read_write> m : array<tint_packed_vec3_f32_array_element, 3u>;
-
-@group(0) @binding(3) var<storage, read_write> arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
-
-@group(0) @binding(4) var<storage, read_write> str : S_tint_packed_vec3;
-
-fn f() {
- let p_v = &(v);
- let v = vec3<f32>(*(p_v));
- *(p_v) = __packed_vec3<f32>(v);
- let p_arr_v = &(arr_v[0].elements);
- let arr_v = vec3<f32>(*(p_arr_v));
- *(p_arr_v) = __packed_vec3<f32>(arr_v);
- let p_m = &(m[0].elements);
- let m = vec3<f32>(*(p_m));
- *(p_m) = __packed_vec3<f32>(m);
- let p_arr_m = &(arr_m[0][1].elements);
- let arr_m = vec3<f32>(*(p_arr_m));
- *(p_arr_m) = __packed_vec3<f32>(arr_m);
- let p_str_v = &(str.v);
- let str_v = vec3<f32>(*(p_str_v));
- *(p_str_v) = __packed_vec3<f32>(str_v);
- let p_str_arr_v = &(str.arr_v[0].elements);
- let str_arr_v = vec3<f32>(*(p_str_arr_v));
- *(p_str_arr_v) = __packed_vec3<f32>(str_arr_v);
- let p_str_m = &(str.m[0].elements);
- let str_m = vec3<f32>(*(p_str_m));
- *(p_str_m) = __packed_vec3<f32>(str_m);
- let p_str_arr_m = &(str.arr_m[0][1].elements);
- let str_arr_m = vec3<f32>(*(p_str_arr_m));
- *(p_str_arr_m) = __packed_vec3<f32>(str_arr_m);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, MatrixPointers) {
- auto* src = R"(
-struct S {
- m : mat3x3<f32>,
- arr_m : array<mat3x3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> m : mat3x3<f32>;
-@group(0) @binding(1) var<storage, read_write> arr_m : array<mat3x3<f32>, 4>;
-@group(0) @binding(2) var<storage, read_write> str : S;
-
-fn f() {
- let p_m = &m;
- let m = *p_m;
- *p_m = m;
-
- let p_arr_m = &arr_m[0];
- let arr_m = *p_arr_m;
- *p_arr_m = arr_m;
-
- let p_str_m = &str.m;
- let str_m = *p_str_m;
- *p_str_m = str_m;
-
- let p_str_arr_m = &str.arr_m[0];
- let str_arr_m = *p_str_arr_m;
- *p_str_arr_m = str_arr_m;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- m : array<tint_packed_vec3_f32_array_element, 3u>,
- @align(16)
- arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
-}
-
-fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
- return result;
-}
-
-fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
- var result = array<tint_packed_vec3_f32_array_element, 3u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])));
- return result;
-}
-
-struct S {
- m : mat3x3<f32>,
- arr_m : array<mat3x3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> m : array<tint_packed_vec3_f32_array_element, 3u>;
-
-@group(0) @binding(1) var<storage, read_write> arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
-
-@group(0) @binding(2) var<storage, read_write> str : S_tint_packed_vec3;
-
-fn f() {
- let p_m = &(m);
- let m = tint_unpack_vec3_in_composite(*(p_m));
- *(p_m) = tint_pack_vec3_in_composite(m);
- let p_arr_m = &(arr_m[0]);
- let arr_m = tint_unpack_vec3_in_composite(*(p_arr_m));
- *(p_arr_m) = tint_pack_vec3_in_composite(arr_m);
- let p_str_m = &(str.m);
- let str_m = tint_unpack_vec3_in_composite(*(p_str_m));
- *(p_str_m) = tint_pack_vec3_in_composite(str_m);
- let p_str_arr_m = &(str.arr_m[0]);
- let str_arr_m = tint_unpack_vec3_in_composite(*(p_str_arr_m));
- *(p_str_arr_m) = tint_pack_vec3_in_composite(str_arr_m);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ArrayOfVec3Pointers) {
- auto* src = R"(
-struct S {
- arr_v : array<vec3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> arr_v : array<vec3<f32>, 4>;
-@group(0) @binding(1) var<storage, read_write> str : S;
-
-fn f() {
- let p_arr_v = &arr_v;
- let arr_v = *p_arr_v;
- *p_arr_v = arr_v;
-
- let p_str_arr_v = &str.arr_v;
- let str_arr_v = *p_str_arr_v;
- *p_str_arr_v = str_arr_v;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr_v : array<tint_packed_vec3_f32_array_element, 4u>,
-}
-
-fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 4u>) -> array<vec3<f32>, 4u> {
- var result = array<vec3<f32>, 4u>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements), vec3<f32>(in[3].elements));
- return result;
-}
-
-fn tint_pack_vec3_in_composite(in : array<vec3<f32>, 4u>) -> array<tint_packed_vec3_f32_array_element, 4u> {
- var result = array<tint_packed_vec3_f32_array_element, 4u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[3])));
- return result;
-}
-
-struct S {
- arr_v : array<vec3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> arr_v : array<tint_packed_vec3_f32_array_element, 4u>;
-
-@group(0) @binding(1) var<storage, read_write> str : S_tint_packed_vec3;
-
-fn f() {
- let p_arr_v = &(arr_v);
- let arr_v = tint_unpack_vec3_in_composite(*(p_arr_v));
- *(p_arr_v) = tint_pack_vec3_in_composite(arr_v);
- let p_str_arr_v = &(str.arr_v);
- let str_arr_v = tint_unpack_vec3_in_composite(*(p_str_arr_v));
- *(p_str_arr_v) = tint_pack_vec3_in_composite(str_arr_v);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ArrayOfMatrixPointers) {
- auto* src = R"(
-struct S {
- arr_m : array<mat3x3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> arr_m : array<mat3x3<f32>, 4>;
-@group(0) @binding(1) var<storage, read_write> str : S;
-
-fn f() {
- let p_arr_m = &arr_m;
- let arr_m = *p_arr_m;
- *p_arr_m = arr_m;
-
- let p_str_arr_m = &str.arr_m;
- let str_arr_m = *p_str_arr_m;
- *p_str_arr_m = str_arr_m;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
-}
-
-fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_1(in : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>) -> array<mat3x3<f32>, 4u> {
- var result = array<mat3x3<f32>, 4u>(tint_unpack_vec3_in_composite(in[0]), tint_unpack_vec3_in_composite(in[1]), tint_unpack_vec3_in_composite(in[2]), tint_unpack_vec3_in_composite(in[3]));
- return result;
-}
-
-fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
- var result = array<tint_packed_vec3_f32_array_element, 3u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])));
- return result;
-}
-
-fn tint_pack_vec3_in_composite_1(in : array<mat3x3<f32>, 4u>) -> array<array<tint_packed_vec3_f32_array_element, 3u>, 4u> {
- var result = array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>(tint_pack_vec3_in_composite(in[0]), tint_pack_vec3_in_composite(in[1]), tint_pack_vec3_in_composite(in[2]), tint_pack_vec3_in_composite(in[3]));
- return result;
-}
-
-struct S {
- arr_m : array<mat3x3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
-
-@group(0) @binding(1) var<storage, read_write> str : S_tint_packed_vec3;
-
-fn f() {
- let p_arr_m = &(arr_m);
- let arr_m = tint_unpack_vec3_in_composite_1(*(p_arr_m));
- *(p_arr_m) = tint_pack_vec3_in_composite_1(arr_m);
- let p_str_arr_m = &(str.arr_m);
- let str_arr_m = tint_unpack_vec3_in_composite_1(*(p_str_arr_m));
- *(p_str_arr_m) = tint_pack_vec3_in_composite_1(str_arr_m);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructPointers) {
- auto* src = R"(
-struct S {
- v : vec3<f32>,
- m : mat3x3<f32>,
- arr_v : array<vec3<f32>, 4>,
- arr_m : array<mat3x3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> str : S;
-
-fn f() {
- let p_str = &str;
- let str = *p_str;
- *p_str = str;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- v : __packed_vec3<f32>,
- @align(16)
- m : array<tint_packed_vec3_f32_array_element, 3u>,
- @align(16)
- arr_v : array<tint_packed_vec3_f32_array_element, 4u>,
- @align(16)
- arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
-}
-
-fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_1(in : array<tint_packed_vec3_f32_array_element, 4u>) -> array<vec3<f32>, 4u> {
- var result = array<vec3<f32>, 4u>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements), vec3<f32>(in[3].elements));
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_2(in : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>) -> array<mat3x3<f32>, 4u> {
- var result = array<mat3x3<f32>, 4u>(tint_unpack_vec3_in_composite(in[0]), tint_unpack_vec3_in_composite(in[1]), tint_unpack_vec3_in_composite(in[2]), tint_unpack_vec3_in_composite(in[3]));
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_3(in : S_tint_packed_vec3) -> S {
- var result : S;
- result.v = vec3<f32>(in.v);
- result.m = tint_unpack_vec3_in_composite(in.m);
- result.arr_v = tint_unpack_vec3_in_composite_1(in.arr_v);
- result.arr_m = tint_unpack_vec3_in_composite_2(in.arr_m);
- return result;
-}
-
-fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
- var result = array<tint_packed_vec3_f32_array_element, 3u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])));
- return result;
-}
-
-fn tint_pack_vec3_in_composite_1(in : array<vec3<f32>, 4u>) -> array<tint_packed_vec3_f32_array_element, 4u> {
- var result = array<tint_packed_vec3_f32_array_element, 4u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[3])));
- return result;
-}
-
-fn tint_pack_vec3_in_composite_2(in : array<mat3x3<f32>, 4u>) -> array<array<tint_packed_vec3_f32_array_element, 3u>, 4u> {
- var result = array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>(tint_pack_vec3_in_composite(in[0]), tint_pack_vec3_in_composite(in[1]), tint_pack_vec3_in_composite(in[2]), tint_pack_vec3_in_composite(in[3]));
- return result;
-}
-
-fn tint_pack_vec3_in_composite_3(in : S) -> S_tint_packed_vec3 {
- var result : S_tint_packed_vec3;
- result.v = __packed_vec3<f32>(in.v);
- result.m = tint_pack_vec3_in_composite(in.m);
- result.arr_v = tint_pack_vec3_in_composite_1(in.arr_v);
- result.arr_m = tint_pack_vec3_in_composite_2(in.arr_m);
- return result;
-}
-
-struct S {
- v : vec3<f32>,
- m : mat3x3<f32>,
- arr_v : array<vec3<f32>, 4>,
- arr_m : array<mat3x3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> str : S_tint_packed_vec3;
-
-fn f() {
- let p_str = &(str);
- let str = tint_unpack_vec3_in_composite_3(*(p_str));
- *(p_str) = tint_pack_vec3_in_composite_3(str);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, VectorPointerParameters) {
- auto* src = R"(
-struct S {
- v : vec3<f32>,
- m : mat3x3<f32>,
- arr_v : array<vec3<f32>, 4>,
- arr_m : array<mat3x3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> v : vec3<f32>;
-@group(0) @binding(1) var<storage, read_write> arr_v : array<vec3<f32>, 4>;
-@group(0) @binding(2) var<storage, read_write> m : mat3x3<f32>;
-@group(0) @binding(3) var<storage, read_write> arr_m : array<mat3x3<f32>, 4>;
-@group(0) @binding(4) var<storage, read_write> str : S;
-
-fn load(p : ptr<storage, vec3<f32>, read_write>) -> vec3<f32> {
- return *p;
-}
-
-fn store(p : ptr<storage, vec3<f32>, read_write>) {
- *p = vec3(1, 2, 3);
-}
-
-fn f() {
- load(&v);
- store(&v);
- load(&arr_v[0]);
- store(&arr_v[0]);
- load(&m[0]);
- store(&m[0]);
- load(&arr_m[0][1]);
- store(&arr_m[0][1]);
- load(&str.v);
- store(&str.v);
- load(&str.arr_v[0]);
- store(&str.arr_v[0]);
- load(&str.m[0]);
- store(&str.m[0]);
- load(&str.arr_m[0][1]);
- store(&str.arr_m[0][1]);
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- v : __packed_vec3<f32>,
- @align(16)
- m : array<tint_packed_vec3_f32_array_element, 3u>,
- @align(16)
- arr_v : array<tint_packed_vec3_f32_array_element, 4u>,
- @align(16)
- arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
-}
-
-struct S {
- v : vec3<f32>,
- m : mat3x3<f32>,
- arr_v : array<vec3<f32>, 4>,
- arr_m : array<mat3x3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> v : __packed_vec3<f32>;
-
-@group(0) @binding(1) var<storage, read_write> arr_v : array<tint_packed_vec3_f32_array_element, 4u>;
-
-@group(0) @binding(2) var<storage, read_write> m : array<tint_packed_vec3_f32_array_element, 3u>;
-
-@group(0) @binding(3) var<storage, read_write> arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
-
-@group(0) @binding(4) var<storage, read_write> str : S_tint_packed_vec3;
-
-fn load(p : ptr<storage, __packed_vec3<f32>, read_write>) -> vec3<f32> {
- return vec3<f32>(*(p));
-}
-
-fn store(p : ptr<storage, __packed_vec3<f32>, read_write>) {
- *(p) = __packed_vec3<f32>(vec3(1, 2, 3));
-}
-
-fn f() {
- load(&(v));
- store(&(v));
- load(&(arr_v[0].elements));
- store(&(arr_v[0].elements));
- load(&(m[0].elements));
- store(&(m[0].elements));
- load(&(arr_m[0][1].elements));
- store(&(arr_m[0][1].elements));
- load(&(str.v));
- store(&(str.v));
- load(&(str.arr_v[0].elements));
- store(&(str.arr_v[0].elements));
- load(&(str.m[0].elements));
- store(&(str.m[0].elements));
- load(&(str.arr_m[0][1].elements));
- store(&(str.arr_m[0][1].elements));
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, MatrixPointerParameters) {
- auto* src = R"(
-struct S {
- m : mat3x3<f32>,
- arr_m : array<mat3x3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> m : mat3x3<f32>;
-@group(0) @binding(1) var<storage, read_write> arr_m : array<mat3x3<f32>, 4>;
-@group(0) @binding(2) var<storage, read_write> str : S;
-
-fn load(p : ptr<storage, mat3x3<f32>, read_write>) -> mat3x3<f32> {
- return *p;
-}
-
-fn store(p : ptr<storage, mat3x3<f32>, read_write>) {
- *p = mat3x3(1, 2, 3, 4, 5, 6, 7, 8, 9);
-}
-
-fn f() {
- load(&m);
- store(&m);
- load(&arr_m[0]);
- store(&arr_m[0]);
- load(&str.m);
- store(&str.m);
- load(&str.arr_m[0]);
- store(&str.arr_m[0]);
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- m : array<tint_packed_vec3_f32_array_element, 3u>,
- @align(16)
- arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
-}
-
-fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
- return result;
-}
-
-fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
- var result = array<tint_packed_vec3_f32_array_element, 3u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])));
- return result;
-}
-
-struct S {
- m : mat3x3<f32>,
- arr_m : array<mat3x3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> m : array<tint_packed_vec3_f32_array_element, 3u>;
-
-@group(0) @binding(1) var<storage, read_write> arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
-
-@group(0) @binding(2) var<storage, read_write> str : S_tint_packed_vec3;
-
-fn load(p : ptr<storage, array<tint_packed_vec3_f32_array_element, 3u>, read_write>) -> mat3x3<f32> {
- return tint_unpack_vec3_in_composite(*(p));
-}
-
-fn store(p : ptr<storage, array<tint_packed_vec3_f32_array_element, 3u>, read_write>) {
- *(p) = tint_pack_vec3_in_composite(mat3x3(1, 2, 3, 4, 5, 6, 7, 8, 9));
-}
-
-fn f() {
- load(&(m));
- store(&(m));
- load(&(arr_m[0]));
- store(&(arr_m[0]));
- load(&(str.m));
- store(&(str.m));
- load(&(str.arr_m[0]));
- store(&(str.arr_m[0]));
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ArrayOfVectorPointerParameters) {
- auto* src = R"(
-struct S {
- arr_v : array<vec3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> arr_v : array<vec3<f32>, 4>;
-@group(0) @binding(1) var<storage, read_write> str : S;
-
-fn load(p : ptr<storage, array<vec3<f32>, 4>, read_write>) -> array<vec3<f32>, 4> {
- return *p;
-}
-
-fn store(p : ptr<storage, array<vec3<f32>, 4>, read_write>) {
- *p = array(vec3(1.0), vec3(2.0), vec3(3.0), vec3(4.0));
-}
-
-fn f() {
- load(&arr_v);
- store(&arr_v);
- load(&str.arr_v);
- store(&str.arr_v);
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr_v : array<tint_packed_vec3_f32_array_element, 4u>,
-}
-
-fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 4u>) -> array<vec3<f32>, 4u> {
- var result = array<vec3<f32>, 4u>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements), vec3<f32>(in[3].elements));
- return result;
-}
-
-fn tint_pack_vec3_in_composite(in : array<vec3<f32>, 4u>) -> array<tint_packed_vec3_f32_array_element, 4u> {
- var result = array<tint_packed_vec3_f32_array_element, 4u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[3])));
- return result;
-}
-
-struct S {
- arr_v : array<vec3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> arr_v : array<tint_packed_vec3_f32_array_element, 4u>;
-
-@group(0) @binding(1) var<storage, read_write> str : S_tint_packed_vec3;
-
-fn load(p : ptr<storage, array<tint_packed_vec3_f32_array_element, 4u>, read_write>) -> array<vec3<f32>, 4> {
- return tint_unpack_vec3_in_composite(*(p));
-}
-
-fn store(p : ptr<storage, array<tint_packed_vec3_f32_array_element, 4u>, read_write>) {
- *(p) = tint_pack_vec3_in_composite(array(vec3(1.0), vec3(2.0), vec3(3.0), vec3(4.0)));
-}
-
-fn f() {
- load(&(arr_v));
- store(&(arr_v));
- load(&(str.arr_v));
- store(&(str.arr_v));
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ArrayOfMatrixPointerParameters) {
- auto* src = R"(
-struct S {
- arr_m : array<mat3x3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> arr_m : array<mat3x3<f32>, 4>;
-@group(0) @binding(1) var<storage, read_write> str : S;
-
-fn load(p : ptr<storage, array<mat3x3<f32>, 4>, read_write>) -> array<mat3x3<f32>, 4> {
- return *p;
-}
-
-fn store(p : ptr<storage, array<mat3x3<f32>, 4>, read_write>) {
- *p = array(mat3x3<f32>(), mat3x3<f32>(), mat3x3<f32>(), mat3x3<f32>());
-}
-
-fn f() {
- load(&arr_m);
- store(&arr_m);
- load(&str.arr_m);
- store(&str.arr_m);
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
-}
-
-fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_1(in : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>) -> array<mat3x3<f32>, 4u> {
- var result = array<mat3x3<f32>, 4u>(tint_unpack_vec3_in_composite(in[0]), tint_unpack_vec3_in_composite(in[1]), tint_unpack_vec3_in_composite(in[2]), tint_unpack_vec3_in_composite(in[3]));
- return result;
-}
-
-fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
- var result = array<tint_packed_vec3_f32_array_element, 3u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])));
- return result;
-}
-
-fn tint_pack_vec3_in_composite_1(in : array<mat3x3<f32>, 4u>) -> array<array<tint_packed_vec3_f32_array_element, 3u>, 4u> {
- var result = array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>(tint_pack_vec3_in_composite(in[0]), tint_pack_vec3_in_composite(in[1]), tint_pack_vec3_in_composite(in[2]), tint_pack_vec3_in_composite(in[3]));
- return result;
-}
-
-struct S {
- arr_m : array<mat3x3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
-
-@group(0) @binding(1) var<storage, read_write> str : S_tint_packed_vec3;
-
-fn load(p : ptr<storage, array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>, read_write>) -> array<mat3x3<f32>, 4> {
- return tint_unpack_vec3_in_composite_1(*(p));
-}
-
-fn store(p : ptr<storage, array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>, read_write>) {
- *(p) = tint_pack_vec3_in_composite_1(array(mat3x3<f32>(), mat3x3<f32>(), mat3x3<f32>(), mat3x3<f32>()));
-}
-
-fn f() {
- load(&(arr_m));
- store(&(arr_m));
- load(&(str.arr_m));
- store(&(str.arr_m));
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, StructPointerParameters) {
- auto* src = R"(
-struct S {
- v : vec3<f32>,
- m : mat3x3<f32>,
- arr_v : array<vec3<f32>, 4>,
- arr_m : array<mat3x3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> str : S;
-
-fn load(p : ptr<storage, S, read_write>) -> S {
- return *p;
-}
-
-fn store(p : ptr<storage, S, read_write>) {
- *p = S();
-}
-
-fn f() {
- load(&str);
- store(&str);
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- v : __packed_vec3<f32>,
- @align(16)
- m : array<tint_packed_vec3_f32_array_element, 3u>,
- @align(16)
- arr_v : array<tint_packed_vec3_f32_array_element, 4u>,
- @align(16)
- arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
-}
-
-fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_1(in : array<tint_packed_vec3_f32_array_element, 4u>) -> array<vec3<f32>, 4u> {
- var result = array<vec3<f32>, 4u>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements), vec3<f32>(in[3].elements));
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_2(in : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>) -> array<mat3x3<f32>, 4u> {
- var result = array<mat3x3<f32>, 4u>(tint_unpack_vec3_in_composite(in[0]), tint_unpack_vec3_in_composite(in[1]), tint_unpack_vec3_in_composite(in[2]), tint_unpack_vec3_in_composite(in[3]));
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_3(in : S_tint_packed_vec3) -> S {
- var result : S;
- result.v = vec3<f32>(in.v);
- result.m = tint_unpack_vec3_in_composite(in.m);
- result.arr_v = tint_unpack_vec3_in_composite_1(in.arr_v);
- result.arr_m = tint_unpack_vec3_in_composite_2(in.arr_m);
- return result;
-}
-
-fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
- var result = array<tint_packed_vec3_f32_array_element, 3u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])));
- return result;
-}
-
-fn tint_pack_vec3_in_composite_1(in : array<vec3<f32>, 4u>) -> array<tint_packed_vec3_f32_array_element, 4u> {
- var result = array<tint_packed_vec3_f32_array_element, 4u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[3])));
- return result;
-}
-
-fn tint_pack_vec3_in_composite_2(in : array<mat3x3<f32>, 4u>) -> array<array<tint_packed_vec3_f32_array_element, 3u>, 4u> {
- var result = array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>(tint_pack_vec3_in_composite(in[0]), tint_pack_vec3_in_composite(in[1]), tint_pack_vec3_in_composite(in[2]), tint_pack_vec3_in_composite(in[3]));
- return result;
-}
-
-fn tint_pack_vec3_in_composite_3(in : S) -> S_tint_packed_vec3 {
- var result : S_tint_packed_vec3;
- result.v = __packed_vec3<f32>(in.v);
- result.m = tint_pack_vec3_in_composite(in.m);
- result.arr_v = tint_pack_vec3_in_composite_1(in.arr_v);
- result.arr_m = tint_pack_vec3_in_composite_2(in.arr_m);
- return result;
-}
-
-struct S {
- v : vec3<f32>,
- m : mat3x3<f32>,
- arr_v : array<vec3<f32>, 4>,
- arr_m : array<mat3x3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> str : S_tint_packed_vec3;
-
-fn load(p : ptr<storage, S_tint_packed_vec3, read_write>) -> S {
- return tint_unpack_vec3_in_composite_3(*(p));
-}
-
-fn store(p : ptr<storage, S_tint_packed_vec3, read_write>) {
- *(p) = tint_pack_vec3_in_composite_3(S());
-}
-
-fn f() {
- load(&(str));
- store(&(str));
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, MixedAddressSpace_Struct) {
- auto* src = R"(
-struct S {
- v : vec3<f32>,
- arr : array<vec3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S;
-
-fn f() {
- var f : S;
- let v = f.v;
- let arr = f.arr;
- P = f;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- v : __packed_vec3<f32>,
- @align(16)
- arr : array<tint_packed_vec3_f32_array_element, 4u>,
-}
-
-fn tint_pack_vec3_in_composite(in : array<vec3<f32>, 4u>) -> array<tint_packed_vec3_f32_array_element, 4u> {
- var result = array<tint_packed_vec3_f32_array_element, 4u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[3])));
- return result;
-}
-
-fn tint_pack_vec3_in_composite_1(in : S) -> S_tint_packed_vec3 {
- var result : S_tint_packed_vec3;
- result.v = __packed_vec3<f32>(in.v);
- result.arr = tint_pack_vec3_in_composite(in.arr);
- return result;
-}
-
-struct S {
- v : vec3<f32>,
- arr : array<vec3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
-
-fn f() {
- var f : S;
- let v = f.v;
- let arr = f.arr;
- P = tint_pack_vec3_in_composite_1(f);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, MixedAddressSpace_NestedStruct) {
- auto* src = R"(
-struct S {
- v : vec3<f32>,
- arr : array<vec3<f32>, 4>,
-}
-
-struct Outer {
- inner : S,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : Outer;
-
-fn f() {
- var f : Outer;
- let v = f.inner.v;
- let arr = f.inner.arr;
- P = f;
- P.inner = f.inner;
- P.inner.v = f.inner.v;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- v : __packed_vec3<f32>,
- @align(16)
- arr : array<tint_packed_vec3_f32_array_element, 4u>,
-}
-
-struct Outer_tint_packed_vec3 {
- @align(16)
- inner : S_tint_packed_vec3,
-}
-
-fn tint_pack_vec3_in_composite(in : array<vec3<f32>, 4u>) -> array<tint_packed_vec3_f32_array_element, 4u> {
- var result = array<tint_packed_vec3_f32_array_element, 4u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[3])));
- return result;
-}
-
-fn tint_pack_vec3_in_composite_1(in : S) -> S_tint_packed_vec3 {
- var result : S_tint_packed_vec3;
- result.v = __packed_vec3<f32>(in.v);
- result.arr = tint_pack_vec3_in_composite(in.arr);
- return result;
-}
-
-fn tint_pack_vec3_in_composite_2(in : Outer) -> Outer_tint_packed_vec3 {
- var result : Outer_tint_packed_vec3;
- result.inner = tint_pack_vec3_in_composite_1(in.inner);
- return result;
-}
-
-struct S {
- v : vec3<f32>,
- arr : array<vec3<f32>, 4>,
-}
-
-struct Outer {
- inner : S,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : Outer_tint_packed_vec3;
-
-fn f() {
- var f : Outer;
- let v = f.inner.v;
- let arr = f.inner.arr;
- P = tint_pack_vec3_in_composite_2(f);
- P.inner = tint_pack_vec3_in_composite_1(f.inner);
- P.inner.v = __packed_vec3<f32>(f.inner.v);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, MixedAddressSpace_AnotherStructNotShared) {
- // Test that we can pass a pointers to a members of both shared and non-shared structs to the
- // same function.
- auto* src = R"(
-struct S {
- v : vec3<f32>,
- arr : array<vec3<f32>, 4>,
-}
-
-struct NotShared {
- v : vec3<f32>,
- arr : array<vec3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S;
-
-fn g(p : ptr<function, vec3<f32>>) -> vec3<f32> {
- return *p;
-}
-
-fn f() {
- var f1 : S;
- var f2 : NotShared;
- g(&f1.v);
- g(&f1.arr[0]);
- g(&f2.v);
- g(&f2.arr[0]);
- P = f1;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- v : __packed_vec3<f32>,
- @align(16)
- arr : array<tint_packed_vec3_f32_array_element, 4u>,
-}
-
-fn tint_pack_vec3_in_composite(in : array<vec3<f32>, 4u>) -> array<tint_packed_vec3_f32_array_element, 4u> {
- var result = array<tint_packed_vec3_f32_array_element, 4u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[3])));
- return result;
-}
-
-fn tint_pack_vec3_in_composite_1(in : S) -> S_tint_packed_vec3 {
- var result : S_tint_packed_vec3;
- result.v = __packed_vec3<f32>(in.v);
- result.arr = tint_pack_vec3_in_composite(in.arr);
- return result;
-}
-
-struct S {
- v : vec3<f32>,
- arr : array<vec3<f32>, 4>,
-}
-
-struct NotShared {
- v : vec3<f32>,
- arr : array<vec3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> P : S_tint_packed_vec3;
-
-fn g(p : ptr<function, vec3<f32>>) -> vec3<f32> {
- return *(p);
-}
-
-fn f() {
- var f1 : S;
- var f2 : NotShared;
- g(&(f1.v));
- g(&(f1.arr[0]));
- g(&(f2.v));
- g(&(f2.arr[0]));
- P = tint_pack_vec3_in_composite_1(f1);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, MixedAddressSpace_InitFromLoad_ExplicitVarType) {
- auto* src = R"(
-struct S {
- v : vec3<f32>,
- m : mat3x3<f32>,
- arr_v : array<vec3<f32>, 4>,
- arr_m : array<mat3x3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
- var f1 : S = P;
- var f2 : vec3<f32> = P.v;
- var f3 : mat3x3<f32> = P.m;
- var f4 : array<vec3<f32>, 4> = P.arr_v;
- var f5 : array<mat3x3<f32>, 4> = P.arr_m;
- let v_1 = f1.v;
- let v_2 = f2;
- let v_3 = f3[0];
- let v_4 = f4[1];
- let v_5 = f5[2][2];
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- v : __packed_vec3<f32>,
- @align(16)
- m : array<tint_packed_vec3_f32_array_element, 3u>,
- @align(16)
- arr_v : array<tint_packed_vec3_f32_array_element, 4u>,
- @align(16)
- arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
-}
-
-fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_1(in : array<tint_packed_vec3_f32_array_element, 4u>) -> array<vec3<f32>, 4u> {
- var result = array<vec3<f32>, 4u>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements), vec3<f32>(in[3].elements));
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_2(in : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>) -> array<mat3x3<f32>, 4u> {
- var result = array<mat3x3<f32>, 4u>(tint_unpack_vec3_in_composite(in[0]), tint_unpack_vec3_in_composite(in[1]), tint_unpack_vec3_in_composite(in[2]), tint_unpack_vec3_in_composite(in[3]));
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_3(in : S_tint_packed_vec3) -> S {
- var result : S;
- result.v = vec3<f32>(in.v);
- result.m = tint_unpack_vec3_in_composite(in.m);
- result.arr_v = tint_unpack_vec3_in_composite_1(in.arr_v);
- result.arr_m = tint_unpack_vec3_in_composite_2(in.arr_m);
- return result;
-}
-
-struct S {
- v : vec3<f32>,
- m : mat3x3<f32>,
- arr_v : array<vec3<f32>, 4>,
- arr_m : array<mat3x3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
-
-fn f() {
- var f1 : S = tint_unpack_vec3_in_composite_3(P);
- var f2 : vec3<f32> = vec3<f32>(P.v);
- var f3 : mat3x3<f32> = tint_unpack_vec3_in_composite(P.m);
- var f4 : array<vec3<f32>, 4> = tint_unpack_vec3_in_composite_1(P.arr_v);
- var f5 : array<mat3x3<f32>, 4> = tint_unpack_vec3_in_composite_2(P.arr_m);
- let v_1 = f1.v;
- let v_2 = f2;
- let v_3 = f3[0];
- let v_4 = f4[1];
- let v_5 = f5[2][2];
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, MixedAddressSpace_InitFromLoad_InferredVarType) {
- auto* src = R"(
-struct S {
- v : vec3<f32>,
- m : mat3x3<f32>,
- arr_v : array<vec3<f32>, 4>,
- arr_m : array<mat3x3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
- var f1 = P;
- var f2 = P.v;
- var f3 = P.m;
- var f4 = P.arr_v;
- var f5 = P.arr_m;
- let v_1 = f1.v;
- let v_2 = f2;
- let v_3 = f3[0];
- let v_4 = f4[1];
- let v_5 = f5[2][2];
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- v : __packed_vec3<f32>,
- @align(16)
- m : array<tint_packed_vec3_f32_array_element, 3u>,
- @align(16)
- arr_v : array<tint_packed_vec3_f32_array_element, 4u>,
- @align(16)
- arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
-}
-
-fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_1(in : array<tint_packed_vec3_f32_array_element, 4u>) -> array<vec3<f32>, 4u> {
- var result = array<vec3<f32>, 4u>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements), vec3<f32>(in[3].elements));
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_2(in : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>) -> array<mat3x3<f32>, 4u> {
- var result = array<mat3x3<f32>, 4u>(tint_unpack_vec3_in_composite(in[0]), tint_unpack_vec3_in_composite(in[1]), tint_unpack_vec3_in_composite(in[2]), tint_unpack_vec3_in_composite(in[3]));
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_3(in : S_tint_packed_vec3) -> S {
- var result : S;
- result.v = vec3<f32>(in.v);
- result.m = tint_unpack_vec3_in_composite(in.m);
- result.arr_v = tint_unpack_vec3_in_composite_1(in.arr_v);
- result.arr_m = tint_unpack_vec3_in_composite_2(in.arr_m);
- return result;
-}
-
-struct S {
- v : vec3<f32>,
- m : mat3x3<f32>,
- arr_v : array<vec3<f32>, 4>,
- arr_m : array<mat3x3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
-
-fn f() {
- var f1 = tint_unpack_vec3_in_composite_3(P);
- var f2 = vec3<f32>(P.v);
- var f3 = tint_unpack_vec3_in_composite(P.m);
- var f4 = tint_unpack_vec3_in_composite_1(P.arr_v);
- var f5 = tint_unpack_vec3_in_composite_2(P.arr_m);
- let v_1 = f1.v;
- let v_2 = f2;
- let v_3 = f3[0];
- let v_4 = f4[1];
- let v_5 = f5[2][2];
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, MixedAddressSpace_InitFromValue_ExplicitVarType) {
- auto* src = R"(
-struct S {
- v : vec3<f32>,
- m : mat3x3<f32>,
- arr_v : array<vec3<f32>, 4>,
- arr_m : array<mat3x3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
- var f1 : S = S();
- var f2 : vec3<f32> = vec3<f32>();
- var f3 : mat3x3<f32> = mat3x3<f32>();
- var f4 : array<vec3<f32>, 4> = array(vec3<f32>(), vec3<f32>(), vec3<f32>(), vec3<f32>());
- var f5 : array<mat3x3<f32>, 4> = array(mat3x3<f32>(), mat3x3<f32>(), mat3x3<f32>(), mat3x3<f32>());
- let v_1 = f1.v;
- let v_2 = f2;
- let v_3 = f3[0];
- let v_4 = f4[1];
- let v_5 = f5[2][2];
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- v : __packed_vec3<f32>,
- @align(16)
- m : array<tint_packed_vec3_f32_array_element, 3u>,
- @align(16)
- arr_v : array<tint_packed_vec3_f32_array_element, 4u>,
- @align(16)
- arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
-}
-
-struct S {
- v : vec3<f32>,
- m : mat3x3<f32>,
- arr_v : array<vec3<f32>, 4>,
- arr_m : array<mat3x3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
-
-fn f() {
- var f1 : S = S();
- var f2 : vec3<f32> = vec3<f32>();
- var f3 : mat3x3<f32> = mat3x3<f32>();
- var f4 : array<vec3<f32>, 4> = array(vec3<f32>(), vec3<f32>(), vec3<f32>(), vec3<f32>());
- var f5 : array<mat3x3<f32>, 4> = array(mat3x3<f32>(), mat3x3<f32>(), mat3x3<f32>(), mat3x3<f32>());
- let v_1 = f1.v;
- let v_2 = f2;
- let v_3 = f3[0];
- let v_4 = f4[1];
- let v_5 = f5[2][2];
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, MixedAddressSpace_InitFromValue_InferredVarType) {
- auto* src = R"(
-struct S {
- v : vec3<f32>,
- m : mat3x3<f32>,
- arr_v : array<vec3<f32>, 4>,
- arr_m : array<mat3x3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
- var f1 = S();
- var f2 = vec3<f32>();
- var f3 = mat3x3<f32>();
- var f4 = array(vec3<f32>(), vec3<f32>(), vec3<f32>(), vec3<f32>());
- var f5 = array(mat3x3<f32>(), mat3x3<f32>(), mat3x3<f32>(), mat3x3<f32>());
- let v_1 = f1.v;
- let v_2 = f2;
- let v_3 = f3[0];
- let v_4 = f4[1];
- let v_5 = f5[2][2];
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- v : __packed_vec3<f32>,
- @align(16)
- m : array<tint_packed_vec3_f32_array_element, 3u>,
- @align(16)
- arr_v : array<tint_packed_vec3_f32_array_element, 4u>,
- @align(16)
- arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
-}
-
-struct S {
- v : vec3<f32>,
- m : mat3x3<f32>,
- arr_v : array<vec3<f32>, 4>,
- arr_m : array<mat3x3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
-
-fn f() {
- var f1 = S();
- var f2 = vec3<f32>();
- var f3 = mat3x3<f32>();
- var f4 = array(vec3<f32>(), vec3<f32>(), vec3<f32>(), vec3<f32>());
- var f5 = array(mat3x3<f32>(), mat3x3<f32>(), mat3x3<f32>(), mat3x3<f32>());
- let v_1 = f1.v;
- let v_2 = f2;
- let v_3 = f3[0];
- let v_4 = f4[1];
- let v_5 = f5[2][2];
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, MixedAddressSpace_Pointers_Function) {
- auto* src = R"(
-struct S {
- v : vec3<f32>,
- m : mat3x3<f32>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn f() {
- var f1 : S = P;
- var f2 : vec3<f32> = P.v;
- var f3 : array<vec3<f32>, 4>;
- var f4 : mat3x3<f32> = P.m;
- let pv_1 : ptr<function, vec3<f32>> = &f1.v;
- let pv_2 : ptr<function, vec3<f32>> = &f2;
- let pv_3 : ptr<function, vec3<f32>> = &f3[0];
- let pv_4 : ptr<function, mat3x3<f32>> = &f1.m;
- let pv_5 : ptr<function, mat3x3<f32>> = &f4;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- v : __packed_vec3<f32>,
- @align(16)
- m : array<tint_packed_vec3_f32_array_element, 3u>,
-}
-
-fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_1(in : S_tint_packed_vec3) -> S {
- var result : S;
- result.v = vec3<f32>(in.v);
- result.m = tint_unpack_vec3_in_composite(in.m);
- return result;
-}
-
-struct S {
- v : vec3<f32>,
- m : mat3x3<f32>,
-}
-
-@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
-
-fn f() {
- var f1 : S = tint_unpack_vec3_in_composite_1(P);
- var f2 : vec3<f32> = vec3<f32>(P.v);
- var f3 : array<vec3<f32>, 4>;
- var f4 : mat3x3<f32> = tint_unpack_vec3_in_composite(P.m);
- let pv_1 : ptr<function, vec3<f32>> = &(f1.v);
- let pv_2 : ptr<function, vec3<f32>> = &(f2);
- let pv_3 : ptr<function, vec3<f32>> = &(f3[0]);
- let pv_4 : ptr<function, mat3x3<f32>> = &(f1.m);
- let pv_5 : ptr<function, mat3x3<f32>> = &(f4);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, MixedAddressSpace_Pointers_Private) {
- auto* src = R"(
-struct S {
- v : vec3<f32>,
- m : mat3x3<f32>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-var<private> p1 : S;
-var<private> p2 : vec3<f32>;
-var<private> p3 : array<vec3<f32>, 4>;
-var<private> p4 : mat3x3<f32>;
-
-fn f() {
- let pv_1 : ptr<private, vec3<f32>> = &p1.v;
- let pv_2 : ptr<private, vec3<f32>> = &p2;
- let pv_3 : ptr<private, vec3<f32>> = &p3[0];
- let pv_4 : ptr<private, mat3x3<f32>> = &p1.m;
- let pv_5 : ptr<private, mat3x3<f32>> = &p4;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- v : __packed_vec3<f32>,
- @align(16)
- m : array<tint_packed_vec3_f32_array_element, 3u>,
-}
-
-struct S {
- v : vec3<f32>,
- m : mat3x3<f32>,
-}
-
-@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
-
-var<private> p1 : S;
-
-var<private> p2 : vec3<f32>;
-
-var<private> p3 : array<vec3<f32>, 4>;
-
-var<private> p4 : mat3x3<f32>;
-
-fn f() {
- let pv_1 : ptr<private, vec3<f32>> = &(p1.v);
- let pv_2 : ptr<private, vec3<f32>> = &(p2);
- let pv_3 : ptr<private, vec3<f32>> = &(p3[0]);
- let pv_4 : ptr<private, mat3x3<f32>> = &(p1.m);
- let pv_5 : ptr<private, mat3x3<f32>> = &(p4);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, MixedAddressSpace_Pointers_Workgroup) {
- auto* src = R"(
-struct S {
- v : vec3<f32>,
- m : mat3x3<f32>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-var<workgroup> w1 : S;
-var<workgroup> w2 : vec3<f32>;
-var<workgroup> w3 : array<vec3<f32>, 4>;
-var<workgroup> w4 : mat3x3<f32>;
-
-fn f() {
- let pv_1 : ptr<workgroup, vec3<f32>> = &w1.v;
- let pv_2 : ptr<workgroup, vec3<f32>> = &w2;
- let pv_3 : ptr<workgroup, vec3<f32>> = &w3[0];
- let pv_4 : ptr<workgroup, mat3x3<f32>> = &w1.m;
- let pv_5 : ptr<workgroup, mat3x3<f32>> = &w4;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- v : __packed_vec3<f32>,
- @align(16)
- m : array<tint_packed_vec3_f32_array_element, 3u>,
-}
-
-struct S {
- v : vec3<f32>,
- m : mat3x3<f32>,
-}
-
-@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
-
-var<workgroup> w1 : S_tint_packed_vec3;
-
-var<workgroup> w2 : __packed_vec3<f32>;
-
-var<workgroup> w3 : array<tint_packed_vec3_f32_array_element, 4u>;
-
-var<workgroup> w4 : array<tint_packed_vec3_f32_array_element, 3u>;
-
-fn f() {
- let pv_1 : ptr<workgroup, __packed_vec3<f32>> = &(w1.v);
- let pv_2 : ptr<workgroup, __packed_vec3<f32>> = &(w2);
- let pv_3 : ptr<workgroup, __packed_vec3<f32>> = &(w3[0].elements);
- let pv_4 : ptr<workgroup, array<tint_packed_vec3_f32_array_element, 3u>> = &(w1.m);
- let pv_5 : ptr<workgroup, array<tint_packed_vec3_f32_array_element, 3u>> = &(w4);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, MixedAddressSpace_PointerParameters) {
- auto* src = R"(
-struct S {
- v : vec3<f32>,
- m : mat3x3<f32>,
-}
-
-@group(0) @binding(0) var<storage> P : S;
-
-fn g_v(p : ptr<function, vec3<f32>>) -> vec3<f32> {
- return *p;
-}
-
-fn g_m(p : ptr<function, mat3x3<f32>>) -> mat3x3<f32> {
- return *p;
-}
-
-fn f() {
- var f1 : S = P;
- var f2 : vec3<f32> = P.v;
- var f3 : array<vec3<f32>, 4>;
- var f4 : mat3x3<f32> = P.m;
- g_v(&f1.v);
- g_v(&f2);
- g_v(&f3[0]);
- g_m(&f1.m);
- g_m(&f4);
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- v : __packed_vec3<f32>,
- @align(16)
- m : array<tint_packed_vec3_f32_array_element, 3u>,
-}
-
-fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_1(in : S_tint_packed_vec3) -> S {
- var result : S;
- result.v = vec3<f32>(in.v);
- result.m = tint_unpack_vec3_in_composite(in.m);
- return result;
-}
-
-struct S {
- v : vec3<f32>,
- m : mat3x3<f32>,
-}
-
-@group(0) @binding(0) var<storage> P : S_tint_packed_vec3;
-
-fn g_v(p : ptr<function, vec3<f32>>) -> vec3<f32> {
- return *(p);
-}
-
-fn g_m(p : ptr<function, mat3x3<f32>>) -> mat3x3<f32> {
- return *(p);
-}
-
-fn f() {
- var f1 : S = tint_unpack_vec3_in_composite_1(P);
- var f2 : vec3<f32> = vec3<f32>(P.v);
- var f3 : array<vec3<f32>, 4>;
- var f4 : mat3x3<f32> = tint_unpack_vec3_in_composite(P.m);
- g_v(&(f1.v));
- g_v(&(f2));
- g_v(&(f3[0]));
- g_m(&(f1.m));
- g_m(&(f4));
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, WriteVec3Swizzle_FromRef) {
- auto* src = R"(
-@group(0) @binding(0) var<storage, read_write> v : vec3<f32>;
-
-fn f() {
- v = v.zyx;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-@group(0) @binding(0) var<storage, read_write> v : __packed_vec3<f32>;
-
-fn f() {
- v = __packed_vec3<f32>(vec3<f32>(v).zyx);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, WriteVec3Swizzle_FromValue) {
- auto* src = R"(
-@group(0) @binding(0) var<storage, read_write> v : vec3<f32>;
-
-fn f() {
- v = vec3f(1, 2, 3).zyx;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-@group(0) @binding(0) var<storage, read_write> v : __packed_vec3<f32>;
-
-fn f() {
- v = __packed_vec3<f32>(vec3f(1, 2, 3).zyx);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, WriteVec3Component_FromPackedValueIndexAccessor) {
- auto* src = R"(
-struct S {
- v : vec3<f32>
-}
-
-@group(0) @binding(0) var<storage, read_write> s : S;
-
-fn g() -> S {
- return S();
-}
-
-fn f() {
- s.v[0] = g().v[1];
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct S_tint_packed_vec3 {
- @align(16)
- v : __packed_vec3<f32>,
-}
-
-struct S {
- v : vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> s : S_tint_packed_vec3;
-
-fn g() -> S {
- return S();
-}
-
-fn f() {
- s.v[0] = g().v[1];
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ExtractVec3FromStructValueExpression) {
- auto* src = R"(
-struct S {
- v : vec3<f32>
-}
-
-@group(0) @binding(0) var<storage, read_write> buffer : S;
-
-fn f() {
- var v_var : vec3<f32> = S().v;
- let v_let : vec3<f32> = S().v;
- v_var = S().v;
- v_var = S().v * 2.0;
- buffer = S(S().v);
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct S_tint_packed_vec3 {
- @align(16)
- v : __packed_vec3<f32>,
-}
-
-fn tint_pack_vec3_in_composite(in : S) -> S_tint_packed_vec3 {
- var result : S_tint_packed_vec3;
- result.v = __packed_vec3<f32>(in.v);
- return result;
-}
-
-struct S {
- v : vec3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> buffer : S_tint_packed_vec3;
-
-fn f() {
- var v_var : vec3<f32> = S().v;
- let v_let : vec3<f32> = S().v;
- v_var = S().v;
- v_var = (S().v * 2.0);
- buffer = tint_pack_vec3_in_composite(S(S().v));
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ExtractArrayOfVec3FromStructValueExpression) {
- auto* src = R"(
-struct S {
- arr : array<vec3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> buffer : S;
-
-fn f() {
- var arr_var : array<vec3<f32>, 4> = S().arr;
- let arr_let : array<vec3<f32>, 4> = S().arr;
- arr_var = S().arr;
- arr_var[0] = S().arr[0] * 2.0;
- buffer = S(S().arr);
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr : array<tint_packed_vec3_f32_array_element, 4u>,
-}
-
-fn tint_pack_vec3_in_composite(in : array<vec3<f32>, 4u>) -> array<tint_packed_vec3_f32_array_element, 4u> {
- var result = array<tint_packed_vec3_f32_array_element, 4u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[3])));
- return result;
-}
-
-fn tint_pack_vec3_in_composite_1(in : S) -> S_tint_packed_vec3 {
- var result : S_tint_packed_vec3;
- result.arr = tint_pack_vec3_in_composite(in.arr);
- return result;
-}
-
-struct S {
- arr : array<vec3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> buffer : S_tint_packed_vec3;
-
-fn f() {
- var arr_var : array<vec3<f32>, 4> = S().arr;
- let arr_let : array<vec3<f32>, 4> = S().arr;
- arr_var = S().arr;
- arr_var[0] = (S().arr[0] * 2.0);
- buffer = tint_pack_vec3_in_composite_1(S(S().arr));
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ExtractNestedArrayFromStructValueExpression) {
- auto* src = R"(
-struct S {
- arr : array<array<vec3<f32>, 4>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> buffer : S;
-
-fn f() {
- var arr_var : array<array<vec3<f32>, 4>, 4> = S().arr;
- var inner_var : array<vec3<f32>, 4> = S().arr[0];
- let arr_let : array<array<vec3<f32>, 4>, 4> = S().arr;
- arr_var = S().arr;
- inner_var = S().arr[0];
- arr_var[0][0] = S().arr[0][0] * 2.0;
- buffer = S(S().arr);
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr : array<array<tint_packed_vec3_f32_array_element, 4u>, 4u>,
-}
-
-fn tint_pack_vec3_in_composite(in : array<vec3<f32>, 4u>) -> array<tint_packed_vec3_f32_array_element, 4u> {
- var result = array<tint_packed_vec3_f32_array_element, 4u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[3])));
- return result;
-}
-
-fn tint_pack_vec3_in_composite_1(in : array<array<vec3<f32>, 4u>, 4u>) -> array<array<tint_packed_vec3_f32_array_element, 4u>, 4u> {
- var result = array<array<tint_packed_vec3_f32_array_element, 4u>, 4u>(tint_pack_vec3_in_composite(in[0]), tint_pack_vec3_in_composite(in[1]), tint_pack_vec3_in_composite(in[2]), tint_pack_vec3_in_composite(in[3]));
- return result;
-}
-
-fn tint_pack_vec3_in_composite_2(in : S) -> S_tint_packed_vec3 {
- var result : S_tint_packed_vec3;
- result.arr = tint_pack_vec3_in_composite_1(in.arr);
- return result;
-}
-
-struct S {
- arr : array<array<vec3<f32>, 4>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> buffer : S_tint_packed_vec3;
-
-fn f() {
- var arr_var : array<array<vec3<f32>, 4>, 4> = S().arr;
- var inner_var : array<vec3<f32>, 4> = S().arr[0];
- let arr_let : array<array<vec3<f32>, 4>, 4> = S().arr;
- arr_var = S().arr;
- inner_var = S().arr[0];
- arr_var[0][0] = (S().arr[0][0] * 2.0);
- buffer = tint_pack_vec3_in_composite_2(S(S().arr));
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ExtractMatrixFromStructValueExpression) {
- auto* src = R"(
-struct S {
- m : mat3x3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> buffer : S;
-
-fn f() {
- var m_var : mat3x3<f32> = S().m;
- let m_let : mat3x3<f32> = S().m;
- m_var = S().m;
- m_var = S().m * 2.0;
- buffer = S(S().m);
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- m : array<tint_packed_vec3_f32_array_element, 3u>,
-}
-
-fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
- var result = array<tint_packed_vec3_f32_array_element, 3u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])));
- return result;
-}
-
-fn tint_pack_vec3_in_composite_1(in : S) -> S_tint_packed_vec3 {
- var result : S_tint_packed_vec3;
- result.m = tint_pack_vec3_in_composite(in.m);
- return result;
-}
-
-struct S {
- m : mat3x3<f32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> buffer : S_tint_packed_vec3;
-
-fn f() {
- var m_var : mat3x3<f32> = S().m;
- let m_let : mat3x3<f32> = S().m;
- m_var = S().m;
- m_var = (S().m * 2.0);
- buffer = tint_pack_vec3_in_composite_1(S(S().m));
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, ExtractArrayOfMatrixFromStructValueExpression) {
- auto* src = R"(
-struct S {
- arr : array<mat3x3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> buffer : S;
-
-fn f() {
- var arr_var : array<mat3x3<f32>, 4> = S().arr;
- let arr_let : array<mat3x3<f32>, 4> = S().arr;
- arr_var = S().arr;
- arr_var[0] = S().arr[0] * 2.0;
- buffer = S(S().arr);
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
-}
-
-fn tint_pack_vec3_in_composite(in : mat3x3<f32>) -> array<tint_packed_vec3_f32_array_element, 3u> {
- var result = array<tint_packed_vec3_f32_array_element, 3u>(tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[0])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[1])), tint_packed_vec3_f32_array_element(__packed_vec3<f32>(in[2])));
- return result;
-}
-
-fn tint_pack_vec3_in_composite_1(in : array<mat3x3<f32>, 4u>) -> array<array<tint_packed_vec3_f32_array_element, 3u>, 4u> {
- var result = array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>(tint_pack_vec3_in_composite(in[0]), tint_pack_vec3_in_composite(in[1]), tint_pack_vec3_in_composite(in[2]), tint_pack_vec3_in_composite(in[3]));
- return result;
-}
-
-fn tint_pack_vec3_in_composite_2(in : S) -> S_tint_packed_vec3 {
- var result : S_tint_packed_vec3;
- result.arr = tint_pack_vec3_in_composite_1(in.arr);
- return result;
-}
-
-struct S {
- arr : array<mat3x3<f32>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> buffer : S_tint_packed_vec3;
-
-fn f() {
- var arr_var : array<mat3x3<f32>, 4> = S().arr;
- let arr_let : array<mat3x3<f32>, 4> = S().arr;
- arr_var = S().arr;
- arr_var[0] = (S().arr[0] * 2.0);
- buffer = tint_pack_vec3_in_composite_2(S(S().arr));
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, NestedArrays_Let) {
- auto* src = R"(
-struct S {
- arr_v : array<array<vec3<f32>, 4>, 4>,
- arr_m : array<array<mat3x3<f32>, 4>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> arr_s : array<S, 4>;
-
-fn f() {
- let full_let : array<S, 4> = arr_s;
- let struct_let : S = arr_s[0];
- let outer_arr_v_let : array<array<vec3<f32>, 4>, 4> = arr_s[0].arr_v;
- let inner_arr_v_let : array<vec3<f32>, 4> = arr_s[0].arr_v[1];
- let v_let : vec3<f32> = arr_s[0].arr_v[1][2];
- let v_element_let : f32 = arr_s[0].arr_v[1][2].y;
- let outer_arr_m_let : array<array<mat3x3<f32>, 4>, 4> = arr_s[0].arr_m;
- let inner_arr_m_let : array<mat3x3<f32>, 4> = arr_s[0].arr_m[1];
- let m_let : mat3x3<f32> = arr_s[0].arr_m[1][2];
- let m_col_let : vec3<f32> = arr_s[0].arr_m[1][2][0];
- let m_element_let : f32 = arr_s[0].arr_m[1][2][0].y;
-}
-)";
-
- auto* expect = R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr_v : array<array<tint_packed_vec3_f32_array_element, 4u>, 4u>,
- @align(16)
- arr_m : array<array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>, 4u>,
-}
-
-fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 4u>) -> array<vec3<f32>, 4u> {
- var result = array<vec3<f32>, 4u>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements), vec3<f32>(in[3].elements));
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_1(in : array<array<tint_packed_vec3_f32_array_element, 4u>, 4u>) -> array<array<vec3<f32>, 4u>, 4u> {
- var result = array<array<vec3<f32>, 4u>, 4u>(tint_unpack_vec3_in_composite(in[0]), tint_unpack_vec3_in_composite(in[1]), tint_unpack_vec3_in_composite(in[2]), tint_unpack_vec3_in_composite(in[3]));
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_2(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_3(in : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>) -> array<mat3x3<f32>, 4u> {
- var result = array<mat3x3<f32>, 4u>(tint_unpack_vec3_in_composite_2(in[0]), tint_unpack_vec3_in_composite_2(in[1]), tint_unpack_vec3_in_composite_2(in[2]), tint_unpack_vec3_in_composite_2(in[3]));
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_4(in : array<array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>, 4u>) -> array<array<mat3x3<f32>, 4u>, 4u> {
- var result = array<array<mat3x3<f32>, 4u>, 4u>(tint_unpack_vec3_in_composite_3(in[0]), tint_unpack_vec3_in_composite_3(in[1]), tint_unpack_vec3_in_composite_3(in[2]), tint_unpack_vec3_in_composite_3(in[3]));
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_5(in : S_tint_packed_vec3) -> S {
- var result : S;
- result.arr_v = tint_unpack_vec3_in_composite_1(in.arr_v);
- result.arr_m = tint_unpack_vec3_in_composite_4(in.arr_m);
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_6(in : array<S_tint_packed_vec3, 4u>) -> array<S, 4u> {
- var result = array<S, 4u>(tint_unpack_vec3_in_composite_5(in[0]), tint_unpack_vec3_in_composite_5(in[1]), tint_unpack_vec3_in_composite_5(in[2]), tint_unpack_vec3_in_composite_5(in[3]));
- return result;
-}
-
-struct S {
- arr_v : array<array<vec3<f32>, 4>, 4>,
- arr_m : array<array<mat3x3<f32>, 4>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> arr_s : array<S_tint_packed_vec3, 4u>;
-
-fn f() {
- let full_let : array<S, 4> = tint_unpack_vec3_in_composite_6(arr_s);
- let struct_let : S = tint_unpack_vec3_in_composite_5(arr_s[0]);
- let outer_arr_v_let : array<array<vec3<f32>, 4>, 4> = tint_unpack_vec3_in_composite_1(arr_s[0].arr_v);
- let inner_arr_v_let : array<vec3<f32>, 4> = tint_unpack_vec3_in_composite(arr_s[0].arr_v[1]);
- let v_let : vec3<f32> = vec3<f32>(arr_s[0].arr_v[1][2].elements);
- let v_element_let : f32 = arr_s[0].arr_v[1][2].elements.y;
- let outer_arr_m_let : array<array<mat3x3<f32>, 4>, 4> = tint_unpack_vec3_in_composite_4(arr_s[0].arr_m);
- let inner_arr_m_let : array<mat3x3<f32>, 4> = tint_unpack_vec3_in_composite_3(arr_s[0].arr_m[1]);
- let m_let : mat3x3<f32> = tint_unpack_vec3_in_composite_2(arr_s[0].arr_m[1][2]);
- let m_col_let : vec3<f32> = vec3<f32>(arr_s[0].arr_m[1][2][0].elements);
- let m_element_let : f32 = arr_s[0].arr_m[1][2][0].elements.y;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, NestedArrays_VarInit_Small) {
- auto* src = R"(
-struct S {
- arr_v : array<array<vec3<f32>, 4>, 4>,
- arr_m : array<array<mat3x3<f32>, 4>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> arr_s : array<S, 4>;
-
-fn f() {
- var full_var : array<S, 4> = arr_s;
- var struct_var : S = arr_s[0];
- var outer_arr_v_var : array<array<vec3<f32>, 4>, 4> = arr_s[0].arr_v;
- var inner_arr_v_var : array<vec3<f32>, 4> = arr_s[0].arr_v[1];
- var v_var : vec3<f32> = arr_s[0].arr_v[1][2];
- var v_element_var : f32 = arr_s[0].arr_v[1][2].y;
- var outer_arr_m_var : array<array<mat3x3<f32>, 4>, 4> = arr_s[0].arr_m;
- var inner_arr_m_var : array<mat3x3<f32>, 4> = arr_s[0].arr_m[1];
- var m_var : mat3x3<f32> = arr_s[0].arr_m[1][2];
- var m_col_var : vec3<f32> = arr_s[0].arr_m[1][2][0];
- var m_element_var : f32 = arr_s[0].arr_m[1][2][0].y;
-}
-)";
-
- auto* expect =
- R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr_v : array<array<tint_packed_vec3_f32_array_element, 4u>, 4u>,
- @align(16)
- arr_m : array<array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>, 4u>,
-}
-
-fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 4u>) -> array<vec3<f32>, 4u> {
- var result = array<vec3<f32>, 4u>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements), vec3<f32>(in[3].elements));
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_1(in : array<array<tint_packed_vec3_f32_array_element, 4u>, 4u>) -> array<array<vec3<f32>, 4u>, 4u> {
- var result = array<array<vec3<f32>, 4u>, 4u>(tint_unpack_vec3_in_composite(in[0]), tint_unpack_vec3_in_composite(in[1]), tint_unpack_vec3_in_composite(in[2]), tint_unpack_vec3_in_composite(in[3]));
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_2(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_3(in : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>) -> array<mat3x3<f32>, 4u> {
- var result = array<mat3x3<f32>, 4u>(tint_unpack_vec3_in_composite_2(in[0]), tint_unpack_vec3_in_composite_2(in[1]), tint_unpack_vec3_in_composite_2(in[2]), tint_unpack_vec3_in_composite_2(in[3]));
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_4(in : array<array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>, 4u>) -> array<array<mat3x3<f32>, 4u>, 4u> {
- var result = array<array<mat3x3<f32>, 4u>, 4u>(tint_unpack_vec3_in_composite_3(in[0]), tint_unpack_vec3_in_composite_3(in[1]), tint_unpack_vec3_in_composite_3(in[2]), tint_unpack_vec3_in_composite_3(in[3]));
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_5(in : S_tint_packed_vec3) -> S {
- var result : S;
- result.arr_v = tint_unpack_vec3_in_composite_1(in.arr_v);
- result.arr_m = tint_unpack_vec3_in_composite_4(in.arr_m);
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_6(in : array<S_tint_packed_vec3, 4u>) -> array<S, 4u> {
- var result = array<S, 4u>(tint_unpack_vec3_in_composite_5(in[0]), tint_unpack_vec3_in_composite_5(in[1]), tint_unpack_vec3_in_composite_5(in[2]), tint_unpack_vec3_in_composite_5(in[3]));
- return result;
-}
-
-struct S {
- arr_v : array<array<vec3<f32>, 4>, 4>,
- arr_m : array<array<mat3x3<f32>, 4>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> arr_s : array<S_tint_packed_vec3, 4u>;
-
-fn f() {
- var full_var : array<S, 4> = tint_unpack_vec3_in_composite_6(arr_s);
- var struct_var : S = tint_unpack_vec3_in_composite_5(arr_s[0]);
- var outer_arr_v_var : array<array<vec3<f32>, 4>, 4> = tint_unpack_vec3_in_composite_1(arr_s[0].arr_v);
- var inner_arr_v_var : array<vec3<f32>, 4> = tint_unpack_vec3_in_composite(arr_s[0].arr_v[1]);
- var v_var : vec3<f32> = vec3<f32>(arr_s[0].arr_v[1][2].elements);
- var v_element_var : f32 = arr_s[0].arr_v[1][2].elements.y;
- var outer_arr_m_var : array<array<mat3x3<f32>, 4>, 4> = tint_unpack_vec3_in_composite_4(arr_s[0].arr_m);
- var inner_arr_m_var : array<mat3x3<f32>, 4> = tint_unpack_vec3_in_composite_3(arr_s[0].arr_m[1]);
- var m_var : mat3x3<f32> = tint_unpack_vec3_in_composite_2(arr_s[0].arr_m[1][2]);
- var m_col_var : vec3<f32> = vec3<f32>(arr_s[0].arr_m[1][2][0].elements);
- var m_element_var : f32 = arr_s[0].arr_m[1][2][0].elements.y;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, NestedArrays_VarInit_Large) {
- auto* src = R"(
-struct S {
- arr_v : array<array<vec3<f32>, 9>, 9>,
- arr_m : array<array<mat3x3<f32>, 9>, 9>,
-}
-
-@group(0) @binding(0) var<storage, read_write> arr_s : array<S, 9>;
-
-fn f() {
- var full_var : array<S, 9> = arr_s;
- var struct_var : S = arr_s[0];
- var outer_arr_v_var : array<array<vec3<f32>, 9>, 9> = arr_s[0].arr_v;
- var inner_arr_v_var : array<vec3<f32>, 9> = arr_s[0].arr_v[1];
- var v_var : vec3<f32> = arr_s[0].arr_v[1][2];
- var v_element_var : f32 = arr_s[0].arr_v[1][2].y;
- var outer_arr_m_var : array<array<mat3x3<f32>, 9>, 9> = arr_s[0].arr_m;
- var inner_arr_m_var : array<mat3x3<f32>, 9> = arr_s[0].arr_m[1];
- var m_var : mat3x3<f32> = arr_s[0].arr_m[1][2];
- var m_col_var : vec3<f32> = arr_s[0].arr_m[1][2][0];
- var m_element_var : f32 = arr_s[0].arr_m[1][2][0].y;
-}
-)";
-
- auto* expect =
- R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr_v : array<array<tint_packed_vec3_f32_array_element, 9u>, 9u>,
- @align(16)
- arr_m : array<array<array<tint_packed_vec3_f32_array_element, 3u>, 9u>, 9u>,
-}
-
-fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 9u>) -> array<vec3<f32>, 9u> {
- var result : array<vec3<f32>, 9u>;
- for(var i : u32; (i < 9u); i = (i + 1)) {
- result[i] = vec3<f32>(in[i].elements);
- }
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_1(in : array<array<tint_packed_vec3_f32_array_element, 9u>, 9u>) -> array<array<vec3<f32>, 9u>, 9u> {
- var result : array<array<vec3<f32>, 9u>, 9u>;
- for(var i : u32; (i < 9u); i = (i + 1)) {
- result[i] = tint_unpack_vec3_in_composite(in[i]);
- }
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_2(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_3(in : array<array<tint_packed_vec3_f32_array_element, 3u>, 9u>) -> array<mat3x3<f32>, 9u> {
- var result : array<mat3x3<f32>, 9u>;
- for(var i : u32; (i < 9u); i = (i + 1)) {
- result[i] = tint_unpack_vec3_in_composite_2(in[i]);
- }
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_4(in : array<array<array<tint_packed_vec3_f32_array_element, 3u>, 9u>, 9u>) -> array<array<mat3x3<f32>, 9u>, 9u> {
- var result : array<array<mat3x3<f32>, 9u>, 9u>;
- for(var i : u32; (i < 9u); i = (i + 1)) {
- result[i] = tint_unpack_vec3_in_composite_3(in[i]);
- }
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_5(in : S_tint_packed_vec3) -> S {
- var result : S;
- result.arr_v = tint_unpack_vec3_in_composite_1(in.arr_v);
- result.arr_m = tint_unpack_vec3_in_composite_4(in.arr_m);
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_6(in : array<S_tint_packed_vec3, 9u>) -> array<S, 9u> {
- var result : array<S, 9u>;
- for(var i : u32; (i < 9u); i = (i + 1)) {
- result[i] = tint_unpack_vec3_in_composite_5(in[i]);
- }
- return result;
-}
-
-struct S {
- arr_v : array<array<vec3<f32>, 9>, 9>,
- arr_m : array<array<mat3x3<f32>, 9>, 9>,
-}
-
-@group(0) @binding(0) var<storage, read_write> arr_s : array<S_tint_packed_vec3, 9u>;
-
-fn f() {
- var full_var : array<S, 9> = tint_unpack_vec3_in_composite_6(arr_s);
- var struct_var : S = tint_unpack_vec3_in_composite_5(arr_s[0]);
- var outer_arr_v_var : array<array<vec3<f32>, 9>, 9> = tint_unpack_vec3_in_composite_1(arr_s[0].arr_v);
- var inner_arr_v_var : array<vec3<f32>, 9> = tint_unpack_vec3_in_composite(arr_s[0].arr_v[1]);
- var v_var : vec3<f32> = vec3<f32>(arr_s[0].arr_v[1][2].elements);
- var v_element_var : f32 = arr_s[0].arr_v[1][2].elements.y;
- var outer_arr_m_var : array<array<mat3x3<f32>, 9>, 9> = tint_unpack_vec3_in_composite_4(arr_s[0].arr_m);
- var inner_arr_m_var : array<mat3x3<f32>, 9> = tint_unpack_vec3_in_composite_3(arr_s[0].arr_m[1]);
- var m_var : mat3x3<f32> = tint_unpack_vec3_in_composite_2(arr_s[0].arr_m[1][2]);
- var m_col_var : vec3<f32> = vec3<f32>(arr_s[0].arr_m[1][2][0].elements);
- var m_element_var : f32 = arr_s[0].arr_m[1][2][0].elements.y;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, NestedArrays_VarAssignment_Small) {
- auto* src = R"(
-struct S {
- arr_v : array<array<vec3<f32>, 4>, 4>,
- arr_m : array<array<mat3x3<f32>, 4>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> arr_s : array<S, 4>;
-
-fn f() {
- var full_var : array<S, 4>;
- var struct_var : S;
- var outer_arr_v_var : array<array<vec3<f32>, 4>, 4>;
- var inner_arr_v_var : array<vec3<f32>, 4>;
- var v_var : vec3<f32>;
- var v_element_var : f32;
- var outer_arr_m_var : array<array<mat3x3<f32>, 4>, 4>;
- var inner_arr_m_var : array<mat3x3<f32>, 4>;
- var m_var : mat3x3<f32>;
- var m_col_var : vec3<f32>;
- var m_element_var : f32;
-
- full_var = arr_s;
- struct_var = arr_s[0];
- outer_arr_v_var = arr_s[0].arr_v;
- inner_arr_v_var = arr_s[0].arr_v[1];
- v_var = arr_s[0].arr_v[1][2];
- v_element_var = arr_s[0].arr_v[1][2].y;
- outer_arr_m_var = arr_s[0].arr_m;
- inner_arr_m_var = arr_s[0].arr_m[1];
- m_var = arr_s[0].arr_m[1][2];
- m_col_var = arr_s[0].arr_m[1][2][0];
- m_element_var = arr_s[0].arr_m[1][2][0].y;
-}
-)";
-
- auto* expect =
- R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr_v : array<array<tint_packed_vec3_f32_array_element, 4u>, 4u>,
- @align(16)
- arr_m : array<array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>, 4u>,
-}
-
-fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 4u>) -> array<vec3<f32>, 4u> {
- var result = array<vec3<f32>, 4u>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements), vec3<f32>(in[3].elements));
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_1(in : array<array<tint_packed_vec3_f32_array_element, 4u>, 4u>) -> array<array<vec3<f32>, 4u>, 4u> {
- var result = array<array<vec3<f32>, 4u>, 4u>(tint_unpack_vec3_in_composite(in[0]), tint_unpack_vec3_in_composite(in[1]), tint_unpack_vec3_in_composite(in[2]), tint_unpack_vec3_in_composite(in[3]));
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_2(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_3(in : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>) -> array<mat3x3<f32>, 4u> {
- var result = array<mat3x3<f32>, 4u>(tint_unpack_vec3_in_composite_2(in[0]), tint_unpack_vec3_in_composite_2(in[1]), tint_unpack_vec3_in_composite_2(in[2]), tint_unpack_vec3_in_composite_2(in[3]));
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_4(in : array<array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>, 4u>) -> array<array<mat3x3<f32>, 4u>, 4u> {
- var result = array<array<mat3x3<f32>, 4u>, 4u>(tint_unpack_vec3_in_composite_3(in[0]), tint_unpack_vec3_in_composite_3(in[1]), tint_unpack_vec3_in_composite_3(in[2]), tint_unpack_vec3_in_composite_3(in[3]));
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_5(in : S_tint_packed_vec3) -> S {
- var result : S;
- result.arr_v = tint_unpack_vec3_in_composite_1(in.arr_v);
- result.arr_m = tint_unpack_vec3_in_composite_4(in.arr_m);
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_6(in : array<S_tint_packed_vec3, 4u>) -> array<S, 4u> {
- var result = array<S, 4u>(tint_unpack_vec3_in_composite_5(in[0]), tint_unpack_vec3_in_composite_5(in[1]), tint_unpack_vec3_in_composite_5(in[2]), tint_unpack_vec3_in_composite_5(in[3]));
- return result;
-}
-
-struct S {
- arr_v : array<array<vec3<f32>, 4>, 4>,
- arr_m : array<array<mat3x3<f32>, 4>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> arr_s : array<S_tint_packed_vec3, 4u>;
-
-fn f() {
- var full_var : array<S, 4>;
- var struct_var : S;
- var outer_arr_v_var : array<array<vec3<f32>, 4>, 4>;
- var inner_arr_v_var : array<vec3<f32>, 4>;
- var v_var : vec3<f32>;
- var v_element_var : f32;
- var outer_arr_m_var : array<array<mat3x3<f32>, 4>, 4>;
- var inner_arr_m_var : array<mat3x3<f32>, 4>;
- var m_var : mat3x3<f32>;
- var m_col_var : vec3<f32>;
- var m_element_var : f32;
- full_var = tint_unpack_vec3_in_composite_6(arr_s);
- struct_var = tint_unpack_vec3_in_composite_5(arr_s[0]);
- outer_arr_v_var = tint_unpack_vec3_in_composite_1(arr_s[0].arr_v);
- inner_arr_v_var = tint_unpack_vec3_in_composite(arr_s[0].arr_v[1]);
- v_var = vec3<f32>(arr_s[0].arr_v[1][2].elements);
- v_element_var = arr_s[0].arr_v[1][2].elements.y;
- outer_arr_m_var = tint_unpack_vec3_in_composite_4(arr_s[0].arr_m);
- inner_arr_m_var = tint_unpack_vec3_in_composite_3(arr_s[0].arr_m[1]);
- m_var = tint_unpack_vec3_in_composite_2(arr_s[0].arr_m[1][2]);
- m_col_var = vec3<f32>(arr_s[0].arr_m[1][2][0].elements);
- m_element_var = arr_s[0].arr_m[1][2][0].elements.y;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, NestedArrays_VarAssignment_Large) {
- auto* src = R"(
-struct S {
- arr_v : array<array<vec3<f32>, 9>, 9>,
- arr_m : array<array<mat3x3<f32>, 9>, 9>,
-}
-
-@group(0) @binding(0) var<storage, read_write> arr_s : array<S, 9>;
-
-fn f() {
- var full_var : array<S, 9>;
- var struct_var : S;
- var outer_arr_v_var : array<array<vec3<f32>, 9>, 9>;
- var inner_arr_v_var : array<vec3<f32>, 9>;
- var v_var : vec3<f32>;
- var v_element_var : f32;
- var outer_arr_m_var : array<array<mat3x3<f32>, 9>, 9>;
- var inner_arr_m_var : array<mat3x3<f32>, 9>;
- var m_var : mat3x3<f32>;
- var m_col_var : vec3<f32>;
- var m_element_var : f32;
-
- full_var = arr_s;
- struct_var = arr_s[0];
- outer_arr_v_var = arr_s[0].arr_v;
- inner_arr_v_var = arr_s[0].arr_v[1];
- v_var = arr_s[0].arr_v[1][2];
- v_element_var = arr_s[0].arr_v[1][2].y;
- outer_arr_m_var = arr_s[0].arr_m;
- inner_arr_m_var = arr_s[0].arr_m[1];
- m_var = arr_s[0].arr_m[1][2];
- m_col_var = arr_s[0].arr_m[1][2][0];
- m_element_var = arr_s[0].arr_m[1][2][0].y;
-}
-)";
-
- auto* expect =
- R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr_v : array<array<tint_packed_vec3_f32_array_element, 9u>, 9u>,
- @align(16)
- arr_m : array<array<array<tint_packed_vec3_f32_array_element, 3u>, 9u>, 9u>,
-}
-
-fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 9u>) -> array<vec3<f32>, 9u> {
- var result : array<vec3<f32>, 9u>;
- for(var i : u32; (i < 9u); i = (i + 1)) {
- result[i] = vec3<f32>(in[i].elements);
- }
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_1(in : array<array<tint_packed_vec3_f32_array_element, 9u>, 9u>) -> array<array<vec3<f32>, 9u>, 9u> {
- var result : array<array<vec3<f32>, 9u>, 9u>;
- for(var i : u32; (i < 9u); i = (i + 1)) {
- result[i] = tint_unpack_vec3_in_composite(in[i]);
- }
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_2(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_3(in : array<array<tint_packed_vec3_f32_array_element, 3u>, 9u>) -> array<mat3x3<f32>, 9u> {
- var result : array<mat3x3<f32>, 9u>;
- for(var i : u32; (i < 9u); i = (i + 1)) {
- result[i] = tint_unpack_vec3_in_composite_2(in[i]);
- }
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_4(in : array<array<array<tint_packed_vec3_f32_array_element, 3u>, 9u>, 9u>) -> array<array<mat3x3<f32>, 9u>, 9u> {
- var result : array<array<mat3x3<f32>, 9u>, 9u>;
- for(var i : u32; (i < 9u); i = (i + 1)) {
- result[i] = tint_unpack_vec3_in_composite_3(in[i]);
- }
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_5(in : S_tint_packed_vec3) -> S {
- var result : S;
- result.arr_v = tint_unpack_vec3_in_composite_1(in.arr_v);
- result.arr_m = tint_unpack_vec3_in_composite_4(in.arr_m);
- return result;
-}
-
-fn tint_unpack_vec3_in_composite_6(in : array<S_tint_packed_vec3, 9u>) -> array<S, 9u> {
- var result : array<S, 9u>;
- for(var i : u32; (i < 9u); i = (i + 1)) {
- result[i] = tint_unpack_vec3_in_composite_5(in[i]);
- }
- return result;
-}
-
-struct S {
- arr_v : array<array<vec3<f32>, 9>, 9>,
- arr_m : array<array<mat3x3<f32>, 9>, 9>,
-}
-
-@group(0) @binding(0) var<storage, read_write> arr_s : array<S_tint_packed_vec3, 9u>;
-
-fn f() {
- var full_var : array<S, 9>;
- var struct_var : S;
- var outer_arr_v_var : array<array<vec3<f32>, 9>, 9>;
- var inner_arr_v_var : array<vec3<f32>, 9>;
- var v_var : vec3<f32>;
- var v_element_var : f32;
- var outer_arr_m_var : array<array<mat3x3<f32>, 9>, 9>;
- var inner_arr_m_var : array<mat3x3<f32>, 9>;
- var m_var : mat3x3<f32>;
- var m_col_var : vec3<f32>;
- var m_element_var : f32;
- full_var = tint_unpack_vec3_in_composite_6(arr_s);
- struct_var = tint_unpack_vec3_in_composite_5(arr_s[0]);
- outer_arr_v_var = tint_unpack_vec3_in_composite_1(arr_s[0].arr_v);
- inner_arr_v_var = tint_unpack_vec3_in_composite(arr_s[0].arr_v[1]);
- v_var = vec3<f32>(arr_s[0].arr_v[1][2].elements);
- v_element_var = arr_s[0].arr_v[1][2].elements.y;
- outer_arr_m_var = tint_unpack_vec3_in_composite_4(arr_s[0].arr_m);
- inner_arr_m_var = tint_unpack_vec3_in_composite_3(arr_s[0].arr_m[1]);
- m_var = tint_unpack_vec3_in_composite_2(arr_s[0].arr_m[1][2]);
- m_col_var = vec3<f32>(arr_s[0].arr_m[1][2][0].elements);
- m_element_var = arr_s[0].arr_m[1][2][0].elements.y;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, RuntimeSizedArray) {
- auto* src = R"(
-struct S {
- arr : array<vec3<f32>>,
-}
-
-@group(0) @binding(0) var<storage, read_write> arr_v : array<vec3<f32>>;
-@group(0) @binding(1) var<storage, read_write> s : S;
-
-fn main() {
- s.arr[0] = arr_v[0];
-}
-)";
-
- auto* expect =
- R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- arr : array<tint_packed_vec3_f32_array_element>,
-}
-
-struct S {
- arr : array<vec3<f32>>,
-}
-
-@group(0) @binding(0) var<storage, read_write> arr_v : array<tint_packed_vec3_f32_array_element>;
-
-@group(0) @binding(1) var<storage, read_write> s : S_tint_packed_vec3;
-
-fn main() {
- s.arr[0].elements = arr_v[0].elements;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, Mat3x3_F16_Uniform) {
- // Test that array element alignment validation rules do not trigger when we rewrite an f16
- // matrix into an array of vec3s in uniform storage.
- auto* src = R"(
-enable f16;
-@group(0) @binding(0) var<uniform> m : mat3x3<f16>;
-
-fn g(p : ptr<uniform, mat3x3<f16>>) -> vec3<f16> {
- return (*p)[0] + vec3<f16>(1);
-}
-
-fn f() {
- let v = g(&m);
-}
-)";
-
- auto* expect =
- R"(
-enable chromium_internal_relaxed_uniform_layout;
-enable f16;
-
-struct tint_packed_vec3_f16_array_element {
- @align(8)
- elements : __packed_vec3<f16>,
-}
-
-@group(0) @binding(0) var<uniform> m : array<tint_packed_vec3_f16_array_element, 3u>;
-
-fn g(p : ptr<uniform, array<tint_packed_vec3_f16_array_element, 3u>>) -> vec3<f16> {
- return (vec3<f16>((*(p))[0].elements) + vec3<f16>(1));
-}
-
-fn f() {
- let v = g(&(m));
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, MultipleComponentTypes_StructMembers) {
- auto* src = R"(
-enable f16;
-
-struct S {
- f : vec3f,
- h : vec3h,
- i : vec3i,
- u : vec3u,
-}
-
-@group(0) @binding(0) var<storage, read_write> s : S;
-
-fn f() {
- let f = s.f;
- let h = s.h;
- let i = s.i;
- let u = s.u;
-}
-)";
-
- auto* expect =
- R"(
-enable chromium_internal_relaxed_uniform_layout;
-enable f16;
-
-struct S_tint_packed_vec3 {
- @align(16)
- f : __packed_vec3<f32>,
- @align(8)
- h : __packed_vec3<f16>,
- @align(16)
- i : __packed_vec3<i32>,
- @align(16)
- u : __packed_vec3<u32>,
-}
-
-struct S {
- f : vec3f,
- h : vec3h,
- i : vec3i,
- u : vec3u,
-}
-
-@group(0) @binding(0) var<storage, read_write> s : S_tint_packed_vec3;
-
-fn f() {
- let f = vec3<f32>(s.f);
- let h = vec3<f16>(s.h);
- let i = vec3<i32>(s.i);
- let u = vec3<u32>(s.u);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, MultipleComponentTypes_ArrayElement) {
- auto* src = R"(
-enable f16;
-
-@group(0) @binding(0) var<storage, read_write> arr_f : array<vec3f>;
-@group(0) @binding(1) var<storage, read_write> arr_h : array<vec3h>;
-@group(0) @binding(2) var<storage, read_write> arr_i : array<vec3i>;
-@group(0) @binding(3) var<storage, read_write> arr_u : array<vec3u>;
-
-fn main() {
- let f = arr_f[0];
- let h = arr_h[0];
- let i = arr_i[0];
- let u = arr_u[0];
-}
-)";
-
- auto* expect =
- R"(
-enable chromium_internal_relaxed_uniform_layout;
-enable f16;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct tint_packed_vec3_f16_array_element {
- @align(8)
- elements : __packed_vec3<f16>,
-}
-
-struct tint_packed_vec3_i32_array_element {
- @align(16)
- elements : __packed_vec3<i32>,
-}
-
-struct tint_packed_vec3_u32_array_element {
- @align(16)
- elements : __packed_vec3<u32>,
-}
-
-@group(0) @binding(0) var<storage, read_write> arr_f : array<tint_packed_vec3_f32_array_element>;
-
-@group(0) @binding(1) var<storage, read_write> arr_h : array<tint_packed_vec3_f16_array_element>;
-
-@group(0) @binding(2) var<storage, read_write> arr_i : array<tint_packed_vec3_i32_array_element>;
-
-@group(0) @binding(3) var<storage, read_write> arr_u : array<tint_packed_vec3_u32_array_element>;
-
-fn main() {
- let f = vec3<f32>(arr_f[0].elements);
- let h = vec3<f16>(arr_h[0].elements);
- let i = vec3<i32>(arr_i[0].elements);
- let u = vec3<u32>(arr_u[0].elements);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, Arithmetic_FromRef) {
- auto* src = R"(
-@group(0) @binding(0) var<storage, read_write> buffer_v : vec3<f32>;
-@group(0) @binding(1) var<storage, read_write> buffer_m : mat3x3<f32>;
-@group(0) @binding(2) var<storage, read_write> buffer_arr_v : array<vec3<f32>, 4>;
-@group(0) @binding(3) var<storage, read_write> buffer_arr_m : array<mat3x3<f32>, 4>;
-@group(0) @binding(4) var<storage, read_write> buffer_nested_arr_v : array<array<vec3<f32>, 4>, 4>;
-
-fn f() {
- var v : vec3<f32> = buffer_v * 2;
- v = -v;
- v = buffer_m * v;
- v = buffer_m[0] + v;
- v = buffer_arr_v[0] + v;
- v = buffer_arr_m[0] * v;
- v = buffer_arr_m[0][1] + v;
- v = buffer_nested_arr_v[0][0] + v;
-}
-)";
-
- auto* expect =
- R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
- return result;
-}
-
-@group(0) @binding(0) var<storage, read_write> buffer_v : __packed_vec3<f32>;
-
-@group(0) @binding(1) var<storage, read_write> buffer_m : array<tint_packed_vec3_f32_array_element, 3u>;
-
-@group(0) @binding(2) var<storage, read_write> buffer_arr_v : array<tint_packed_vec3_f32_array_element, 4u>;
-
-@group(0) @binding(3) var<storage, read_write> buffer_arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
-
-@group(0) @binding(4) var<storage, read_write> buffer_nested_arr_v : array<array<tint_packed_vec3_f32_array_element, 4u>, 4u>;
-
-fn f() {
- var v : vec3<f32> = (vec3<f32>(buffer_v) * 2);
- v = -(v);
- v = (tint_unpack_vec3_in_composite(buffer_m) * v);
- v = (vec3<f32>(buffer_m[0].elements) + v);
- v = (vec3<f32>(buffer_arr_v[0].elements) + v);
- v = (tint_unpack_vec3_in_composite(buffer_arr_m[0]) * v);
- v = (vec3<f32>(buffer_arr_m[0][1].elements) + v);
- v = (vec3<f32>(buffer_nested_arr_v[0][0].elements) + v);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, Arithmetic_FromValue) {
- auto* src = R"(
-@group(0) @binding(0) var<storage, read_write> buffer_v : vec3f;
-
-fn f() {
- var v : vec3f = buffer_v;
- v = -vec3f(1, 2, 3);
- v = mat3x3f() * v;
- v = mat3x3f()[0] + v;
- v = array<vec3f, 4>()[0] + v;
- v = array<mat3x3f, 4>()[0] * v;
- v = array<mat3x3f, 4>()[0][1] + v;
- v = array<array<vec3f, 4>, 4>()[0][0] + v;
-}
-)";
-
- auto* expect =
- R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-@group(0) @binding(0) var<storage, read_write> buffer_v : __packed_vec3<f32>;
-
-fn f() {
- var v : vec3f = vec3<f32>(buffer_v);
- v = -(vec3f(1, 2, 3));
- v = (mat3x3f() * v);
- v = (mat3x3f()[0] + v);
- v = (array<vec3f, 4>()[0] + v);
- v = (array<mat3x3f, 4>()[0] * v);
- v = (array<mat3x3f, 4>()[0][1] + v);
- v = (array<array<vec3f, 4>, 4>()[0][0] + v);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, Arithmetic_FromRefStruct) {
- auto* src = R"(
-struct S {
- v : vec3<f32>,
- m : mat3x3<f32>,
- arr_v : array<vec3<f32>, 4>,
- arr_m : array<mat3x3<f32>, 4>,
- nested_arr_v : array<array<vec3<f32>, 4>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> buffer : S;
-
-fn f() {
- var v : vec3<f32> = buffer.v * 2;
- v = -v;
- v = buffer.m * v;
- v = buffer.m[0] + v;
- v = buffer.arr_v[0] + v;
- v = buffer.arr_m[0] * v;
- v = buffer.arr_m[0][1] + v;
- v = buffer.nested_arr_v[0][0] + v;
-}
-)";
-
- auto* expect =
- R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- v : __packed_vec3<f32>,
- @align(16)
- m : array<tint_packed_vec3_f32_array_element, 3u>,
- @align(16)
- arr_v : array<tint_packed_vec3_f32_array_element, 4u>,
- @align(16)
- arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
- @align(16)
- nested_arr_v : array<array<tint_packed_vec3_f32_array_element, 4u>, 4u>,
-}
-
-fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 3u>) -> mat3x3<f32> {
- var result = mat3x3<f32>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements));
- return result;
-}
-
-struct S {
- v : vec3<f32>,
- m : mat3x3<f32>,
- arr_v : array<vec3<f32>, 4>,
- arr_m : array<mat3x3<f32>, 4>,
- nested_arr_v : array<array<vec3<f32>, 4>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> buffer : S_tint_packed_vec3;
-
-fn f() {
- var v : vec3<f32> = (vec3<f32>(buffer.v) * 2);
- v = -(v);
- v = (tint_unpack_vec3_in_composite(buffer.m) * v);
- v = (vec3<f32>(buffer.m[0].elements) + v);
- v = (vec3<f32>(buffer.arr_v[0].elements) + v);
- v = (tint_unpack_vec3_in_composite(buffer.arr_m[0]) * v);
- v = (vec3<f32>(buffer.arr_m[0][1].elements) + v);
- v = (vec3<f32>(buffer.nested_arr_v[0][0].elements) + v);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, Arithmetic_FromValueStruct) {
- auto* src = R"(
-struct S {
- v : vec3<f32>,
- m : mat3x3<f32>,
- arr_v : array<vec3<f32>, 4>,
- arr_m : array<mat3x3<f32>, 4>,
- nested_arr_v : array<array<vec3<f32>, 4>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> buffer : S;
-
-fn f() {
- var v : vec3<f32> = S().v;
- v = -S().v;
- v = S().m * v;
- v = S().m[0] + v;
- v = S().arr_v[0] + v;
- v = S().arr_m[0] * v;
- v = S().arr_m[0][1] + v;
- v = S().nested_arr_v[0][0] + v;
-}
-)";
-
- auto* expect =
- R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- v : __packed_vec3<f32>,
- @align(16)
- m : array<tint_packed_vec3_f32_array_element, 3u>,
- @align(16)
- arr_v : array<tint_packed_vec3_f32_array_element, 4u>,
- @align(16)
- arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
- @align(16)
- nested_arr_v : array<array<tint_packed_vec3_f32_array_element, 4u>, 4u>,
-}
-
-struct S {
- v : vec3<f32>,
- m : mat3x3<f32>,
- arr_v : array<vec3<f32>, 4>,
- arr_m : array<mat3x3<f32>, 4>,
- nested_arr_v : array<array<vec3<f32>, 4>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> buffer : S_tint_packed_vec3;
-
-fn f() {
- var v : vec3<f32> = S().v;
- v = -(S().v);
- v = (S().m * v);
- v = (S().m[0] + v);
- v = (S().arr_v[0] + v);
- v = (S().arr_m[0] * v);
- v = (S().arr_m[0][1] + v);
- v = (S().nested_arr_v[0][0] + v);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, Aliases_Small) {
- auto* src = R"(
-alias VecArray = array<vec3<f32>, 4>;
-alias MatArray = array<mat3x3<f32>, 4>;
-alias NestedArray = array<VecArray, 4>;
-
-struct S {
- v : VecArray,
- m : MatArray,
- n : NestedArray,
-}
-
-@group(0) @binding(0) var<storage, read_write> s : S;
-@group(0) @binding(1) var<storage, read_write> arr_v : VecArray;
-@group(0) @binding(2) var<storage, read_write> arr_m : MatArray;
-@group(0) @binding(3) var<storage, read_write> arr_n : NestedArray;
-
-fn g(p : ptr<function, VecArray>) {
-}
-
-fn f() {
- var f_arr_v : VecArray = s.v;
- g(&f_arr_v);
-
- arr_v = s.v;
- arr_m[0] = s.m[0];
- arr_n[1][2] = s.n[1][2];
-}
-)";
-
- auto* expect =
- R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- v : array<tint_packed_vec3_f32_array_element, 4u>,
- @align(16)
- m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>,
- @align(16)
- n : array<array<tint_packed_vec3_f32_array_element, 4u>, 4u>,
-}
-
-fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 4u>) -> array<vec3<f32>, 4u> {
- var result = array<vec3<f32>, 4u>(vec3<f32>(in[0].elements), vec3<f32>(in[1].elements), vec3<f32>(in[2].elements), vec3<f32>(in[3].elements));
- return result;
-}
-
-alias VecArray = array<vec3<f32>, 4>;
-
-alias MatArray = array<mat3x3<f32>, 4>;
-
-alias NestedArray = array<VecArray, 4>;
-
-struct S {
- v : VecArray,
- m : MatArray,
- n : NestedArray,
-}
-
-@group(0) @binding(0) var<storage, read_write> s : S_tint_packed_vec3;
-
-@group(0) @binding(1) var<storage, read_write> arr_v : array<tint_packed_vec3_f32_array_element, 4u>;
-
-@group(0) @binding(2) var<storage, read_write> arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 4u>;
-
-@group(0) @binding(3) var<storage, read_write> arr_n : array<array<tint_packed_vec3_f32_array_element, 4u>, 4u>;
-
-fn g(p : ptr<function, VecArray>) {
-}
-
-fn f() {
- var f_arr_v : VecArray = tint_unpack_vec3_in_composite(s.v);
- g(&(f_arr_v));
- arr_v = s.v;
- arr_m[0] = s.m[0];
- arr_n[1][2].elements = s.n[1][2].elements;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, Aliases_Large) {
- auto* src = R"(
-alias VecArray = array<vec3<f32>, 9>;
-alias MatArray = array<mat3x3<f32>, 9>;
-alias NestedArray = array<VecArray, 9>;
-
-struct S {
- v : VecArray,
- m : MatArray,
- n : NestedArray,
-}
-
-@group(0) @binding(0) var<storage, read_write> s : S;
-@group(0) @binding(1) var<storage, read_write> arr_v : VecArray;
-@group(0) @binding(2) var<storage, read_write> arr_m : MatArray;
-@group(0) @binding(3) var<storage, read_write> arr_n : NestedArray;
-
-fn g(p : ptr<function, VecArray>) {
-}
-
-fn f() {
- var f_arr_v : VecArray = s.v;
- g(&f_arr_v);
-
- arr_v = s.v;
- arr_m[0] = s.m[0];
- arr_n[1][2] = s.n[1][2];
-}
-)";
-
- auto* expect =
- R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct tint_packed_vec3_f32_array_element {
- @align(16)
- elements : __packed_vec3<f32>,
-}
-
-struct S_tint_packed_vec3 {
- @align(16)
- v : array<tint_packed_vec3_f32_array_element, 9u>,
- @align(16)
- m : array<array<tint_packed_vec3_f32_array_element, 3u>, 9u>,
- @align(16)
- n : array<array<tint_packed_vec3_f32_array_element, 9u>, 9u>,
-}
-
-fn tint_unpack_vec3_in_composite(in : array<tint_packed_vec3_f32_array_element, 9u>) -> array<vec3<f32>, 9u> {
- var result : array<vec3<f32>, 9u>;
- for(var i : u32; (i < 9u); i = (i + 1)) {
- result[i] = vec3<f32>(in[i].elements);
- }
- return result;
-}
-
-alias VecArray = array<vec3<f32>, 9>;
-
-alias MatArray = array<mat3x3<f32>, 9>;
-
-alias NestedArray = array<VecArray, 9>;
-
-struct S {
- v : VecArray,
- m : MatArray,
- n : NestedArray,
-}
-
-@group(0) @binding(0) var<storage, read_write> s : S_tint_packed_vec3;
-
-@group(0) @binding(1) var<storage, read_write> arr_v : array<tint_packed_vec3_f32_array_element, 9u>;
-
-@group(0) @binding(2) var<storage, read_write> arr_m : array<array<tint_packed_vec3_f32_array_element, 3u>, 9u>;
-
-@group(0) @binding(3) var<storage, read_write> arr_n : array<array<tint_packed_vec3_f32_array_element, 9u>, 9u>;
-
-fn g(p : ptr<function, VecArray>) {
-}
-
-fn f() {
- var f_arr_v : VecArray = tint_unpack_vec3_in_composite(s.v);
- g(&(f_arr_v));
- arr_v = s.v;
- arr_m[0] = s.m[0];
- arr_n[1][2].elements = s.n[1][2].elements;
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PackedVec3Test, Vec3Bool) {
- // Make sure that we don't rewrite vec3<bool> types, as the `packed_bool<n>` types are reserved
- // in MSL and might not be supported everywhere.
- auto* src = R"(
-struct S {
- vf : vec3<f32>,
- af : array<vec3<f32>, 4>,
- vb : vec3<bool>,
- ab : array<vec3<bool>, 4>,
-}
-
-// Create a vec3 storage buffer so that the transform is not skipped.
-@group(0) @binding(0) var<storage, read_write> buffer : vec3<f32>;
-
-fn f() {
- var f : S;
- f.vf = buffer;
- buffer = f.af[0];
-}
-)";
-
- auto* expect =
- R"(
-enable chromium_internal_relaxed_uniform_layout;
-
-struct S {
- vf : vec3<f32>,
- af : array<vec3<f32>, 4>,
- vb : vec3<bool>,
- ab : array<vec3<bool>, 4>,
-}
-
-@group(0) @binding(0) var<storage, read_write> buffer : __packed_vec3<f32>;
-
-fn f() {
- var f : S;
- f.vf = vec3<f32>(buffer);
- buffer = __packed_vec3<f32>(f.af[0]);
-}
-)";
-
- ast::transform::DataMap data;
- auto got = Run<PackedVec3>(src, data);
-
- EXPECT_EQ(expect, str(got));
-}
-
-} // namespace
-} // namespace tint::msl::writer
diff --git a/src/tint/lang/msl/writer/ast_raise/pixel_local.cc b/src/tint/lang/msl/writer/ast_raise/pixel_local.cc
deleted file mode 100644
index 572939b..0000000
--- a/src/tint/lang/msl/writer/ast_raise/pixel_local.cc
+++ /dev/null
@@ -1,282 +0,0 @@
-// Copyright 2023 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/tint/lang/msl/writer/ast_raise/pixel_local.h"
-
-#include <utility>
-
-#include "src/tint/lang/core/fluent_types.h"
-#include "src/tint/lang/wgsl/program/clone_context.h"
-#include "src/tint/lang/wgsl/resolver/resolve.h"
-#include "src/tint/lang/wgsl/sem/function.h"
-#include "src/tint/lang/wgsl/sem/module.h"
-#include "src/tint/lang/wgsl/sem/statement.h"
-#include "src/tint/lang/wgsl/sem/struct.h"
-#include "src/tint/utils/containers/transform.h"
-
-TINT_INSTANTIATE_TYPEINFO(tint::msl::writer::PixelLocal);
-TINT_INSTANTIATE_TYPEINFO(tint::msl::writer::PixelLocal::Config);
-
-using namespace tint::core::number_suffixes; // NOLINT
-using namespace tint::core::fluent_types; // NOLINT
-
-namespace tint::msl::writer {
-
-/// PIMPL state for the transform
-struct PixelLocal::State {
- /// The source program
- const Program& src;
- /// The target program builder
- ProgramBuilder b;
- /// The clone context
- program::CloneContext ctx = {&b, &src, /* auto_clone_symbols */ true};
- /// The transform config
- const Config& cfg;
-
- /// Constructor
- /// @param program the source program
- /// @param config the transform config
- State(const Program& program, const Config& config) : src(program), cfg(config) {}
-
- /// Runs the transform
- /// @returns the new program or SkipTransform if the transform is not required
- ApplyResult Run() {
- auto& sem = src.Sem();
-
- // If the pixel local extension isn't enabled, then there must be no use of pixel_local
- // variables, and so there's nothing for this transform to do.
- if (!sem.Module()->Extensions().Contains(
- wgsl::Extension::kChromiumExperimentalPixelLocal)) {
- return SkipTransform;
- }
-
- bool made_changes = false;
-
- // Change all module scope `var<pixel_local>` variables to `var<private>`.
- // We need to do this even if the variable is not referenced by the entry point as later
- // stages do not understand the pixel_local address space.
- for (auto* global : src.AST().GlobalVariables()) {
- if (auto* var = global->As<ast::Var>()) {
- if (sem.Get(var)->AddressSpace() == core::AddressSpace::kPixelLocal) {
- // Change the 'var<pixel_local>' to 'var<private>'
- ctx.Replace(var->declared_address_space, b.Expr(core::AddressSpace::kPrivate));
- made_changes = true;
- }
- }
- }
-
- /// The pixel local struct
- Hashset<const sem::Struct*, 1> pixel_local_structs;
-
- // Find the entry points
- for (auto* fn : src.AST().Functions()) {
- if (!fn->IsEntryPoint()) {
- continue;
- }
-
- auto* entry_point = sem.Get(fn);
-
- // Look for a `var<pixel_local>` used by the entry point...
- for (auto* global : entry_point->TransitivelyReferencedGlobals()) {
- if (global->AddressSpace() != core::AddressSpace::kPixelLocal) {
- continue;
- }
-
- // Obtain struct of the pixel local.
- auto* pixel_local_str = global->Type()->UnwrapRef()->As<sem::Struct>();
- if (pixel_local_structs.Add(pixel_local_str)) {
- // Add an Color attribute to each member of the pixel_local structure.
- for (auto* member : pixel_local_str->Members()) {
- ctx.InsertBack(member->Declaration()->attributes,
- b.Color(u32(AttachmentIndex(member->Index()))));
- ctx.InsertBack(member->Declaration()->attributes,
- b.Disable(ast::DisabledValidation::kEntryPointParameter));
- }
- }
-
- TransformEntryPoint(entry_point, global, pixel_local_str);
- made_changes = true;
- break; // Only a single `var<pixel_local>` can be used by an entry point.
- }
- }
-
- if (!made_changes) {
- return SkipTransform;
- }
-
- // At this point, the `var<pixel_local>` will have been replaced with `var<private>`, and
- // the entry point will use `@color`, which requires the framebuffer fetch extension.
- // Replace the `chromium_experimental_pixel_local` enable with
- // `chromium_experimental_framebuffer_fetch`.
- for (auto* enable : src.AST().Enables()) {
- for (auto* ext : enable->extensions) {
- if (ext->name == wgsl::Extension::kChromiumExperimentalPixelLocal) {
- ctx.Replace(ext, b.create<ast::Extension>(
- wgsl::Extension::kChromiumExperimentalFramebufferFetch));
- }
- }
- }
-
- ctx.Clone();
- return resolver::Resolve(b);
- }
-
- /// Transforms the entry point @p entry_point to handle the direct or transitive usage of the
- /// `var<pixel_local>` @p pixel_local_var.
- /// @param entry_point the entry point
- /// @param pixel_local_var the `var<pixel_local>`
- /// @param pixel_local_str the struct type of the var
- void TransformEntryPoint(const sem::Function* entry_point,
- const sem::GlobalVariable* pixel_local_var,
- const sem::Struct* pixel_local_str) {
- auto* fn = entry_point->Declaration();
- auto fn_name = fn->name->symbol.Name();
- auto pixel_local_str_name = ctx.Clone(pixel_local_str->Name());
- auto pixel_local_var_name = ctx.Clone(pixel_local_var->Declaration()->name->symbol);
-
- // Remove the @fragment attribute from the entry point
- ctx.Remove(fn->attributes, ast::GetAttribute<ast::StageAttribute>(fn->attributes));
- // Rename the entry point
- auto inner_name = b.Symbols().New(fn_name + "_inner");
- ctx.Replace(fn->name, b.Ident(inner_name));
-
- // Create a new function that wraps the entry point.
- // This function has all the existing entry point parameters and an additional
- // parameter for the input pixel local structure.
- auto params = ctx.Clone(fn->params);
- auto pl_param = b.Symbols().New("pixel_local");
- params.Push(b.Param(pl_param, b.ty(pixel_local_str_name)));
-
- // Remove any entry-point attributes from the inner function.
- // This must come after `ctx.Clone(fn->params)` as we want these attributes on the outer
- // function.
- for (auto* param : fn->params) {
- for (auto* attr : param->attributes) {
- if (attr->IsAnyOf<ast::BuiltinAttribute, ast::LocationAttribute,
- ast::InterpolateAttribute, ast::InvariantAttribute>()) {
- ctx.Remove(param->attributes, attr);
- }
- }
- }
-
- // Build the outer function's statements, starting with an assignment of the pixel local
- // parameter to the module scope var.
- Vector<const ast::Statement*, 3> body{
- b.Assign(pixel_local_var_name, pl_param),
- };
-
- // Build the arguments to call the inner function
- auto call_args =
- tint::Transform(fn->params, [&](auto* p) { return b.Expr(ctx.Clone(p->name)); });
-
- // Create a structure to hold the combined flattened result of the entry point and the pixel
- // local structure.
- auto str_name = b.Symbols().New(fn_name + "_res");
- Vector<const ast::StructMember*, 8> members;
- Vector<const ast::Expression*, 8> return_args; // arguments to the final `return` statement
-
- auto add_member = [&](const core::type::Type* ty, VectorRef<const ast::Attribute*> attrs) {
- members.Push(b.Member("output_" + std::to_string(members.Length()),
- CreateASTTypeFor(ctx, ty), std::move(attrs)));
- };
- for (auto* member : pixel_local_str->Members()) {
- add_member(member->Type(), Vector{
- b.Location(AInt(AttachmentIndex(member->Index()))),
- });
- return_args.Push(b.MemberAccessor(pixel_local_var_name, ctx.Clone(member->Name())));
- }
- if (fn->return_type) {
- Symbol call_result = b.Symbols().New("result");
- if (auto* str = entry_point->ReturnType()->As<sem::Struct>()) {
- // The entry point returned a structure.
- for (auto* member : str->Members()) {
- auto& member_attrs = member->Declaration()->attributes;
- add_member(member->Type(), ctx.Clone(member_attrs));
- return_args.Push(b.MemberAccessor(call_result, ctx.Clone(member->Name())));
- }
- } else {
- // The entry point returned a non-structure
- add_member(entry_point->ReturnType(), ctx.Clone(fn->return_type_attributes));
- return_args.Push(b.Expr(call_result));
-
- // Remove the @location from the inner function's return type attributes
- ctx.Remove(fn->return_type_attributes,
- ast::GetAttribute<ast::LocationAttribute>(fn->return_type_attributes));
- }
- body.Push(b.Decl(b.Let(call_result, b.Call(inner_name, std::move(call_args)))));
- } else {
- body.Push(b.CallStmt(b.Call(inner_name, std::move(call_args))));
- }
-
- // Declare the output structure
- b.Structure(str_name, std::move(members));
-
- // Return the output structure
- body.Push(b.Return(b.Call(str_name, std::move(return_args))));
-
- // Declare the new entry point that calls the inner function
- b.Func(fn_name, std::move(params), b.ty(str_name), body,
- Vector{b.Stage(ast::PipelineStage::kFragment)});
- }
-
- /// @returns the attachment index for the pixel local field with the given index
- /// @param field_index the pixel local field index
- uint32_t AttachmentIndex(uint32_t field_index) {
- auto idx = cfg.attachments.Get(field_index);
- if (DAWN_UNLIKELY(!idx)) {
- b.Diagnostics().AddError(Source{})
- << "PixelLocal::Config::attachments missing entry for field " << field_index;
- return 0;
- }
- return *idx;
- }
-};
-
-PixelLocal::PixelLocal() = default;
-
-PixelLocal::~PixelLocal() = default;
-
-ast::transform::Transform::ApplyResult PixelLocal::Apply(const Program& src,
- const ast::transform::DataMap& inputs,
- ast::transform::DataMap&) const {
- auto* cfg = inputs.Get<Config>();
- if (!cfg) {
- ProgramBuilder b;
- b.Diagnostics().AddError(Source{}) << "missing transform data for " << TypeInfo().name;
- return resolver::Resolve(b);
- }
-
- return State(src, *cfg).Run();
-}
-
-PixelLocal::Config::Config() = default;
-
-PixelLocal::Config::Config(const Config&) = default;
-
-PixelLocal::Config::~Config() = default;
-
-} // namespace tint::msl::writer
diff --git a/src/tint/lang/msl/writer/ast_raise/pixel_local.h b/src/tint/lang/msl/writer/ast_raise/pixel_local.h
deleted file mode 100644
index 2fa06d5..0000000
--- a/src/tint/lang/msl/writer/ast_raise/pixel_local.h
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright 2023 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef SRC_TINT_LANG_MSL_WRITER_AST_RAISE_PIXEL_LOCAL_H_
-#define SRC_TINT_LANG_MSL_WRITER_AST_RAISE_PIXEL_LOCAL_H_
-
-#include <string>
-
-#include "src/tint/lang/wgsl/ast/internal_attribute.h"
-#include "src/tint/lang/wgsl/ast/transform/transform.h"
-#include "src/tint/utils/containers/hashmap.h"
-
-namespace tint::msl::writer {
-
-/// PixelLocal transforms module-scope `var<pixel_local>`s and fragment entry point functions that
-/// use them:
-/// * `var<pixel_local>` will be transformed to `var<private>`.
-/// * All of the members of the pixel local struct will have an additional `@color` attribute added.
-/// * The chromium_experimental_pixel_local extension enable will be replaced with an enable for
-/// chromium_experimental_framebuffer_fetch.
-/// * The entry point function will be wrapped with another function ('outer') that calls the
-/// 'inner' function.
-/// * The outer function will have an additional parameter of the pixel local struct type, which is
-/// copied to the module-scope var before calling the 'inner' function.
-/// * The outer function will have a new struct return type which holds both the pixel local members
-/// and the returned value(s) of the 'inner' function.
-class PixelLocal final : public Castable<PixelLocal, ast::transform::Transform> {
- public:
- /// Transform configuration options
- struct Config final : public Castable<Config, ast::transform::Data> {
- /// Constructor
- Config();
-
- /// Copy Constructor
- Config(const Config&);
-
- /// Destructor
- ~Config() override;
-
- /// Index of pixel_local structure member index to attachment index
- Hashmap<uint32_t, uint32_t, 8> attachments;
- };
-
- /// Constructor
- PixelLocal();
-
- /// Destructor
- ~PixelLocal() override;
-
- /// @copydoc ast::transform::Transform::Apply
- ApplyResult Apply(const Program& program,
- const ast::transform::DataMap& inputs,
- ast::transform::DataMap& outputs) const override;
-
- private:
- struct State;
-};
-
-} // namespace tint::msl::writer
-
-#endif // SRC_TINT_LANG_MSL_WRITER_AST_RAISE_PIXEL_LOCAL_H_
diff --git a/src/tint/lang/msl/writer/ast_raise/pixel_local_test.cc b/src/tint/lang/msl/writer/ast_raise/pixel_local_test.cc
deleted file mode 100644
index 09776c1..0000000
--- a/src/tint/lang/msl/writer/ast_raise/pixel_local_test.cc
+++ /dev/null
@@ -1,1121 +0,0 @@
-// Copyright 2023 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/tint/lang/msl/writer/ast_raise/pixel_local.h"
-
-#include <utility>
-
-#include "src/tint/lang/wgsl/ast/transform/helper_test.h"
-
-namespace tint::msl::writer {
-namespace {
-
-struct Binding {
- uint32_t field_index;
- uint32_t attachment_index;
-};
-
-ast::transform::DataMap Bindings(std::initializer_list<Binding> bindings) {
- PixelLocal::Config cfg;
- for (auto& binding : bindings) {
- cfg.attachments.Add(binding.field_index, binding.attachment_index);
- }
- ast::transform::DataMap data;
- data.Add<PixelLocal::Config>(std::move(cfg));
- return data;
-}
-
-using PixelLocalTest = ast::transform::TransformTest;
-
-TEST_F(PixelLocalTest, EmptyModule) {
- auto* src = "";
-
- EXPECT_FALSE(ShouldRun<PixelLocal>(src, Bindings({})));
-}
-
-TEST_F(PixelLocalTest, Var) {
- auto* src = R"(
-enable chromium_experimental_pixel_local;
-
-struct PixelLocal {
- a : i32,
-};
-
-var<pixel_local> P : PixelLocal;
-)";
-
- auto* expect =
- R"(
-enable chromium_experimental_framebuffer_fetch;
-
-struct PixelLocal {
- a : i32,
-}
-
-var<private> P : PixelLocal;
-)";
-
- auto got = Run<PixelLocal>(src, Bindings({{0, 1}}));
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PixelLocalTest, UsedInSingleEntryPoint) {
- auto* src = R"(
-enable chromium_experimental_pixel_local;
-
-struct PixelLocal {
- a : u32,
-}
-
-var<pixel_local> P : PixelLocal;
-
-@fragment
-fn F() {
- P.a += 42;
-}
-)";
-
- auto* expect =
- R"(
-enable chromium_experimental_framebuffer_fetch;
-
-struct F_res {
- @location(1)
- output_0 : u32,
-}
-
-@fragment
-fn F(pixel_local_1 : PixelLocal) -> F_res {
- P = pixel_local_1;
- F_inner();
- return F_res(P.a);
-}
-
-struct PixelLocal {
- @color(1u) @internal(disable_validation__entry_point_parameter)
- a : u32,
-}
-
-var<private> P : PixelLocal;
-
-fn F_inner() {
- P.a += 42;
-}
-)";
-
- auto got = Run<PixelLocal>(src, Bindings({{0, 1}}));
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PixelLocalTest, SameVarUsedInMultipleEntryPoints) {
- auto* src = R"(
-enable chromium_experimental_pixel_local;
-
-struct PixelLocal {
- a : u32,
-}
-
-var<pixel_local> P : PixelLocal;
-
-@fragment
-fn F1() {
- P.a += 10;
-}
-
-@fragment
-fn F2() {
- P.a += 20;
-}
-)";
-
- auto* expect =
- R"(
-enable chromium_experimental_framebuffer_fetch;
-
-struct F1_res {
- @location(1)
- output_0 : u32,
-}
-
-@fragment
-fn F1(pixel_local_1 : PixelLocal) -> F1_res {
- P = pixel_local_1;
- F1_inner();
- return F1_res(P.a);
-}
-
-struct F2_res {
- @location(1)
- output_0 : u32,
-}
-
-@fragment
-fn F2(pixel_local_2 : PixelLocal) -> F2_res {
- P = pixel_local_2;
- F2_inner();
- return F2_res(P.a);
-}
-
-struct PixelLocal {
- @color(1u) @internal(disable_validation__entry_point_parameter)
- a : u32,
-}
-
-var<private> P : PixelLocal;
-
-fn F1_inner() {
- P.a += 10;
-}
-
-fn F2_inner() {
- P.a += 20;
-}
-)";
-
- auto got = Run<PixelLocal>(src, Bindings({{0, 1}}));
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PixelLocalTest, DifferentVarUsedInMultipleEntryPoints) {
- auto* src = R"(
-enable chromium_experimental_pixel_local;
-
-struct PixelLocal {
- a : u32,
-}
-
-var<pixel_local> P1 : PixelLocal;
-var<pixel_local> P2 : PixelLocal;
-
-@fragment
-fn F1() {
- P1.a += 10;
-}
-
-@fragment
-fn F2() {
- P2.a += 20;
-}
-)";
-
- auto* expect =
- R"(
-enable chromium_experimental_framebuffer_fetch;
-
-struct F1_res {
- @location(1)
- output_0 : u32,
-}
-
-@fragment
-fn F1(pixel_local_1 : PixelLocal) -> F1_res {
- P1 = pixel_local_1;
- F1_inner();
- return F1_res(P1.a);
-}
-
-struct F2_res {
- @location(1)
- output_0 : u32,
-}
-
-@fragment
-fn F2(pixel_local_2 : PixelLocal) -> F2_res {
- P2 = pixel_local_2;
- F2_inner();
- return F2_res(P2.a);
-}
-
-struct PixelLocal {
- @color(1u) @internal(disable_validation__entry_point_parameter)
- a : u32,
-}
-
-var<private> P1 : PixelLocal;
-
-var<private> P2 : PixelLocal;
-
-fn F1_inner() {
- P1.a += 10;
-}
-
-fn F2_inner() {
- P2.a += 20;
-}
-)";
-
- auto got = Run<PixelLocal>(src, Bindings({{0, 1}}));
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PixelLocalTest, DifferentStructUsedInMultipleEntryPoints) {
- auto* src = R"(
-enable chromium_experimental_pixel_local;
-
-struct PixelLocal1 {
- a : u32,
-}
-
-struct PixelLocal2 {
- a : u32,
-}
-
-var<pixel_local> P1 : PixelLocal1;
-var<pixel_local> P2 : PixelLocal2;
-
-@fragment
-fn F1() {
- P1.a += 10;
-}
-
-@fragment
-fn F2() {
- P2.a += 20;
-}
-)";
-
- auto* expect =
- R"(
-enable chromium_experimental_framebuffer_fetch;
-
-struct F1_res {
- @location(1)
- output_0 : u32,
-}
-
-@fragment
-fn F1(pixel_local_1 : PixelLocal1) -> F1_res {
- P1 = pixel_local_1;
- F1_inner();
- return F1_res(P1.a);
-}
-
-struct F2_res {
- @location(1)
- output_0 : u32,
-}
-
-@fragment
-fn F2(pixel_local_2 : PixelLocal2) -> F2_res {
- P2 = pixel_local_2;
- F2_inner();
- return F2_res(P2.a);
-}
-
-struct PixelLocal1 {
- @color(1u) @internal(disable_validation__entry_point_parameter)
- a : u32,
-}
-
-struct PixelLocal2 {
- @color(1u) @internal(disable_validation__entry_point_parameter)
- a : u32,
-}
-
-var<private> P1 : PixelLocal1;
-
-var<private> P2 : PixelLocal2;
-
-fn F1_inner() {
- P1.a += 10;
-}
-
-fn F2_inner() {
- P2.a += 20;
-}
-)";
-
- auto got = Run<PixelLocal>(src, Bindings({{0, 1}}));
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PixelLocalTest, UseInCallee) {
- auto* src = R"(
-enable chromium_experimental_pixel_local;
-
-struct PixelLocal {
- a : u32,
-}
-
-var<pixel_local> P : PixelLocal;
-
-fn X() {
- P.a += 42;
-}
-
-@fragment
-fn F() {
- X();
-}
-)";
-
- auto* expect =
- R"(
-enable chromium_experimental_framebuffer_fetch;
-
-struct F_res {
- @location(1)
- output_0 : u32,
-}
-
-@fragment
-fn F(pixel_local_1 : PixelLocal) -> F_res {
- P = pixel_local_1;
- F_inner();
- return F_res(P.a);
-}
-
-struct PixelLocal {
- @color(1u) @internal(disable_validation__entry_point_parameter)
- a : u32,
-}
-
-var<private> P : PixelLocal;
-
-fn X() {
- P.a += 42;
-}
-
-fn F_inner() {
- X();
-}
-)";
-
- auto got = Run<PixelLocal>(src, Bindings({{0, 1}}));
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PixelLocalTest, MultipleAttachments) {
- auto* src = R"(
-enable chromium_experimental_pixel_local;
-
-struct PixelLocal {
- a : u32,
- b : i32,
- c : f32,
-}
-
-var<pixel_local> P : PixelLocal;
-
-@fragment
-fn F() {
- P.a = 42;
- P.b = i32(P.c);
-}
-)";
-
- auto* expect =
- R"(
-enable chromium_experimental_framebuffer_fetch;
-
-struct F_res {
- @location(1)
- output_0 : u32,
- @location(0)
- output_1 : i32,
- @location(10)
- output_2 : f32,
-}
-
-@fragment
-fn F(pixel_local_1 : PixelLocal) -> F_res {
- P = pixel_local_1;
- F_inner();
- return F_res(P.a, P.b, P.c);
-}
-
-struct PixelLocal {
- @color(1u) @internal(disable_validation__entry_point_parameter)
- a : u32,
- @color(0u) @internal(disable_validation__entry_point_parameter)
- b : i32,
- @color(10u) @internal(disable_validation__entry_point_parameter)
- c : f32,
-}
-
-var<private> P : PixelLocal;
-
-fn F_inner() {
- P.a = 42;
- P.b = i32(P.c);
-}
-)";
-
- auto got = Run<PixelLocal>(src, Bindings({{0, 1}, {1, 0}, {2, 10}}));
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PixelLocalTest, WithBuiltinInputParameter) {
- auto* src = R"(
-enable chromium_experimental_pixel_local;
-
-struct PixelLocal {
- a : u32,
-}
-
-var<pixel_local> P : PixelLocal;
-
-@fragment
-fn F(@builtin(position) pos : vec4f) {
- P.a += u32(pos.x);
-}
-)";
-
- auto* expect =
- R"(
-enable chromium_experimental_framebuffer_fetch;
-
-struct F_res {
- @location(1)
- output_0 : u32,
-}
-
-@fragment
-fn F(@builtin(position) pos : vec4f, pixel_local_1 : PixelLocal) -> F_res {
- P = pixel_local_1;
- F_inner(pos);
- return F_res(P.a);
-}
-
-struct PixelLocal {
- @color(1u) @internal(disable_validation__entry_point_parameter)
- a : u32,
-}
-
-var<private> P : PixelLocal;
-
-fn F_inner(pos : vec4f) {
- P.a += u32(pos.x);
-}
-)";
-
- auto got = Run<PixelLocal>(src, Bindings({{0, 1}}));
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PixelLocalTest, WithInvariantBuiltinInputParameter) {
- auto* src = R"(
-enable chromium_experimental_pixel_local;
-
-struct PixelLocal {
- a : u32,
-}
-
-var<pixel_local> P : PixelLocal;
-
-@fragment
-fn F(@invariant @builtin(position) pos : vec4f) {
- P.a += u32(pos.x);
-}
-)";
-
- auto* expect =
- R"(
-enable chromium_experimental_framebuffer_fetch;
-
-struct F_res {
- @location(1)
- output_0 : u32,
-}
-
-@fragment
-fn F(@invariant @builtin(position) pos : vec4f, pixel_local_1 : PixelLocal) -> F_res {
- P = pixel_local_1;
- F_inner(pos);
- return F_res(P.a);
-}
-
-struct PixelLocal {
- @color(1u) @internal(disable_validation__entry_point_parameter)
- a : u32,
-}
-
-var<private> P : PixelLocal;
-
-fn F_inner(pos : vec4f) {
- P.a += u32(pos.x);
-}
-)";
-
- auto got = Run<PixelLocal>(src, Bindings({{0, 1}}));
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PixelLocalTest, WithBuiltinInputStructParameter) {
- auto* src = R"(
-enable chromium_experimental_pixel_local;
-
-struct PixelLocal {
- a : u32,
-}
-
-var<pixel_local> P : PixelLocal;
-
-struct In {
- @builtin(position) pos : vec4f,
-}
-
-@fragment
-fn F(in : In) {
- P.a += u32(in.pos.x);
-}
-)";
-
- auto* expect =
- R"(
-enable chromium_experimental_framebuffer_fetch;
-
-struct F_res {
- @location(1)
- output_0 : u32,
-}
-
-@fragment
-fn F(in : In, pixel_local_1 : PixelLocal) -> F_res {
- P = pixel_local_1;
- F_inner(in);
- return F_res(P.a);
-}
-
-struct PixelLocal {
- @color(1u) @internal(disable_validation__entry_point_parameter)
- a : u32,
-}
-
-var<private> P : PixelLocal;
-
-struct In {
- @builtin(position)
- pos : vec4f,
-}
-
-fn F_inner(in : In) {
- P.a += u32(in.pos.x);
-}
-)";
-
- auto got = Run<PixelLocal>(src, Bindings({{0, 1}}));
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PixelLocalTest, WithInvariantBuiltinInputStructParameter) {
- auto* src = R"(
-enable chromium_experimental_pixel_local;
-
-struct PixelLocal {
- a : u32,
-}
-
-var<pixel_local> P : PixelLocal;
-
-struct In {
- @invariant @builtin(position) pos : vec4f,
-}
-
-@fragment
-fn F(in : In) {
- P.a += u32(in.pos.x);
-}
-)";
-
- auto* expect =
- R"(
-enable chromium_experimental_framebuffer_fetch;
-
-struct F_res {
- @location(1)
- output_0 : u32,
-}
-
-@fragment
-fn F(in : In, pixel_local_1 : PixelLocal) -> F_res {
- P = pixel_local_1;
- F_inner(in);
- return F_res(P.a);
-}
-
-struct PixelLocal {
- @color(1u) @internal(disable_validation__entry_point_parameter)
- a : u32,
-}
-
-var<private> P : PixelLocal;
-
-struct In {
- @invariant @builtin(position)
- pos : vec4f,
-}
-
-fn F_inner(in : In) {
- P.a += u32(in.pos.x);
-}
-)";
-
- auto got = Run<PixelLocal>(src, Bindings({{0, 1}}));
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PixelLocalTest, WithLocationInputParameter) {
- auto* src = R"(
-enable chromium_experimental_pixel_local;
-
-struct PixelLocal {
- a : u32,
-}
-
-var<pixel_local> P : PixelLocal;
-
-@fragment
-fn F(@location(0) a : vec4f, @interpolate(flat) @location(1) b : vec4f) {
- P.a += u32(a.x) + u32(b.y);
-}
-)";
-
- auto* expect =
- R"(
-enable chromium_experimental_framebuffer_fetch;
-
-struct F_res {
- @location(1)
- output_0 : u32,
-}
-
-@fragment
-fn F(@location(0) a : vec4f, @interpolate(flat) @location(1) b : vec4f, pixel_local_1 : PixelLocal) -> F_res {
- P = pixel_local_1;
- F_inner(a, b);
- return F_res(P.a);
-}
-
-struct PixelLocal {
- @color(1u) @internal(disable_validation__entry_point_parameter)
- a : u32,
-}
-
-var<private> P : PixelLocal;
-
-fn F_inner(a : vec4f, b : vec4f) {
- P.a += (u32(a.x) + u32(b.y));
-}
-)";
-
- auto got = Run<PixelLocal>(src, Bindings({{0, 1}}));
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PixelLocalTest, WithLocationInputStructParameter) {
- auto* src = R"(
-enable chromium_experimental_pixel_local;
-
-struct PixelLocal {
- a : u32,
-}
-
-var<pixel_local> P : PixelLocal;
-
-struct In {
- @location(0) a : vec4f,
- @interpolate(flat) @location(1) b : vec4f,
-}
-
-@fragment
-fn F(in : In) {
- P.a += u32(in.a.x) + u32(in.b.y);
-}
-)";
-
- auto* expect =
- R"(
-enable chromium_experimental_framebuffer_fetch;
-
-struct F_res {
- @location(1)
- output_0 : u32,
-}
-
-@fragment
-fn F(in : In, pixel_local_1 : PixelLocal) -> F_res {
- P = pixel_local_1;
- F_inner(in);
- return F_res(P.a);
-}
-
-struct PixelLocal {
- @color(1u) @internal(disable_validation__entry_point_parameter)
- a : u32,
-}
-
-var<private> P : PixelLocal;
-
-struct In {
- @location(0)
- a : vec4f,
- @interpolate(flat) @location(1)
- b : vec4f,
-}
-
-fn F_inner(in : In) {
- P.a += (u32(in.a.x) + u32(in.b.y));
-}
-)";
-
- auto got = Run<PixelLocal>(src, Bindings({{0, 1}}));
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PixelLocalTest, WithBuiltinAndLocationInputParameter) {
- auto* src = R"(
-enable chromium_experimental_pixel_local;
-
-struct PixelLocal {
- a : u32,
-}
-
-var<pixel_local> P : PixelLocal;
-
-@fragment
-fn F(@builtin(position) pos : vec4f, @location(0) uv : vec4f) {
- P.a += u32(pos.x) + u32(uv.x);
-}
-)";
-
- auto* expect =
- R"(
-enable chromium_experimental_framebuffer_fetch;
-
-struct F_res {
- @location(1)
- output_0 : u32,
-}
-
-@fragment
-fn F(@builtin(position) pos : vec4f, @location(0) uv : vec4f, pixel_local_1 : PixelLocal) -> F_res {
- P = pixel_local_1;
- F_inner(pos, uv);
- return F_res(P.a);
-}
-
-struct PixelLocal {
- @color(1u) @internal(disable_validation__entry_point_parameter)
- a : u32,
-}
-
-var<private> P : PixelLocal;
-
-fn F_inner(pos : vec4f, uv : vec4f) {
- P.a += (u32(pos.x) + u32(uv.x));
-}
-)";
-
- auto got = Run<PixelLocal>(src, Bindings({{0, 1}}));
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PixelLocalTest, WithBuiltinAndLocationInputStructParameter) {
- auto* src = R"(
-enable chromium_experimental_pixel_local;
-
-struct PixelLocal {
- a : u32,
-}
-
-var<pixel_local> P : PixelLocal;
-
-struct In {
- @builtin(position) pos : vec4f,
- @location(0) uv : vec4f,
-}
-
-@fragment
-fn F(in : In) {
- P.a += u32(in.pos.x) + u32(in.uv.x);
-}
-)";
-
- auto* expect =
- R"(
-enable chromium_experimental_framebuffer_fetch;
-
-struct F_res {
- @location(1)
- output_0 : u32,
-}
-
-@fragment
-fn F(in : In, pixel_local_1 : PixelLocal) -> F_res {
- P = pixel_local_1;
- F_inner(in);
- return F_res(P.a);
-}
-
-struct PixelLocal {
- @color(1u) @internal(disable_validation__entry_point_parameter)
- a : u32,
-}
-
-var<private> P : PixelLocal;
-
-struct In {
- @builtin(position)
- pos : vec4f,
- @location(0)
- uv : vec4f,
-}
-
-fn F_inner(in : In) {
- P.a += (u32(in.pos.x) + u32(in.uv.x));
-}
-)";
-
- auto got = Run<PixelLocal>(src, Bindings({{0, 1}}));
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PixelLocalTest, WithSingleFragmentOutput) {
- auto* src = R"(
-enable chromium_experimental_pixel_local;
-
-struct PixelLocal {
- a : u32,
-}
-
-var<pixel_local> P : PixelLocal;
-
-@fragment
-fn F() -> @location(0) vec4f {
- P.a += 42;
- return vec4f(1);
-}
-)";
-
- auto* expect =
- R"(
-enable chromium_experimental_framebuffer_fetch;
-
-struct F_res {
- @location(1)
- output_0 : u32,
- @location(0)
- output_1 : vec4<f32>,
-}
-
-@fragment
-fn F(pixel_local_1 : PixelLocal) -> F_res {
- P = pixel_local_1;
- let result = F_inner();
- return F_res(P.a, result);
-}
-
-struct PixelLocal {
- @color(1u) @internal(disable_validation__entry_point_parameter)
- a : u32,
-}
-
-var<private> P : PixelLocal;
-
-fn F_inner() -> vec4f {
- P.a += 42;
- return vec4f(1);
-}
-)";
-
- auto got = Run<PixelLocal>(src, Bindings({{0, 1}}));
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PixelLocalTest, WithMultipleFragmentOutputs) {
- auto* src = R"(
-enable chromium_experimental_pixel_local;
-
-struct PixelLocal {
- a : u32,
- b : u32,
-}
-
-var<pixel_local> P : PixelLocal;
-
-struct Output {
- @location(0) x : vec4f,
- @location(2) y : vec4f,
-}
-
-@fragment
-fn F() -> Output {
- P.a += 42;
- return Output(vec4f(1), vec4f(9));
-}
-)";
-
- auto* expect =
- R"(
-enable chromium_experimental_framebuffer_fetch;
-
-struct F_res {
- @location(1)
- output_0 : u32,
- @location(5)
- output_1 : u32,
- @location(0)
- output_2 : vec4<f32>,
- @location(2)
- output_3 : vec4<f32>,
-}
-
-@fragment
-fn F(pixel_local_1 : PixelLocal) -> F_res {
- P = pixel_local_1;
- let result = F_inner();
- return F_res(P.a, P.b, result.x, result.y);
-}
-
-struct PixelLocal {
- @color(1u) @internal(disable_validation__entry_point_parameter)
- a : u32,
- @color(5u) @internal(disable_validation__entry_point_parameter)
- b : u32,
-}
-
-var<private> P : PixelLocal;
-
-struct Output {
- @location(0)
- x : vec4f,
- @location(2)
- y : vec4f,
-}
-
-fn F_inner() -> Output {
- P.a += 42;
- return Output(vec4f(1), vec4f(9));
-}
-)";
-
- auto got = Run<PixelLocal>(src, Bindings({{0, 1}, {1, 5}}));
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(PixelLocalTest, OutputStructUsedByMultipleEntryPoints) {
- auto* src = R"(
-enable chromium_experimental_pixel_local;
-
-struct PixelLocal {
- a : u32,
- b : u32,
-}
-
-var<pixel_local> P : PixelLocal;
-
-struct Output {
- @location(0) x : vec4f,
- @location(2) y : vec4f,
-}
-
-@fragment
-fn F1() -> Output {
- P.a += 42;
- return Output(vec4f(1), vec4f(9));
-}
-
-@fragment
-fn F2() -> Output {
- return Output(vec4f(1), vec4f(9));
-}
-)";
-
- auto* expect =
- R"(
-enable chromium_experimental_framebuffer_fetch;
-
-struct F1_res {
- @location(1)
- output_0 : u32,
- @location(5)
- output_1 : u32,
- @location(0)
- output_2 : vec4<f32>,
- @location(2)
- output_3 : vec4<f32>,
-}
-
-@fragment
-fn F1(pixel_local_1 : PixelLocal) -> F1_res {
- P = pixel_local_1;
- let result = F1_inner();
- return F1_res(P.a, P.b, result.x, result.y);
-}
-
-struct PixelLocal {
- @color(1u) @internal(disable_validation__entry_point_parameter)
- a : u32,
- @color(5u) @internal(disable_validation__entry_point_parameter)
- b : u32,
-}
-
-var<private> P : PixelLocal;
-
-struct Output {
- @location(0)
- x : vec4f,
- @location(2)
- y : vec4f,
-}
-
-fn F1_inner() -> Output {
- P.a += 42;
- return Output(vec4f(1), vec4f(9));
-}
-
-@fragment
-fn F2() -> Output {
- return Output(vec4f(1), vec4f(9));
-}
-)";
-
- auto got = Run<PixelLocal>(src, Bindings({{0, 1}, {1, 5}}));
-
- EXPECT_EQ(expect, str(got));
-}
-
-} // namespace
-} // namespace tint::msl::writer
diff --git a/src/tint/lang/msl/writer/ast_raise/quad_swap.cc b/src/tint/lang/msl/writer/ast_raise/quad_swap.cc
deleted file mode 100644
index 0afe1a0..0000000
--- a/src/tint/lang/msl/writer/ast_raise/quad_swap.cc
+++ /dev/null
@@ -1,253 +0,0 @@
-// Copyright 2024 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/tint/lang/msl/writer/ast_raise/quad_swap.h"
-
-#include <utility>
-
-#include "src/tint/lang/core/builtin_fn.h"
-#include "src/tint/lang/core/fluent_types.h"
-#include "src/tint/lang/wgsl/ast/transform/transform.h"
-#include "src/tint/lang/wgsl/builtin_fn.h"
-#include "src/tint/lang/wgsl/program/clone_context.h"
-#include "src/tint/lang/wgsl/program/program_builder.h"
-#include "src/tint/lang/wgsl/resolver/resolve.h"
-#include "src/tint/lang/wgsl/sem/call.h"
-#include "src/tint/lang/wgsl/sem/function.h"
-#include "src/tint/lang/wgsl/sem/statement.h"
-
-TINT_INSTANTIATE_TYPEINFO(tint::msl::writer::QuadSwap);
-TINT_INSTANTIATE_TYPEINFO(tint::msl::writer::QuadSwap::QuadShuffle);
-TINT_INSTANTIATE_TYPEINFO(tint::msl::writer::QuadSwap::ThreadIndexInQuadgroup);
-
-using namespace tint::core::number_suffixes; // NOLINT
-using namespace tint::core::fluent_types; // NOLINT
-
-namespace tint::msl::writer {
-
-/// PIMPL state for the transform
-struct QuadSwap::State {
- /// The source program
- const Program& src;
- /// The target program builder
- ProgramBuilder b;
- /// The clone context
- program::CloneContext ctx = {&b, &src, /* auto_clone_symbols */ true};
-
- /// The set of names for the tint_msl_quadSwap* helper functions.
- Hashmap<std::pair<wgsl::BuiltinFn, const core::type::Type*>, Symbol, 8> quad_swap_helpers;
-
- /// The set of names for the tint_msl_quad_shuffle* intrinsic functions.
- Hashmap<const core::type::Type*, Symbol, 8> quad_shuffle_intrinsics;
-
- /// The name of the `tint_msl_thread_index_in_quadgroup` global variable.
- Symbol thread_index_in_quadgroup{};
-
- /// The set of a functions that directly call `quadSwap*()` builtin functions.
- Hashset<const sem::Function*, 4> quad_swap_callers;
-
- /// Constructor
- /// @param program the source program
- explicit State(const Program& program) : src(program) {}
-
- /// Runs the transform
- /// @returns the new program or SkipTransform if the transform is not required
- ApplyResult Run() {
- auto& sem = src.Sem();
-
- bool made_changes = false;
- for (auto* node : ctx.src->ASTNodes().Objects()) {
- auto* call = sem.Get<sem::Call>(node);
- if (call) {
- // If this is a call to a `quadSwap*()` builtin, replace it with a call to the
- // helper function and make a note of the function that we are in.
- auto* builtin = call->Target()->As<sem::BuiltinFn>();
- if (builtin && builtin->IsQuadSwap()) {
- auto* expr = ctx.Clone(call->Arguments()[0]->Declaration());
- ctx.Replace(call->Declaration(),
- b.Call(GetHelper(builtin->Fn(), call->Type()), expr));
- quad_swap_callers.Add(call->Stmt()->Function());
- made_changes = true;
- }
- }
- }
- if (!made_changes) {
- return SkipTransform;
- }
-
- // Set the thread_index_in_quadgroup global variable at the start of each entry point that
- // transitively calls the `quadSwap*()` builtin function.
- for (auto* global : src.AST().GlobalDeclarations()) {
- auto* func = global->As<ast::Function>();
- if (func && func->IsEntryPoint() && TransitvelyCallsQuadSwap(sem.Get(func))) {
- SetThreadIndexInQuadgroup(func);
- }
- }
-
- ctx.Clone();
- return resolver::Resolve(b);
- }
-
- /// Get or create the appropriate `tint_msl_quadSwap*` helper function for the given builtin
- /// function and return type.
- /// @returns the name of the helper function
- Symbol GetHelper(wgsl::BuiltinFn func, const core::type::Type* type) {
- return quad_swap_helpers.GetOrAdd(std::make_pair(func, type), [&] {
- Symbol quad_swap_helper = b.Symbols().New(std::string("tint_msl_") + str(func));
- Symbol intrinsic = GetIntrinsic(type);
-
- // Declare the `tint_msl_quadSwap*` helper function as follows:
- // fn tint_msl_quadSwapFnName(e : T) -> T {
- // tint_msl_quad_shuffle(e, tint_msl_thread_index_in_quadgroup ^ rhs)
- // }
- // where rhs is determined based on the builtin function call:
- // +------------------+------+
- // | func | rhs |
- // +------------------+------+
- // | quadSwapX | 0b1 |
- // | quadSwapY | 0b10 |
- // | quadSwapDiagonal | 0b11 |
- // +------------------+------+
- auto* expr = b.Param("e", CreateASTTypeFor(ctx, type));
- core::u32 rhs;
- switch (func) {
- case wgsl::BuiltinFn::kQuadSwapX:
- rhs = 0b1;
- break;
- case wgsl::BuiltinFn::kQuadSwapY:
- rhs = 0b10;
- break;
- case wgsl::BuiltinFn::kQuadSwapDiagonal:
- rhs = 0b11;
- break;
- default:
- TINT_UNREACHABLE() << "unsupported builtin function";
- }
- b.Func(quad_swap_helper, Vector{expr}, CreateASTTypeFor(ctx, type),
- Vector{
- b.Return(b.Call(intrinsic, expr, b.Xor(GetGlobalVar(), rhs))),
- });
- return quad_swap_helper;
- });
- }
-
- /// Get or create the `tint_msl_quad_shuffle` intrinsic placeholder function for the given
- /// return type.
- /// @returns the name of the function
- Symbol GetIntrinsic(const core::type::Type* type) {
- return quad_shuffle_intrinsics.GetOrAdd(type, [&] {
- auto intrinsic = b.Symbols().New(std::string("tint_msl_quad_shuffle"));
-
- // Declare the `tint_msl_quad_shuffle` function, which will be replaced by the MSL
- // `quad_shuffle` intrinsic function to perform the swap.
- {
- auto* data = b.Param("data", CreateASTTypeFor(ctx, type));
- auto* quad_lane_id = b.Param("quad_lane_id", b.ty.u32());
- b.Func(intrinsic, Vector{data, quad_lane_id}, CreateASTTypeFor(ctx, type), nullptr,
- Vector{b.ASTNodes().Create<QuadShuffle>(b.ID(), b.AllocateNodeID()),
- b.Disable(ast::DisabledValidation::kFunctionHasNoBody)});
- }
-
- return intrinsic;
- });
- }
-
- /// Get or create the `tint_msl_thread_index_in_quadgroup` global variable.
- /// @returns the name of the variable
- Symbol GetGlobalVar() {
- if (!thread_index_in_quadgroup) {
- thread_index_in_quadgroup = b.Symbols().New("tint_msl_thread_index_in_quadgroup");
-
- // Declare the `tint_msl_thread_index_in_quadgroup` variable.
- b.GlobalVar(thread_index_in_quadgroup, core::AddressSpace::kPrivate, b.ty.u32());
- }
-
- return thread_index_in_quadgroup;
- }
-
- /// Check if a function directly or transitively calls a `quadSwap*()` builtin.
- /// @param func the function to check
- /// @returns true if the function transitively calls `quadSwap*()`
- bool TransitvelyCallsQuadSwap(const sem::Function* func) {
- if (quad_swap_callers.Contains(func)) {
- return true;
- }
- for (auto* called : func->TransitivelyCalledFunctions()) {
- if (quad_swap_callers.Contains(called)) {
- return true;
- }
- }
- return false;
- }
-
- /// Add code to set the `thread_index_in_quadgroup` variable at the start of an entry point.
- /// @param ep the entry point
- void SetThreadIndexInQuadgroup(const ast::Function* ep) {
- // Add the entry point parameter with an attribute to indicate to the the MSL backend that
- // it should be annotated with [[thread_index_in_quadgroup]].
- Symbol thread_index_in_quadgroup_param = b.Symbols().New("tint_thread_index_in_quadgroup");
- ctx.InsertBack(ep->params, b.Param(thread_index_in_quadgroup_param, b.ty.u32(),
- Vector{b.ASTNodes().Create<ThreadIndexInQuadgroup>(
- b.ID(), b.AllocateNodeID())}));
-
- // Add the following to the top of the entry point:
- // {
- // tint_msl_thread_index_in_quadgroup = tint_thread_index_in_quadgroup;
- // }
- auto* block = b.Block(Vector{
- b.Assign(thread_index_in_quadgroup, thread_index_in_quadgroup_param),
- });
- ctx.InsertFront(ep->body->statements, block);
- }
-};
-
-QuadSwap::QuadSwap() = default;
-
-QuadSwap::~QuadSwap() = default;
-
-ast::transform::Transform::ApplyResult QuadSwap::Apply(const Program& src,
- const ast::transform::DataMap&,
- ast::transform::DataMap&) const {
- return State(src).Run();
-}
-
-QuadSwap::QuadShuffle::~QuadShuffle() = default;
-
-const QuadSwap::QuadShuffle* QuadSwap::QuadShuffle::Clone(ast::CloneContext& ctx) const {
- return ctx.dst->ASTNodes().Create<QuadSwap::QuadShuffle>(ctx.dst->ID(),
- ctx.dst->AllocateNodeID());
-}
-
-QuadSwap::ThreadIndexInQuadgroup::~ThreadIndexInQuadgroup() = default;
-
-const QuadSwap::ThreadIndexInQuadgroup* QuadSwap::ThreadIndexInQuadgroup::Clone(
- ast::CloneContext& ctx) const {
- return ctx.dst->ASTNodes().Create<QuadSwap::ThreadIndexInQuadgroup>(ctx.dst->ID(),
- ctx.dst->AllocateNodeID());
-}
-
-} // namespace tint::msl::writer
diff --git a/src/tint/lang/msl/writer/ast_raise/quad_swap.h b/src/tint/lang/msl/writer/ast_raise/quad_swap.h
deleted file mode 100644
index 1654ad4..0000000
--- a/src/tint/lang/msl/writer/ast_raise/quad_swap.h
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright 2024 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef SRC_TINT_LANG_MSL_WRITER_AST_RAISE_QUAD_SWAP_H_
-#define SRC_TINT_LANG_MSL_WRITER_AST_RAISE_QUAD_SWAP_H_
-
-#include <string>
-
-#include "src/tint/lang/wgsl/ast/internal_attribute.h"
-#include "src/tint/lang/wgsl/ast/transform/transform.h"
-
-namespace tint::msl::writer {
-
-/// QuadSwap is a transform that replaces calls to `quadSwap{X, Y, Diagonal}()` with an
-/// implementation that uses MSL's `quad_shuffle()` using the following mapping:
-/// +------------------+------------------------------------------------------------------+
-/// | WGSL | MSL |
-/// +------------------+------------------------------------------------------------------+
-/// | quadSwapX | quad_shuffle with quad_lane_id=thread_index_in_quad_group ^ 0b1 |
-/// | quadSwapY | quad_shuffle with quad_lane_id=thread_index_in_quad_group ^ 0b10 |
-/// | quadSwapDiagonal | quad_shuffle with quad_lane_id=thread_index_in_quad_group ^ 0b11 |
-/// +------------------+------------------------------------------------------------------+
-///
-/// @note Depends on the following transforms to have been run first:
-/// * CanonicalizeEntryPointIO
-class QuadSwap final : public Castable<QuadSwap, ast::transform::Transform> {
- public:
- /// Constructor
- QuadSwap();
-
- /// Destructor
- ~QuadSwap() override;
-
- /// @copydoc ast::transform::Transform::Apply
- ApplyResult Apply(const Program& program,
- const ast::transform::DataMap& inputs,
- ast::transform::DataMap& outputs) const override;
-
- /// QuadShuffle is an InternalAttribute that is used to decorate a stub function so
- /// that the MSL backend transforms this into calls to the `quad_shuffle` function.
- class QuadShuffle final : public Castable<QuadShuffle, ast::InternalAttribute> {
- public:
- /// Constructor
- /// @param pid the identifier of the program that owns this node
- /// @param nid the unique node identifier
- QuadShuffle(GenerationID pid, ast::NodeID nid) : Base(pid, nid, Empty) {}
-
- /// Destructor
- ~QuadShuffle() override;
-
- /// @copydoc ast::InternalAttribute::InternalName
- std::string InternalName() const override { return "quad_shuffle"; }
-
- /// Performs a deep clone of this object using the program::CloneContext `ctx`.
- /// @param ctx the clone context
- /// @return the newly cloned object
- const QuadShuffle* Clone(ast::CloneContext& ctx) const override;
- };
-
- /// ThreadIndexInQuadgroup is an InternalAttribute that is used to decorate an entrypoint
- /// parameter so that the MSL backend transforms this into a `[[thread_index_in_quadgroup]]`
- /// attribute.
- class ThreadIndexInQuadgroup final
- : public Castable<ThreadIndexInQuadgroup, ast::InternalAttribute> {
- public:
- /// Constructor
- /// @param pid the identifier of the program that owns this node
- /// @param nid the unique node identifier
- ThreadIndexInQuadgroup(GenerationID pid, ast::NodeID nid) : Base(pid, nid, Empty) {}
-
- /// Destructor
- ~ThreadIndexInQuadgroup() override;
-
- /// @copydoc ast::InternalAttribute::InternalName
- std::string InternalName() const override { return "thread_index_in_quadgroup"; }
-
- /// Performs a deep clone of this object using the program::CloneContext `ctx`.
- /// @param ctx the clone context
- /// @return the newly cloned object
- const ThreadIndexInQuadgroup* Clone(ast::CloneContext& ctx) const override;
- };
-
- private:
- struct State;
-};
-
-} // namespace tint::msl::writer
-
-#endif // SRC_TINT_LANG_MSL_WRITER_AST_RAISE_QUAD_SWAP_H_
diff --git a/src/tint/lang/msl/writer/ast_raise/quad_swap_test.cc b/src/tint/lang/msl/writer/ast_raise/quad_swap_test.cc
deleted file mode 100644
index f24f48e..0000000
--- a/src/tint/lang/msl/writer/ast_raise/quad_swap_test.cc
+++ /dev/null
@@ -1,376 +0,0 @@
-// Copyright 2024 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/tint/lang/msl/writer/ast_raise/quad_swap.h"
-
-#include "src/tint/lang/wgsl/ast/transform/helper_test.h"
-
-namespace tint::msl::writer {
-namespace {
-
-using QuadSwapTest = ast::transform::TransformTest;
-
-TEST_F(QuadSwapTest, EmptyModule) {
- auto* src = "";
-
- EXPECT_FALSE(ShouldRun<QuadSwap>(src));
-}
-
-TEST_F(QuadSwapTest, DirectUseQuadSwapX) {
- auto* src = R"(
-enable subgroups;
-
-@compute @workgroup_size(64)
-fn foo() {
- let x: f32 = quadSwapX(1.f);
-}
-)";
-
- auto* expect =
- R"(
-enable subgroups;
-
-@internal(quad_shuffle) @internal(disable_validation__function_has_no_body)
-fn tint_msl_quad_shuffle(data : f32, quad_lane_id : u32) -> f32
-
-var<private> tint_msl_thread_index_in_quadgroup : u32;
-
-fn tint_msl_quadSwapX(e : f32) -> f32 {
- return tint_msl_quad_shuffle(e, (tint_msl_thread_index_in_quadgroup ^ 1u));
-}
-
-@compute @workgroup_size(64)
-fn foo(@internal(thread_index_in_quadgroup) tint_thread_index_in_quadgroup : u32) {
- {
- tint_msl_thread_index_in_quadgroup = tint_thread_index_in_quadgroup;
- }
- let x : f32 = tint_msl_quadSwapX(1.0f);
-}
-)";
-
- auto got = Run<QuadSwap>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(QuadSwapTest, IndirectUseQuadSwapX) {
- auto* src = R"(
-enable subgroups;
-
-fn bar() -> vec4u {
- let expr = vec4u(1u, 1u, 1u, 1u);
- return quadSwapX(expr);
-}
-
-@compute @workgroup_size(64)
-fn foo() {
- let x: vec4u = bar();
-}
-)";
-
- auto* expect =
- R"(
-enable subgroups;
-
-@internal(quad_shuffle) @internal(disable_validation__function_has_no_body)
-fn tint_msl_quad_shuffle(data : vec4<u32>, quad_lane_id : u32) -> vec4<u32>
-
-var<private> tint_msl_thread_index_in_quadgroup : u32;
-
-fn tint_msl_quadSwapX(e : vec4<u32>) -> vec4<u32> {
- return tint_msl_quad_shuffle(e, (tint_msl_thread_index_in_quadgroup ^ 1u));
-}
-
-fn bar() -> vec4u {
- let expr = vec4u(1u, 1u, 1u, 1u);
- return tint_msl_quadSwapX(expr);
-}
-
-@compute @workgroup_size(64)
-fn foo(@internal(thread_index_in_quadgroup) tint_thread_index_in_quadgroup : u32) {
- {
- tint_msl_thread_index_in_quadgroup = tint_thread_index_in_quadgroup;
- }
- let x : vec4u = bar();
-}
-)";
-
- auto got = Run<QuadSwap>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(QuadSwapTest, DirectUseQuadSwapY) {
- auto* src = R"(
-enable subgroups;
-
-@compute @workgroup_size(64)
-fn foo() {
- let x: i32 = quadSwapY(1i);
-}
-)";
-
- auto* expect =
- R"(
-enable subgroups;
-
-@internal(quad_shuffle) @internal(disable_validation__function_has_no_body)
-fn tint_msl_quad_shuffle(data : i32, quad_lane_id : u32) -> i32
-
-var<private> tint_msl_thread_index_in_quadgroup : u32;
-
-fn tint_msl_quadSwapY(e : i32) -> i32 {
- return tint_msl_quad_shuffle(e, (tint_msl_thread_index_in_quadgroup ^ 2u));
-}
-
-@compute @workgroup_size(64)
-fn foo(@internal(thread_index_in_quadgroup) tint_thread_index_in_quadgroup : u32) {
- {
- tint_msl_thread_index_in_quadgroup = tint_thread_index_in_quadgroup;
- }
- let x : i32 = tint_msl_quadSwapY(1i);
-}
-)";
-
- auto got = Run<QuadSwap>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(QuadSwapTest, DirectUseQuadSwapDiagonal) {
- auto* src = R"(
-enable subgroups;
-
-@compute @workgroup_size(64)
-fn foo() {
- let x: i32 = quadSwapDiagonal(1i);
-}
-)";
-
- auto* expect =
- R"(
-enable subgroups;
-
-@internal(quad_shuffle) @internal(disable_validation__function_has_no_body)
-fn tint_msl_quad_shuffle(data : i32, quad_lane_id : u32) -> i32
-
-var<private> tint_msl_thread_index_in_quadgroup : u32;
-
-fn tint_msl_quadSwapDiagonal(e : i32) -> i32 {
- return tint_msl_quad_shuffle(e, (tint_msl_thread_index_in_quadgroup ^ 3u));
-}
-
-@compute @workgroup_size(64)
-fn foo(@internal(thread_index_in_quadgroup) tint_thread_index_in_quadgroup : u32) {
- {
- tint_msl_thread_index_in_quadgroup = tint_thread_index_in_quadgroup;
- }
- let x : i32 = tint_msl_quadSwapDiagonal(1i);
-}
-)";
-
- auto got = Run<QuadSwap>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(QuadSwapTest, MultipleCallsSameFunction) {
- auto* src = R"(
-enable subgroups;
-
-@compute @workgroup_size(64)
-fn foo() {
- let x: u32 = quadSwapX(1u);
- let y: u32 = quadSwapX(1u);
-}
-)";
-
- auto* expect =
- R"(
-enable subgroups;
-
-@internal(quad_shuffle) @internal(disable_validation__function_has_no_body)
-fn tint_msl_quad_shuffle(data : u32, quad_lane_id : u32) -> u32
-
-var<private> tint_msl_thread_index_in_quadgroup : u32;
-
-fn tint_msl_quadSwapX(e : u32) -> u32 {
- return tint_msl_quad_shuffle(e, (tint_msl_thread_index_in_quadgroup ^ 1u));
-}
-
-@compute @workgroup_size(64)
-fn foo(@internal(thread_index_in_quadgroup) tint_thread_index_in_quadgroup : u32) {
- {
- tint_msl_thread_index_in_quadgroup = tint_thread_index_in_quadgroup;
- }
- let x : u32 = tint_msl_quadSwapX(1u);
- let y : u32 = tint_msl_quadSwapX(1u);
-}
-)";
-
- auto got = Run<QuadSwap>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(QuadSwapTest, MultipleCallsSameFunctionDifferentType) {
- auto* src = R"(
-enable subgroups;
-
-@compute @workgroup_size(64)
-fn foo() {
- let x: u32 = quadSwapX(1u);
- let y: i32 = quadSwapX(1i);
-}
-)";
-
- auto* expect =
- R"(
-enable subgroups;
-
-@internal(quad_shuffle) @internal(disable_validation__function_has_no_body)
-fn tint_msl_quad_shuffle(data : u32, quad_lane_id : u32) -> u32
-
-var<private> tint_msl_thread_index_in_quadgroup : u32;
-
-fn tint_msl_quadSwapX(e : u32) -> u32 {
- return tint_msl_quad_shuffle(e, (tint_msl_thread_index_in_quadgroup ^ 1u));
-}
-
-@internal(quad_shuffle) @internal(disable_validation__function_has_no_body)
-fn tint_msl_quad_shuffle_1(data : i32, quad_lane_id : u32) -> i32
-
-fn tint_msl_quadSwapX_1(e : i32) -> i32 {
- return tint_msl_quad_shuffle_1(e, (tint_msl_thread_index_in_quadgroup ^ 1u));
-}
-
-@compute @workgroup_size(64)
-fn foo(@internal(thread_index_in_quadgroup) tint_thread_index_in_quadgroup : u32) {
- {
- tint_msl_thread_index_in_quadgroup = tint_thread_index_in_quadgroup;
- }
- let x : u32 = tint_msl_quadSwapX(1u);
- let y : i32 = tint_msl_quadSwapX_1(1i);
-}
-)";
-
- auto got = Run<QuadSwap>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(QuadSwapTest, MultipleCallsSameTypeDifferentFunction) {
- auto* src = R"(
-enable subgroups;
-
-@compute @workgroup_size(64)
-fn foo() {
- let x: u32 = quadSwapX(1u);
- let y: u32 = quadSwapY(1u);
-}
-)";
-
- auto* expect =
- R"(
-enable subgroups;
-
-@internal(quad_shuffle) @internal(disable_validation__function_has_no_body)
-fn tint_msl_quad_shuffle(data : u32, quad_lane_id : u32) -> u32
-
-var<private> tint_msl_thread_index_in_quadgroup : u32;
-
-fn tint_msl_quadSwapX(e : u32) -> u32 {
- return tint_msl_quad_shuffle(e, (tint_msl_thread_index_in_quadgroup ^ 1u));
-}
-
-fn tint_msl_quadSwapY(e : u32) -> u32 {
- return tint_msl_quad_shuffle(e, (tint_msl_thread_index_in_quadgroup ^ 2u));
-}
-
-@compute @workgroup_size(64)
-fn foo(@internal(thread_index_in_quadgroup) tint_thread_index_in_quadgroup : u32) {
- {
- tint_msl_thread_index_in_quadgroup = tint_thread_index_in_quadgroup;
- }
- let x : u32 = tint_msl_quadSwapX(1u);
- let y : u32 = tint_msl_quadSwapY(1u);
-}
-)";
-
- auto got = Run<QuadSwap>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(QuadSwapTest, MultipleCallsDifferentTypeDifferentFunction) {
- auto* src = R"(
-enable subgroups;
-
-@compute @workgroup_size(64)
-fn foo() {
- let x: i32 = quadSwapX(1i);
- let y: u32 = quadSwapY(1u);
-}
-)";
-
- auto* expect =
- R"(
-enable subgroups;
-
-@internal(quad_shuffle) @internal(disable_validation__function_has_no_body)
-fn tint_msl_quad_shuffle(data : i32, quad_lane_id : u32) -> i32
-
-var<private> tint_msl_thread_index_in_quadgroup : u32;
-
-fn tint_msl_quadSwapX(e : i32) -> i32 {
- return tint_msl_quad_shuffle(e, (tint_msl_thread_index_in_quadgroup ^ 1u));
-}
-
-@internal(quad_shuffle) @internal(disable_validation__function_has_no_body)
-fn tint_msl_quad_shuffle_1(data : u32, quad_lane_id : u32) -> u32
-
-fn tint_msl_quadSwapY(e : u32) -> u32 {
- return tint_msl_quad_shuffle_1(e, (tint_msl_thread_index_in_quadgroup ^ 2u));
-}
-
-@compute @workgroup_size(64)
-fn foo(@internal(thread_index_in_quadgroup) tint_thread_index_in_quadgroup : u32) {
- {
- tint_msl_thread_index_in_quadgroup = tint_thread_index_in_quadgroup;
- }
- let x : i32 = tint_msl_quadSwapX(1i);
- let y : u32 = tint_msl_quadSwapY(1u);
-}
-)";
-
- auto got = Run<QuadSwap>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-} // namespace
-} // namespace tint::msl::writer
diff --git a/src/tint/lang/msl/writer/ast_raise/subgroup_ballot.cc b/src/tint/lang/msl/writer/ast_raise/subgroup_ballot.cc
deleted file mode 100644
index 6a93177..0000000
--- a/src/tint/lang/msl/writer/ast_raise/subgroup_ballot.cc
+++ /dev/null
@@ -1,215 +0,0 @@
-// Copyright 2023 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/tint/lang/msl/writer/ast_raise/subgroup_ballot.h"
-
-#include <utility>
-
-#include "src/tint/lang/core/fluent_types.h"
-#include "src/tint/lang/wgsl/program/clone_context.h"
-#include "src/tint/lang/wgsl/program/program_builder.h"
-#include "src/tint/lang/wgsl/resolver/resolve.h"
-#include "src/tint/lang/wgsl/sem/call.h"
-#include "src/tint/lang/wgsl/sem/function.h"
-#include "src/tint/lang/wgsl/sem/statement.h"
-
-TINT_INSTANTIATE_TYPEINFO(tint::msl::writer::SubgroupBallot);
-TINT_INSTANTIATE_TYPEINFO(tint::msl::writer::SubgroupBallot::SimdBallot);
-
-using namespace tint::core::number_suffixes; // NOLINT
-using namespace tint::core::fluent_types; // NOLINT
-
-namespace tint::msl::writer {
-
-/// PIMPL state for the transform
-struct SubgroupBallot::State {
- /// The source program
- const Program& src;
- /// The target program builder
- ProgramBuilder b;
- /// The clone context
- program::CloneContext ctx = {&b, &src, /* auto_clone_symbols */ true};
-
- /// The name of the `tint_subgroup_ballot` helper function.
- Symbol ballot_helper{};
-
- /// The name of the `tint_subgroup_size_mask` global variable.
- Symbol subgroup_size_mask{};
-
- /// The set of a functions that directly call `subgroupBallot()`.
- Hashset<const sem::Function*, 4> ballot_callers;
-
- /// Constructor
- /// @param program the source program
- explicit State(const Program& program) : src(program) {}
-
- /// Runs the transform
- /// @returns the new program or SkipTransform if the transform is not required
- ApplyResult Run() {
- auto& sem = src.Sem();
-
- bool made_changes = false;
- for (auto* node : ctx.src->ASTNodes().Objects()) {
- auto* call = sem.Get<sem::Call>(node);
- if (call) {
- // If this is a call to a `subgroupBallot()` builtin, replace it with a call to the
- // helper function and make a note of the function that we are in.
- auto* builtin = call->Target()->As<sem::BuiltinFn>();
- if (builtin && builtin->Fn() == wgsl::BuiltinFn::kSubgroupBallot) {
- auto* pred = ctx.Clone(call->Arguments()[0]->Declaration());
- ctx.Replace(call->Declaration(), b.Call(GetHelper(), pred));
- ballot_callers.Add(call->Stmt()->Function());
- made_changes = true;
- }
- }
- }
- if (!made_changes) {
- return SkipTransform;
- }
-
- // Set the subgroup size mask at the start of each entry point that transitively calls
- // `subgroupBallot()`.
- for (auto* global : src.AST().GlobalDeclarations()) {
- auto* func = global->As<ast::Function>();
- if (func && func->IsEntryPoint() && TransitvelyCallsSubgroupBallot(sem.Get(func))) {
- SetSubgroupSizeMask(func);
- }
- }
-
- ctx.Clone();
- return resolver::Resolve(b);
- }
-
- /// Get (or create) the `tint_msl_subgroup_ballot` helper function.
- /// @returns the name of the helper function
- Symbol GetHelper() {
- if (!ballot_helper) {
- auto intrinsic = b.Symbols().New("tint_msl_simd_ballot");
- subgroup_size_mask = b.Symbols().New("tint_subgroup_size_mask");
- ballot_helper = b.Symbols().New("tint_msl_subgroup_ballot");
-
- // Declare the `tint_msl_subgroup_ballot` intrinsic function, which will use the
- // `simd_ballot` function to return 64-bit vote.
- {
- auto* pred = b.Param("pred", b.ty.bool_());
- b.Func(intrinsic, Vector{pred}, b.ty.vec2<u32>(), nullptr,
- Vector{b.ASTNodes().Create<SimdBallot>(b.ID(), b.AllocateNodeID()),
- b.Disable(ast::DisabledValidation::kFunctionHasNoBody)});
- }
-
- // Declare the `tint_subgroup_size_mask` variable.
- b.GlobalVar(subgroup_size_mask, core::AddressSpace::kPrivate, b.ty.vec4<u32>());
-
- // Declare the `tint_msl_subgroup_ballot` helper function as follows:
- // fn tint_msl_subgroup_ballot(pred : bool) -> vec4u {
- // let vote : vec2u = vec4f(tint_simd_ballot(pred), 0, 0);
- // return (vote & tint_subgroup_size_mask);
- // }
- auto* pred = b.Param("pred", b.ty.bool_());
- auto* vote =
- b.Let(b.Sym(), b.Call(b.ty.vec4<u32>(), b.Call(intrinsic, pred), 0_u, 0_u));
- b.Func(ballot_helper, Vector{pred}, b.ty.vec4<u32>(),
- Vector{
- b.Decl(vote),
- b.Return(b.And(vote, subgroup_size_mask)),
- });
- }
- return ballot_helper;
- }
-
- /// Check if a function directly or transitively calls the `subgroupBallot()` builtin.
- /// @param func the function to check
- /// @returns true if the function transitively calls `subgroupBallot()`
- bool TransitvelyCallsSubgroupBallot(const sem::Function* func) {
- if (ballot_callers.Contains(func)) {
- return true;
- }
- for (auto* called : func->TransitivelyCalledFunctions()) {
- if (ballot_callers.Contains(called)) {
- return true;
- }
- }
- return false;
- }
-
- /// Add code to set the `subgroup_size_mask` variable at the start of an entry point.
- /// @param ep the entry point
- void SetSubgroupSizeMask(const ast::Function* ep) {
- // Check the entry point parameters for an existing `subgroup_size` builtin.
- Symbol subgroup_size;
- for (auto* param : ep->params) {
- auto* builtin = ast::GetAttribute<ast::BuiltinAttribute>(param->attributes);
- if (builtin && builtin->builtin == core::BuiltinValue::kSubgroupSize) {
- subgroup_size = ctx.Clone(param->name->symbol);
- }
- }
- if (!subgroup_size.IsValid()) {
- // No `subgroup_size` builtin parameter was found, so add one.
- subgroup_size = b.Symbols().New("tint_subgroup_size");
- ctx.InsertBack(ep->params, b.Param(subgroup_size, b.ty.u32(),
- Vector{
- b.Builtin(core::BuiltinValue::kSubgroupSize),
- }));
- }
-
- // Add the following to the top of the entry point:
- // {
- // let gt = subgroup_size > 32;
- // subgroup_size_mask[0] = select(0xffffffff >> (32 - subgroup_size), 0xffffffff, gt);
- // subgroup_size_mask[1] = select(0, 0xffffffff >> (64 - subgroup_size), gt);
- // }
- auto* gt = b.Let(b.Sym("gt"), b.GreaterThan(subgroup_size, 32_u));
- auto* lo =
- b.Call("select", b.Shr(0xffffffff_u, b.Sub(32_u, subgroup_size)), 0xffffffff_u, gt);
- auto* hi = b.Call("select", 0_u, b.Shr(0xffffffff_u, b.Sub(64_u, subgroup_size)), gt);
- auto* block = b.Block(Vector{
- b.Decl(gt),
- b.Assign(b.IndexAccessor(subgroup_size_mask, 0_u), lo),
- b.Assign(b.IndexAccessor(subgroup_size_mask, 1_u), hi),
- });
- ctx.InsertFront(ep->body->statements, block);
- }
-};
-
-SubgroupBallot::SubgroupBallot() = default;
-
-SubgroupBallot::~SubgroupBallot() = default;
-
-ast::transform::Transform::ApplyResult SubgroupBallot::Apply(const Program& src,
- const ast::transform::DataMap&,
- ast::transform::DataMap&) const {
- return State(src).Run();
-}
-
-SubgroupBallot::SimdBallot::~SimdBallot() = default;
-
-const SubgroupBallot::SimdBallot* SubgroupBallot::SimdBallot::Clone(ast::CloneContext& ctx) const {
- return ctx.dst->ASTNodes().Create<SubgroupBallot::SimdBallot>(ctx.dst->ID(),
- ctx.dst->AllocateNodeID());
-}
-
-} // namespace tint::msl::writer
diff --git a/src/tint/lang/msl/writer/ast_raise/subgroup_ballot.h b/src/tint/lang/msl/writer/ast_raise/subgroup_ballot.h
deleted file mode 100644
index 3d5922b..0000000
--- a/src/tint/lang/msl/writer/ast_raise/subgroup_ballot.h
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright 2023 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef SRC_TINT_LANG_MSL_WRITER_AST_RAISE_SUBGROUP_BALLOT_H_
-#define SRC_TINT_LANG_MSL_WRITER_AST_RAISE_SUBGROUP_BALLOT_H_
-
-#include <string>
-
-#include "src/tint/lang/wgsl/ast/internal_attribute.h"
-#include "src/tint/lang/wgsl/ast/transform/transform.h"
-
-namespace tint::msl::writer {
-
-/// SubgroupBallot is a transform that replaces calls to `subgroupBallot()` with an
-/// implementation that uses MSL's `simd_ballot()`.
-///
-/// @note Depends on the following transforms to have been run first:
-/// * CanonicalizeEntryPointIO
-class SubgroupBallot final : public Castable<SubgroupBallot, ast::transform::Transform> {
- public:
- /// Constructor
- SubgroupBallot();
-
- /// Destructor
- ~SubgroupBallot() override;
-
- /// @copydoc ast::transform::Transform::Apply
- ApplyResult Apply(const Program& program,
- const ast::transform::DataMap& inputs,
- ast::transform::DataMap& outputs) const override;
-
- /// SimdBallot is an InternalAttribute that is used to decorate a stub function so
- /// that the MSL backend transforms this into calls to the `simd_ballot` function.
- class SimdBallot final : public Castable<SimdBallot, ast::InternalAttribute> {
- public:
- /// Constructor
- /// @param pid the identifier of the program that owns this node
- /// @param nid the unique node identifier
- SimdBallot(GenerationID pid, ast::NodeID nid) : Base(pid, nid, Empty) {}
-
- /// Destructor
- ~SimdBallot() override;
-
- /// @copydoc ast::InternalAttribute::InternalName
- std::string InternalName() const override { return "simd_ballot"; }
-
- /// Performs a deep clone of this object using the program::CloneContext `ctx`.
- /// @param ctx the clone context
- /// @return the newly cloned object
- const SimdBallot* Clone(ast::CloneContext& ctx) const override;
- };
-
- private:
- struct State;
-};
-
-} // namespace tint::msl::writer
-
-#endif // SRC_TINT_LANG_MSL_WRITER_AST_RAISE_SUBGROUP_BALLOT_H_
diff --git a/src/tint/lang/msl/writer/ast_raise/subgroup_ballot_test.cc b/src/tint/lang/msl/writer/ast_raise/subgroup_ballot_test.cc
deleted file mode 100644
index d5d6ab5..0000000
--- a/src/tint/lang/msl/writer/ast_raise/subgroup_ballot_test.cc
+++ /dev/null
@@ -1,182 +0,0 @@
-// Copyright 2023 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/tint/lang/msl/writer/ast_raise/subgroup_ballot.h"
-
-#include "src/tint/lang/wgsl/ast/transform/helper_test.h"
-
-namespace tint::msl::writer {
-namespace {
-
-using SubgroupBallotTest = ast::transform::TransformTest;
-
-TEST_F(SubgroupBallotTest, EmptyModule) {
- auto* src = "";
-
- EXPECT_FALSE(ShouldRun<SubgroupBallot>(src));
-}
-
-TEST_F(SubgroupBallotTest, DirectUse) {
- auto* src = R"(
-enable subgroups;
-
-@compute @workgroup_size(64)
-fn foo() {
- let pred = true;
- let x : vec4u = subgroupBallot(pred);
-}
-)";
-
- auto* expect =
- R"(
-enable subgroups;
-
-@internal(simd_ballot) @internal(disable_validation__function_has_no_body)
-fn tint_msl_simd_ballot(pred : bool) -> vec2<u32>
-
-var<private> tint_subgroup_size_mask : vec4<u32>;
-
-fn tint_msl_subgroup_ballot(pred : bool) -> vec4<u32> {
- let tint_symbol = vec4<u32>(tint_msl_simd_ballot(pred), 0u, 0u);
- return (tint_symbol & tint_subgroup_size_mask);
-}
-
-@compute @workgroup_size(64)
-fn foo(@builtin(subgroup_size) tint_subgroup_size : u32) {
- {
- let gt = (tint_subgroup_size > 32u);
- tint_subgroup_size_mask[0u] = select((4294967295u >> (32u - tint_subgroup_size)), 4294967295u, gt);
- tint_subgroup_size_mask[1u] = select(0u, (4294967295u >> (64u - tint_subgroup_size)), gt);
- }
- let pred = true;
- let x : vec4u = tint_msl_subgroup_ballot(pred);
-}
-)";
-
- auto got = Run<SubgroupBallot>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(SubgroupBallotTest, IndirectUse) {
- auto* src = R"(
-enable subgroups;
-
-fn bar() -> vec4u {
- let pred = true;
- return subgroupBallot(pred);
-}
-
-@compute @workgroup_size(64)
-fn foo() {
- let x: vec4u = bar();
-}
-)";
-
- auto* expect =
- R"(
-enable subgroups;
-
-@internal(simd_ballot) @internal(disable_validation__function_has_no_body)
-fn tint_msl_simd_ballot(pred : bool) -> vec2<u32>
-
-var<private> tint_subgroup_size_mask : vec4<u32>;
-
-fn tint_msl_subgroup_ballot(pred : bool) -> vec4<u32> {
- let tint_symbol = vec4<u32>(tint_msl_simd_ballot(pred), 0u, 0u);
- return (tint_symbol & tint_subgroup_size_mask);
-}
-
-fn bar() -> vec4u {
- let pred = true;
- return tint_msl_subgroup_ballot(pred);
-}
-
-@compute @workgroup_size(64)
-fn foo(@builtin(subgroup_size) tint_subgroup_size : u32) {
- {
- let gt = (tint_subgroup_size > 32u);
- tint_subgroup_size_mask[0u] = select((4294967295u >> (32u - tint_subgroup_size)), 4294967295u, gt);
- tint_subgroup_size_mask[1u] = select(0u, (4294967295u >> (64u - tint_subgroup_size)), gt);
- }
- let x : vec4u = bar();
-}
-)";
-
- auto got = Run<SubgroupBallot>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-TEST_F(SubgroupBallotTest, PreexistingSubgroupSizeBuiltin) {
- auto* src = R"(
-enable subgroups;
-
-@compute @workgroup_size(64)
-fn foo(@builtin(workgroup_id) group_id: vec3u,
- @builtin(subgroup_size) size : u32,
- @builtin(local_invocation_index) index : u32) {
- let sz = size;
- let pred = true;
- let x : vec4u = subgroupBallot(pred);
-}
-)";
-
- auto* expect =
- R"(
-enable subgroups;
-
-@internal(simd_ballot) @internal(disable_validation__function_has_no_body)
-fn tint_msl_simd_ballot(pred : bool) -> vec2<u32>
-
-var<private> tint_subgroup_size_mask : vec4<u32>;
-
-fn tint_msl_subgroup_ballot(pred : bool) -> vec4<u32> {
- let tint_symbol = vec4<u32>(tint_msl_simd_ballot(pred), 0u, 0u);
- return (tint_symbol & tint_subgroup_size_mask);
-}
-
-@compute @workgroup_size(64)
-fn foo(@builtin(workgroup_id) group_id : vec3u, @builtin(subgroup_size) size : u32, @builtin(local_invocation_index) index : u32) {
- {
- let gt = (size > 32u);
- tint_subgroup_size_mask[0u] = select((4294967295u >> (32u - size)), 4294967295u, gt);
- tint_subgroup_size_mask[1u] = select(0u, (4294967295u >> (64u - size)), gt);
- }
- let sz = size;
- let pred = true;
- let x : vec4u = tint_msl_subgroup_ballot(pred);
-}
-)";
-
- auto got = Run<SubgroupBallot>(src);
-
- EXPECT_EQ(expect, str(got));
-}
-
-} // namespace
-} // namespace tint::msl::writer
diff --git a/src/tint/lang/msl/writer/helpers/BUILD.bazel b/src/tint/lang/msl/writer/helpers/BUILD.bazel
index 2ef72a6..d56a19a 100644
--- a/src/tint/lang/msl/writer/helpers/BUILD.bazel
+++ b/src/tint/lang/msl/writer/helpers/BUILD.bazel
@@ -50,11 +50,6 @@
"//src/tint/lang/core/constant",
"//src/tint/lang/core/ir",
"//src/tint/lang/core/type",
- "//src/tint/lang/wgsl",
- "//src/tint/lang/wgsl/ast",
- "//src/tint/lang/wgsl/features",
- "//src/tint/lang/wgsl/program",
- "//src/tint/lang/wgsl/sem",
"//src/tint/utils",
"//src/tint/utils/containers",
"//src/tint/utils/diagnostic",
diff --git a/src/tint/lang/msl/writer/helpers/BUILD.cmake b/src/tint/lang/msl/writer/helpers/BUILD.cmake
index d46b225..2b29562 100644
--- a/src/tint/lang/msl/writer/helpers/BUILD.cmake
+++ b/src/tint/lang/msl/writer/helpers/BUILD.cmake
@@ -51,11 +51,6 @@
tint_lang_core_constant
tint_lang_core_ir
tint_lang_core_type
- tint_lang_wgsl
- tint_lang_wgsl_ast
- tint_lang_wgsl_features
- tint_lang_wgsl_program
- tint_lang_wgsl_sem
tint_utils
tint_utils_containers
tint_utils_diagnostic
diff --git a/src/tint/lang/msl/writer/helpers/BUILD.gn b/src/tint/lang/msl/writer/helpers/BUILD.gn
index 569bb72..8b74a73 100644
--- a/src/tint/lang/msl/writer/helpers/BUILD.gn
+++ b/src/tint/lang/msl/writer/helpers/BUILD.gn
@@ -51,11 +51,6 @@
"${tint_src_dir}/lang/core/constant",
"${tint_src_dir}/lang/core/ir",
"${tint_src_dir}/lang/core/type",
- "${tint_src_dir}/lang/wgsl",
- "${tint_src_dir}/lang/wgsl/ast",
- "${tint_src_dir}/lang/wgsl/features",
- "${tint_src_dir}/lang/wgsl/program",
- "${tint_src_dir}/lang/wgsl/sem",
"${tint_src_dir}/utils",
"${tint_src_dir}/utils/containers",
"${tint_src_dir}/utils/diagnostic",
diff --git a/src/tint/lang/msl/writer/helpers/generate_bindings.cc b/src/tint/lang/msl/writer/helpers/generate_bindings.cc
index e0ca733..8f124ae 100644
--- a/src/tint/lang/msl/writer/helpers/generate_bindings.cc
+++ b/src/tint/lang/msl/writer/helpers/generate_bindings.cc
@@ -39,9 +39,6 @@
#include "src/tint/lang/core/type/pointer.h"
#include "src/tint/lang/core/type/storage_texture.h"
#include "src/tint/lang/msl/writer/common/options.h"
-#include "src/tint/lang/wgsl/ast/module.h"
-#include "src/tint/lang/wgsl/program/program.h"
-#include "src/tint/lang/wgsl/sem/variable.h"
#include "src/tint/utils/ice/ice.h"
#include "src/tint/utils/rtti/switch.h"
@@ -121,80 +118,4 @@
return bindings;
}
-Bindings GenerateBindings(const Program& program) {
- // TODO(tint:1491): Use Inspector once we can get binding info for all
- // variables, not just those referenced by entry points.
-
- Bindings bindings{};
-
- std::unordered_set<tint::BindingPoint> seen_binding_points;
-
- // Collect next valid binding number per group
- Hashmap<uint32_t, uint32_t, 4> group_to_next_binding_number;
- Vector<tint::BindingPoint, 4> ext_tex_bps;
- for (auto* var : program.AST().GlobalVariables()) {
- if (auto* sem_var = program.Sem().Get(var)->As<sem::GlobalVariable>()) {
- if (auto bp = sem_var->Attributes().binding_point) {
- if (auto val = group_to_next_binding_number.Get(bp->group)) {
- *val = std::max(*val, bp->binding + 1);
- } else {
- group_to_next_binding_number.Add(bp->group, bp->binding + 1);
- }
-
- // Store up the external textures, we'll add them in the next step
- if (sem_var->Type()->UnwrapRef()->Is<core::type::ExternalTexture>()) {
- ext_tex_bps.Push(*bp);
- continue;
- }
-
- binding::BindingInfo info{bp->binding};
- switch (sem_var->AddressSpace()) {
- case core::AddressSpace::kHandle:
- Switch(
- sem_var->Type()->UnwrapRef(), //
- [&](const core::type::Sampler*) {
- bindings.sampler.emplace(*bp, info);
- },
- [&](const core::type::StorageTexture*) {
- bindings.storage_texture.emplace(*bp, info);
- },
- [&](const core::type::Texture*) {
- bindings.texture.emplace(*bp, info);
- });
- break;
- case core::AddressSpace::kStorage:
- bindings.storage.emplace(*bp, info);
- break;
- case core::AddressSpace::kUniform:
- bindings.uniform.emplace(*bp, info);
- break;
-
- case core::AddressSpace::kUndefined:
- case core::AddressSpace::kPixelLocal:
- case core::AddressSpace::kPrivate:
- case core::AddressSpace::kPushConstant:
- case core::AddressSpace::kIn:
- case core::AddressSpace::kOut:
- case core::AddressSpace::kFunction:
- case core::AddressSpace::kWorkgroup:
- break;
- }
- }
- }
- }
-
- for (auto bp : ext_tex_bps) {
- uint32_t g = bp.group;
- uint32_t& next_num = group_to_next_binding_number.GetOrAddZero(g);
-
- binding::BindingInfo plane0{bp.binding};
- binding::BindingInfo plane1{next_num++};
- binding::BindingInfo metadata{next_num++};
-
- bindings.external_texture.emplace(bp, binding::ExternalTexture{metadata, plane0, plane1});
- }
-
- return bindings;
-}
-
} // namespace tint::msl::writer
diff --git a/src/tint/lang/msl/writer/helpers/generate_bindings.h b/src/tint/lang/msl/writer/helpers/generate_bindings.h
index 273132b..cd67655 100644
--- a/src/tint/lang/msl/writer/helpers/generate_bindings.h
+++ b/src/tint/lang/msl/writer/helpers/generate_bindings.h
@@ -31,9 +31,6 @@
#include "src/tint/lang/msl/writer/common/options.h"
// Forward declarations
-namespace tint {
-class Program;
-}
namespace tint::core::ir {
class Module;
} // namespace tint::core::ir
@@ -45,11 +42,6 @@
/// @returns the bindings
Bindings GenerateBindings(const core::ir::Module& module);
-/// Generate the resource bindings
-/// @param program the program to generate from
-/// @returns the bindings
-Bindings GenerateBindings(const Program& program);
-
} // namespace tint::msl::writer
#endif // SRC_TINT_LANG_MSL_WRITER_HELPERS_GENERATE_BINDINGS_H_
diff --git a/src/tint/lang/msl/writer/writer.cc b/src/tint/lang/msl/writer/writer.cc
index 7820b84..df320c3 100644
--- a/src/tint/lang/msl/writer/writer.cc
+++ b/src/tint/lang/msl/writer/writer.cc
@@ -32,8 +32,10 @@
#include "src/tint/lang/core/ir/module.h"
#include "src/tint/lang/core/ir/var.h"
+#include "src/tint/lang/core/type/f16.h"
+#include "src/tint/lang/core/type/f32.h"
#include "src/tint/lang/core/type/input_attachment.h"
-#include "src/tint/lang/msl/writer/ast_printer/ast_printer.h"
+#include "src/tint/lang/core/type/pointer.h"
#include "src/tint/lang/msl/writer/common/option_helpers.h"
#include "src/tint/lang/msl/writer/printer/printer.h"
#include "src/tint/lang/msl/writer/raise/raise.h"
@@ -143,37 +145,4 @@
return result;
}
-Result<Output> Generate(const Program& program, const Options& options) {
- if (!program.IsValid()) {
- return Failure{program.Diagnostics()};
- }
-
- {
- auto res = ValidateBindingOptions(options);
- if (res != Success) {
- return res.Failure();
- }
- }
-
- Output output;
-
- // Sanitize the program.
- auto sanitized_result = Sanitize(program, options);
- if (!sanitized_result.program.IsValid()) {
- return Failure{sanitized_result.program.Diagnostics()};
- }
- output.needs_storage_buffer_sizes = sanitized_result.needs_storage_buffer_sizes;
-
- // Generate the MSL code.
- auto impl = std::make_unique<ASTPrinter>(sanitized_result.program, options);
- if (!impl->Generate()) {
- return Failure{impl->Diagnostics()};
- }
- output.msl = impl->Result();
- output.has_invariant_attribute = impl->HasInvariant();
- output.workgroup_info.allocations = impl->DynamicWorkgroupAllocations();
-
- return output;
-}
-
} // namespace tint::msl::writer
diff --git a/src/tint/lang/msl/writer/writer.h b/src/tint/lang/msl/writer/writer.h
index 93f6505..020e11d 100644
--- a/src/tint/lang/msl/writer/writer.h
+++ b/src/tint/lang/msl/writer/writer.h
@@ -28,17 +28,12 @@
#ifndef SRC_TINT_LANG_MSL_WRITER_WRITER_H_
#define SRC_TINT_LANG_MSL_WRITER_WRITER_H_
-#include <string>
-
#include "src/tint/lang/msl/writer/common/options.h"
#include "src/tint/lang/msl/writer/common/output.h"
#include "src/tint/utils/diagnostic/diagnostic.h"
#include "src/tint/utils/result/result.h"
// Forward declarations
-namespace tint {
-class Program;
-} // namespace tint
namespace tint::core::ir {
class Module;
} // namespace tint::core::ir
@@ -58,13 +53,6 @@
/// @returns the resulting MSL and supplementary information, or failure
Result<Output> Generate(core::ir::Module& ir, const Options& options);
-/// Generate MSL for a program, according to a set of configuration options.
-/// The result will contain the MSL and supplementary information, or failure.
-/// @param program the program to translate to MSL
-/// @param options the configuration options to use when generating MSL
-/// @returns the resulting MSL and supplementary information, or failure
-Result<Output> Generate(const Program& program, const Options& options);
-
} // namespace tint::msl::writer
#endif // SRC_TINT_LANG_MSL_WRITER_WRITER_H_
diff --git a/src/tint/lang/msl/writer/writer_ast_fuzz.cc b/src/tint/lang/msl/writer/writer_ast_fuzz.cc
deleted file mode 100644
index 0441e5c..0000000
--- a/src/tint/lang/msl/writer/writer_ast_fuzz.cc
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2024 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-// list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// GEN_BUILD:CONDITION(tint_build_wgsl_reader)
-
-#include <iostream>
-
-#include "src/tint/cmd/fuzz/wgsl/fuzz.h"
-#include "src/tint/lang/msl/writer/helpers/generate_bindings.h"
-#include "src/tint/lang/msl/writer/writer.h"
-#include "src/tint/lang/wgsl/ast/module.h"
-#include "src/tint/lang/wgsl/sem/variable.h"
-
-namespace tint::msl::writer {
-namespace {
-
-bool CanRun(const Program& program) {
- if (program.AST().HasOverrides()) {
- // MSL writer assumes the SubstituteOverride and SingleEntryPoint transforms have been run.
- return false;
- }
-
- // Check for push constants, which the MSL writer does not support.
- for (auto* global : program.AST().GlobalVariables()) {
- if (program.Sem().Get(global)->AddressSpace() == core::AddressSpace::kPushConstant) {
- return false;
- }
- }
-
- return true;
-}
-
-void ASTFuzzer(const tint::Program& program, const fuzz::wgsl::Context& context, Options options) {
- if (!CanRun(program)) {
- return;
- }
-
- options.bindings = GenerateBindings(program);
-
- auto res = tint::msl::writer::Generate(program, options);
-
- if (res == Success && context.options.dump) {
- std::cout << "Dumping generated MSL:\n" << res->msl << "\n";
- }
-}
-
-} // namespace
-} // namespace tint::msl::writer
-
-TINT_WGSL_PROGRAM_FUZZER(tint::msl::writer::ASTFuzzer);
diff --git a/src/tint/lang/msl/writer/writer_bench.cc b/src/tint/lang/msl/writer/writer_bench.cc
index a48524f..fcf6866 100644
--- a/src/tint/lang/msl/writer/writer_bench.cc
+++ b/src/tint/lang/msl/writer/writer_bench.cc
@@ -70,7 +70,15 @@
6);
gen_options.array_length_from_uniform.bindpoint_to_size_index.emplace(tint::BindingPoint{0, 7},
7);
- gen_options.bindings = tint::msl::writer::GenerateBindings(*program);
+ {
+ // Convert the AST program to an IR module, so that we can generating bindings data.
+ auto ir = tint::wgsl::reader::ProgramToLoweredIR(*program);
+ if (ir != Success) {
+ state.SkipWithError(ir.Failure().reason.Str());
+ return;
+ }
+ gen_options.bindings = tint::msl::writer::GenerateBindings(ir.Get());
+ }
for (auto _ : state) {
// Convert the AST program to an IR module.
@@ -87,50 +95,7 @@
}
}
-void GenerateMSL_AST(benchmark::State& state, std::string input_name) {
- auto res = bench::GetWgslProgram(input_name);
- if (res != Success) {
- state.SkipWithError(res.Failure().reason.Str());
- return;
- }
-
- // Remap resource numbers to a flat namespace.
- const tint::Program* program = &res->program;
- auto flattened = tint::wgsl::FlattenBindings(res->program);
- if (flattened) {
- program = &*flattened;
- }
-
- tint::msl::writer::Options gen_options = {};
- gen_options.array_length_from_uniform.ubo_binding = 30;
- gen_options.array_length_from_uniform.bindpoint_to_size_index.emplace(tint::BindingPoint{0, 0},
- 0);
- gen_options.array_length_from_uniform.bindpoint_to_size_index.emplace(tint::BindingPoint{0, 1},
- 1);
- gen_options.array_length_from_uniform.bindpoint_to_size_index.emplace(tint::BindingPoint{0, 2},
- 2);
- gen_options.array_length_from_uniform.bindpoint_to_size_index.emplace(tint::BindingPoint{0, 3},
- 3);
- gen_options.array_length_from_uniform.bindpoint_to_size_index.emplace(tint::BindingPoint{0, 4},
- 4);
- gen_options.array_length_from_uniform.bindpoint_to_size_index.emplace(tint::BindingPoint{0, 5},
- 5);
- gen_options.array_length_from_uniform.bindpoint_to_size_index.emplace(tint::BindingPoint{0, 6},
- 6);
- gen_options.array_length_from_uniform.bindpoint_to_size_index.emplace(tint::BindingPoint{0, 7},
- 7);
- gen_options.bindings = tint::msl::writer::GenerateBindings(*program);
-
- for (auto _ : state) {
- auto gen_res = Generate(*program, gen_options);
- if (gen_res != Success) {
- state.SkipWithError(gen_res.Failure().reason.Str());
- }
- }
-}
-
TINT_BENCHMARK_PROGRAMS(GenerateMSL);
-TINT_BENCHMARK_PROGRAMS(GenerateMSL_AST);
} // namespace
} // namespace tint::msl::writer