[spirv][ir] Add a spirv.image type.
Add a type to mirror the OpTypeImage in SPIR-V.
Bug: 391485311
Change-Id: I3e9fd37325939b410b19621f35b9d826c7a02a0d
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/233674
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Reviewed-by: James Price <jrprice@google.com>
diff --git a/src/tint/lang/spirv/type/BUILD.bazel b/src/tint/lang/spirv/type/BUILD.bazel
index 6dd7a9d..506a5e7 100644
--- a/src/tint/lang/spirv/type/BUILD.bazel
+++ b/src/tint/lang/spirv/type/BUILD.bazel
@@ -40,10 +40,12 @@
name = "type",
srcs = [
"explicit_layout_array.cc",
+ "image.cc",
"sampled_image.cc",
],
hdrs = [
"explicit_layout_array.h",
+ "image.h",
"sampled_image.h",
],
deps = [
@@ -70,6 +72,7 @@
alwayslink = True,
srcs = [
"explicit_layout_array_test.cc",
+ "image_test.cc",
"sampled_image_test.cc",
],
deps = [
diff --git a/src/tint/lang/spirv/type/BUILD.cmake b/src/tint/lang/spirv/type/BUILD.cmake
index fc93108..d4bad52 100644
--- a/src/tint/lang/spirv/type/BUILD.cmake
+++ b/src/tint/lang/spirv/type/BUILD.cmake
@@ -41,6 +41,8 @@
tint_add_target(tint_lang_spirv_type lib
lang/spirv/type/explicit_layout_array.cc
lang/spirv/type/explicit_layout_array.h
+ lang/spirv/type/image.cc
+ lang/spirv/type/image.h
lang/spirv/type/sampled_image.cc
lang/spirv/type/sampled_image.h
)
@@ -71,6 +73,7 @@
################################################################################
tint_add_target(tint_lang_spirv_type_test test
lang/spirv/type/explicit_layout_array_test.cc
+ lang/spirv/type/image_test.cc
lang/spirv/type/sampled_image_test.cc
)
diff --git a/src/tint/lang/spirv/type/BUILD.gn b/src/tint/lang/spirv/type/BUILD.gn
index f927a5b..affe251 100644
--- a/src/tint/lang/spirv/type/BUILD.gn
+++ b/src/tint/lang/spirv/type/BUILD.gn
@@ -47,6 +47,8 @@
sources = [
"explicit_layout_array.cc",
"explicit_layout_array.h",
+ "image.cc",
+ "image.h",
"sampled_image.cc",
"sampled_image.h",
]
@@ -71,6 +73,7 @@
tint_unittests_source_set("unittests") {
sources = [
"explicit_layout_array_test.cc",
+ "image_test.cc",
"sampled_image_test.cc",
]
deps = [
diff --git a/src/tint/lang/spirv/type/image.cc b/src/tint/lang/spirv/type/image.cc
new file mode 100644
index 0000000..cecf84d
--- /dev/null
+++ b/src/tint/lang/spirv/type/image.cc
@@ -0,0 +1,175 @@
+// Copyright 2025 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/spirv/type/image.h"
+
+#include <sstream>
+
+#include "src/tint/lang/core/type/manager.h"
+
+TINT_INSTANTIATE_TYPEINFO(tint::spirv::type::Image);
+
+namespace tint::spirv::type {
+namespace {
+
+std::ostream& operator<<(std::ostream& out, const Image::Dim dim) {
+ switch (dim) {
+ case Image::Dim::k1D:
+ out << "1d";
+ break;
+ case Image::Dim::k2D:
+ out << "2d";
+ break;
+ case Image::Dim::k3D:
+ out << "3d";
+ break;
+ case Image::Dim::kCube:
+ out << "cube";
+ break;
+ case Image::Dim::kRect:
+ out << "rect";
+ break;
+ case Image::Dim::kBuffer:
+ out << "buffer";
+ break;
+ case Image::Dim::kSubpassData:
+ out << "subpass_data";
+ break;
+ }
+ return out;
+}
+
+std::ostream& operator<<(std::ostream& out, const Image::Depth depth) {
+ switch (depth) {
+ case Image::Depth::kNotDepth:
+ out << "not_depth";
+ break;
+ case Image::Depth::kDepth:
+ out << "depth";
+ break;
+ case Image::Depth::kUnknown:
+ out << "depth_unknown";
+ break;
+ }
+ return out;
+}
+
+std::ostream& operator<<(std::ostream& out, const Image::Arrayed arrayed) {
+ switch (arrayed) {
+ case Image::Arrayed::kNonArrayed:
+ out << "non_arrayed";
+ break;
+ case Image::Arrayed::kArrayed:
+ out << "arrayed";
+ break;
+ }
+ return out;
+}
+
+std::ostream& operator<<(std::ostream& out, const Image::MultiSampled ms) {
+ switch (ms) {
+ case Image::MultiSampled::kSingleSampled:
+ out << "single_sampled";
+ break;
+ case Image::MultiSampled::kMultiSampled:
+ out << "multi_sampled";
+ break;
+ }
+ return out;
+}
+
+std::ostream& operator<<(std::ostream& out, const Image::Sampled sampled) {
+ switch (sampled) {
+ case Image::Sampled::kKnownAtRuntime:
+ out << "sampled_known_at_runtime";
+ break;
+ case Image::Sampled::kSamplingCompatible:
+ out << "sampling_compatible";
+ break;
+ case Image::Sampled::kReadWriteOpCompatible:
+ out << "rw_op_compatible";
+ break;
+ }
+ return out;
+}
+
+} // namespace
+
+Image::Image(const core::type::Type* sampled_type,
+ Dim dim,
+ Depth depth,
+ Arrayed arrayed,
+ MultiSampled ms,
+ Sampled sampled,
+ core::TexelFormat fmt,
+ core::Access access)
+ : Base(static_cast<size_t>(Hash(tint::TypeCode::Of<Image>().bits,
+ sampled_type,
+ dim,
+ depth,
+ arrayed,
+ ms,
+ sampled,
+ fmt,
+ access)),
+ core::type::Flags{}),
+ sampled_type_(sampled_type),
+ dim_(dim),
+ depth_(depth),
+ arrayed_(arrayed),
+ ms_(ms),
+ sampled_(sampled),
+ fmt_(fmt),
+ access_(access) {}
+
+bool Image::Equals(const UniqueNode& other) const {
+ if (auto* o = other.As<Image>()) {
+ return o->sampled_type_ == sampled_type_ && o->dim_ == dim_ && o->depth_ == depth_ &&
+ o->arrayed_ == arrayed_ && o->ms_ == ms_ && o->sampled_ == sampled_ &&
+ o->fmt_ == fmt_ && o->access_ == access_;
+ }
+ return false;
+}
+
+std::string Image::FriendlyName() const {
+ std::stringstream str;
+
+ str << "spirv.image<" << sampled_type_->FriendlyName();
+ str << ", " << dim_ << ", " << depth_ << ", " << arrayed_;
+ str << ", " << ms_ << ", " << sampled_ << ", " << fmt_ << ", " << access_;
+ str << ">";
+
+ return str.str();
+}
+
+Image* Image::Clone(core::type::CloneContext& ctx) const {
+ auto* sampled_type = sampled_type_->Clone(ctx);
+ return ctx.dst.mgr->Get<Image>(sampled_type, dim_, depth_, arrayed_, ms_, sampled_, fmt_,
+ access_);
+}
+
+} // namespace tint::spirv::type
diff --git a/src/tint/lang/spirv/type/image.h b/src/tint/lang/spirv/type/image.h
new file mode 100644
index 0000000..7542c76
--- /dev/null
+++ b/src/tint/lang/spirv/type/image.h
@@ -0,0 +1,116 @@
+// Copyright 2025 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_SPIRV_TYPE_IMAGE_H_
+#define SRC_TINT_LANG_SPIRV_TYPE_IMAGE_H_
+
+#include <string>
+
+#include "src/tint/lang/core/access.h"
+#include "src/tint/lang/core/texel_format.h"
+#include "src/tint/lang/core/type/type.h"
+
+namespace tint::spirv::type {
+
+/// Image represents an OpTypeImage in SPIR-V.
+class Image final : public Castable<Image, core::type::Type> {
+ public:
+ enum class Dim : uint8_t {
+ k1D = 0,
+ k2D = 1,
+ k3D = 2,
+ kCube = 3,
+ kRect = 4,
+ kBuffer = 5,
+ kSubpassData = 6,
+ };
+
+ enum class Depth : uint8_t {
+ kNotDepth = 0,
+ kDepth = 1,
+ kUnknown = 2,
+ };
+
+ enum class Arrayed : uint8_t {
+ kNonArrayed = 0,
+ kArrayed = 1,
+ };
+
+ enum class MultiSampled : uint8_t {
+ kSingleSampled = 0,
+ kMultiSampled = 1,
+ };
+
+ enum class Sampled : uint8_t {
+ kKnownAtRuntime = 0,
+ kSamplingCompatible = 1,
+ kReadWriteOpCompatible = 2,
+ };
+
+ /// Constructor
+ /// @param sampled_type the type of the components that result from sampling or reading
+ /// @param dim the image dimensionality
+ /// @param depth image depth information
+ /// @param arrayed image arrayed information
+ /// @param ms the image multisampled information
+ /// @param sampled the image sampled information
+ /// @param fmt the image format
+ /// @param access the image access qualifier
+ Image(const core::type::Type* sampled_type,
+ Dim dim,
+ Depth depth,
+ Arrayed arrayed,
+ MultiSampled ms,
+ Sampled sampled,
+ core::TexelFormat fmt,
+ core::Access access);
+
+ /// @param other the other node to compare against
+ /// @returns true if the this type is equal to @p other
+ bool Equals(const UniqueNode& other) const override;
+
+ /// @returns the friendly name for this type
+ std::string FriendlyName() const override;
+
+ /// @param ctx the clone context
+ /// @returns a clone of this type
+ Image* Clone(core::type::CloneContext& ctx) const override;
+
+ private:
+ const core::type::Type* sampled_type_;
+ Dim dim_;
+ Depth depth_;
+ Arrayed arrayed_;
+ MultiSampled ms_;
+ Sampled sampled_;
+ core::TexelFormat fmt_;
+ core::Access access_;
+};
+
+} // namespace tint::spirv::type
+
+#endif // SRC_TINT_LANG_SPIRV_TYPE_IMAGE_H_
diff --git a/src/tint/lang/spirv/type/image_test.cc b/src/tint/lang/spirv/type/image_test.cc
new file mode 100644
index 0000000..063a2f2
--- /dev/null
+++ b/src/tint/lang/spirv/type/image_test.cc
@@ -0,0 +1,149 @@
+// Copyright 2025 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/spirv/type/image.h"
+
+#include <gtest/gtest.h>
+
+#include "src/tint/lang/core/type/i32.h"
+#include "src/tint/lang/core/type/u32.h"
+
+namespace tint::spirv::type {
+namespace {
+
+TEST(ImageTest, Equals) {
+ core::type::I32 i32;
+ core::type::U32 u32;
+ Image a{&i32,
+ Image::Dim::k1D,
+ Image::Depth::kNotDepth,
+ Image::Arrayed::kNonArrayed,
+ Image::MultiSampled::kSingleSampled,
+ Image::Sampled::kKnownAtRuntime,
+ core::TexelFormat::kRgba32Float,
+ core::Access::kRead};
+ Image b{&i32,
+ Image::Dim::k1D,
+ Image::Depth::kNotDepth,
+ Image::Arrayed::kNonArrayed,
+ Image::MultiSampled::kSingleSampled,
+ Image::Sampled::kKnownAtRuntime,
+ core::TexelFormat::kRgba32Float,
+ core::Access::kRead};
+ Image c{&u32,
+ Image::Dim::k1D,
+ Image::Depth::kNotDepth,
+ Image::Arrayed::kNonArrayed,
+ Image::MultiSampled::kSingleSampled,
+ Image::Sampled::kKnownAtRuntime,
+ core::TexelFormat::kRgba32Float,
+ core::Access::kRead};
+ Image d{&i32,
+ Image::Dim::k2D,
+ Image::Depth::kNotDepth,
+ Image::Arrayed::kNonArrayed,
+ Image::MultiSampled::kSingleSampled,
+ Image::Sampled::kKnownAtRuntime,
+ core::TexelFormat::kRgba32Float,
+ core::Access::kRead};
+ Image e{&i32,
+ Image::Dim::k1D,
+ Image::Depth::kDepth,
+ Image::Arrayed::kNonArrayed,
+ Image::MultiSampled::kSingleSampled,
+ Image::Sampled::kKnownAtRuntime,
+ core::TexelFormat::kRgba32Float,
+ core::Access::kRead};
+ Image f{&i32,
+ Image::Dim::k1D,
+ Image::Depth::kNotDepth,
+ Image::Arrayed::kArrayed,
+ Image::MultiSampled::kSingleSampled,
+ Image::Sampled::kKnownAtRuntime,
+ core::TexelFormat::kRgba32Float,
+ core::Access::kRead};
+ Image g{&i32,
+ Image::Dim::k1D,
+ Image::Depth::kNotDepth,
+ Image::Arrayed::kNonArrayed,
+ Image::MultiSampled::kMultiSampled,
+ Image::Sampled::kKnownAtRuntime,
+ core::TexelFormat::kRgba32Float,
+ core::Access::kRead};
+ Image h{&i32,
+ Image::Dim::k1D,
+ Image::Depth::kNotDepth,
+ Image::Arrayed::kNonArrayed,
+ Image::MultiSampled::kSingleSampled,
+ Image::Sampled::kSamplingCompatible,
+ core::TexelFormat::kRgba32Float,
+ core::Access::kRead};
+ Image i{&i32,
+ Image::Dim::k1D,
+ Image::Depth::kNotDepth,
+ Image::Arrayed::kNonArrayed,
+ Image::MultiSampled::kSingleSampled,
+ Image::Sampled::kKnownAtRuntime,
+ core::TexelFormat::kR32Float,
+ core::Access::kRead};
+ Image j{&i32,
+ Image::Dim::k1D,
+ Image::Depth::kNotDepth,
+ Image::Arrayed::kNonArrayed,
+ Image::MultiSampled::kSingleSampled,
+ Image::Sampled::kKnownAtRuntime,
+ core::TexelFormat::kRgba32Float,
+ core::Access::kReadWrite};
+
+ EXPECT_TRUE(a.Equals(b));
+ EXPECT_FALSE(a.Equals(c));
+ EXPECT_FALSE(a.Equals(d));
+ EXPECT_FALSE(a.Equals(e));
+ EXPECT_FALSE(a.Equals(f));
+ EXPECT_FALSE(a.Equals(g));
+ EXPECT_FALSE(a.Equals(h));
+ EXPECT_FALSE(a.Equals(i));
+ EXPECT_FALSE(a.Equals(j));
+}
+
+TEST(ImageTest, FriendlyName) {
+ core::type::I32 i32;
+ Image s{&i32,
+ Image::Dim::k1D,
+ Image::Depth::kNotDepth,
+ Image::Arrayed::kNonArrayed,
+ Image::MultiSampled::kSingleSampled,
+ Image::Sampled::kKnownAtRuntime,
+ core::TexelFormat::kRgba32Float,
+ core::Access::kRead};
+ EXPECT_EQ(s.FriendlyName(),
+ "spirv.image<i32, 1d, not_depth, non_arrayed, single_sampled, "
+ "sampled_known_at_runtime, rgba32float, read>");
+}
+
+} // namespace
+} // namespace tint::spirv::type