Implement textureSample builtins
Handle wsgl parsing and spirv writing of:
textureSample(), textureSampleBias(), textureSampleLevel(),
textureSampleGrad(), textureSampleCompare()
Handle the different signature for array texture types.
Includes offset overloads.
Change-Id: I6802d97cd9a7083f12439b32725b9a4b666b8c63
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/32985
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: David Neto <dneto@google.com>
Reviewed-by: Ryan Harrison <rharrison@chromium.org>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
diff --git a/BUILD.gn b/BUILD.gn
index 0a47cd7..529bc60 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -755,6 +755,8 @@
"src/ast/function_test.cc",
"src/ast/identifier_expression_test.cc",
"src/ast/if_statement_test.cc",
+ "src/ast/intrinsic_texture_helper_test.cc",
+ "src/ast/intrinsic_texture_helper_test.h",
"src/ast/int_literal_test.cc",
"src/ast/location_decoration_test.cc",
"src/ast/loop_statement_test.cc",
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 56cda30..cc59d62 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -364,6 +364,8 @@
ast/function_test.cc
ast/identifier_expression_test.cc
ast/if_statement_test.cc
+ ast/intrinsic_texture_helper_test.cc
+ ast/intrinsic_texture_helper_test.h
ast/int_literal_test.cc
ast/location_decoration_test.cc
ast/loop_statement_test.cc
diff --git a/src/ast/identifier_expression.h b/src/ast/identifier_expression.h
index af08b69..4c6ac31 100644
--- a/src/ast/identifier_expression.h
+++ b/src/ast/identifier_expression.h
@@ -15,7 +15,9 @@
#ifndef SRC_AST_IDENTIFIER_EXPRESSION_H_
#define SRC_AST_IDENTIFIER_EXPRESSION_H_
+#include <memory>
#include <string>
+#include <utility>
#include "src/ast/expression.h"
#include "src/ast/intrinsic.h"
@@ -45,6 +47,17 @@
void set_intrinsic(Intrinsic i) { intrinsic_ = i; }
/// @returns the intrinsic this identifier represents
Intrinsic intrinsic() const { return intrinsic_; }
+
+ /// Sets the intrinsic signature
+ /// @param s the intrinsic signature to set
+ void set_intrinsic_signature(std::unique_ptr<intrinsic::Signature> s) {
+ intrinsic_sig_ = std::move(s);
+ }
+ /// @returns the intrinsic signature for this identifier.
+ const intrinsic::Signature* intrinsic_signature() const {
+ return intrinsic_sig_.get();
+ }
+
/// @returns true if this identifier is for an intrinsic
bool IsIntrinsic() const { return intrinsic_ != Intrinsic::kNone; }
@@ -63,6 +76,7 @@
IdentifierExpression(const IdentifierExpression&) = delete;
Intrinsic intrinsic_ = Intrinsic::kNone;
+ std::unique_ptr<intrinsic::Signature> intrinsic_sig_;
std::string name_;
};
diff --git a/src/ast/intrinsic.cc b/src/ast/intrinsic.cc
index 14fdeef..dc6c60a 100644
--- a/src/ast/intrinsic.cc
+++ b/src/ast/intrinsic.cc
@@ -216,6 +216,9 @@
case Intrinsic::kTextureSampleCompare:
out << "textureSampleCompare";
break;
+ case Intrinsic::kTextureSampleGrad:
+ out << "textureSampleGrad";
+ break;
case Intrinsic::kTextureSampleLevel:
out << "textureSampleLevel";
break;
@@ -231,6 +234,12 @@
namespace intrinsic {
+Signature::~Signature() = default;
+TextureSignature::~TextureSignature() = default;
+
+TextureSignature::Parameters::Index::Index() = default;
+TextureSignature::Parameters::Index::Index(const Index&) = default;
+
bool IsCoarseDerivative(ast::Intrinsic i) {
return i == Intrinsic::kDpdxCoarse || i == Intrinsic::kDpdyCoarse ||
i == Intrinsic::kFwidthCoarse;
@@ -256,7 +265,8 @@
return i == Intrinsic::kTextureLoad || i == Intrinsic::kTextureSample ||
i == Intrinsic::kTextureSampleLevel ||
i == Intrinsic::kTextureSampleBias ||
- i == Intrinsic::kTextureSampleCompare;
+ i == Intrinsic::kTextureSampleCompare ||
+ i == Intrinsic::kTextureSampleGrad;
}
} // namespace intrinsic
diff --git a/src/ast/intrinsic.h b/src/ast/intrinsic.h
index 9eb1600..a122ad3 100644
--- a/src/ast/intrinsic.h
+++ b/src/ast/intrinsic.h
@@ -89,6 +89,7 @@
kTextureSample,
kTextureSampleBias,
kTextureSampleCompare,
+ kTextureSampleGrad,
kTextureSampleLevel,
kTrunc
};
@@ -99,6 +100,64 @@
namespace intrinsic {
+/// Signature is the base struct for all intrinsic signature types.
+/// Signatures are used to identify the particular overload for intrinsics that
+/// have different signatures with the same function name.
+struct Signature {
+ virtual ~Signature();
+};
+
+/// TextureSignature describes the signature of a texture intrinsic function.
+struct TextureSignature : public Signature {
+ /// Parameters describes the parameters for the texture function.
+ struct Parameters {
+ /// kNotUsed is the constant that indicates the given parameter is not part
+ /// of the texture function signature.
+ static constexpr const size_t kNotUsed = ~static_cast<size_t>(0u);
+ /// Index holds each of the possible parameter indices. If a parameter index
+ /// is equal to `kNotUsed` then this parameter is not used by the function.
+ struct Index {
+ /// Constructor
+ Index();
+ /// Copy constructor
+ Index(const Index&);
+ /// `array_index` parameter index.
+ size_t array_index = kNotUsed;
+ /// `bias` parameter index.
+ size_t bias = kNotUsed;
+ /// `coords` parameter index.
+ size_t coords = kNotUsed;
+ /// `depth_ref` parameter index.
+ size_t depth_ref = kNotUsed;
+ /// `ddx` parameter index.
+ size_t ddx = kNotUsed;
+ /// `ddy` parameter index.
+ size_t ddy = kNotUsed;
+ /// `level` parameter index.
+ size_t level = kNotUsed;
+ /// `offset` parameter index.
+ size_t offset = kNotUsed;
+ /// `sampler` parameter index.
+ size_t sampler = kNotUsed;
+ /// `texture` parameter index.
+ size_t texture = kNotUsed;
+ };
+ /// The indices of all possible parameters.
+ Index idx;
+ /// Total number of parameters.
+ size_t count = 0;
+ };
+
+ /// Construct an immutable `TextureSignature`.
+ /// @param p the texture intrinsic parameter signature.
+ explicit TextureSignature(const Parameters& p) : params(p) {}
+
+ ~TextureSignature() override;
+
+ /// The texture intrinsic parameter signature.
+ const Parameters params;
+};
+
/// Determines if the given |name| is a coarse derivative
/// @param i the intrinsic
/// @returns true if the given derivative is coarse.
diff --git a/src/ast/intrinsic_texture_helper_test.cc b/src/ast/intrinsic_texture_helper_test.cc
new file mode 100644
index 0000000..5e1587c
--- /dev/null
+++ b/src/ast/intrinsic_texture_helper_test.cc
@@ -0,0 +1,1119 @@
+// Copyright 2020 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/ast/intrinsic_texture_helper_test.h"
+
+#include "src/ast/type_constructor_expression.h"
+
+namespace tint {
+namespace ast {
+namespace intrinsic {
+namespace test {
+
+TextureOverloadCase::TextureOverloadCase() = default;
+TextureOverloadCase::TextureOverloadCase(
+ ValidTextureOverload o,
+ const char* d,
+ TextureKind tk,
+ ast::type::SamplerKind sk,
+ ast::type::TextureDimension td,
+ TextureDataType tdt,
+ const char* f,
+ std::function<ast::ExpressionList(ast::Builder*)> a)
+ : overload(o),
+ description(d),
+ texture_kind(tk),
+ sampler_kind(sk),
+ texture_dimension(td),
+ texture_data_type(tdt),
+ function(f),
+ args(std::move(a)) {}
+TextureOverloadCase::TextureOverloadCase(const TextureOverloadCase&) = default;
+TextureOverloadCase::~TextureOverloadCase() = default;
+
+std::vector<TextureOverloadCase> TextureOverloadCase::ValidCases() {
+ return {{
+ ValidTextureOverload::kSample1dF32,
+ "textureSample(t : texture_1d<f32>,\n"
+ " s : sampler,\n"
+ " coords : f32) -> vec4<f32>",
+ TextureKind::kRegular,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::k1d,
+ TextureDataType::kF32,
+ "textureSample",
+ [](ast::Builder* b) {
+ return b->ExprList("texture", // t
+ "sampler", // s
+ 1.0f); // coords
+ },
+ },
+ {
+ ValidTextureOverload::kSample1dArrayF32,
+ "textureSample(t : texture_1d_array<f32>,\n"
+ " s : sampler,\n"
+ " coords : f32,\n"
+ " array_index : u32) -> vec4<f32>",
+ TextureKind::kRegular,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::k1dArray,
+ TextureDataType::kF32,
+ "textureSample",
+ [](ast::Builder* b) {
+ return b->ExprList("texture", // t
+ "sampler", // s
+ 1.0f, // coords
+ 2u); // array_index
+ },
+ },
+ {
+ ValidTextureOverload::kSample2dF32,
+ "textureSample(t : texture_2d<f32>,\n"
+ " s : sampler,\n"
+ " coords : vec2<f32>) -> vec4<f32>",
+ TextureKind::kRegular,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::k2d,
+ TextureDataType::kF32,
+ "textureSample",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec2<f32>(1.f, 2.f)); // coords
+ },
+ },
+ {
+ ValidTextureOverload::kSample2dOffsetF32,
+ "textureSample(t : texture_2d<f32>,\n"
+ " s : sampler,\n"
+ " coords : vec2<f32>\n"
+ " offset : vec2<i32>) -> vec4<f32>",
+ TextureKind::kRegular,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::k2d,
+ TextureDataType::kF32,
+ "textureSample",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ using i32 = ast::Builder::i32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec2<f32>(1.f, 2.f), // coords
+ b->vec2<i32>(3, 4)); // offset
+ },
+ },
+ {
+ ValidTextureOverload::kSample2dArrayF32,
+ "textureSample(t : texture_2d_array<f32>,\n"
+ " s : sampler,\n"
+ " coords : vec2<f32>,\n"
+ " array_index : u32) -> vec4<f32>",
+ TextureKind::kRegular,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::k2dArray,
+ TextureDataType::kF32,
+ "textureSample",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec2<f32>(1.f, 2.f), // coords
+ 3u); // array_index
+ },
+ },
+ {
+ ValidTextureOverload::kSample2dArrayOffsetF32,
+ "textureSample(t : texture_2d_array<f32>,\n"
+ " s : sampler,\n"
+ " coords : vec2<f32>,\n"
+ " array_index : u32\n"
+ " offset : vec2<i32>) -> vec4<f32>",
+ TextureKind::kRegular,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::k2dArray,
+ TextureDataType::kF32,
+ "textureSample",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ using i32 = ast::Builder::i32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec2<f32>(1.f, 2.f), // coords
+ 3u, // array_index
+ b->vec2<i32>(4, 5)); // offset
+ },
+ },
+ {
+ ValidTextureOverload::kSample3dF32,
+ "textureSample(t : texture_3d<f32>,\n"
+ " s : sampler,\n"
+ " coords : vec3<f32>) -> vec4<f32>",
+ TextureKind::kRegular,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::k3d,
+ TextureDataType::kF32,
+ "textureSample",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec3<f32>(1.f, 2.f, 3.f)); // coords
+ },
+ },
+ {
+ ValidTextureOverload::kSample3dOffsetF32,
+ "textureSample(t : texture_3d<f32>,\n"
+ " s : sampler,\n"
+ " coords : vec3<f32>\n"
+ " offset : vec3<i32>) -> vec4<f32>",
+ TextureKind::kRegular,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::k3d,
+ TextureDataType::kF32,
+ "textureSample",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ using i32 = ast::Builder::i32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec3<f32>(1.f, 2.f, 3.f), // coords
+ b->vec3<i32>(4, 5, 6)); // offset
+ },
+ },
+ {
+ ValidTextureOverload::kSampleCubeF32,
+ "textureSample(t : texture_cube<f32>,\n"
+ " s : sampler,\n"
+ " coords : vec3<f32>) -> vec4<f32>",
+ TextureKind::kRegular,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::kCube,
+ TextureDataType::kF32,
+ "textureSample",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec3<f32>(1.f, 2.f, 3.f)); // coords
+ },
+ },
+ {
+ ValidTextureOverload::kSampleCubeArrayF32,
+ "textureSample(t : texture_cube_array<f32>,\n"
+ " s : sampler,\n"
+ " coords : vec3<f32>,\n"
+ " array_index : u32) -> vec4<f32>",
+ TextureKind::kRegular,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::kCubeArray,
+ TextureDataType::kF32,
+ "textureSample",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec3<f32>(1.f, 2.f, 3.f), // coords
+ 4u); // array_index
+ },
+ },
+ {
+ ValidTextureOverload::kSampleDepth2dF32,
+ "textureSample(t : texture_depth_2d,\n"
+ " s : sampler,\n"
+ " coords : vec2<f32>) -> f32",
+ TextureKind::kDepth,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::k2d,
+ TextureDataType::kF32,
+ "textureSample",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec2<f32>(1.f, 2.f)); // coords
+ },
+ },
+ {
+ ValidTextureOverload::kSampleDepth2dOffsetF32,
+ "textureSample(t : texture_depth_2d,\n"
+ " s : sampler,\n"
+ " coords : vec2<f32>\n"
+ " offset : vec2<i32>) -> f32",
+ TextureKind::kDepth,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::k2d,
+ TextureDataType::kF32,
+ "textureSample",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ using i32 = ast::Builder::i32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec2<f32>(1.f, 2.f), // coords
+ b->vec2<i32>(3, 4)); // offset
+ },
+ },
+ {
+ ValidTextureOverload::kSampleDepth2dArrayF32,
+ "textureSample(t : texture_depth_2d_array,\n"
+ " s : sampler,\n"
+ " coords : vec2<f32>,\n"
+ " array_index : u32) -> f32",
+ TextureKind::kDepth,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::k2dArray,
+ TextureDataType::kF32,
+ "textureSample",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec2<f32>(1.f, 2.f), // coords
+ 3u); // array_index
+ },
+ },
+ {
+ ValidTextureOverload::kSampleDepth2dArrayOffsetF32,
+ "textureSample(t : texture_depth_2d_array,\n"
+ " s : sampler,\n"
+ " coords : vec2<f32>,\n"
+ " array_index : u32\n"
+ " offset : vec2<i32>) -> f32",
+ TextureKind::kDepth,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::k2dArray,
+ TextureDataType::kF32,
+ "textureSample",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ using i32 = ast::Builder::i32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec2<f32>(1.f, 2.f), // coords
+ 3u, // array_index
+ b->vec2<i32>(4, 5)); // offset
+ },
+ },
+ {
+ ValidTextureOverload::kSampleDepthCubeF32,
+ "textureSample(t : texture_depth_cube,\n"
+ " s : sampler,\n"
+ " coords : vec3<f32>) -> f32",
+ TextureKind::kDepth,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::kCube,
+ TextureDataType::kF32,
+ "textureSample",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec2<f32>(1.f, 2.f, 3.f)); // coords
+ },
+ },
+ {
+ ValidTextureOverload::kSampleDepthCubeArrayF32,
+ "textureSample(t : texture_depth_cube_array,\n"
+ " s : sampler,\n"
+ " coords : vec3<f32>,\n"
+ " array_index : u32) -> f32",
+ TextureKind::kDepth,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::kCubeArray,
+ TextureDataType::kF32,
+ "textureSample",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec2<f32>(1.f, 2.f, 3.f), // coords
+ 4u); // array_index
+ },
+ },
+ {
+ ValidTextureOverload::kSampleBias2dF32,
+ "textureSampleBias(t : texture_2d<f32>,\n"
+ " s : sampler,\n"
+ " coords : vec2<f32>,\n"
+ " bias : f32) -> vec4<f32>",
+ TextureKind::kRegular,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::k2d,
+ TextureDataType::kF32,
+ "textureSampleBias",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec2<f32>(1.f, 2.f), // coords
+ 3.f); // bias
+ },
+ },
+ {
+ ValidTextureOverload::kSampleBias2dOffsetF32,
+ "textureSampleBias(t : texture_2d<f32>,\n"
+ " s : sampler,\n"
+ " coords : vec2<f32>,\n"
+ " bias : f32,\n"
+ " offset : vec2<i32>) -> vec4<f32>",
+ TextureKind::kRegular,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::k2d,
+ TextureDataType::kF32,
+ "textureSampleBias",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ using i32 = ast::Builder::i32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec2<f32>(1.f, 2.f), // coords
+ 3.f, // bias
+ b->vec2<i32>(4, 5)); // offset
+ },
+ },
+ {
+ ValidTextureOverload::kSampleBias2dArrayF32,
+ "textureSampleBias(t : texture_2d_array<f32>,\n"
+ " s : sampler,\n"
+ " coords : vec2<f32>,\n"
+ " array_index : u32,\n"
+ " bias : f32) -> vec4<f32>",
+ TextureKind::kRegular,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::k2dArray,
+ TextureDataType::kF32,
+ "textureSampleBias",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec2<f32>(1.f, 2.f), // coords
+ 4u, // array_index
+ 3.f); // bias
+ },
+ },
+ {
+ ValidTextureOverload::kSampleBias2dArrayOffsetF32,
+ "textureSampleBias(t : texture_2d_array<f32>,\n"
+ " s : sampler,\n"
+ " coords : vec2<f32>,\n"
+ " array_index : u32,\n"
+ " bias : f32,\n"
+ " offset : vec2<i32>) -> vec4<f32>",
+ TextureKind::kRegular,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::k2dArray,
+ TextureDataType::kF32,
+ "textureSampleBias",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ using i32 = ast::Builder::i32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec2<f32>(1.f, 2.f), // coords
+ 3u, // array_index
+ 4.f, // bias
+ b->vec2<i32>(5, 6)); // offset
+ },
+ },
+ {
+ ValidTextureOverload::kSampleBias3dF32,
+ "textureSampleBias(t : texture_3d<f32>,\n"
+ " s : sampler,\n"
+ " coords : vec3<f32>,\n"
+ " bias : f32) -> vec4<f32>",
+ TextureKind::kRegular,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::k3d,
+ TextureDataType::kF32,
+ "textureSampleBias",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec3<f32>(1.f, 2.f, 3.f), // coords
+ 4.f); // bias
+ },
+ },
+ {
+ ValidTextureOverload::kSampleBias3dOffsetF32,
+ "textureSampleBias(t : texture_3d<f32>,\n"
+ " s : sampler,\n"
+ " coords : vec3<f32>,\n"
+ " bias : f32,\n"
+ " offset : vec3<i32>) -> vec4<f32>",
+ TextureKind::kRegular,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::k3d,
+ TextureDataType::kF32,
+ "textureSampleBias",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ using i32 = ast::Builder::i32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec3<f32>(1.f, 2.f, 3.f), // coords
+ 4.f, // bias
+ b->vec3<i32>(5, 6, 7)); // offset
+ },
+ },
+ {
+ ValidTextureOverload::kSampleBiasCubeF32,
+ "textureSampleBias(t : texture_cube<f32>,\n"
+ " s : sampler,\n"
+ " coords : vec3<f32>,\n"
+ " bias : f32) -> vec4<f32>",
+ TextureKind::kRegular,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::kCube,
+ TextureDataType::kF32,
+ "textureSampleBias",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec3<f32>(1.f, 2.f, 3.f), // coords
+ 4.f); // bias
+ },
+ },
+ {
+ ValidTextureOverload::kSampleBiasCubeArrayF32,
+ "textureSampleBias(t : texture_cube_array<f32>,\n"
+ " s : sampler,\n"
+ " coords : vec3<f32>,\n"
+ " array_index : u32,\n"
+ " bias : f32) -> vec4<f32>",
+ TextureKind::kRegular,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::kCubeArray,
+ TextureDataType::kF32,
+ "textureSampleBias",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec3<f32>(1.f, 2.f, 3.f), // coords
+ 3u, // array_index
+ 4.f); // bias
+ },
+ },
+ {
+ ValidTextureOverload::kSampleLevel2dF32,
+ "textureSampleLevel(t : texture_2d<f32>,\n"
+ " s : sampler,\n"
+ " coords : vec2<f32>,\n"
+ " level : f32) -> vec4<f32>",
+ TextureKind::kRegular,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::k2d,
+ TextureDataType::kF32,
+ "textureSampleLevel",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec2<f32>(1.f, 2.f), // coords
+ 3.f); // level
+ },
+ },
+ {
+ ValidTextureOverload::kSampleLevel2dOffsetF32,
+ "textureSampleLevel(t : texture_2d<f32>,\n"
+ " s : sampler,\n"
+ " coords : vec2<f32>,\n"
+ " level : f32,\n"
+ " offset : vec2<i32>) -> vec4<f32>",
+ TextureKind::kRegular,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::k2d,
+ TextureDataType::kF32,
+ "textureSampleLevel",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ using i32 = ast::Builder::i32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec2<f32>(1.f, 2.f), // coords
+ 3.f, // level
+ b->vec2<i32>(4, 5)); // offset
+ },
+ },
+ {
+ ValidTextureOverload::kSampleLevel2dArrayF32,
+ "textureSampleLevel(t : texture_2d_array<f32>,\n"
+ " s : sampler,\n"
+ " coords : vec2<f32>,\n"
+ " array_index : u32,\n"
+ " level : f32) -> vec4<f32>",
+ TextureKind::kRegular,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::k2dArray,
+ TextureDataType::kF32,
+ "textureSampleLevel",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec2<f32>(1.f, 2.f), // coords
+ 3u, // array_index
+ 4.f); // level
+ },
+ },
+ {
+ ValidTextureOverload::kSampleLevel2dArrayOffsetF32,
+ "textureSampleLevel(t : texture_2d_array<f32>,\n"
+ " s : sampler,\n"
+ " coords : vec2<f32>,\n"
+ " array_index : u32,\n"
+ " level : f32,\n"
+ " offset : vec2<i32>) -> vec4<f32>",
+ TextureKind::kRegular,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::k2dArray,
+ TextureDataType::kF32,
+ "textureSampleLevel",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ using i32 = ast::Builder::i32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec2<f32>(1.f, 2.f), // coords
+ 3u, // array_index
+ 4.f, // level
+ b->vec2<i32>(5, 6)); // offset
+ },
+ },
+ {
+ ValidTextureOverload::kSampleLevel3dF32,
+ "textureSampleLevel(t : texture_3d<f32>,\n"
+ " s : sampler,\n"
+ " coords : vec3<f32>,\n"
+ " level : f32) -> vec4<f32>",
+ TextureKind::kRegular,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::k3d,
+ TextureDataType::kF32,
+ "textureSampleLevel",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec3<f32>(1.f, 2.f, 3.f), // coords
+ 4.f); // level
+ },
+ },
+ {
+ ValidTextureOverload::kSampleLevel3dOffsetF32,
+ "textureSampleLevel(t : texture_3d<f32>,\n"
+ " s : sampler,\n"
+ " coords : vec3<f32>,\n"
+ " level : f32,\n"
+ " offset : vec3<i32>) -> vec4<f32>",
+ TextureKind::kRegular,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::k3d,
+ TextureDataType::kF32,
+ "textureSampleLevel",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ using i32 = ast::Builder::i32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec3<f32>(1.f, 2.f, 3.f), // coords
+ 4.f, // level
+ b->vec3<i32>(5, 6, 7)); // offset
+ },
+ },
+ {
+ ValidTextureOverload::kSampleLevelCubeF32,
+ "textureSampleLevel(t : texture_cube<f32>,\n"
+ " s : sampler,\n"
+ " coords : vec3<f32>,\n"
+ " level : f32) -> vec4<f32>",
+ TextureKind::kRegular,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::kCube,
+ TextureDataType::kF32,
+ "textureSampleLevel",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec3<f32>(1.f, 2.f, 3.f), // coords
+ 4.f); // level
+ },
+ },
+ {
+ ValidTextureOverload::kSampleLevelCubeArrayF32,
+ "textureSampleLevel(t : texture_cube_array<f32>,\n"
+ " s : sampler,\n"
+ " coords : vec3<f32>,\n"
+ " array_index : u32,\n"
+ " level : f32) -> vec4<f32>",
+ TextureKind::kRegular,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::kCubeArray,
+ TextureDataType::kF32,
+ "textureSampleLevel",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec3<f32>(1.f, 2.f, 3.f), // coords
+ 4u, // array_index
+ 5.f); // level
+ },
+ },
+ {
+ ValidTextureOverload::kSampleLevelDepth2dF32,
+ "textureSampleLevel(t : texture_depth_2d,\n"
+ " s : sampler,\n"
+ " coords : vec2<f32>,\n"
+ " level : u32) -> f32",
+ TextureKind::kDepth,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::k2d,
+ TextureDataType::kF32,
+ "textureSampleLevel",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec2<f32>(1.f, 2.f), // coords
+ 3u); // level
+ },
+ },
+ {
+ ValidTextureOverload::kSampleLevelDepth2dOffsetF32,
+ "textureSampleLevel(t : texture_depth_2d,\n"
+ " s : sampler,\n"
+ " coords : vec2<f32>,\n"
+ " level : u32,\n"
+ " offset : vec2<i32>) -> f32",
+ TextureKind::kDepth,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::k2d,
+ TextureDataType::kF32,
+ "textureSampleLevel",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ using i32 = ast::Builder::i32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec2<f32>(1.f, 2.f), // coords
+ 3u, // level
+ b->vec2<i32>(4, 5)); // offset
+ },
+ },
+ {
+ ValidTextureOverload::kSampleLevelDepth2dArrayF32,
+ "textureSampleLevel(t : texture_depth_2d_array,\n"
+ " s : sampler,\n"
+ " coords : vec2<f32>,\n"
+ " array_index : u32,\n"
+ " level : u32) -> f32",
+ TextureKind::kDepth,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::k2dArray,
+ TextureDataType::kF32,
+ "textureSampleLevel",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec2<f32>(1.f, 2.f), // coords
+ 3u, // array_index
+ 4u); // level
+ },
+ },
+ {
+ ValidTextureOverload::kSampleLevelDepth2dArrayOffsetF32,
+ "textureSampleLevel(t : texture_depth_2d_array,\n"
+ " s : sampler,\n"
+ " coords : vec2<f32>,\n"
+ " array_index : u32,\n"
+ " level : u32,\n"
+ " offset : vec2<i32>) -> f32",
+ TextureKind::kDepth,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::k2dArray,
+ TextureDataType::kF32,
+ "textureSampleLevel",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ using i32 = ast::Builder::i32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec2<f32>(1.f, 2.f), // coords
+ 3u, // array_index
+ 4u, // level
+ b->vec2<i32>(5, 6)); // offset
+ },
+ },
+ {
+ ValidTextureOverload::kSampleLevelDepthCubeF32,
+ "textureSampleLevel(t : texture_depth_cube,\n"
+ " s : sampler,\n"
+ " coords : vec3<f32>,\n"
+ " level : u32) -> f32",
+ TextureKind::kDepth,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::kCube,
+ TextureDataType::kF32,
+ "textureSampleLevel",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec3<f32>(1.f, 2.f, 3.f), // coords
+ 4u); // level
+ },
+ },
+ {
+ ValidTextureOverload::kSampleLevelDepthCubeArrayF32,
+ "textureSampleLevel(t : texture_depth_cube_array,\n"
+ " s : sampler,\n"
+ " coords : vec3<f32>,\n"
+ " array_index : u32,\n"
+ " level : u32) -> f32",
+ TextureKind::kDepth,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::kCubeArray,
+ TextureDataType::kF32,
+ "textureSampleLevel",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec3<f32>(1.f, 2.f, 3.f), // coords
+ 4u, // array_index
+ 5u); // level
+ },
+ },
+ {
+ ValidTextureOverload::kSampleGrad2dF32,
+ "textureSampleGrad(t : texture_2d<f32>,\n"
+ " s : sampler,\n"
+ " coords : vec2<f32>\n"
+ " ddx : vec2<f32>,\n"
+ " ddy : vec2<f32>) -> vec4<f32>",
+ TextureKind::kRegular,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::k2d,
+ TextureDataType::kF32,
+ "textureSampleGrad",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec2<f32>(1.0f, 2.0f), // coords
+ b->vec2<f32>(3.0f, 4.0f), // ddx
+ b->vec2<f32>(5.0f, 6.0f)); // ddy
+ },
+ },
+ {
+ ValidTextureOverload::kSampleGrad2dOffsetF32,
+ "textureSampleGrad(t : texture_2d<f32>,\n"
+ " s : sampler,\n"
+ " coords : vec2<f32>,\n"
+ " ddx : vec2<f32>,\n"
+ " ddy : vec2<f32>,\n"
+ " offset : vec2<i32>) -> vec4<f32>",
+ TextureKind::kRegular,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::k2d,
+ TextureDataType::kF32,
+ "textureSampleGrad",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ using i32 = ast::Builder::i32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec2<f32>(1.f, 2.f), // coords
+ b->vec2<f32>(3.f, 4.f), // ddx
+ b->vec2<f32>(5.f, 6.f), // ddy
+ b->vec2<i32>(7, 8)); // offset
+ },
+ },
+ {
+ ValidTextureOverload::kSampleGrad2dArrayF32,
+ "textureSampleGrad(t : texture_2d_array<f32>,\n"
+ " s : sampler,\n"
+ " coords : vec2<f32>,\n"
+ " array_index : u32,\n"
+ " ddx : vec2<f32>,\n"
+ " ddy : vec2<f32>) -> vec4<f32>",
+ TextureKind::kRegular,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::k2dArray,
+ TextureDataType::kF32,
+ "textureSampleGrad",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec2<f32>(1.f, 2.f), // coords
+ 3u, // array_index
+ b->vec2<f32>(4.f, 5.f), // ddx
+ b->vec2<f32>(6.f, 7.f)); // ddy
+ },
+ },
+ {
+ ValidTextureOverload::kSampleGrad2dArrayOffsetF32,
+ "textureSampleGrad(t : texture_2d_array<f32>,\n"
+ " s : sampler,\n"
+ " coords : vec2<f32>,\n"
+ " array_index : u32,\n"
+ " ddx : vec2<f32>,\n"
+ " ddy : vec2<f32>,\n"
+ " offset : vec2<i32>) -> vec4<f32>",
+ TextureKind::kRegular,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::k2dArray,
+ TextureDataType::kF32,
+ "textureSampleGrad",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ using i32 = ast::Builder::i32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec2<f32>(1.f, 2.f), // coords
+ 3u, // array_index
+ b->vec2<f32>(4.f, 5.f), // ddx
+ b->vec2<f32>(6.f, 7.f), // ddy
+ b->vec2<i32>(8, 9)); // offset
+ },
+ },
+ {
+ ValidTextureOverload::kSampleGrad3dF32,
+ "textureSampleGrad(t : texture_3d<f32>,\n"
+ " s : sampler,\n"
+ " coords : vec3<f32>,\n"
+ " ddx : vec3<f32>,\n"
+ " ddy : vec3<f32>) -> vec4<f32>",
+ TextureKind::kRegular,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::k3d,
+ TextureDataType::kF32,
+ "textureSampleGrad",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec3<f32>(1.f, 2.f, 3.f), // coords
+ b->vec3<f32>(4.f, 5.f, 6.f), // ddx
+ b->vec3<f32>(7.f, 8.f, 9.f)); // ddy
+ },
+ },
+ {
+ ValidTextureOverload::kSampleGrad3dOffsetF32,
+ "textureSampleGrad(t : texture_3d<f32>,\n"
+ " s : sampler,\n"
+ " coords : vec3<f32>,\n"
+ " ddx : vec3<f32>,\n"
+ " ddy : vec3<f32>,\n"
+ " offset : vec3<i32>) -> vec4<f32>",
+ TextureKind::kRegular,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::k3d,
+ TextureDataType::kF32,
+ "textureSampleGrad",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ using i32 = ast::Builder::i32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec3<f32>(1.f, 2.f, 3.f), // coords
+ b->vec3<f32>(4.f, 5.f, 6.f), // ddx
+ b->vec3<f32>(7.f, 8.f, 9.f), // ddy
+ b->vec3<i32>(10, 11, 12)); // offset
+ },
+ },
+ {
+ ValidTextureOverload::kSampleGradCubeF32,
+ "textureSampleGrad(t : texture_cube<f32>,\n"
+ " s : sampler,\n"
+ " coords : vec3<f32>,\n"
+ " ddx : vec3<f32>,\n"
+ " ddy : vec3<f32>) -> vec4<f32>",
+ TextureKind::kRegular,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::kCube,
+ TextureDataType::kF32,
+ "textureSampleGrad",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec3<f32>(1.f, 2.f, 3.f), // coords
+ b->vec3<f32>(4.f, 5.f, 6.f), // ddx
+ b->vec3<f32>(7.f, 8.f, 9.f)); // ddy
+ },
+ },
+ {
+ ValidTextureOverload::kSampleGradCubeArrayF32,
+ "textureSampleGrad(t : texture_cube_array<f32>,\n"
+ " s : sampler,\n"
+ " coords : vec3<f32>,\n"
+ " array_index : u32,\n"
+ " ddx : vec3<f32>,\n"
+ " ddy : vec3<f32>) -> vec4<f32>",
+ TextureKind::kRegular,
+ ast::type::SamplerKind::kSampler,
+ ast::type::TextureDimension::kCubeArray,
+ TextureDataType::kF32,
+ "textureSampleGrad",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec3<f32>(1.f, 2.f, 3.f), // coords
+ 4u, // array_index
+ b->vec3<f32>(5.f, 6.f, 7.f), // ddx
+ b->vec3<f32>(8.f, 9.f, 10.f)); // ddy
+ },
+ },
+ {
+ ValidTextureOverload::kSampleGradDepth2dF32,
+ "textureSampleCompare(t : texture_depth_2d,\n"
+ " s : sampler_comparison,\n"
+ " coords : vec2<f32>,\n"
+ " depth_ref : f32) -> f32",
+ TextureKind::kDepth,
+ ast::type::SamplerKind::kComparisonSampler,
+ ast::type::TextureDimension::k2d,
+ TextureDataType::kF32,
+ "textureSampleCompare",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec2<f32>(1.f, 2.f), // coords
+ 3.f); // depth_ref
+ },
+ },
+ {
+ ValidTextureOverload::kSampleGradDepth2dOffsetF32,
+ "textureSampleCompare(t : texture_depth_2d,\n"
+ " s : sampler_comparison,\n"
+ " coords : vec2<f32>,\n"
+ " depth_ref : f32,\n"
+ " offset : vec2<i32>) -> f32",
+ TextureKind::kDepth,
+ ast::type::SamplerKind::kComparisonSampler,
+ ast::type::TextureDimension::k2d,
+ TextureDataType::kF32,
+ "textureSampleCompare",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ using i32 = ast::Builder::i32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec2<f32>(1.f, 2.f), // coords
+ 3.f, // depth_ref
+ b->vec2<i32>(4, 5)); // offset
+ },
+ },
+ {
+ ValidTextureOverload::kSampleGradDepth2dArrayF32,
+ "textureSampleCompare(t : texture_depth_2d_array,\n"
+ " s : sampler_comparison,\n"
+ " coords : vec2<f32>,\n"
+ " array_index : u32,\n"
+ " depth_ref : f32) -> f32",
+ TextureKind::kDepth,
+ ast::type::SamplerKind::kComparisonSampler,
+ ast::type::TextureDimension::k2dArray,
+ TextureDataType::kF32,
+ "textureSampleCompare",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec2<f32>(1.f, 2.f), // coords
+ 4u, // array_index
+ 3.f); // depth_ref
+ },
+ },
+ {
+ ValidTextureOverload::kSampleGradDepth2dArrayOffsetF32,
+ "textureSampleCompare(t : texture_depth_2d_array,\n"
+ " s : sampler_comparison,\n"
+ " coords : vec2<f32>,\n"
+ " array_index : u32,\n"
+ " depth_ref : f32,\n"
+ " offset : vec2<i32>) -> f32",
+ TextureKind::kDepth,
+ ast::type::SamplerKind::kComparisonSampler,
+ ast::type::TextureDimension::k2dArray,
+ TextureDataType::kF32,
+ "textureSampleCompare",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ using i32 = ast::Builder::i32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec2<f32>(1.f, 2.f), // coords
+ 4u, // array_index
+ 3.f, // depth_ref
+ b->vec2<i32>(5, 6)); // offset
+ },
+ },
+ {
+ ValidTextureOverload::kSampleGradDepthCubeF32,
+ "textureSampleCompare(t : texture_depth_cube,\n"
+ " s : sampler_comparison,\n"
+ " coords : vec3<f32>,\n"
+ " depth_ref : f32) -> f32",
+ TextureKind::kDepth,
+ ast::type::SamplerKind::kComparisonSampler,
+ ast::type::TextureDimension::kCube,
+ TextureDataType::kF32,
+ "textureSampleCompare",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec3<f32>(1.f, 2.f, 3.f), // coords
+ 4.f); // depth_ref
+ },
+ },
+ {
+ ValidTextureOverload::kSampleGradDepthCubeArrayF32,
+ "textureSampleCompare(t : texture_depth_cube_array,\n"
+ " s : sampler_comparison,\n"
+ " coords : vec3<f32>,\n"
+ " array_index : u32,\n"
+ " depth_ref : f32) -> f32",
+ TextureKind::kDepth,
+ ast::type::SamplerKind::kComparisonSampler,
+ ast::type::TextureDimension::kCubeArray,
+ TextureDataType::kF32,
+ "textureSampleCompare",
+ [](ast::Builder* b) {
+ using f32 = ast::Builder::f32;
+ return b->ExprList("texture", // t
+ "sampler", // s
+ b->vec3<f32>(1.f, 2.f, 3.f), // coords
+ 4u, // array_index
+ 5.f); // depth_ref
+ },
+ }};
+}
+
+} // namespace test
+} // namespace intrinsic
+} // namespace ast
+} // namespace tint
diff --git a/src/ast/intrinsic_texture_helper_test.h b/src/ast/intrinsic_texture_helper_test.h
new file mode 100644
index 0000000..5e7da8a
--- /dev/null
+++ b/src/ast/intrinsic_texture_helper_test.h
@@ -0,0 +1,171 @@
+// Copyright 2020 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_AST_INTRINSIC_TEXTURE_HELPER_TEST_H_
+#define SRC_AST_INTRINSIC_TEXTURE_HELPER_TEST_H_
+
+#include <functional>
+#include <vector>
+
+#include "src/ast/builder.h"
+#include "src/ast/type/sampler_type.h"
+#include "src/ast/type/texture_type.h"
+
+namespace tint {
+namespace ast {
+namespace intrinsic {
+namespace test {
+
+enum class TextureKind { kRegular, kDepth };
+
+inline std::ostream& operator<<(std::ostream& out, const TextureKind& kind) {
+ switch (kind) {
+ case TextureKind::kRegular:
+ out << "regular";
+ break;
+ case TextureKind::kDepth:
+ out << "depth";
+ break;
+ }
+ return out;
+}
+
+enum class TextureDataType { kF32, kU32, kI32 };
+
+inline std::ostream& operator<<(std::ostream& out, const TextureDataType& ty) {
+ switch (ty) {
+ case TextureDataType::kF32:
+ out << "f32";
+ break;
+ case TextureDataType::kU32:
+ out << "u32";
+ break;
+ case TextureDataType::kI32:
+ out << "i32";
+ break;
+ }
+ return out;
+}
+
+enum class ValidTextureOverload {
+ kSample1dF32,
+ kSample1dArrayF32,
+ kSample2dF32,
+ kSample2dOffsetF32,
+ kSample2dArrayF32,
+ kSample2dArrayOffsetF32,
+ kSample3dF32,
+ kSample3dOffsetF32,
+ kSampleCubeF32,
+ kSampleCubeArrayF32,
+ kSampleDepth2dF32,
+ kSampleDepth2dOffsetF32,
+ kSampleDepth2dArrayF32,
+ kSampleDepth2dArrayOffsetF32,
+ kSampleDepthCubeF32,
+ kSampleDepthCubeArrayF32,
+ kSampleBias2dF32,
+ kSampleBias2dOffsetF32,
+ kSampleBias2dArrayF32,
+ kSampleBias2dArrayOffsetF32,
+ kSampleBias3dF32,
+ kSampleBias3dOffsetF32,
+ kSampleBiasCubeF32,
+ kSampleBiasCubeArrayF32,
+ kSampleLevel2dF32,
+ kSampleLevel2dOffsetF32,
+ kSampleLevel2dArrayF32,
+ kSampleLevel2dArrayOffsetF32,
+ kSampleLevel3dF32,
+ kSampleLevel3dOffsetF32,
+ kSampleLevelCubeF32,
+ kSampleLevelCubeArrayF32,
+ kSampleLevelDepth2dF32,
+ kSampleLevelDepth2dOffsetF32,
+ kSampleLevelDepth2dArrayF32,
+ kSampleLevelDepth2dArrayOffsetF32,
+ kSampleLevelDepthCubeF32,
+ kSampleLevelDepthCubeArrayF32,
+ kSampleGrad2dF32,
+ kSampleGrad2dOffsetF32,
+ kSampleGrad2dArrayF32,
+ kSampleGrad2dArrayOffsetF32,
+ kSampleGrad3dF32,
+ kSampleGrad3dOffsetF32,
+ kSampleGradCubeF32,
+ kSampleGradCubeArrayF32,
+ kSampleGradDepth2dF32,
+ kSampleGradDepth2dOffsetF32,
+ kSampleGradDepth2dArrayF32,
+ kSampleGradDepth2dArrayOffsetF32,
+ kSampleGradDepthCubeF32,
+ kSampleGradDepthCubeArrayF32,
+};
+
+/// Describes a texture intrinsic overload
+struct TextureOverloadCase {
+ /// Constructor
+ TextureOverloadCase();
+ /// Constructor
+ TextureOverloadCase(ValidTextureOverload,
+ const char*,
+ TextureKind,
+ ast::type::SamplerKind,
+ ast::type::TextureDimension,
+ TextureDataType,
+ const char*,
+ std::function<ast::ExpressionList(ast::Builder*)>);
+ /// Copy constructor
+ TextureOverloadCase(const TextureOverloadCase&);
+ /// Destructor
+ ~TextureOverloadCase();
+
+ /// @return a vector containing a large number of valid texture overloads
+ static std::vector<TextureOverloadCase> ValidCases();
+
+ /// The enumerator for this overload
+ ValidTextureOverload overload;
+ /// A human readable description of the overload
+ const char* description;
+ /// The texture kind for the texture parameter
+ TextureKind texture_kind;
+ /// The sampler kind for the sampler parameter
+ ast::type::SamplerKind sampler_kind;
+ /// The dimensions of the texture parameter
+ ast::type::TextureDimension texture_dimension;
+ /// The data type of the texture parameter
+ TextureDataType texture_data_type;
+ /// Name of the function. e.g. `textureSample`, `textureSampleGrad`, etc
+ const char* function;
+ /// A function that builds the AST arguments for the overload
+ std::function<ast::ExpressionList(ast::Builder*)> args;
+};
+
+inline std::ostream& operator<<(std::ostream& out,
+ const TextureOverloadCase& data) {
+ out << "TextureOverloadCase" << static_cast<int>(data.overload) << "\n";
+ out << data.description << "\n";
+ out << "texture_kind: " << data.texture_kind << "\n";
+ out << "sampler_kind: " << data.sampler_kind << "\n";
+ out << "texture_dimension: " << data.texture_dimension << "\n";
+ out << "texture_data_type: " << data.texture_data_type << "\n";
+ return out;
+}
+
+} // namespace test
+} // namespace intrinsic
+} // namespace ast
+} // namespace tint
+
+#endif // SRC_AST_INTRINSIC_TEXTURE_HELPER_TEST_H_
diff --git a/src/inspector/inspector_test.cc b/src/inspector/inspector_test.cc
index d1d39e6..eb2a3a0 100644
--- a/src/inspector/inspector_test.cc
+++ b/src/inspector/inspector_test.cc
@@ -529,6 +529,44 @@
body);
}
+ /// Generates a function that references a specific sampler variable
+ /// @param func_name name of the function created
+ /// @param texture_name name of the texture to be sampled
+ /// @param sampler_name name of the sampler to use
+ /// @param coords_name name of the coords variable to use
+ /// @param array_index name of the array index variable to use
+ /// @returns a function that references all of the values specified
+ ast::Function* MakeSamplerReferenceBodyFunction(
+ const std::string& func_name,
+ const std::string& texture_name,
+ const std::string& sampler_name,
+ const std::string& coords_name,
+ const std::string& array_index,
+ ast::type::Type* base_type) {
+ std::string result_name = "sampler_result";
+
+ auto* body = create<ast::BlockStatement>();
+
+ auto* call_result = create<ast::Variable>(
+ "sampler_result", ast::StorageClass::kFunction, vec_type(base_type, 4));
+ body->append(create<ast::VariableDeclStatement>(call_result));
+
+ ast::ExpressionList call_params;
+ call_params.push_back(create<ast::IdentifierExpression>(texture_name));
+ call_params.push_back(create<ast::IdentifierExpression>(sampler_name));
+ call_params.push_back(create<ast::IdentifierExpression>(coords_name));
+ call_params.push_back(create<ast::IdentifierExpression>(array_index));
+ auto* call_expr = create<ast::CallExpression>(
+ create<ast::IdentifierExpression>("textureSample"), call_params);
+
+ body->append(create<ast::AssignmentStatement>(
+ create<ast::IdentifierExpression>("sampler_result"), call_expr));
+ body->append(create<ast::ReturnStatement>());
+
+ return create<ast::Function>(func_name, ast::VariableList(), void_type(),
+ body);
+ }
+
/// Generates a function that references a specific comparison sampler
/// variable.
/// @param func_name name of the function created
@@ -683,6 +721,9 @@
public testing::Test {};
class InspectorGetSampledTextureResourceBindingsTest : public InspectorHelper,
public testing::Test {};
+class InspectorGetSampledArrayTextureResourceBindingsTest
+ : public InspectorHelper,
+ public testing::Test {};
struct GetSampledTextureTestParams {
ast::type::TextureDimension type_dim;
inspector::ResourceBinding::TextureDimension inspector_dim;
@@ -691,11 +732,19 @@
class InspectorGetSampledTextureResourceBindingsTestWithParam
: public InspectorHelper,
public testing::TestWithParam<GetSampledTextureTestParams> {};
-
+class InspectorGetSampledArrayTextureResourceBindingsTestWithParam
+ : public InspectorHelper,
+ public testing::TestWithParam<GetSampledTextureTestParams> {};
class InspectorGetMultisampledTextureResourceBindingsTest
: public InspectorHelper,
public testing::Test {};
+class InspectorGetMultisampledArrayTextureResourceBindingsTest
+ : public InspectorHelper,
+ public testing::Test {};
typedef GetSampledTextureTestParams GetMultisampledTextureTestParams;
+class InspectorGetMultisampledArrayTextureResourceBindingsTestWithParam
+ : public InspectorHelper,
+ public testing::TestWithParam<GetMultisampledTextureTestParams> {};
class InspectorGetMultisampledTextureResourceBindingsTestWithParam
: public InspectorHelper,
public testing::TestWithParam<GetMultisampledTextureTestParams> {};
@@ -2009,18 +2058,6 @@
inspector::ResourceBinding::TextureDimension::k1d,
inspector::ResourceBinding::SampledKind::kUInt},
GetSampledTextureTestParams{
- ast::type::TextureDimension::k1dArray,
- inspector::ResourceBinding::TextureDimension::k1dArray,
- inspector::ResourceBinding::SampledKind::kFloat},
- GetSampledTextureTestParams{
- ast::type::TextureDimension::k1dArray,
- inspector::ResourceBinding::TextureDimension::k1dArray,
- inspector::ResourceBinding::SampledKind::kSInt},
- GetSampledTextureTestParams{
- ast::type::TextureDimension::k1dArray,
- inspector::ResourceBinding::TextureDimension::k1dArray,
- inspector::ResourceBinding::SampledKind::kUInt},
- GetSampledTextureTestParams{
ast::type::TextureDimension::k2d,
inspector::ResourceBinding::TextureDimension::k2d,
inspector::ResourceBinding::SampledKind::kFloat},
@@ -2033,18 +2070,6 @@
inspector::ResourceBinding::TextureDimension::k2d,
inspector::ResourceBinding::SampledKind::kUInt},
GetSampledTextureTestParams{
- ast::type::TextureDimension::k2dArray,
- inspector::ResourceBinding::TextureDimension::k2dArray,
- inspector::ResourceBinding::SampledKind::kFloat},
- GetSampledTextureTestParams{
- ast::type::TextureDimension::k2dArray,
- inspector::ResourceBinding::TextureDimension::k2dArray,
- inspector::ResourceBinding::SampledKind::kSInt},
- GetSampledTextureTestParams{
- ast::type::TextureDimension::k2dArray,
- inspector::ResourceBinding::TextureDimension::k2dArray,
- inspector::ResourceBinding::SampledKind::kUInt},
- GetSampledTextureTestParams{
ast::type::TextureDimension::k3d,
inspector::ResourceBinding::TextureDimension::k3d,
inspector::ResourceBinding::SampledKind::kFloat},
@@ -2067,6 +2092,65 @@
GetSampledTextureTestParams{
ast::type::TextureDimension::kCube,
inspector::ResourceBinding::TextureDimension::kCube,
+ inspector::ResourceBinding::SampledKind::kUInt}));
+
+TEST_P(InspectorGetSampledArrayTextureResourceBindingsTestWithParam,
+ textureSample) {
+ auto sampled_texture_type = MakeSampledTextureType(
+ GetParam().type_dim, GetBaseType(GetParam().sampled_kind));
+ AddSampledTexture("foo_texture", sampled_texture_type.get(), 0, 0);
+ AddSampler("foo_sampler", 0, 1);
+ auto* coord_type =
+ GetCoordsType(GetParam().type_dim, GetParam().sampled_kind);
+ AddGlobalVariable("foo_coords", coord_type);
+ AddGlobalVariable("foo_array_index", u32_type());
+
+ auto* func = MakeSamplerReferenceBodyFunction(
+ "ep", "foo_texture", "foo_sampler", "foo_coords", "foo_array_index",
+ GetBaseType(GetParam().sampled_kind));
+ func->add_decoration(
+ create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+ mod()->AddFunction(func);
+
+ ASSERT_TRUE(td()->Determine()) << td()->error();
+
+ auto result = inspector()->GetSampledTextureResourceBindings("ep");
+ ASSERT_FALSE(inspector()->has_error()) << inspector()->error();
+
+ ASSERT_EQ(1u, result.size());
+ EXPECT_EQ(0u, result[0].bind_group);
+ EXPECT_EQ(0u, result[0].binding);
+ EXPECT_EQ(GetParam().inspector_dim, result[0].dim);
+ EXPECT_EQ(GetParam().sampled_kind, result[0].sampled_kind);
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ InspectorGetSampledArrayTextureResourceBindingsTest,
+ InspectorGetSampledArrayTextureResourceBindingsTestWithParam,
+ testing::Values(
+ GetSampledTextureTestParams{
+ ast::type::TextureDimension::k1dArray,
+ inspector::ResourceBinding::TextureDimension::k1dArray,
+ inspector::ResourceBinding::SampledKind::kFloat},
+ GetSampledTextureTestParams{
+ ast::type::TextureDimension::k1dArray,
+ inspector::ResourceBinding::TextureDimension::k1dArray,
+ inspector::ResourceBinding::SampledKind::kSInt},
+ GetSampledTextureTestParams{
+ ast::type::TextureDimension::k1dArray,
+ inspector::ResourceBinding::TextureDimension::k1dArray,
+ inspector::ResourceBinding::SampledKind::kUInt},
+ GetSampledTextureTestParams{
+ ast::type::TextureDimension::k2dArray,
+ inspector::ResourceBinding::TextureDimension::k2dArray,
+ inspector::ResourceBinding::SampledKind::kFloat},
+ GetSampledTextureTestParams{
+ ast::type::TextureDimension::k2dArray,
+ inspector::ResourceBinding::TextureDimension::k2dArray,
+ inspector::ResourceBinding::SampledKind::kSInt},
+ GetSampledTextureTestParams{
+ ast::type::TextureDimension::k2dArray,
+ inspector::ResourceBinding::TextureDimension::k2dArray,
inspector::ResourceBinding::SampledKind::kUInt},
GetSampledTextureTestParams{
ast::type::TextureDimension::kCubeArray,
@@ -2081,18 +2165,6 @@
inspector::ResourceBinding::TextureDimension::kCubeArray,
inspector::ResourceBinding::SampledKind::kUInt}));
-TEST_F(InspectorGetMultisampledTextureResourceBindingsTest, Empty) {
- auto* foo = MakeEmptyBodyFunction("foo");
- foo->add_decoration(
- create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
- mod()->AddFunction(foo);
-
- auto result = inspector()->GetSampledTextureResourceBindings("foo");
- ASSERT_FALSE(inspector()->has_error()) << inspector()->error();
-
- EXPECT_EQ(0u, result.size());
-}
-
TEST_P(InspectorGetMultisampledTextureResourceBindingsTestWithParam,
textureSample) {
auto multisampled_texture_type = MakeMultisampledTextureType(
@@ -2139,18 +2211,6 @@
inspector::ResourceBinding::TextureDimension::k1d,
inspector::ResourceBinding::SampledKind::kUInt},
GetMultisampledTextureTestParams{
- ast::type::TextureDimension::k1dArray,
- inspector::ResourceBinding::TextureDimension::k1dArray,
- inspector::ResourceBinding::SampledKind::kFloat},
- GetMultisampledTextureTestParams{
- ast::type::TextureDimension::k1dArray,
- inspector::ResourceBinding::TextureDimension::k1dArray,
- inspector::ResourceBinding::SampledKind::kSInt},
- GetMultisampledTextureTestParams{
- ast::type::TextureDimension::k1dArray,
- inspector::ResourceBinding::TextureDimension::k1dArray,
- inspector::ResourceBinding::SampledKind::kUInt},
- GetMultisampledTextureTestParams{
ast::type::TextureDimension::k2d,
inspector::ResourceBinding::TextureDimension::k2d,
inspector::ResourceBinding::SampledKind::kFloat},
@@ -2161,6 +2221,65 @@
GetMultisampledTextureTestParams{
ast::type::TextureDimension::k2d,
inspector::ResourceBinding::TextureDimension::k2d,
+ inspector::ResourceBinding::SampledKind::kUInt}));
+
+TEST_F(InspectorGetMultisampledArrayTextureResourceBindingsTest, Empty) {
+ auto* foo = MakeEmptyBodyFunction("foo");
+ foo->add_decoration(
+ create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+ mod()->AddFunction(foo);
+
+ auto result = inspector()->GetSampledTextureResourceBindings("foo");
+ ASSERT_FALSE(inspector()->has_error()) << inspector()->error();
+
+ EXPECT_EQ(0u, result.size());
+}
+
+TEST_P(InspectorGetMultisampledArrayTextureResourceBindingsTestWithParam,
+ textureSample) {
+ auto multisampled_texture_type = MakeMultisampledTextureType(
+ GetParam().type_dim, GetBaseType(GetParam().sampled_kind));
+ AddMultisampledTexture("foo_texture", multisampled_texture_type.get(), 0, 0);
+ AddSampler("foo_sampler", 0, 1);
+ auto* coord_type =
+ GetCoordsType(GetParam().type_dim, GetParam().sampled_kind);
+ AddGlobalVariable("foo_coords", coord_type);
+ AddGlobalVariable("foo_array_index", u32_type());
+
+ auto* func = MakeSamplerReferenceBodyFunction(
+ "ep", "foo_texture", "foo_sampler", "foo_coords", "foo_array_index",
+ GetBaseType(GetParam().sampled_kind));
+ func->add_decoration(
+ create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+ mod()->AddFunction(func);
+
+ ASSERT_TRUE(td()->Determine()) << td()->error();
+
+ auto result = inspector()->GetMultisampledTextureResourceBindings("ep");
+ ASSERT_FALSE(inspector()->has_error()) << inspector()->error();
+
+ ASSERT_EQ(1u, result.size());
+ EXPECT_EQ(0u, result[0].bind_group);
+ EXPECT_EQ(0u, result[0].binding);
+ EXPECT_EQ(GetParam().inspector_dim, result[0].dim);
+ EXPECT_EQ(GetParam().sampled_kind, result[0].sampled_kind);
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ InspectorGetMultisampledArrayTextureResourceBindingsTest,
+ InspectorGetMultisampledArrayTextureResourceBindingsTestWithParam,
+ testing::Values(
+ GetMultisampledTextureTestParams{
+ ast::type::TextureDimension::k1dArray,
+ inspector::ResourceBinding::TextureDimension::k1dArray,
+ inspector::ResourceBinding::SampledKind::kFloat},
+ GetMultisampledTextureTestParams{
+ ast::type::TextureDimension::k1dArray,
+ inspector::ResourceBinding::TextureDimension::k1dArray,
+ inspector::ResourceBinding::SampledKind::kSInt},
+ GetMultisampledTextureTestParams{
+ ast::type::TextureDimension::k1dArray,
+ inspector::ResourceBinding::TextureDimension::k1dArray,
inspector::ResourceBinding::SampledKind::kUInt},
GetMultisampledTextureTestParams{
ast::type::TextureDimension::k2dArray,
diff --git a/src/type_determiner.cc b/src/type_determiner.cc
index a4d2382..6208fef 100644
--- a/src/type_determiner.cc
+++ b/src/type_determiner.cc
@@ -552,26 +552,7 @@
return true;
}
if (ast::intrinsic::IsTextureIntrinsic(ident->intrinsic())) {
- // TODO(dsinclair): Remove the LOD param from textureLoad on storage
- // textures when https://github.com/gpuweb/gpuweb/pull/1032 gets merged.
- uint32_t num_of_params =
- (ident->intrinsic() == ast::Intrinsic::kTextureLoad ||
- ident->intrinsic() == ast::Intrinsic::kTextureSample)
- ? 3
- : 4;
- if (expr->params().size() != num_of_params) {
- set_error(expr->source(),
- "incorrect number of parameters for " + ident->name() +
- ", got " + std::to_string(expr->params().size()) +
- " and expected " + std::to_string(num_of_params));
- return false;
- }
-
- if (ident->intrinsic() == ast::Intrinsic::kTextureSampleCompare) {
- expr->func()->set_result_type(
- ctx_.type_mgr().Get(std::make_unique<ast::type::F32Type>()));
- return true;
- }
+ ast::intrinsic::TextureSignature::Parameters param;
auto* texture_param = expr->params()[0];
if (!texture_param->result_type()->UnwrapPtrIfNeeded()->IsTexture()) {
@@ -581,6 +562,115 @@
ast::type::TextureType* texture =
texture_param->result_type()->UnwrapPtrIfNeeded()->AsTexture();
+ bool is_array = false;
+ switch (texture->dim()) {
+ case ast::type::TextureDimension::k1dArray:
+ case ast::type::TextureDimension::k2dArray:
+ case ast::type::TextureDimension::kCubeArray:
+ is_array = true;
+ break;
+ default:
+ break;
+ }
+ switch (ident->intrinsic()) {
+ case ast::Intrinsic::kTextureLoad:
+ param.idx.texture = param.count++;
+ param.idx.coords = param.count++;
+ if (is_array) {
+ param.idx.array_index = param.count++;
+ }
+
+ // TODO(dsinclair): Remove the LOD param from textureLoad on storage
+ // textures when https://github.com/gpuweb/gpuweb/pull/1032 gets merged.
+ if (expr->params().size() > param.count) {
+ param.idx.level = param.count++;
+ }
+
+ break;
+ case ast::Intrinsic::kTextureSample:
+ param.idx.texture = param.count++;
+ param.idx.sampler = param.count++;
+ param.idx.coords = param.count++;
+ if (is_array) {
+ param.idx.array_index = param.count++;
+ }
+ if (expr->params().size() > param.count) {
+ param.idx.offset = param.count++;
+ }
+ break;
+ case ast::Intrinsic::kTextureSampleBias:
+ param.idx.texture = param.count++;
+ param.idx.sampler = param.count++;
+ param.idx.coords = param.count++;
+ if (is_array) {
+ param.idx.array_index = param.count++;
+ }
+ param.idx.bias = param.count++;
+ if (expr->params().size() > param.count) {
+ param.idx.offset = param.count++;
+ }
+ break;
+ case ast::Intrinsic::kTextureSampleLevel:
+ param.idx.texture = param.count++;
+ param.idx.sampler = param.count++;
+ param.idx.coords = param.count++;
+ if (is_array) {
+ param.idx.array_index = param.count++;
+ }
+ param.idx.level = param.count++;
+ if (expr->params().size() > param.count) {
+ param.idx.offset = param.count++;
+ }
+ break;
+ case ast::Intrinsic::kTextureSampleCompare:
+ param.idx.texture = param.count++;
+ param.idx.sampler = param.count++;
+ param.idx.coords = param.count++;
+ if (is_array) {
+ param.idx.array_index = param.count++;
+ }
+ param.idx.depth_ref = param.count++;
+ if (expr->params().size() > param.count) {
+ param.idx.offset = param.count++;
+ }
+ break;
+ case ast::Intrinsic::kTextureSampleGrad:
+ param.idx.texture = param.count++;
+ param.idx.sampler = param.count++;
+ param.idx.coords = param.count++;
+ if (is_array) {
+ param.idx.array_index = param.count++;
+ }
+ param.idx.ddx = param.count++;
+ param.idx.ddy = param.count++;
+ if (expr->params().size() > param.count) {
+ param.idx.offset = param.count++;
+ }
+ break;
+ default:
+ set_error(expr->source(),
+ "Internal compiler error: Unreachable intrinsic " +
+ std::to_string(static_cast<int>(ident->intrinsic())));
+ return false;
+ }
+
+ if (expr->params().size() != param.count) {
+ set_error(expr->source(),
+ "incorrect number of parameters for " + ident->name() +
+ ", got " + std::to_string(expr->params().size()) +
+ " and expected " + std::to_string(param.count));
+ return false;
+ }
+
+ ident->set_intrinsic_signature(
+ std::make_unique<ast::intrinsic::TextureSignature>(param));
+
+ if (texture->IsDepth()) {
+ expr->func()->set_result_type(
+ ctx_.type_mgr().Get(std::make_unique<ast::type::F32Type>()));
+ return true;
+ }
+
if (!texture->IsStorage() &&
!(texture->IsSampled() || texture->IsMultisampled())) {
set_error(expr->source(), "invalid texture for " + ident->name());
@@ -925,6 +1015,8 @@
ident->set_intrinsic(ast::Intrinsic::kTextureSampleBias);
} else if (ident->name() == "textureSampleCompare") {
ident->set_intrinsic(ast::Intrinsic::kTextureSampleCompare);
+ } else if (ident->name() == "textureSampleGrad") {
+ ident->set_intrinsic(ast::Intrinsic::kTextureSampleGrad);
} else if (ident->name() == "textureSampleLevel") {
ident->set_intrinsic(ast::Intrinsic::kTextureSampleLevel);
} else if (ident->name() == "trunc") {
diff --git a/src/type_determiner_test.cc b/src/type_determiner_test.cc
index c12c0d2..66094a2 100644
--- a/src/type_determiner_test.cc
+++ b/src/type_determiner_test.cc
@@ -14,6 +14,7 @@
#include "src/type_determiner.h"
+#include <algorithm>
#include <memory>
#include <utility>
#include <vector>
@@ -26,6 +27,7 @@
#include "src/ast/block_statement.h"
#include "src/ast/bool_literal.h"
#include "src/ast/break_statement.h"
+#include "src/ast/builder.h"
#include "src/ast/call_expression.h"
#include "src/ast/call_statement.h"
#include "src/ast/case_statement.h"
@@ -34,6 +36,7 @@
#include "src/ast/float_literal.h"
#include "src/ast/identifier_expression.h"
#include "src/ast/if_statement.h"
+#include "src/ast/intrinsic_texture_helper_test.h"
#include "src/ast/loop_statement.h"
#include "src/ast/member_accessor_expression.h"
#include "src/ast/pipeline_stage.h"
@@ -79,27 +82,17 @@
void to_str(std::ostream&, size_t) const override {}
};
-class TypeDeterminerHelper {
+class TypeDeterminerHelper : public ast::BuilderWithContextAndModule {
public:
- TypeDeterminerHelper()
- : td_(std::make_unique<TypeDeterminer>(&ctx_, &mod_)) {}
+ TypeDeterminerHelper() : td_(std::make_unique<TypeDeterminer>(ctx, mod)) {}
TypeDeterminer* td() const { return td_.get(); }
- ast::Module* mod() { return &mod_; }
- Context* ctx() { return &ctx_; }
-
- /// Creates a new `ast::Node` owned by the Module. When the Module is
- /// destructed, the `ast::Node` will also be destructed.
- /// @param args the arguments to pass to the type constructor
- /// @returns the node pointer
- template <typename T, typename... ARGS>
- T* create(ARGS&&... args) {
- return mod_.create<T>(std::forward<ARGS>(args)...);
- }
private:
- Context ctx_;
- ast::Module mod_;
+ void OnVariableBuilt(ast::Variable* var) override {
+ td_->RegisterVariableForTesting(var);
+ }
+
std::unique_ptr<TypeDeterminer> td_;
};
@@ -350,7 +343,7 @@
ast::VariableList params;
auto* func = create<ast::Function>("my_func", params, &f32,
create<ast::BlockStatement>());
- mod()->AddFunction(func);
+ mod->AddFunction(func);
// Register the function
EXPECT_TRUE(td()->Determine());
@@ -379,12 +372,12 @@
main_body->append(create<ast::CallStatement>(call_expr));
main_body->append(create<ast::ReturnStatement>());
auto* func_main = create<ast::Function>("main", params0, &f32, main_body);
- mod()->AddFunction(func_main);
+ mod->AddFunction(func_main);
auto* body = create<ast::BlockStatement>();
body->append(create<ast::ReturnStatement>());
auto* func = create<ast::Function>("func", params0, &f32, body);
- mod()->AddFunction(func);
+ mod->AddFunction(func);
EXPECT_FALSE(td()->Determine()) << td()->error();
EXPECT_EQ(td()->error(),
@@ -412,7 +405,7 @@
create<ast::SintLiteral>(&i32, 2)));
auto* init = var->constructor();
- mod()->AddGlobalVariable(var);
+ mod->AddGlobalVariable(var);
EXPECT_TRUE(td()->Determine());
ASSERT_NE(init->result_type(), nullptr);
@@ -436,7 +429,7 @@
create<ast::SintLiteral>(&i32, 2));
auto* var =
create<ast::Variable>("my_var", ast::StorageClass::kFunction, &ary);
- mod()->AddGlobalVariable(var);
+ mod->AddGlobalVariable(var);
// Register the global
EXPECT_TRUE(td()->Determine());
@@ -461,7 +454,7 @@
create<ast::SintLiteral>(&i32, 2));
auto* var =
create<ast::Variable>("my_var", ast::StorageClass::kFunction, &aary);
- mod()->AddGlobalVariable(var);
+ mod->AddGlobalVariable(var);
// Register the global
EXPECT_TRUE(td()->Determine());
@@ -486,7 +479,7 @@
auto* var =
create<ast::Variable>("my_var", ast::StorageClass::kFunction, &ary);
var->set_is_const(true);
- mod()->AddGlobalVariable(var);
+ mod->AddGlobalVariable(var);
// Register the global
EXPECT_TRUE(td()->Determine());
@@ -506,7 +499,7 @@
auto* idx = create<ast::ScalarConstructorExpression>(
create<ast::SintLiteral>(&i32, 2));
auto* var = create<ast::Variable>("my_var", ast::StorageClass::kNone, &mat);
- mod()->AddGlobalVariable(var);
+ mod->AddGlobalVariable(var);
// Register the global
EXPECT_TRUE(td()->Determine());
@@ -532,7 +525,7 @@
auto* idx2 = create<ast::ScalarConstructorExpression>(
create<ast::SintLiteral>(&i32, 1));
auto* var = create<ast::Variable>("my_var", ast::StorageClass::kNone, &mat);
- mod()->AddGlobalVariable(var);
+ mod->AddGlobalVariable(var);
// Register the global
EXPECT_TRUE(td()->Determine());
@@ -558,7 +551,7 @@
auto* idx = create<ast::ScalarConstructorExpression>(
create<ast::SintLiteral>(&i32, 2));
auto* var = create<ast::Variable>("my_var", ast::StorageClass::kNone, &vec);
- mod()->AddGlobalVariable(var);
+ mod->AddGlobalVariable(var);
// Register the global
EXPECT_TRUE(td()->Determine());
@@ -592,7 +585,7 @@
ast::VariableList params;
auto* func = create<ast::Function>("my_func", params, &f32,
create<ast::BlockStatement>());
- mod()->AddFunction(func);
+ mod->AddFunction(func);
// Register the function
EXPECT_TRUE(td()->Determine());
@@ -611,7 +604,7 @@
ast::VariableList params;
auto* func = create<ast::Function>("my_func", params, &f32,
create<ast::BlockStatement>());
- mod()->AddFunction(func);
+ mod->AddFunction(func);
// Register the function
EXPECT_TRUE(td()->Determine());
@@ -695,7 +688,7 @@
TEST_F(TypeDeterminerTest, Expr_Identifier_GlobalVariable) {
ast::type::F32Type f32;
auto* var = create<ast::Variable>("my_var", ast::StorageClass::kNone, &f32);
- mod()->AddGlobalVariable(var);
+ mod->AddGlobalVariable(var);
// Register the global
EXPECT_TRUE(td()->Determine());
@@ -711,7 +704,7 @@
ast::type::F32Type f32;
auto* var = create<ast::Variable>("my_var", ast::StorageClass::kNone, &f32);
var->set_is_const(true);
- mod()->AddGlobalVariable(var);
+ mod->AddGlobalVariable(var);
// Register the global
EXPECT_TRUE(td()->Determine());
@@ -792,7 +785,7 @@
ast::VariableList params;
auto* func = create<ast::Function>("my_func", params, &f32,
create<ast::BlockStatement>());
- mod()->AddFunction(func);
+ mod->AddFunction(func);
// Register the function
EXPECT_TRUE(td()->Determine());
@@ -822,11 +815,11 @@
auto* priv_var =
create<ast::Variable>("priv_var", ast::StorageClass::kPrivate, &f32);
- mod()->AddGlobalVariable(in_var);
- mod()->AddGlobalVariable(out_var);
- mod()->AddGlobalVariable(sb_var);
- mod()->AddGlobalVariable(wg_var);
- mod()->AddGlobalVariable(priv_var);
+ mod->AddGlobalVariable(in_var);
+ mod->AddGlobalVariable(out_var);
+ mod->AddGlobalVariable(sb_var);
+ mod->AddGlobalVariable(wg_var);
+ mod->AddGlobalVariable(priv_var);
ast::VariableList params;
auto* body = create<ast::BlockStatement>();
@@ -844,7 +837,7 @@
create<ast::IdentifierExpression>("priv_var")));
auto* func = create<ast::Function>("my_func", params, &f32, body);
- mod()->AddFunction(func);
+ mod->AddFunction(func);
// Register the function
EXPECT_TRUE(td()->Determine());
@@ -872,11 +865,11 @@
auto* priv_var =
create<ast::Variable>("priv_var", ast::StorageClass::kPrivate, &f32);
- mod()->AddGlobalVariable(in_var);
- mod()->AddGlobalVariable(out_var);
- mod()->AddGlobalVariable(sb_var);
- mod()->AddGlobalVariable(wg_var);
- mod()->AddGlobalVariable(priv_var);
+ mod->AddGlobalVariable(in_var);
+ mod->AddGlobalVariable(out_var);
+ mod->AddGlobalVariable(sb_var);
+ mod->AddGlobalVariable(wg_var);
+ mod->AddGlobalVariable(priv_var);
auto* body = create<ast::BlockStatement>();
body->append(create<ast::AssignmentStatement>(
@@ -894,7 +887,7 @@
ast::VariableList params;
auto* func = create<ast::Function>("my_func", params, &f32, body);
- mod()->AddFunction(func);
+ mod->AddFunction(func);
body = create<ast::BlockStatement>();
body->append(create<ast::AssignmentStatement>(
@@ -903,7 +896,7 @@
ast::ExpressionList{})));
auto* func2 = create<ast::Function>("func", params, &f32, body);
- mod()->AddFunction(func2);
+ mod->AddFunction(func2);
// Register the function
EXPECT_TRUE(td()->Determine());
@@ -933,7 +926,7 @@
ast::VariableList params;
auto* func = create<ast::Function>("my_func", params, &f32, body);
- mod()->AddFunction(func);
+ mod->AddFunction(func);
ast::Variable v("var", ast::StorageClass::kFunction, &f32);
td()->RegisterVariableForTesting(&v);
@@ -959,7 +952,7 @@
auto* var = create<ast::Variable>("my_struct", ast::StorageClass::kNone, &st);
- mod()->AddGlobalVariable(var);
+ mod->AddGlobalVariable(var);
// Register the global
EXPECT_TRUE(td()->Determine());
@@ -993,7 +986,7 @@
auto* var =
create<ast::Variable>("my_struct", ast::StorageClass::kNone, &alias);
- mod()->AddGlobalVariable(var);
+ mod->AddGlobalVariable(var);
// Register the global
EXPECT_TRUE(td()->Determine());
@@ -1015,7 +1008,7 @@
ast::type::VectorType vec3(&f32, 3);
auto* var = create<ast::Variable>("my_vec", ast::StorageClass::kNone, &vec3);
- mod()->AddGlobalVariable(var);
+ mod->AddGlobalVariable(var);
// Register the global
EXPECT_TRUE(td()->Determine());
@@ -1036,7 +1029,7 @@
ast::type::VectorType vec3(&f32, 3);
auto* var = create<ast::Variable>("my_vec", ast::StorageClass::kNone, &vec3);
- mod()->AddGlobalVariable(var);
+ mod->AddGlobalVariable(var);
// Register the global
EXPECT_TRUE(td()->Determine());
@@ -1100,7 +1093,7 @@
ast::type::StructType stA("A", strctA);
auto* var = create<ast::Variable>("c", ast::StorageClass::kNone, &stA);
- mod()->AddGlobalVariable(var);
+ mod->AddGlobalVariable(var);
// Register the global
EXPECT_TRUE(td()->Determine());
@@ -1133,7 +1126,7 @@
ast::type::I32Type i32;
auto* var = create<ast::Variable>("val", ast::StorageClass::kNone, &i32);
- mod()->AddGlobalVariable(var);
+ mod->AddGlobalVariable(var);
// Register the global
ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -1153,7 +1146,7 @@
ast::type::VectorType vec3(&i32, 3);
auto* var = create<ast::Variable>("val", ast::StorageClass::kNone, &vec3);
- mod()->AddGlobalVariable(var);
+ mod->AddGlobalVariable(var);
// Register the global
ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -1187,7 +1180,7 @@
auto* var =
create<ast::Variable>("val", ast::StorageClass::kNone, &bool_type);
- mod()->AddGlobalVariable(var);
+ mod->AddGlobalVariable(var);
// Register the global
ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -1207,7 +1200,7 @@
ast::type::VectorType vec3(&bool_type, 3);
auto* var = create<ast::Variable>("val", ast::StorageClass::kNone, &vec3);
- mod()->AddGlobalVariable(var);
+ mod->AddGlobalVariable(var);
// Register the global
ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -1233,7 +1226,7 @@
ast::type::I32Type i32;
auto* var = create<ast::Variable>("val", ast::StorageClass::kNone, &i32);
- mod()->AddGlobalVariable(var);
+ mod->AddGlobalVariable(var);
// Register the global
ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -1253,7 +1246,7 @@
ast::type::VectorType vec3(&i32, 3);
auto* var = create<ast::Variable>("val", ast::StorageClass::kNone, &vec3);
- mod()->AddGlobalVariable(var);
+ mod->AddGlobalVariable(var);
// Register the global
ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -1280,7 +1273,7 @@
ast::type::I32Type i32;
auto* var = create<ast::Variable>("val", ast::StorageClass::kNone, &i32);
- mod()->AddGlobalVariable(var);
+ mod->AddGlobalVariable(var);
// Register the global
ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -1302,8 +1295,8 @@
create<ast::Variable>("scalar", ast::StorageClass::kNone, &f32);
auto* vector =
create<ast::Variable>("vector", ast::StorageClass::kNone, &vec3);
- mod()->AddGlobalVariable(scalar);
- mod()->AddGlobalVariable(vector);
+ mod->AddGlobalVariable(scalar);
+ mod->AddGlobalVariable(vector);
// Register the global
ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -1327,8 +1320,8 @@
create<ast::Variable>("scalar", ast::StorageClass::kNone, &f32);
auto* vector =
create<ast::Variable>("vector", ast::StorageClass::kNone, &vec3);
- mod()->AddGlobalVariable(scalar);
- mod()->AddGlobalVariable(vector);
+ mod->AddGlobalVariable(scalar);
+ mod->AddGlobalVariable(vector);
// Register the global
ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -1350,7 +1343,7 @@
auto* vector =
create<ast::Variable>("vector", ast::StorageClass::kNone, &vec3);
- mod()->AddGlobalVariable(vector);
+ mod->AddGlobalVariable(vector);
// Register the global
ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -1374,8 +1367,8 @@
create<ast::Variable>("scalar", ast::StorageClass::kNone, &f32);
auto* matrix =
create<ast::Variable>("matrix", ast::StorageClass::kNone, &mat3x2);
- mod()->AddGlobalVariable(scalar);
- mod()->AddGlobalVariable(matrix);
+ mod->AddGlobalVariable(scalar);
+ mod->AddGlobalVariable(matrix);
// Register the global
ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -1402,8 +1395,8 @@
create<ast::Variable>("scalar", ast::StorageClass::kNone, &f32);
auto* matrix =
create<ast::Variable>("matrix", ast::StorageClass::kNone, &mat3x2);
- mod()->AddGlobalVariable(scalar);
- mod()->AddGlobalVariable(matrix);
+ mod->AddGlobalVariable(scalar);
+ mod->AddGlobalVariable(matrix);
// Register the global
ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -1431,8 +1424,8 @@
create<ast::Variable>("vector", ast::StorageClass::kNone, &vec3);
auto* matrix =
create<ast::Variable>("matrix", ast::StorageClass::kNone, &mat3x2);
- mod()->AddGlobalVariable(vector);
- mod()->AddGlobalVariable(matrix);
+ mod->AddGlobalVariable(vector);
+ mod->AddGlobalVariable(matrix);
// Register the global
ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -1457,8 +1450,8 @@
create<ast::Variable>("vector", ast::StorageClass::kNone, &vec3);
auto* matrix =
create<ast::Variable>("matrix", ast::StorageClass::kNone, &mat3x2);
- mod()->AddGlobalVariable(vector);
- mod()->AddGlobalVariable(matrix);
+ mod->AddGlobalVariable(vector);
+ mod->AddGlobalVariable(matrix);
// Register the global
ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -1483,8 +1476,8 @@
create<ast::Variable>("mat4x3", ast::StorageClass::kNone, &mat4x3);
auto* matrix2 =
create<ast::Variable>("mat3x4", ast::StorageClass::kNone, &mat3x4);
- mod()->AddGlobalVariable(matrix1);
- mod()->AddGlobalVariable(matrix2);
+ mod->AddGlobalVariable(matrix1);
+ mod->AddGlobalVariable(matrix2);
// Register the global
ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -1510,7 +1503,7 @@
ast::type::F32Type f32;
auto* var = create<ast::Variable>("ident", ast::StorageClass::kNone, &f32);
- mod()->AddGlobalVariable(var);
+ mod->AddGlobalVariable(var);
// Register the global
EXPECT_TRUE(td()->Determine());
@@ -1533,7 +1526,7 @@
ast::type::VectorType vec4(&f32, 4);
auto* var = create<ast::Variable>("ident", ast::StorageClass::kNone, &vec4);
- mod()->AddGlobalVariable(var);
+ mod->AddGlobalVariable(var);
// Register the global
EXPECT_TRUE(td()->Determine());
@@ -1575,8 +1568,8 @@
auto* var1 = create<ast::Variable>("ident1", ast::StorageClass::kNone, &vec4);
auto* var2 = create<ast::Variable>("ident2", ast::StorageClass::kNone, &vec4);
- mod()->AddGlobalVariable(var1);
- mod()->AddGlobalVariable(var2);
+ mod->AddGlobalVariable(var1);
+ mod->AddGlobalVariable(var2);
// Register the global
EXPECT_TRUE(td()->Determine());
@@ -1610,7 +1603,7 @@
ast::type::VectorType vec3(&bool_type, 3);
auto* var = create<ast::Variable>("my_var", ast::StorageClass::kNone, &vec3);
- mod()->AddGlobalVariable(var);
+ mod->AddGlobalVariable(var);
ast::ExpressionList call_params;
call_params.push_back(create<ast::IdentifierExpression>("my_var"));
@@ -1637,7 +1630,7 @@
ast::type::VectorType vec3(&f32, 3);
auto* var = create<ast::Variable>("my_var", ast::StorageClass::kNone, &vec3);
- mod()->AddGlobalVariable(var);
+ mod->AddGlobalVariable(var);
ast::ExpressionList call_params;
call_params.push_back(create<ast::IdentifierExpression>("my_var"));
@@ -1661,7 +1654,7 @@
ast::type::F32Type f32;
auto* var = create<ast::Variable>("my_var", ast::StorageClass::kNone, &f32);
- mod()->AddGlobalVariable(var);
+ mod->AddGlobalVariable(var);
ast::ExpressionList call_params;
call_params.push_back(create<ast::IdentifierExpression>("my_var"));
@@ -1682,7 +1675,7 @@
ast::type::F32Type f32;
auto* var = create<ast::Variable>("my_var", ast::StorageClass::kNone, &f32);
- mod()->AddGlobalVariable(var);
+ mod->AddGlobalVariable(var);
ast::ExpressionList call_params;
ast::CallExpression expr(create<ast::IdentifierExpression>(name),
@@ -1700,7 +1693,7 @@
ast::type::F32Type f32;
auto* var = create<ast::Variable>("my_var", ast::StorageClass::kNone, &f32);
- mod()->AddGlobalVariable(var);
+ mod->AddGlobalVariable(var);
ast::ExpressionList call_params;
call_params.push_back(create<ast::IdentifierExpression>("my_var"));
@@ -1769,7 +1762,7 @@
ast::type::Type* type,
ast::ExpressionList* call_params) {
auto* var = create<ast::Variable>(name, ast::StorageClass::kNone, type);
- mod()->AddGlobalVariable(var);
+ mod->AddGlobalVariable(var);
call_params->push_back(create<ast::IdentifierExpression>(name));
}
@@ -1794,7 +1787,7 @@
auto coords_type = get_coords_type(dim, &i32);
ast::type::Type* texture_type =
- ctx()->type_mgr().Get(std::make_unique<ast::type::StorageTextureType>(
+ ctx->type_mgr().Get(std::make_unique<ast::type::StorageTextureType>(
dim, ast::AccessControl::kReadOnly, format));
ast::ExpressionList call_params;
@@ -1891,184 +1884,9 @@
EXPECT_EQ(expr.result_type()->AsVector()->size(), 4u);
}
-TEST_P(Intrinsic_SampledTextureOperation, TextureSample) {
- auto dim = GetParam().dim;
- auto type = GetParam().type;
-
- auto s = subtype(type);
- ast::type::F32Type f32;
- auto sampler_type = std::make_unique<ast::type::SamplerType>(
- ast::type::SamplerKind::kSampler);
- auto coords_type = get_coords_type(dim, &f32);
- auto texture_type =
- std::make_unique<ast::type::SampledTextureType>(dim, s.get());
-
- ast::ExpressionList call_params;
-
- add_call_param("texture", texture_type.get(), &call_params);
- add_call_param("sampler", sampler_type.get(), &call_params);
- add_call_param("coords", coords_type.get(), &call_params);
-
- ast::CallExpression expr(create<ast::IdentifierExpression>("textureSample"),
- call_params);
-
- EXPECT_TRUE(td()->Determine());
- EXPECT_TRUE(td()->DetermineResultType(&expr));
-
- ASSERT_NE(expr.result_type(), nullptr);
- ASSERT_TRUE(expr.result_type()->IsVector());
- if (type == TextureType::kF32) {
- EXPECT_TRUE(expr.result_type()->AsVector()->type()->IsF32());
- } else if (type == TextureType::kI32) {
- EXPECT_TRUE(expr.result_type()->AsVector()->type()->IsI32());
- } else {
- EXPECT_TRUE(expr.result_type()->AsVector()->type()->IsU32());
- }
- EXPECT_EQ(expr.result_type()->AsVector()->size(), 4u);
-}
-
-TEST_P(Intrinsic_SampledTextureOperation, TextureSampleLevel) {
- auto dim = GetParam().dim;
- auto type = GetParam().type;
-
- ast::type::F32Type f32;
- auto s = subtype(type);
- auto sampler_type = std::make_unique<ast::type::SamplerType>(
- ast::type::SamplerKind::kSampler);
- auto coords_type = get_coords_type(dim, &f32);
- auto texture_type =
- std::make_unique<ast::type::SampledTextureType>(dim, s.get());
-
- ast::ExpressionList call_params;
-
- add_call_param("texture", texture_type.get(), &call_params);
- add_call_param("sampler", sampler_type.get(), &call_params);
- add_call_param("coords", coords_type.get(), &call_params);
- add_call_param("lod", &f32, &call_params);
-
- ast::CallExpression expr(
- create<ast::IdentifierExpression>("textureSampleLevel"), call_params);
-
- EXPECT_TRUE(td()->Determine());
- EXPECT_TRUE(td()->DetermineResultType(&expr));
-
- ASSERT_NE(expr.result_type(), nullptr);
- ASSERT_TRUE(expr.result_type()->IsVector());
- if (type == TextureType::kF32) {
- EXPECT_TRUE(expr.result_type()->AsVector()->type()->IsF32());
- } else if (type == TextureType::kI32) {
- EXPECT_TRUE(expr.result_type()->AsVector()->type()->IsI32());
- } else {
- EXPECT_TRUE(expr.result_type()->AsVector()->type()->IsU32());
- }
- EXPECT_EQ(expr.result_type()->AsVector()->size(), 4u);
-}
-
-TEST_P(Intrinsic_SampledTextureOperation, TextureSampleBias) {
- auto dim = GetParam().dim;
- auto type = GetParam().type;
-
- ast::type::F32Type f32;
- auto s = subtype(type);
- auto sampler_type = std::make_unique<ast::type::SamplerType>(
- ast::type::SamplerKind::kSampler);
- auto coords_type = get_coords_type(dim, &f32);
- auto texture_type =
- std::make_unique<ast::type::SampledTextureType>(dim, s.get());
-
- ast::ExpressionList call_params;
-
- add_call_param("texture", texture_type.get(), &call_params);
- add_call_param("sampler", sampler_type.get(), &call_params);
- add_call_param("coords", coords_type.get(), &call_params);
- add_call_param("bias", &f32, &call_params);
-
- ast::CallExpression expr(
- create<ast::IdentifierExpression>("textureSampleBias"), call_params);
-
- EXPECT_TRUE(td()->Determine());
- EXPECT_TRUE(td()->DetermineResultType(&expr));
-
- ASSERT_NE(expr.result_type(), nullptr);
- ASSERT_TRUE(expr.result_type()->IsVector());
- if (type == TextureType::kF32) {
- EXPECT_TRUE(expr.result_type()->AsVector()->type()->IsF32());
- } else if (type == TextureType::kI32) {
- EXPECT_TRUE(expr.result_type()->AsVector()->type()->IsI32());
- } else {
- EXPECT_TRUE(expr.result_type()->AsVector()->type()->IsU32());
- }
- EXPECT_EQ(expr.result_type()->AsVector()->size(), 4u);
-}
-
INSTANTIATE_TEST_SUITE_P(
TypeDeterminerTest,
Intrinsic_SampledTextureOperation,
- testing::Values(
- TextureTestParams{ast::type::TextureDimension::k1d, TextureType::kF32},
- TextureTestParams{ast::type::TextureDimension::k1d, TextureType::kI32},
- TextureTestParams{ast::type::TextureDimension::k1d, TextureType::kU32},
- TextureTestParams{ast::type::TextureDimension::k1dArray,
- TextureType::kF32},
- TextureTestParams{ast::type::TextureDimension::k1dArray,
- TextureType::kI32},
- TextureTestParams{ast::type::TextureDimension::k1dArray,
- TextureType::kU32},
- TextureTestParams{ast::type::TextureDimension::k2d, TextureType::kF32},
- TextureTestParams{ast::type::TextureDimension::k2d, TextureType::kI32},
- TextureTestParams{ast::type::TextureDimension::k2d, TextureType::kU32},
- TextureTestParams{ast::type::TextureDimension::k2dArray,
- TextureType::kF32},
- TextureTestParams{ast::type::TextureDimension::k2dArray,
- TextureType::kI32},
- TextureTestParams{ast::type::TextureDimension::k2dArray,
- TextureType::kU32},
- TextureTestParams{ast::type::TextureDimension::k3d, TextureType::kF32},
- TextureTestParams{ast::type::TextureDimension::k3d, TextureType::kI32},
- TextureTestParams{ast::type::TextureDimension::k3d, TextureType::kU32},
- TextureTestParams{ast::type::TextureDimension::kCube,
- TextureType::kF32},
- TextureTestParams{ast::type::TextureDimension::kCube,
- TextureType::kI32},
- TextureTestParams{ast::type::TextureDimension::kCube,
- TextureType::kU32},
- TextureTestParams{ast::type::TextureDimension::kCubeArray,
- TextureType::kF32},
- TextureTestParams{ast::type::TextureDimension::kCubeArray,
- TextureType::kI32},
- TextureTestParams{ast::type::TextureDimension::kCubeArray,
- TextureType::kU32}));
-
-using Intrinsic_DepthTextureOperation = Intrinsic_TextureOperation;
-TEST_P(Intrinsic_DepthTextureOperation, TextureSampleCompare) {
- auto dim = GetParam().dim;
-
- ast::type::F32Type f32;
- auto sampler_type = std::make_unique<ast::type::SamplerType>(
- ast::type::SamplerKind::kComparisonSampler);
- auto coords_type = get_coords_type(dim, &f32);
- auto texture_type = std::make_unique<ast::type::DepthTextureType>(dim);
-
- ast::ExpressionList call_params;
-
- add_call_param("texture", texture_type.get(), &call_params);
- add_call_param("sampler_comparison", sampler_type.get(), &call_params);
- add_call_param("coords", coords_type.get(), &call_params);
- add_call_param("depth_reference", &f32, &call_params);
-
- ast::CallExpression expr(
- create<ast::IdentifierExpression>("textureSampleCompare"), call_params);
-
- EXPECT_TRUE(td()->Determine());
- EXPECT_TRUE(td()->DetermineResultType(&expr));
-
- ASSERT_NE(expr.result_type(), nullptr);
- EXPECT_TRUE(expr.result_type()->IsF32());
-}
-
-INSTANTIATE_TEST_SUITE_P(
- TypeDeterminerTest,
- Intrinsic_DepthTextureOperation,
testing::Values(TextureTestParams{ast::type::TextureDimension::k2d},
TextureTestParams{ast::type::TextureDimension::k2dArray},
TextureTestParams{ast::type::TextureDimension::kCube},
@@ -2080,7 +1898,7 @@
ast::type::VectorType vec3(&f32, 3);
auto* var = create<ast::Variable>("my_var", ast::StorageClass::kNone, &vec3);
- mod()->AddGlobalVariable(var);
+ mod->AddGlobalVariable(var);
ast::ExpressionList call_params;
call_params.push_back(create<ast::IdentifierExpression>("my_var"));
@@ -2105,8 +1923,8 @@
auto* var = create<ast::Variable>("my_var", ast::StorageClass::kNone, &vec3);
auto* bool_var =
create<ast::Variable>("bool_var", ast::StorageClass::kNone, &bool_vec3);
- mod()->AddGlobalVariable(var);
- mod()->AddGlobalVariable(bool_var);
+ mod->AddGlobalVariable(var);
+ mod->AddGlobalVariable(bool_var);
ast::ExpressionList call_params;
call_params.push_back(create<ast::IdentifierExpression>("my_var"));
@@ -2130,7 +1948,7 @@
ast::type::VectorType vec3(&f32, 3);
auto* var = create<ast::Variable>("v", ast::StorageClass::kNone, &vec3);
- mod()->AddGlobalVariable(var);
+ mod->AddGlobalVariable(var);
ast::ExpressionList call_params;
call_params.push_back(create<ast::IdentifierExpression>("v"));
@@ -2150,7 +1968,7 @@
ast::type::VectorType vec3(&f32, 3);
auto* var = create<ast::Variable>("v", ast::StorageClass::kNone, &vec3);
- mod()->AddGlobalVariable(var);
+ mod->AddGlobalVariable(var);
ast::ExpressionList call_params;
call_params.push_back(create<ast::IdentifierExpression>("v"));
@@ -2175,8 +1993,8 @@
auto* var1 = create<ast::Variable>("v3", ast::StorageClass::kNone, &vec3);
auto* var2 = create<ast::Variable>("v2", ast::StorageClass::kNone, &vec2);
- mod()->AddGlobalVariable(var1);
- mod()->AddGlobalVariable(var2);
+ mod->AddGlobalVariable(var1);
+ mod->AddGlobalVariable(var2);
ast::ExpressionList call_params;
call_params.push_back(create<ast::IdentifierExpression>("v3"));
@@ -2204,7 +2022,7 @@
ast::type::VectorType vec2(&f32, 2);
auto* var2 = create<ast::Variable>("v2", ast::StorageClass::kNone, &vec2);
- mod()->AddGlobalVariable(var2);
+ mod->AddGlobalVariable(var2);
ast::ExpressionList call_params;
call_params.push_back(create<ast::IdentifierExpression>("v2"));
@@ -2224,7 +2042,7 @@
ast::type::VectorType vec2(&f32, 2);
auto* var2 = create<ast::Variable>("v2", ast::StorageClass::kNone, &vec2);
- mod()->AddGlobalVariable(var2);
+ mod->AddGlobalVariable(var2);
ast::ExpressionList call_params;
call_params.push_back(create<ast::IdentifierExpression>("v2"));
@@ -2249,7 +2067,7 @@
ast::type::VectorType vec4(&f32, 4);
auto* var = create<ast::Variable>("ident", ast::StorageClass::kNone, &vec4);
- mod()->AddGlobalVariable(var);
+ mod->AddGlobalVariable(var);
// Register the global
EXPECT_TRUE(td()->Determine());
@@ -2276,7 +2094,7 @@
body->append(stmt);
auto* func = create<ast::Function>("func", ast::VariableList{}, &i32, body);
- mod()->AddFunction(func);
+ mod->AddFunction(func);
EXPECT_TRUE(td()->Determine()) << td()->error();
EXPECT_EQ(var->storage_class(), ast::StorageClass::kFunction);
@@ -2293,7 +2111,7 @@
body->append(stmt);
auto* func = create<ast::Function>("func", ast::VariableList{}, &i32, body);
- mod()->AddFunction(func);
+ mod->AddFunction(func);
EXPECT_TRUE(td()->Determine()) << td()->error();
EXPECT_EQ(var->storage_class(), ast::StorageClass::kNone);
@@ -2309,7 +2127,7 @@
body->append(stmt);
auto* func = create<ast::Function>("func", ast::VariableList{}, &i32, body);
- mod()->AddFunction(func);
+ mod->AddFunction(func);
EXPECT_FALSE(td()->Determine());
EXPECT_EQ(td()->error(),
@@ -2403,6 +2221,7 @@
IntrinsicData{"textureSampleBias", ast::Intrinsic::kTextureSampleBias},
IntrinsicData{"textureSampleCompare",
ast::Intrinsic::kTextureSampleCompare},
+ IntrinsicData{"textureSampleGrad", ast::Intrinsic::kTextureSampleGrad},
IntrinsicData{"textureSampleLevel",
ast::Intrinsic::kTextureSampleLevel},
IntrinsicData{"trunc", ast::Intrinsic::kTrunc}));
@@ -4358,7 +4177,7 @@
ast::type::MatrixType mat(&f32, 3, 3);
auto* var = create<ast::Variable>("var", ast::StorageClass::kFunction, &mat);
- mod()->AddGlobalVariable(var);
+ mod->AddGlobalVariable(var);
// Register the global
ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -4383,7 +4202,7 @@
ast::type::F32Type f32;
auto* var = create<ast::Variable>("var", ast::StorageClass::kFunction, &f32);
- mod()->AddGlobalVariable(var);
+ mod->AddGlobalVariable(var);
// Register the global
ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -4419,7 +4238,7 @@
ast::type::MatrixType mat(&f32, 3, 3);
auto* var = create<ast::Variable>("var", ast::StorageClass::kFunction, &mat);
- mod()->AddGlobalVariable(var);
+ mod->AddGlobalVariable(var);
// Register the global
ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -4495,21 +4314,21 @@
ep_2->add_decoration(
create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
- mod()->AddFunction(func_b);
- mod()->AddFunction(func_c);
- mod()->AddFunction(func_a);
- mod()->AddFunction(ep_1);
- mod()->AddFunction(ep_2);
+ mod->AddFunction(func_b);
+ mod->AddFunction(func_c);
+ mod->AddFunction(func_a);
+ mod->AddFunction(ep_1);
+ mod->AddFunction(ep_2);
- mod()->AddGlobalVariable(
+ mod->AddGlobalVariable(
create<ast::Variable>("first", ast::StorageClass::kPrivate, &f32));
- mod()->AddGlobalVariable(
+ mod->AddGlobalVariable(
create<ast::Variable>("second", ast::StorageClass::kPrivate, &f32));
- mod()->AddGlobalVariable(
+ mod->AddGlobalVariable(
create<ast::Variable>("call_a", ast::StorageClass::kPrivate, &f32));
- mod()->AddGlobalVariable(
+ mod->AddGlobalVariable(
create<ast::Variable>("call_b", ast::StorageClass::kPrivate, &f32));
- mod()->AddGlobalVariable(
+ mod->AddGlobalVariable(
create<ast::Variable>("call_c", ast::StorageClass::kPrivate, &f32));
// Register the functions and calculate the callers
@@ -4533,5 +4352,238 @@
EXPECT_TRUE(ep_2->ancestor_entry_points().empty());
}
+using TypeDeterminerTextureIntrinsicTest =
+ TypeDeterminerTestWithParam<ast::intrinsic::test::TextureOverloadCase>;
+
+INSTANTIATE_TEST_SUITE_P(
+ TypeDeterminerTest,
+ TypeDeterminerTextureIntrinsicTest,
+ testing::ValuesIn(ast::intrinsic::test::TextureOverloadCase::ValidCases()));
+
+std::string to_str(const std::string& function,
+ const ast::intrinsic::TextureSignature* sig) {
+ struct Parameter {
+ size_t idx;
+ std::string name;
+ };
+ std::vector<Parameter> params;
+ auto maybe_add_param = [¶ms](size_t idx, const char* name) {
+ if (idx != ast::intrinsic::TextureSignature::Parameters::kNotUsed) {
+ params.emplace_back(Parameter{idx, name});
+ }
+ };
+ maybe_add_param(sig->params.idx.array_index, "array_index");
+ maybe_add_param(sig->params.idx.bias, "bias");
+ maybe_add_param(sig->params.idx.coords, "coords");
+ maybe_add_param(sig->params.idx.depth_ref, "depth_ref");
+ maybe_add_param(sig->params.idx.ddx, "ddx");
+ maybe_add_param(sig->params.idx.ddy, "ddy");
+ maybe_add_param(sig->params.idx.level, "level");
+ maybe_add_param(sig->params.idx.offset, "offset");
+ maybe_add_param(sig->params.idx.sampler, "sampler");
+ maybe_add_param(sig->params.idx.texture, "texture");
+ std::sort(
+ params.begin(), params.end(),
+ [](const Parameter& a, const Parameter& b) { return a.idx < b.idx; });
+
+ std::stringstream out;
+ out << function << "(";
+ bool first = true;
+ for (auto& param : params) {
+ if (!first) {
+ out << ", ";
+ }
+ out << param.name;
+ first = false;
+ }
+ out << ")";
+ return out.str();
+}
+
+const char* expected_texture_overload(
+ ast::intrinsic::test::ValidTextureOverload overload) {
+ using ValidTextureOverload = ast::intrinsic::test::ValidTextureOverload;
+ switch (overload) {
+ case ValidTextureOverload::kSample1dF32:
+ return "textureSample(texture, sampler, coords)";
+ case ValidTextureOverload::kSample1dArrayF32:
+ return "textureSample(texture, sampler, coords, array_index)";
+ case ValidTextureOverload::kSample2dF32:
+ return "textureSample(texture, sampler, coords)";
+ case ValidTextureOverload::kSample2dOffsetF32:
+ return "textureSample(texture, sampler, coords, offset)";
+ case ValidTextureOverload::kSample2dArrayF32:
+ return "textureSample(texture, sampler, coords, array_index)";
+ case ValidTextureOverload::kSample2dArrayOffsetF32:
+ return "textureSample(texture, sampler, coords, array_index, offset)";
+ case ValidTextureOverload::kSample3dF32:
+ return "textureSample(texture, sampler, coords)";
+ case ValidTextureOverload::kSample3dOffsetF32:
+ return "textureSample(texture, sampler, coords, offset)";
+ case ValidTextureOverload::kSampleCubeF32:
+ return "textureSample(texture, sampler, coords)";
+ case ValidTextureOverload::kSampleCubeArrayF32:
+ return "textureSample(texture, sampler, coords, array_index)";
+ case ValidTextureOverload::kSampleDepth2dF32:
+ return "textureSample(texture, sampler, coords)";
+ case ValidTextureOverload::kSampleDepth2dOffsetF32:
+ return "textureSample(texture, sampler, coords, offset)";
+ case ValidTextureOverload::kSampleDepth2dArrayF32:
+ return "textureSample(texture, sampler, coords, array_index)";
+ case ValidTextureOverload::kSampleDepth2dArrayOffsetF32:
+ return "textureSample(texture, sampler, coords, array_index, offset)";
+ case ValidTextureOverload::kSampleDepthCubeF32:
+ return "textureSample(texture, sampler, coords)";
+ case ValidTextureOverload::kSampleDepthCubeArrayF32:
+ return "textureSample(texture, sampler, coords, array_index)";
+ case ValidTextureOverload::kSampleBias2dF32:
+ return "textureSampleBias(texture, sampler, coords, bias)";
+ case ValidTextureOverload::kSampleBias2dOffsetF32:
+ return "textureSampleBias(texture, sampler, coords, bias, offset)";
+ case ValidTextureOverload::kSampleBias2dArrayF32:
+ return "textureSampleBias(texture, sampler, coords, array_index, "
+ "bias)";
+ case ValidTextureOverload::kSampleBias2dArrayOffsetF32:
+ return "textureSampleBias(texture, sampler, coords, array_index, "
+ "bias, offset)";
+ case ValidTextureOverload::kSampleBias3dF32:
+ return "textureSampleBias(texture, sampler, coords, bias)";
+ case ValidTextureOverload::kSampleBias3dOffsetF32:
+ return "textureSampleBias(texture, sampler, coords, bias, offset)";
+ case ValidTextureOverload::kSampleBiasCubeF32:
+ return "textureSampleBias(texture, sampler, coords, bias)";
+ case ValidTextureOverload::kSampleBiasCubeArrayF32:
+ return "textureSampleBias(texture, sampler, coords, array_index, "
+ "bias)";
+ case ValidTextureOverload::kSampleLevel2dF32:
+ return "textureSampleLevel(texture, sampler, coords, level)";
+ case ValidTextureOverload::kSampleLevel2dOffsetF32:
+ return "textureSampleLevel(texture, sampler, coords, level, offset)";
+ case ValidTextureOverload::kSampleLevel2dArrayF32:
+ return "textureSampleLevel(texture, sampler, coords, array_index, "
+ "level)";
+ case ValidTextureOverload::kSampleLevel2dArrayOffsetF32:
+ return "textureSampleLevel(texture, sampler, coords, array_index, "
+ "level, offset)";
+ case ValidTextureOverload::kSampleLevel3dF32:
+ return "textureSampleLevel(texture, sampler, coords, level)";
+ case ValidTextureOverload::kSampleLevel3dOffsetF32:
+ return "textureSampleLevel(texture, sampler, coords, level, offset)";
+ case ValidTextureOverload::kSampleLevelCubeF32:
+ return "textureSampleLevel(texture, sampler, coords, level)";
+ case ValidTextureOverload::kSampleLevelCubeArrayF32:
+ return "textureSampleLevel(texture, sampler, coords, array_index, "
+ "level)";
+ case ValidTextureOverload::kSampleLevelDepth2dF32:
+ return "textureSampleLevel(texture, sampler, coords, level)";
+ case ValidTextureOverload::kSampleLevelDepth2dOffsetF32:
+ return "textureSampleLevel(texture, sampler, coords, level, offset)";
+ case ValidTextureOverload::kSampleLevelDepth2dArrayF32:
+ return "textureSampleLevel(texture, sampler, coords, array_index, level)";
+ case ValidTextureOverload::kSampleLevelDepth2dArrayOffsetF32:
+ return "textureSampleLevel(texture, sampler, coords, array_index, level, "
+ "offset)";
+ case ValidTextureOverload::kSampleLevelDepthCubeF32:
+ return "textureSampleLevel(texture, sampler, coords, level)";
+ case ValidTextureOverload::kSampleLevelDepthCubeArrayF32:
+ return "textureSampleLevel(texture, sampler, coords, array_index, "
+ "level)";
+ case ValidTextureOverload::kSampleGrad2dF32:
+ return "textureSampleGrad(texture, sampler, coords, ddx, ddy)";
+ case ValidTextureOverload::kSampleGrad2dOffsetF32:
+ return "textureSampleGrad(texture, sampler, coords, ddx, ddy, "
+ "offset)";
+ case ValidTextureOverload::kSampleGrad2dArrayF32:
+ return "textureSampleGrad(texture, sampler, coords, array_index, ddx, "
+ "ddy)";
+ case ValidTextureOverload::kSampleGrad2dArrayOffsetF32:
+ return "textureSampleGrad(texture, sampler, coords, array_index, ddx, "
+ "ddy, offset)";
+ case ValidTextureOverload::kSampleGrad3dF32:
+ return "textureSampleGrad(texture, sampler, coords, ddx, ddy)";
+ case ValidTextureOverload::kSampleGrad3dOffsetF32:
+ return "textureSampleGrad(texture, sampler, coords, ddx, ddy, "
+ "offset)";
+ case ValidTextureOverload::kSampleGradCubeF32:
+ return "textureSampleGrad(texture, sampler, coords, ddx, ddy)";
+ case ValidTextureOverload::kSampleGradCubeArrayF32:
+ return "textureSampleGrad(texture, sampler, coords, array_index, ddx, "
+ "ddy)";
+ case ValidTextureOverload::kSampleGradDepth2dF32:
+ return "textureSampleCompare(texture, sampler, coords, depth_ref)";
+ case ValidTextureOverload::kSampleGradDepth2dOffsetF32:
+ return "textureSampleCompare(texture, sampler, coords, depth_ref, "
+ "offset)";
+ case ValidTextureOverload::kSampleGradDepth2dArrayF32:
+ return "textureSampleCompare(texture, sampler, coords, array_index, "
+ "depth_ref)";
+ case ValidTextureOverload::kSampleGradDepth2dArrayOffsetF32:
+ return "textureSampleCompare(texture, sampler, coords, array_index, "
+ "depth_ref, offset)";
+ case ValidTextureOverload::kSampleGradDepthCubeF32:
+ return "textureSampleCompare(texture, sampler, coords, depth_ref)";
+ case ValidTextureOverload::kSampleGradDepthCubeArrayF32:
+ return "textureSampleCompare(texture, sampler, coords, array_index, "
+ "depth_ref)";
+ }
+ return "<unmatched texture overload>";
+}
+
+TEST_P(TypeDeterminerTextureIntrinsicTest, Call) {
+ auto param = GetParam();
+
+ ast::type::Type* datatype = nullptr;
+ switch (param.texture_data_type) {
+ case ast::intrinsic::test::TextureDataType::kF32:
+ datatype = ty.f32;
+ break;
+ case ast::intrinsic::test::TextureDataType::kU32:
+ datatype = ty.u32;
+ break;
+ case ast::intrinsic::test::TextureDataType::kI32:
+ datatype = ty.i32;
+ break;
+ }
+
+ ast::type::SamplerType sampler_type{param.sampler_kind};
+ switch (param.texture_kind) {
+ case ast::intrinsic::test::TextureKind::kRegular:
+ Var("texture", ast::StorageClass::kNone,
+ ctx->type_mgr().Get<ast::type::SampledTextureType>(
+ param.texture_dimension, datatype));
+ break;
+
+ case ast::intrinsic::test::TextureKind::kDepth:
+ Var("texture", ast::StorageClass::kNone,
+ ctx->type_mgr().Get<ast::type::DepthTextureType>(
+ param.texture_dimension));
+ break;
+ }
+
+ Var("sampler", ast::StorageClass::kNone, &sampler_type);
+
+ auto* ident = Expr(param.function);
+ ast::CallExpression call{ident, param.args(this)};
+
+ EXPECT_TRUE(td()->DetermineResultType(&call)) << td()->error();
+
+ switch (param.texture_kind) {
+ case ast::intrinsic::test::TextureKind::kRegular:
+ ASSERT_TRUE(call.result_type()->IsVector());
+ EXPECT_EQ(call.result_type()->AsVector()->type(), datatype);
+ break;
+
+ case ast::intrinsic::test::TextureKind::kDepth:
+ EXPECT_EQ(call.result_type(), ty.f32);
+ break;
+ }
+
+ auto* sig = static_cast<const ast::intrinsic::TextureSignature*>(
+ ident->intrinsic_signature());
+
+ auto* expected = expected_texture_overload(param.overload);
+ EXPECT_EQ(to_str(param.function, sig), expected);
+}
+
} // namespace
} // namespace tint
diff --git a/src/writer/spirv/builder.cc b/src/writer/spirv/builder.cc
index 518e9ce..081a3a2 100644
--- a/src/writer/spirv/builder.cc
+++ b/src/writer/spirv/builder.cc
@@ -1749,9 +1749,15 @@
return 0;
}
+ auto intrinsic = ident->intrinsic();
+
+ if (ast::intrinsic::IsTextureIntrinsic(intrinsic)) {
+ GenerateTextureIntrinsic(ident, call, Operand::Int(result_type_id), result);
+ return result_id;
+ }
+
OperandList params = {Operand::Int(result_type_id), result};
- auto intrinsic = ident->intrinsic();
if (ast::intrinsic::IsFineDerivative(intrinsic) ||
ast::intrinsic::IsCoarseDerivative(intrinsic)) {
push_capability(SpvCapabilityDerivativeControl);
@@ -1825,7 +1831,7 @@
op = spv::Op::OpBitReverse;
} else if (intrinsic == ast::Intrinsic::kSelect) {
op = spv::Op::OpSelect;
- } else if (!ast::intrinsic::IsTextureIntrinsic(intrinsic)) {
+ } else {
GenerateGLSLstd450Import();
auto set_iter = import_name_to_id_.find(kGLSLstd450);
@@ -1846,7 +1852,8 @@
op = spv::Op::OpExtInst;
}
- if (!ast::intrinsic::IsTextureIntrinsic(intrinsic) && op == spv::Op::OpNop) {
+
+ if (op == spv::Op::OpNop) {
error_ = "unable to determine operator for: " + ident->name();
return 0;
}
@@ -1854,15 +1861,11 @@
for (auto* p : call->params()) {
auto val_id = GenerateExpression(p);
if (val_id == 0) {
- return 0;
+ return false;
}
val_id = GenerateLoadIfNeeded(p->result_type(), val_id);
- params.push_back(Operand::Int(val_id));
- }
-
- if (ast::intrinsic::IsTextureIntrinsic(intrinsic)) {
- return GenerateTextureIntrinsic(ident, call, result_id, params);
+ params.emplace_back(Operand::Int(val_id));
}
push_function_inst(op, params);
@@ -1870,68 +1873,171 @@
return result_id;
}
-uint32_t Builder::GenerateTextureIntrinsic(ast::IdentifierExpression* ident,
- ast::CallExpression* call,
- uint32_t result_id,
- OperandList wgsl_params) {
+void Builder::GenerateTextureIntrinsic(ast::IdentifierExpression* ident,
+ ast::CallExpression* call,
+ spirv::Operand result_type,
+ spirv::Operand result_id) {
auto* texture_type =
call->params()[0]->result_type()->UnwrapAll()->AsTexture();
- // TODO(dsinclair): Remove the LOD param from textureLoad on storage textures
- // when https://github.com/gpuweb/gpuweb/pull/1032 gets merged.
+ auto* sig = static_cast<const ast::intrinsic::TextureSignature*>(
+ ident->intrinsic_signature());
+ assert(sig != nullptr);
+ auto& pidx = sig->params.idx;
+ auto const kNotUsed = ast::intrinsic::TextureSignature::Parameters::kNotUsed;
+
+ assert(pidx.texture != kNotUsed);
+
+ auto op = spv::Op::OpNop;
+
+ auto gen_param = [&](size_t idx) {
+ auto* p = call->params()[idx];
+ auto val_id = GenerateExpression(p);
+ if (val_id == 0) {
+ return Operand::Int(0);
+ }
+ val_id = GenerateLoadIfNeeded(p->result_type(), val_id);
+
+ return Operand::Int(val_id);
+ };
+
+ // Populate the spirv_params with common parameters
+ OperandList spirv_params;
+ spirv_params.reserve(8); // Enough to fit most parameter lists
+ spirv_params.emplace_back(std::move(result_type)); // result type
+ spirv_params.emplace_back(std::move(result_id)); // result id
+
+ // Extra image operands, appended to spirv_params.
+ uint32_t spirv_operand_mask = 0;
+ OperandList spirv_operands;
+ spirv_operands.reserve(4); // Enough to fit most parameter lists
+
if (ident->intrinsic() == ast::Intrinsic::kTextureLoad) {
- std::vector<Operand> spirv_params = {
- std::move(wgsl_params[0]), std::move(wgsl_params[1]),
- std::move(wgsl_params[2]), std::move(wgsl_params[3])};
- if (texture_type->IsMultisampled()) {
- spirv_params.push_back(Operand::Int(SpvImageOperandsSampleMask));
+ op = texture_type->IsStorage() ? spv::Op::OpImageRead
+ : spv::Op::OpImageFetch;
+ spirv_params.emplace_back(gen_param(pidx.texture));
+ spirv_params.emplace_back(gen_param(pidx.coords));
+
+ // TODO(dsinclair): Remove the LOD param from textureLoad on storage
+ // textures when https://github.com/gpuweb/gpuweb/pull/1032 gets merged.
+ if (pidx.level != kNotUsed) {
+ if (texture_type->IsMultisampled()) {
+ spirv_operand_mask |= SpvImageOperandsSampleMask;
+ } else {
+ spirv_operand_mask |= SpvImageOperandsLodMask;
+ }
+ spirv_operands.emplace_back(gen_param(pidx.level));
+ }
+ } else {
+ assert(pidx.sampler != kNotUsed);
+
+ auto sampler_param = gen_param(pidx.sampler);
+ auto texture_param = gen_param(pidx.texture);
+ auto sampled_image =
+ GenerateSampledImage(texture_type, texture_param, sampler_param);
+
+ // Populate the spirv_params with the common parameters
+ spirv_params.emplace_back(Operand::Int(sampled_image)); // sampled image
+
+ if (pidx.array_index != kNotUsed) {
+ // Array index needs to be appended to the coordinates.
+ auto* param_coords = call->params()[pidx.coords];
+ auto* param_array_index = call->params()[pidx.array_index];
+
+ uint32_t packed_coords_size;
+ ast::type::Type* packed_coords_el_ty; // Currenly must be f32.
+ if (param_coords->result_type()->IsVector()) {
+ auto* vec = param_coords->result_type()->AsVector();
+ packed_coords_size = vec->size() + 1;
+ packed_coords_el_ty = vec->type();
+ } else {
+ packed_coords_size = 2;
+ packed_coords_el_ty = param_coords->result_type();
+ }
+
+ // Cast param_array_index to the vector element type
+ ast::TypeConstructorExpression array_index_cast(packed_coords_el_ty,
+ {param_array_index});
+ array_index_cast.set_result_type(packed_coords_el_ty);
+
+ ast::type::VectorType packed_coords_ty(packed_coords_el_ty,
+ packed_coords_size);
+
+ ast::TypeConstructorExpression constructor{
+ &packed_coords_ty, {param_coords, &array_index_cast}};
+ auto packed_coords =
+ GenerateTypeConstructorExpression(&constructor, false);
+
+ spirv_params.emplace_back(Operand::Int(packed_coords)); // coordinates
+
} else {
- spirv_params.push_back(Operand::Int(SpvImageOperandsLodMask));
+ spirv_params.emplace_back(gen_param(pidx.coords)); // coordinates
}
- spirv_params.push_back(std::move(wgsl_params[4]));
- auto op = spv::Op::OpImageFetch;
- if (texture_type->IsStorage()) {
- op = spv::Op::OpImageRead;
+ switch (ident->intrinsic()) {
+ case ast::Intrinsic::kTextureSample: {
+ op = spv::Op::OpImageSampleImplicitLod;
+ break;
+ }
+ case ast::Intrinsic::kTextureSampleBias: {
+ op = spv::Op::OpImageSampleImplicitLod;
+ assert(pidx.bias != kNotUsed);
+ spirv_operand_mask |= SpvImageOperandsBiasMask;
+ spirv_operands.emplace_back(gen_param(pidx.bias));
+ break;
+ }
+ case ast::Intrinsic::kTextureSampleLevel: {
+ op = spv::Op::OpImageSampleExplicitLod;
+ assert(pidx.level != kNotUsed);
+ spirv_operand_mask |= SpvImageOperandsLodMask;
+ spirv_operands.emplace_back(gen_param(pidx.level));
+ break;
+ }
+ case ast::Intrinsic::kTextureSampleGrad: {
+ op = spv::Op::OpImageSampleExplicitLod;
+ assert(pidx.ddx != kNotUsed);
+ assert(pidx.ddy != kNotUsed);
+ spirv_operand_mask |= SpvImageOperandsGradMask;
+ spirv_operands.emplace_back(gen_param(pidx.ddx));
+ spirv_operands.emplace_back(gen_param(pidx.ddy));
+ break;
+ }
+ case ast::Intrinsic::kTextureSampleCompare: {
+ op = spv::Op::OpImageSampleDrefExplicitLod;
+ assert(pidx.depth_ref != kNotUsed);
+ spirv_params.emplace_back(gen_param(pidx.depth_ref));
+
+ spirv_operand_mask |= SpvImageOperandsLodMask;
+ ast::type::F32Type f32;
+ ast::FloatLiteral float_0(&f32, 0.0);
+ spirv_operands.emplace_back(
+ Operand::Int(GenerateLiteralIfNeeded(nullptr, &float_0)));
+ break;
+ }
+ default:
+ break; // unreachable
}
- push_function_inst(op, spirv_params);
- return result_id;
}
- spv::Op op = spv::Op::OpNop;
- OperandList spirv_params = {
- wgsl_params[0], std::move(wgsl_params[1]),
- Operand::Int(GenerateSampledImage(texture_type, std::move(wgsl_params[2]),
- std::move(wgsl_params[3]))),
- std::move(wgsl_params[4])};
-
- if (ident->intrinsic() == ast::Intrinsic::kTextureSample) {
- op = spv::Op::OpImageSampleImplicitLod;
- } else if (ident->intrinsic() == ast::Intrinsic::kTextureSampleLevel) {
- op = spv::Op::OpImageSampleExplicitLod;
- spirv_params.push_back(Operand::Int(SpvImageOperandsLodMask));
- spirv_params.push_back(std::move(wgsl_params[5]));
- } else if (ident->intrinsic() == ast::Intrinsic::kTextureSampleBias) {
- op = spv::Op::OpImageSampleImplicitLod;
- spirv_params.push_back(Operand::Int(SpvImageOperandsBiasMask));
- spirv_params.push_back(std::move(wgsl_params[5]));
- } else if (ident->intrinsic() == ast::Intrinsic::kTextureSampleCompare) {
- op = spv::Op::OpImageSampleDrefExplicitLod;
- spirv_params.push_back(std::move(wgsl_params[5]));
-
- spirv_params.push_back(Operand::Int(SpvImageOperandsLodMask));
- ast::type::F32Type f32;
- ast::FloatLiteral float_0(&f32, 0.0);
- spirv_params.push_back(
- Operand::Int(GenerateLiteralIfNeeded(nullptr, &float_0)));
+ if (pidx.offset != kNotUsed) {
+ spirv_operand_mask |= SpvImageOperandsOffsetMask;
+ spirv_operands.emplace_back(gen_param(pidx.offset));
}
+
+ if (spirv_operand_mask != 0) {
+ // Note: Order of operands is based on SpvImageXXXOperands value -
+ // smaller-numbered SpvImageXXXOperands bits appear first.
+ spirv_params.emplace_back(Operand::Int(spirv_operand_mask));
+ spirv_params.insert(std::end(spirv_params), std::begin(spirv_operands),
+ std::end(spirv_operands));
+ }
+
if (op == spv::Op::OpNop) {
error_ = "unable to determine operator for: " + ident->name();
- return 0;
+ return;
}
- push_function_inst(op, spirv_params);
- return result_id;
+ push_function_inst(op, spirv_params);
}
uint32_t Builder::GenerateSampledImage(ast::type::Type* texture_type,
diff --git a/src/writer/spirv/builder.h b/src/writer/spirv/builder.h
index dd0d20d..ac3f452 100644
--- a/src/writer/spirv/builder.h
+++ b/src/writer/spirv/builder.h
@@ -231,7 +231,7 @@
bool GenerateExecutionModes(ast::Function* func, uint32_t id);
/// Generates an expression
/// @param expr the expression to generate
- /// @returns the resulting ID of the exp = {};ression or 0 on error
+ /// @returns the resulting ID of the expression or 0 on error
uint32_t GenerateExpression(ast::Expression* expr);
/// Generates the instructions for a function
/// @param func the function to generate
@@ -335,14 +335,13 @@
/// Generates a texture intrinsic call
/// @param ident the texture intrinsic
/// @param call the call expression
- /// @param result_id result ID of the texture instruction
- /// @param wgsl_params SPIR-V arguments for WGSL-specific intrinsic's call
+ /// @param result_type result type operand of the texture instruction
+ /// @param result_id result identifier operand of the texture instruction
/// parameters
- /// @returns the expression ID on success or 0 otherwise
- uint32_t GenerateTextureIntrinsic(ast::IdentifierExpression* ident,
- ast::CallExpression* call,
- uint32_t result_id,
- OperandList wgsl_params);
+ void GenerateTextureIntrinsic(ast::IdentifierExpression* ident,
+ ast::CallExpression* call,
+ spirv::Operand result_type,
+ spirv::Operand result_id);
/// Generates a sampled image
/// @param texture_type the texture type
/// @param texture_operand the texture operand
diff --git a/src/writer/spirv/builder_intrinsic_test.cc b/src/writer/spirv/builder_intrinsic_test.cc
index 3b05637..e41cc8a 100644
--- a/src/writer/spirv/builder_intrinsic_test.cc
+++ b/src/writer/spirv/builder_intrinsic_test.cc
@@ -19,6 +19,7 @@
#include "src/ast/call_expression.h"
#include "src/ast/float_literal.h"
#include "src/ast/identifier_expression.h"
+#include "src/ast/intrinsic_texture_helper_test.h"
#include "src/ast/member_accessor_expression.h"
#include "src/ast/scalar_constructor_expression.h"
#include "src/ast/sint_literal.h"
@@ -581,103 +582,27 @@
)");
}
-TEST_F(IntrinsicBuilderTest, Call_TextureSample_1d) {
- ast::type::SamplerType s(ast::type::SamplerKind::kSampler);
- ast::type::SampledTextureType t(ast::type::TextureDimension::k1d, &s);
+using IntrinsicTextureTest =
+ IntrinsicBuilderTestWithParam<ast::intrinsic::test::TextureOverloadCase>;
- b.push_function(Function{});
+INSTANTIATE_TEST_SUITE_P(
+ IntrinsicBuilderTest,
+ IntrinsicTextureTest,
+ testing::ValuesIn(ast::intrinsic::test::TextureOverloadCase::ValidCases()));
- auto* tex = Var("texture", ast::StorageClass::kNone, &t);
- ASSERT_TRUE(b.GenerateGlobalVariable(tex)) << b.error();
+struct expected_texture_overload_spirv {
+ std::string types;
+ std::string instructions;
+};
- auto* sampler = Var("sampler", ast::StorageClass::kNone, &s);
- ASSERT_TRUE(b.GenerateGlobalVariable(sampler)) << b.error();
-
- auto expr = Call("textureSample", "texture", "sampler", 1.0f);
-
- EXPECT_TRUE(td.DetermineResultType(&expr)) << td.error();
- EXPECT_EQ(b.GenerateExpression(&expr), 7u) << b.error();
- EXPECT_EQ(DumpInstructions(b.types()),
- R"(%4 = OpTypeSampler
-%3 = OpTypeImage %4 1D 0 0 0 1 Unknown
-%2 = OpTypePointer Private %3
-%1 = OpVariable %2 Private
-%6 = OpTypePointer Private %4
-%5 = OpVariable %6 Private
-%8 = OpTypeVector %4 4
-%11 = OpTypeFloat 32
-%12 = OpConstant %11 1
-%13 = OpTypeSampledImage %3
-)");
-
- EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
- R"(%9 = OpLoad %3 %1
-%10 = OpLoad %4 %5
-%14 = OpSampledImage %13 %9 %10
-%7 = OpImageSampleImplicitLod %8 %14 %12
-)");
-}
-
-TEST_F(IntrinsicBuilderTest, Call_TextureSample_2d) {
- ast::type::SamplerType s(ast::type::SamplerKind::kSampler);
- ast::type::SampledTextureType t(ast::type::TextureDimension::k2d, &s);
-
- b.push_function(Function{});
-
- auto* tex = Var("texture", ast::StorageClass::kNone, &t);
- ASSERT_TRUE(b.GenerateGlobalVariable(tex)) << b.error();
-
- auto* sampler = Var("sampler", ast::StorageClass::kNone, &s);
- ASSERT_TRUE(b.GenerateGlobalVariable(sampler)) << b.error();
-
- auto expr =
- Call("textureSample", "texture", "sampler", vec2<f32>(1.0f, 2.0f));
-
- EXPECT_TRUE(td.DetermineResultType(&expr)) << td.error();
- EXPECT_EQ(b.GenerateExpression(&expr), 7u) << b.error();
- EXPECT_EQ(DumpInstructions(b.types()),
- R"(%4 = OpTypeSampler
-%3 = OpTypeImage %4 2D 0 0 0 1 Unknown
-%2 = OpTypePointer Private %3
-%1 = OpVariable %2 Private
-%6 = OpTypePointer Private %4
-%5 = OpVariable %6 Private
-%8 = OpTypeVector %4 4
-%12 = OpTypeFloat 32
-%11 = OpTypeVector %12 2
-%13 = OpConstant %12 1
-%14 = OpConstant %12 2
-%15 = OpConstantComposite %11 %13 %14
-%16 = OpTypeSampledImage %3
-)");
-
- EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
- R"(%9 = OpLoad %3 %1
-%10 = OpLoad %4 %5
-%17 = OpSampledImage %16 %9 %10
-%7 = OpImageSampleImplicitLod %8 %17 %15
-)");
-}
-
-TEST_F(IntrinsicBuilderTest, Call_TextureSampleLevel_1d) {
- ast::type::SamplerType s(ast::type::SamplerKind::kSampler);
- ast::type::SampledTextureType t(ast::type::TextureDimension::k1d, ty.f32);
-
- b.push_function(Function{});
-
- auto* tex = Var("texture", ast::StorageClass::kNone, &t);
- ASSERT_TRUE(b.GenerateGlobalVariable(tex)) << b.error();
-
- auto* sampler = Var("sampler", ast::StorageClass::kNone, &s);
- ASSERT_TRUE(b.GenerateGlobalVariable(sampler)) << b.error();
-
- auto expr = Call("textureSampleLevel", "texture", "sampler", 1.0f, 2.0f);
-
- EXPECT_TRUE(td.DetermineResultType(&expr)) << td.error();
- EXPECT_EQ(b.GenerateExpression(&expr), 8u) << b.error();
-
- EXPECT_EQ(DumpInstructions(b.types()),
- R"(%4 = OpTypeFloat 32
+expected_texture_overload_spirv expected_texture_overload(
+ ast::intrinsic::test::ValidTextureOverload overload) {
+ using ValidTextureOverload = ast::intrinsic::test::ValidTextureOverload;
+ switch (overload) {
+ case ValidTextureOverload::kSample1dF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
%3 = OpTypeImage %4 1D 0 0 0 1 Unknown
%2 = OpTypePointer Private %3
%1 = OpVariable %2 Private
@@ -685,39 +610,44 @@
%6 = OpTypePointer Private %7
%5 = OpVariable %6 Private
%9 = OpTypeVector %4 4
-%12 = OpConstant %4 1
-%13 = OpConstant %4 2
-%14 = OpTypeSampledImage %3
-)");
-
- EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
- R"(%10 = OpLoad %3 %1
-%11 = OpLoad %7 %5
-%15 = OpSampledImage %14 %10 %11
-%8 = OpImageSampleExplicitLod %9 %15 %12 Lod %13
-)");
-}
-
-TEST_F(IntrinsicBuilderTest, Call_TextureSampleLevel_2d) {
- ast::type::SamplerType s(ast::type::SamplerKind::kSampler);
- ast::type::SampledTextureType t(ast::type::TextureDimension::k2d, ty.f32);
-
- b.push_function(Function{});
-
- auto* tex = Var("texture", ast::StorageClass::kNone, &t);
- ASSERT_TRUE(b.GenerateGlobalVariable(tex)) << b.error();
-
- auto* sampler = Var("sampler", ast::StorageClass::kNone, &s);
- ASSERT_TRUE(b.GenerateGlobalVariable(sampler)) << b.error();
-
- auto expr = Call("textureSampleLevel", "texture", "sampler",
- vec2<f32>(1.0f, 2.0f), 2.0f);
-
- EXPECT_TRUE(td.DetermineResultType(&expr)) << td.error();
- EXPECT_EQ(b.GenerateExpression(&expr), 8u) << b.error();
-
- EXPECT_EQ(DumpInstructions(b.types()),
- R"(%4 = OpTypeFloat 32
+%12 = OpTypeSampledImage %3
+%14 = OpConstant %4 1
+)",
+ R"(
+%10 = OpLoad %7 %5
+%11 = OpLoad %3 %1
+%13 = OpSampledImage %12 %11 %10
+%8 = OpImageSampleImplicitLod %9 %13 %14
+)"};
+ case ValidTextureOverload::kSample1dArrayF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 1D 0 1 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%9 = OpTypeVector %4 4
+%12 = OpTypeSampledImage %3
+%14 = OpTypeVector %4 2
+%15 = OpConstant %4 1
+%17 = OpTypeInt 32 0
+%18 = OpConstant %17 2
+)",
+ R"(
+%10 = OpLoad %7 %5
+%11 = OpLoad %3 %1
+%13 = OpSampledImage %12 %11 %10
+%16 = OpConvertUToF %4 %18
+%19 = OpCompositeConstruct %14 %15 %16
+%8 = OpImageSampleImplicitLod %9 %13 %19
+)"};
+ case ValidTextureOverload::kSample2dF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
%3 = OpTypeImage %4 2D 0 0 0 1 Unknown
%2 = OpTypePointer Private %3
%1 = OpVariable %2 Private
@@ -725,141 +655,1537 @@
%6 = OpTypePointer Private %7
%5 = OpVariable %6 Private
%9 = OpTypeVector %4 4
-%12 = OpTypeVector %4 2
-%13 = OpConstant %4 1
-%14 = OpConstant %4 2
-%15 = OpConstantComposite %12 %13 %14
-%16 = OpTypeSampledImage %3
-)");
-
- EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
- R"(%10 = OpLoad %3 %1
-%11 = OpLoad %7 %5
-%17 = OpSampledImage %16 %10 %11
-%8 = OpImageSampleExplicitLod %9 %17 %15 Lod %14
-)");
-}
-
-TEST_F(IntrinsicBuilderTest, Call_TextureSampleBias_1d) {
- ast::type::SamplerType s(ast::type::SamplerKind::kSampler);
- ast::type::SampledTextureType t(ast::type::TextureDimension::k1d, ty.f32);
-
- b.push_function(Function{});
-
- auto* tex = Var("texture", ast::StorageClass::kNone, &t);
- ASSERT_TRUE(b.GenerateGlobalVariable(tex)) << b.error();
-
- auto* sampler = Var("sampler", ast::StorageClass::kNone, &s);
- ASSERT_TRUE(b.GenerateGlobalVariable(sampler)) << b.error();
-
- auto expr = Call("textureSampleBias", "texture", "sampler", 1.0f, 2.0f);
-
- EXPECT_TRUE(td.DetermineResultType(&expr)) << td.error();
- EXPECT_EQ(b.GenerateExpression(&expr), 8u) << b.error();
-
- EXPECT_EQ(DumpInstructions(b.types()),
- R"(%4 = OpTypeFloat 32
-%3 = OpTypeImage %4 1D 0 0 0 1 Unknown
+%12 = OpTypeSampledImage %3
+%14 = OpTypeVector %4 2
+%15 = OpConstant %4 1
+%16 = OpConstant %4 2
+%17 = OpConstantComposite %14 %15 %16
+)",
+ R"(
+%10 = OpLoad %7 %5
+%11 = OpLoad %3 %1
+%13 = OpSampledImage %12 %11 %10
+%8 = OpImageSampleImplicitLod %9 %13 %17
+)"};
+ case ValidTextureOverload::kSample2dOffsetF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 2D 0 0 0 1 Unknown
%2 = OpTypePointer Private %3
%1 = OpVariable %2 Private
%7 = OpTypeSampler
%6 = OpTypePointer Private %7
%5 = OpVariable %6 Private
%9 = OpTypeVector %4 4
-%12 = OpConstant %4 1
-%13 = OpConstant %4 2
-%14 = OpTypeSampledImage %3
-)");
-
- EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
- R"(%10 = OpLoad %3 %1
-%11 = OpLoad %7 %5
-%15 = OpSampledImage %14 %10 %11
-%8 = OpImageSampleImplicitLod %9 %15 %12 Bias %13
-)");
-}
-
-TEST_F(IntrinsicBuilderTest, Call_TextureSampleBias_2d) {
- ast::type::SamplerType s(ast::type::SamplerKind::kSampler);
- ast::type::SampledTextureType t(ast::type::TextureDimension::k1d, ty.f32);
-
- b.push_function(Function{});
-
- auto* tex = Var("texture", ast::StorageClass::kNone, &t);
- ASSERT_TRUE(b.GenerateGlobalVariable(tex)) << b.error();
-
- auto* sampler = Var("sampler", ast::StorageClass::kNone, &s);
- ASSERT_TRUE(b.GenerateGlobalVariable(sampler)) << b.error();
-
- auto expr = Call("textureSampleBias", "texture", "sampler",
- vec2<f32>(1.0f, 2.0f), 2.0f);
-
- EXPECT_TRUE(td.DetermineResultType(&expr)) << td.error();
- EXPECT_EQ(b.GenerateExpression(&expr), 8u) << b.error();
-
- EXPECT_EQ(DumpInstructions(b.types()),
- R"(%4 = OpTypeFloat 32
-%3 = OpTypeImage %4 1D 0 0 0 1 Unknown
+%12 = OpTypeSampledImage %3
+%14 = OpTypeVector %4 2
+%15 = OpConstant %4 1
+%16 = OpConstant %4 2
+%17 = OpConstantComposite %14 %15 %16
+%19 = OpTypeInt 32 1
+%18 = OpTypeVector %19 2
+%20 = OpConstant %19 3
+%21 = OpConstant %19 4
+%22 = OpConstantComposite %18 %20 %21
+)",
+ R"(
+%10 = OpLoad %7 %5
+%11 = OpLoad %3 %1
+%13 = OpSampledImage %12 %11 %10
+%8 = OpImageSampleImplicitLod %9 %13 %17 Offset %22
+)"};
+ case ValidTextureOverload::kSample2dArrayF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 2D 0 1 0 1 Unknown
%2 = OpTypePointer Private %3
%1 = OpVariable %2 Private
%7 = OpTypeSampler
%6 = OpTypePointer Private %7
%5 = OpVariable %6 Private
%9 = OpTypeVector %4 4
-%12 = OpTypeVector %4 2
-%13 = OpConstant %4 1
-%14 = OpConstant %4 2
-%15 = OpConstantComposite %12 %13 %14
-%16 = OpTypeSampledImage %3
-)");
-
- EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
- R"(%10 = OpLoad %3 %1
-%11 = OpLoad %7 %5
-%17 = OpSampledImage %16 %10 %11
-%8 = OpImageSampleImplicitLod %9 %17 %15 Bias %14
-)");
-}
-
-TEST_F(IntrinsicBuilderTest, Call_TextureSampleCompare) {
- ast::type::SamplerType s(ast::type::SamplerKind::kComparisonSampler);
- ast::type::DepthTextureType t(ast::type::TextureDimension::k2d);
-
- b.push_function(Function{});
-
- auto* tex = Var("texture", ast::StorageClass::kNone, &t);
- ASSERT_TRUE(b.GenerateGlobalVariable(tex)) << b.error();
-
- auto* sampler = Var("sampler", ast::StorageClass::kNone, &s);
- ASSERT_TRUE(b.GenerateGlobalVariable(sampler)) << b.error();
-
- auto expr = Call("textureSampleCompare", "texture", "sampler",
- vec2<f32>(1.0f, 2.0f), 2.0f);
-
- EXPECT_TRUE(td.DetermineResultType(&expr)) << td.error();
- EXPECT_EQ(b.GenerateExpression(&expr), 8u) << b.error();
- EXPECT_EQ(DumpInstructions(b.types()),
- R"(%4 = OpTypeFloat 32
+%12 = OpTypeSampledImage %3
+%14 = OpTypeVector %4 3
+%15 = OpTypeVector %4 2
+%16 = OpConstant %4 1
+%17 = OpConstant %4 2
+%18 = OpConstantComposite %15 %16 %17
+%22 = OpTypeInt 32 0
+%23 = OpConstant %22 3
+)",
+ R"(
+%10 = OpLoad %7 %5
+%11 = OpLoad %3 %1
+%13 = OpSampledImage %12 %11 %10
+%19 = OpCompositeExtract %4 %18 0
+%20 = OpCompositeExtract %4 %18 1
+%21 = OpConvertUToF %4 %23
+%24 = OpCompositeConstruct %14 %19 %20 %21
+%8 = OpImageSampleImplicitLod %9 %13 %24
+)"};
+ case ValidTextureOverload::kSample2dArrayOffsetF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 2D 0 1 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%9 = OpTypeVector %4 4
+%12 = OpTypeSampledImage %3
+%14 = OpTypeVector %4 3
+%15 = OpTypeVector %4 2
+%16 = OpConstant %4 1
+%17 = OpConstant %4 2
+%18 = OpConstantComposite %15 %16 %17
+%22 = OpTypeInt 32 0
+%23 = OpConstant %22 3
+%26 = OpTypeInt 32 1
+%25 = OpTypeVector %26 2
+%27 = OpConstant %26 4
+%28 = OpConstant %26 5
+%29 = OpConstantComposite %25 %27 %28
+)",
+ R"(
+%10 = OpLoad %7 %5
+%11 = OpLoad %3 %1
+%13 = OpSampledImage %12 %11 %10
+%19 = OpCompositeExtract %4 %18 0
+%20 = OpCompositeExtract %4 %18 1
+%21 = OpConvertUToF %4 %23
+%24 = OpCompositeConstruct %14 %19 %20 %21
+%8 = OpImageSampleImplicitLod %9 %13 %24 Offset %29
+)"};
+ case ValidTextureOverload::kSample3dF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 3D 0 0 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%9 = OpTypeVector %4 4
+%12 = OpTypeSampledImage %3
+%14 = OpTypeVector %4 3
+%15 = OpConstant %4 1
+%16 = OpConstant %4 2
+%17 = OpConstant %4 3
+%18 = OpConstantComposite %14 %15 %16 %17
+)",
+ R"(
+%10 = OpLoad %7 %5
+%11 = OpLoad %3 %1
+%13 = OpSampledImage %12 %11 %10
+%8 = OpImageSampleImplicitLod %9 %13 %18
+)"};
+ case ValidTextureOverload::kSample3dOffsetF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 3D 0 0 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%9 = OpTypeVector %4 4
+%12 = OpTypeSampledImage %3
+%14 = OpTypeVector %4 3
+%15 = OpConstant %4 1
+%16 = OpConstant %4 2
+%17 = OpConstant %4 3
+%18 = OpConstantComposite %14 %15 %16 %17
+%20 = OpTypeInt 32 1
+%19 = OpTypeVector %20 3
+%21 = OpConstant %20 4
+%22 = OpConstant %20 5
+%23 = OpConstant %20 6
+%24 = OpConstantComposite %19 %21 %22 %23
+)",
+ R"(
+%10 = OpLoad %7 %5
+%11 = OpLoad %3 %1
+%13 = OpSampledImage %12 %11 %10
+%8 = OpImageSampleImplicitLod %9 %13 %18 Offset %24
+)"};
+ case ValidTextureOverload::kSampleCubeF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 Cube 0 0 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%9 = OpTypeVector %4 4
+%12 = OpTypeSampledImage %3
+%14 = OpTypeVector %4 3
+%15 = OpConstant %4 1
+%16 = OpConstant %4 2
+%17 = OpConstant %4 3
+%18 = OpConstantComposite %14 %15 %16 %17
+)",
+ R"(
+%10 = OpLoad %7 %5
+%11 = OpLoad %3 %1
+%13 = OpSampledImage %12 %11 %10
+%8 = OpImageSampleImplicitLod %9 %13 %18
+)"};
+ case ValidTextureOverload::kSampleCubeArrayF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 Cube 0 1 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%9 = OpTypeVector %4 4
+%12 = OpTypeSampledImage %3
+%14 = OpTypeVector %4 3
+%15 = OpConstant %4 1
+%16 = OpConstant %4 2
+%17 = OpConstant %4 3
+%18 = OpConstantComposite %14 %15 %16 %17
+%23 = OpTypeInt 32 0
+%24 = OpConstant %23 4
+)",
+ R"(
+%10 = OpLoad %7 %5
+%11 = OpLoad %3 %1
+%13 = OpSampledImage %12 %11 %10
+%19 = OpCompositeExtract %4 %18 0
+%20 = OpCompositeExtract %4 %18 1
+%21 = OpCompositeExtract %4 %18 2
+%22 = OpConvertUToF %4 %24
+%25 = OpCompositeConstruct %9 %19 %20 %21 %22
+%8 = OpImageSampleImplicitLod %9 %13 %25
+)"};
+ case ValidTextureOverload::kSampleDepth2dF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
%3 = OpTypeImage %4 2D 1 0 0 1 Unknown
%2 = OpTypePointer Private %3
%1 = OpVariable %2 Private
%7 = OpTypeSampler
%6 = OpTypePointer Private %7
%5 = OpVariable %6 Private
-%11 = OpTypeVector %4 2
-%12 = OpConstant %4 1
-%13 = OpConstant %4 2
-%14 = OpConstantComposite %11 %12 %13
-%15 = OpTypeSampledImage %3
-%17 = OpConstant %4 0
-)");
-
- EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
- R"(%9 = OpLoad %3 %1
+%11 = OpTypeSampledImage %3
+%13 = OpTypeVector %4 2
+%14 = OpConstant %4 1
+%15 = OpConstant %4 2
+%16 = OpConstantComposite %13 %14 %15
+)",
+ R"(
+%9 = OpLoad %7 %5
+%10 = OpLoad %3 %1
+%12 = OpSampledImage %11 %10 %9
+%8 = OpImageSampleImplicitLod %4 %12 %16
+)"};
+ case ValidTextureOverload::kSampleDepth2dOffsetF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 2D 1 0 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%11 = OpTypeSampledImage %3
+%13 = OpTypeVector %4 2
+%14 = OpConstant %4 1
+%15 = OpConstant %4 2
+%16 = OpConstantComposite %13 %14 %15
+%18 = OpTypeInt 32 1
+%17 = OpTypeVector %18 2
+%19 = OpConstant %18 3
+%20 = OpConstant %18 4
+%21 = OpConstantComposite %17 %19 %20
+)",
+ R"(
+%9 = OpLoad %7 %5
+%10 = OpLoad %3 %1
+%12 = OpSampledImage %11 %10 %9
+%8 = OpImageSampleImplicitLod %4 %12 %16 Offset %21
+)"};
+ case ValidTextureOverload::kSampleDepth2dArrayF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 2D 1 1 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%11 = OpTypeSampledImage %3
+%13 = OpTypeVector %4 3
+%14 = OpTypeVector %4 2
+%15 = OpConstant %4 1
+%16 = OpConstant %4 2
+%17 = OpConstantComposite %14 %15 %16
+%21 = OpTypeInt 32 0
+%22 = OpConstant %21 3
+)",
+ R"(
+%9 = OpLoad %7 %5
+%10 = OpLoad %3 %1
+%12 = OpSampledImage %11 %10 %9
+%18 = OpCompositeExtract %4 %17 0
+%19 = OpCompositeExtract %4 %17 1
+%20 = OpConvertUToF %4 %22
+%23 = OpCompositeConstruct %13 %18 %19 %20
+%8 = OpImageSampleImplicitLod %4 %12 %23
+)"};
+ case ValidTextureOverload::kSampleDepth2dArrayOffsetF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 2D 1 1 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%11 = OpTypeSampledImage %3
+%13 = OpTypeVector %4 3
+%14 = OpTypeVector %4 2
+%15 = OpConstant %4 1
+%16 = OpConstant %4 2
+%17 = OpConstantComposite %14 %15 %16
+%21 = OpTypeInt 32 0
+%22 = OpConstant %21 3
+%25 = OpTypeInt 32 1
+%24 = OpTypeVector %25 2
+%26 = OpConstant %25 4
+%27 = OpConstant %25 5
+%28 = OpConstantComposite %24 %26 %27
+)",
+ R"(
+%9 = OpLoad %7 %5
+%10 = OpLoad %3 %1
+%12 = OpSampledImage %11 %10 %9
+%18 = OpCompositeExtract %4 %17 0
+%19 = OpCompositeExtract %4 %17 1
+%20 = OpConvertUToF %4 %22
+%23 = OpCompositeConstruct %13 %18 %19 %20
+%8 = OpImageSampleImplicitLod %4 %12 %23 Offset %28
+)"};
+ case ValidTextureOverload::kSampleDepthCubeF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 Cube 1 0 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%11 = OpTypeSampledImage %3
+%13 = OpTypeVector %4 2
+%14 = OpConstant %4 1
+%15 = OpConstant %4 2
+%16 = OpConstant %4 3
+%17 = OpConstantComposite %13 %14 %15 %16
+)",
+ R"(
+%9 = OpLoad %7 %5
+%10 = OpLoad %3 %1
+%12 = OpSampledImage %11 %10 %9
+%8 = OpImageSampleImplicitLod %4 %12 %17
+)"};
+ case ValidTextureOverload::kSampleDepthCubeArrayF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 Cube 1 1 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%11 = OpTypeSampledImage %3
+%13 = OpTypeVector %4 3
+%14 = OpTypeVector %4 2
+%15 = OpConstant %4 1
+%16 = OpConstant %4 2
+%17 = OpConstant %4 3
+%18 = OpConstantComposite %14 %15 %16 %17
+%22 = OpTypeInt 32 0
+%23 = OpConstant %22 4
+)",
+ R"(
+%9 = OpLoad %7 %5
+%10 = OpLoad %3 %1
+%12 = OpSampledImage %11 %10 %9
+%19 = OpCompositeExtract %4 %18 0
+%20 = OpCompositeExtract %4 %18 1
+%21 = OpConvertUToF %4 %23
+%24 = OpCompositeConstruct %13 %19 %20 %21
+%8 = OpImageSampleImplicitLod %4 %12 %24
+)"};
+ case ValidTextureOverload::kSampleBias2dF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 2D 0 0 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%9 = OpTypeVector %4 4
+%12 = OpTypeSampledImage %3
+%14 = OpTypeVector %4 2
+%15 = OpConstant %4 1
+%16 = OpConstant %4 2
+%17 = OpConstantComposite %14 %15 %16
+%18 = OpConstant %4 3
+)",
+ R"(
%10 = OpLoad %7 %5
-%16 = OpSampledImage %15 %9 %10
-%8 = OpImageSampleDrefExplicitLod %4 %16 %14 %13 Lod %17
-)");
+%11 = OpLoad %3 %1
+%13 = OpSampledImage %12 %11 %10
+%8 = OpImageSampleImplicitLod %9 %13 %17 Bias %18
+)"};
+ case ValidTextureOverload::kSampleBias2dOffsetF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 2D 0 0 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%9 = OpTypeVector %4 4
+%12 = OpTypeSampledImage %3
+%14 = OpTypeVector %4 2
+%15 = OpConstant %4 1
+%16 = OpConstant %4 2
+%17 = OpConstantComposite %14 %15 %16
+%18 = OpConstant %4 3
+%20 = OpTypeInt 32 1
+%19 = OpTypeVector %20 2
+%21 = OpConstant %20 4
+%22 = OpConstant %20 5
+%23 = OpConstantComposite %19 %21 %22
+)",
+ R"(
+%10 = OpLoad %7 %5
+%11 = OpLoad %3 %1
+%13 = OpSampledImage %12 %11 %10
+%8 = OpImageSampleImplicitLod %9 %13 %17 Bias|Offset %18 %23
+)"};
+ case ValidTextureOverload::kSampleBias2dArrayF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 2D 0 1 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%9 = OpTypeVector %4 4
+%12 = OpTypeSampledImage %3
+%14 = OpTypeVector %4 3
+%15 = OpTypeVector %4 2
+%16 = OpConstant %4 1
+%17 = OpConstant %4 2
+%18 = OpConstantComposite %15 %16 %17
+%22 = OpTypeInt 32 0
+%23 = OpConstant %22 4
+%25 = OpConstant %4 3
+)",
+ R"(
+%10 = OpLoad %7 %5
+%11 = OpLoad %3 %1
+%13 = OpSampledImage %12 %11 %10
+%19 = OpCompositeExtract %4 %18 0
+%20 = OpCompositeExtract %4 %18 1
+%21 = OpConvertUToF %4 %23
+%24 = OpCompositeConstruct %14 %19 %20 %21
+%8 = OpImageSampleImplicitLod %9 %13 %24 Bias %25
+)"};
+ case ValidTextureOverload::kSampleBias2dArrayOffsetF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 2D 0 1 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%9 = OpTypeVector %4 4
+%12 = OpTypeSampledImage %3
+%14 = OpTypeVector %4 3
+%15 = OpTypeVector %4 2
+%16 = OpConstant %4 1
+%17 = OpConstant %4 2
+%18 = OpConstantComposite %15 %16 %17
+%22 = OpTypeInt 32 0
+%23 = OpConstant %22 3
+%25 = OpConstant %4 4
+%27 = OpTypeInt 32 1
+%26 = OpTypeVector %27 2
+%28 = OpConstant %27 5
+%29 = OpConstant %27 6
+%30 = OpConstantComposite %26 %28 %29
+)",
+ R"(
+%10 = OpLoad %7 %5
+%11 = OpLoad %3 %1
+%13 = OpSampledImage %12 %11 %10
+%19 = OpCompositeExtract %4 %18 0
+%20 = OpCompositeExtract %4 %18 1
+%21 = OpConvertUToF %4 %23
+%24 = OpCompositeConstruct %14 %19 %20 %21
+%8 = OpImageSampleImplicitLod %9 %13 %24 Bias|Offset %25 %30
+)"};
+ case ValidTextureOverload::kSampleBias3dF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 3D 0 0 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%9 = OpTypeVector %4 4
+%12 = OpTypeSampledImage %3
+%14 = OpTypeVector %4 3
+%15 = OpConstant %4 1
+%16 = OpConstant %4 2
+%17 = OpConstant %4 3
+%18 = OpConstantComposite %14 %15 %16 %17
+%19 = OpConstant %4 4
+)",
+ R"(
+%10 = OpLoad %7 %5
+%11 = OpLoad %3 %1
+%13 = OpSampledImage %12 %11 %10
+%8 = OpImageSampleImplicitLod %9 %13 %18 Bias %19
+)"};
+ case ValidTextureOverload::kSampleBias3dOffsetF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 3D 0 0 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%9 = OpTypeVector %4 4
+%12 = OpTypeSampledImage %3
+%14 = OpTypeVector %4 3
+%15 = OpConstant %4 1
+%16 = OpConstant %4 2
+%17 = OpConstant %4 3
+%18 = OpConstantComposite %14 %15 %16 %17
+%19 = OpConstant %4 4
+%21 = OpTypeInt 32 1
+%20 = OpTypeVector %21 3
+%22 = OpConstant %21 5
+%23 = OpConstant %21 6
+%24 = OpConstant %21 7
+%25 = OpConstantComposite %20 %22 %23 %24
+)",
+ R"(
+%10 = OpLoad %7 %5
+%11 = OpLoad %3 %1
+%13 = OpSampledImage %12 %11 %10
+%8 = OpImageSampleImplicitLod %9 %13 %18 Bias|Offset %19 %25
+)"};
+ case ValidTextureOverload::kSampleBiasCubeF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 Cube 0 0 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%9 = OpTypeVector %4 4
+%12 = OpTypeSampledImage %3
+%14 = OpTypeVector %4 3
+%15 = OpConstant %4 1
+%16 = OpConstant %4 2
+%17 = OpConstant %4 3
+%18 = OpConstantComposite %14 %15 %16 %17
+%19 = OpConstant %4 4
+)",
+ R"(
+%10 = OpLoad %7 %5
+%11 = OpLoad %3 %1
+%13 = OpSampledImage %12 %11 %10
+%8 = OpImageSampleImplicitLod %9 %13 %18 Bias %19
+)"};
+ case ValidTextureOverload::kSampleBiasCubeArrayF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 Cube 0 1 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%9 = OpTypeVector %4 4
+%12 = OpTypeSampledImage %3
+%14 = OpTypeVector %4 3
+%15 = OpConstant %4 1
+%16 = OpConstant %4 2
+%17 = OpConstant %4 3
+%18 = OpConstantComposite %14 %15 %16 %17
+%23 = OpTypeInt 32 0
+%24 = OpConstant %23 3
+%26 = OpConstant %4 4
+)",
+ R"(
+%10 = OpLoad %7 %5
+%11 = OpLoad %3 %1
+%13 = OpSampledImage %12 %11 %10
+%19 = OpCompositeExtract %4 %18 0
+%20 = OpCompositeExtract %4 %18 1
+%21 = OpCompositeExtract %4 %18 2
+%22 = OpConvertUToF %4 %24
+%25 = OpCompositeConstruct %9 %19 %20 %21 %22
+%8 = OpImageSampleImplicitLod %9 %13 %25 Bias %26
+)"};
+ case ValidTextureOverload::kSampleLevel2dF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 2D 0 0 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%9 = OpTypeVector %4 4
+%12 = OpTypeSampledImage %3
+%14 = OpTypeVector %4 2
+%15 = OpConstant %4 1
+%16 = OpConstant %4 2
+%17 = OpConstantComposite %14 %15 %16
+%18 = OpConstant %4 3
+)",
+ R"(
+%10 = OpLoad %7 %5
+%11 = OpLoad %3 %1
+%13 = OpSampledImage %12 %11 %10
+%8 = OpImageSampleExplicitLod %9 %13 %17 Lod %18
+)"};
+ case ValidTextureOverload::kSampleLevel2dOffsetF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 2D 0 0 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%9 = OpTypeVector %4 4
+%12 = OpTypeSampledImage %3
+%14 = OpTypeVector %4 2
+%15 = OpConstant %4 1
+%16 = OpConstant %4 2
+%17 = OpConstantComposite %14 %15 %16
+%18 = OpConstant %4 3
+%20 = OpTypeInt 32 1
+%19 = OpTypeVector %20 2
+%21 = OpConstant %20 4
+%22 = OpConstant %20 5
+%23 = OpConstantComposite %19 %21 %22
+)",
+ R"(
+%10 = OpLoad %7 %5
+%11 = OpLoad %3 %1
+%13 = OpSampledImage %12 %11 %10
+%8 = OpImageSampleExplicitLod %9 %13 %17 Lod|Offset %18 %23
+)"};
+ case ValidTextureOverload::kSampleLevel2dArrayF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 2D 0 1 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%9 = OpTypeVector %4 4
+%12 = OpTypeSampledImage %3
+%14 = OpTypeVector %4 3
+%15 = OpTypeVector %4 2
+%16 = OpConstant %4 1
+%17 = OpConstant %4 2
+%18 = OpConstantComposite %15 %16 %17
+%22 = OpTypeInt 32 0
+%23 = OpConstant %22 3
+%25 = OpConstant %4 4
+)",
+ R"(
+%10 = OpLoad %7 %5
+%11 = OpLoad %3 %1
+%13 = OpSampledImage %12 %11 %10
+%19 = OpCompositeExtract %4 %18 0
+%20 = OpCompositeExtract %4 %18 1
+%21 = OpConvertUToF %4 %23
+%24 = OpCompositeConstruct %14 %19 %20 %21
+%8 = OpImageSampleExplicitLod %9 %13 %24 Lod %25
+)"};
+ case ValidTextureOverload::kSampleLevel2dArrayOffsetF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 2D 0 1 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%9 = OpTypeVector %4 4
+%12 = OpTypeSampledImage %3
+%14 = OpTypeVector %4 3
+%15 = OpTypeVector %4 2
+%16 = OpConstant %4 1
+%17 = OpConstant %4 2
+%18 = OpConstantComposite %15 %16 %17
+%22 = OpTypeInt 32 0
+%23 = OpConstant %22 3
+%25 = OpConstant %4 4
+%27 = OpTypeInt 32 1
+%26 = OpTypeVector %27 2
+%28 = OpConstant %27 5
+%29 = OpConstant %27 6
+%30 = OpConstantComposite %26 %28 %29
+)",
+ R"(
+%10 = OpLoad %7 %5
+%11 = OpLoad %3 %1
+%13 = OpSampledImage %12 %11 %10
+%19 = OpCompositeExtract %4 %18 0
+%20 = OpCompositeExtract %4 %18 1
+%21 = OpConvertUToF %4 %23
+%24 = OpCompositeConstruct %14 %19 %20 %21
+%8 = OpImageSampleExplicitLod %9 %13 %24 Lod|Offset %25 %30
+)"};
+ case ValidTextureOverload::kSampleLevel3dF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 3D 0 0 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%9 = OpTypeVector %4 4
+%12 = OpTypeSampledImage %3
+%14 = OpTypeVector %4 3
+%15 = OpConstant %4 1
+%16 = OpConstant %4 2
+%17 = OpConstant %4 3
+%18 = OpConstantComposite %14 %15 %16 %17
+%19 = OpConstant %4 4
+)",
+ R"(
+%10 = OpLoad %7 %5
+%11 = OpLoad %3 %1
+%13 = OpSampledImage %12 %11 %10
+%8 = OpImageSampleExplicitLod %9 %13 %18 Lod %19
+)"};
+ case ValidTextureOverload::kSampleLevel3dOffsetF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 3D 0 0 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%9 = OpTypeVector %4 4
+%12 = OpTypeSampledImage %3
+%14 = OpTypeVector %4 3
+%15 = OpConstant %4 1
+%16 = OpConstant %4 2
+%17 = OpConstant %4 3
+%18 = OpConstantComposite %14 %15 %16 %17
+%19 = OpConstant %4 4
+%21 = OpTypeInt 32 1
+%20 = OpTypeVector %21 3
+%22 = OpConstant %21 5
+%23 = OpConstant %21 6
+%24 = OpConstant %21 7
+%25 = OpConstantComposite %20 %22 %23 %24
+)",
+ R"(
+%10 = OpLoad %7 %5
+%11 = OpLoad %3 %1
+%13 = OpSampledImage %12 %11 %10
+%8 = OpImageSampleExplicitLod %9 %13 %18 Lod|Offset %19 %25
+)"};
+ case ValidTextureOverload::kSampleLevelCubeF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 Cube 0 0 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%9 = OpTypeVector %4 4
+%12 = OpTypeSampledImage %3
+%14 = OpTypeVector %4 3
+%15 = OpConstant %4 1
+%16 = OpConstant %4 2
+%17 = OpConstant %4 3
+%18 = OpConstantComposite %14 %15 %16 %17
+%19 = OpConstant %4 4
+)",
+ R"(
+%10 = OpLoad %7 %5
+%11 = OpLoad %3 %1
+%13 = OpSampledImage %12 %11 %10
+%8 = OpImageSampleExplicitLod %9 %13 %18 Lod %19
+)"};
+ case ValidTextureOverload::kSampleLevelCubeArrayF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 Cube 0 1 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%9 = OpTypeVector %4 4
+%12 = OpTypeSampledImage %3
+%14 = OpTypeVector %4 3
+%15 = OpConstant %4 1
+%16 = OpConstant %4 2
+%17 = OpConstant %4 3
+%18 = OpConstantComposite %14 %15 %16 %17
+%23 = OpTypeInt 32 0
+%24 = OpConstant %23 4
+%26 = OpConstant %4 5
+)",
+ R"(
+%10 = OpLoad %7 %5
+%11 = OpLoad %3 %1
+%13 = OpSampledImage %12 %11 %10
+%19 = OpCompositeExtract %4 %18 0
+%20 = OpCompositeExtract %4 %18 1
+%21 = OpCompositeExtract %4 %18 2
+%22 = OpConvertUToF %4 %24
+%25 = OpCompositeConstruct %9 %19 %20 %21 %22
+%8 = OpImageSampleExplicitLod %9 %13 %25 Lod %26
+)"};
+ case ValidTextureOverload::kSampleLevelDepth2dF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 2D 1 0 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%11 = OpTypeSampledImage %3
+%13 = OpTypeVector %4 2
+%14 = OpConstant %4 1
+%15 = OpConstant %4 2
+%16 = OpConstantComposite %13 %14 %15
+%17 = OpTypeInt 32 0
+%18 = OpConstant %17 3
+)",
+ R"(
+%9 = OpLoad %7 %5
+%10 = OpLoad %3 %1
+%12 = OpSampledImage %11 %10 %9
+%8 = OpImageSampleExplicitLod %4 %12 %16 Lod %18
+)"};
+ case ValidTextureOverload::kSampleLevelDepth2dOffsetF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 2D 1 0 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%11 = OpTypeSampledImage %3
+%13 = OpTypeVector %4 2
+%14 = OpConstant %4 1
+%15 = OpConstant %4 2
+%16 = OpConstantComposite %13 %14 %15
+%17 = OpTypeInt 32 0
+%18 = OpConstant %17 3
+%20 = OpTypeInt 32 1
+%19 = OpTypeVector %20 2
+%21 = OpConstant %20 4
+%22 = OpConstant %20 5
+%23 = OpConstantComposite %19 %21 %22
+)",
+ R"(
+%9 = OpLoad %7 %5
+%10 = OpLoad %3 %1
+%12 = OpSampledImage %11 %10 %9
+%8 = OpImageSampleExplicitLod %4 %12 %16 Lod|Offset %18 %23
+)"};
+ case ValidTextureOverload::kSampleLevelDepth2dArrayF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 2D 1 1 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%11 = OpTypeSampledImage %3
+%13 = OpTypeVector %4 3
+%14 = OpTypeVector %4 2
+%15 = OpConstant %4 1
+%16 = OpConstant %4 2
+%17 = OpConstantComposite %14 %15 %16
+%21 = OpTypeInt 32 0
+%22 = OpConstant %21 3
+%24 = OpConstant %21 4
+)",
+ R"(
+%9 = OpLoad %7 %5
+%10 = OpLoad %3 %1
+%12 = OpSampledImage %11 %10 %9
+%18 = OpCompositeExtract %4 %17 0
+%19 = OpCompositeExtract %4 %17 1
+%20 = OpConvertUToF %4 %22
+%23 = OpCompositeConstruct %13 %18 %19 %20
+%8 = OpImageSampleExplicitLod %4 %12 %23 Lod %24
+)"};
+ case ValidTextureOverload::kSampleLevelDepth2dArrayOffsetF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 2D 1 1 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%11 = OpTypeSampledImage %3
+%13 = OpTypeVector %4 3
+%14 = OpTypeVector %4 2
+%15 = OpConstant %4 1
+%16 = OpConstant %4 2
+%17 = OpConstantComposite %14 %15 %16
+%21 = OpTypeInt 32 0
+%22 = OpConstant %21 3
+%24 = OpConstant %21 4
+%26 = OpTypeInt 32 1
+%25 = OpTypeVector %26 2
+%27 = OpConstant %26 5
+%28 = OpConstant %26 6
+%29 = OpConstantComposite %25 %27 %28
+)",
+ R"(
+%9 = OpLoad %7 %5
+%10 = OpLoad %3 %1
+%12 = OpSampledImage %11 %10 %9
+%18 = OpCompositeExtract %4 %17 0
+%19 = OpCompositeExtract %4 %17 1
+%20 = OpConvertUToF %4 %22
+%23 = OpCompositeConstruct %13 %18 %19 %20
+%8 = OpImageSampleExplicitLod %4 %12 %23 Lod|Offset %24 %29
+)"};
+ case ValidTextureOverload::kSampleLevelDepthCubeF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 Cube 1 0 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%11 = OpTypeSampledImage %3
+%13 = OpTypeVector %4 3
+%14 = OpConstant %4 1
+%15 = OpConstant %4 2
+%16 = OpConstant %4 3
+%17 = OpConstantComposite %13 %14 %15 %16
+%18 = OpTypeInt 32 0
+%19 = OpConstant %18 4
+)",
+ R"(
+%9 = OpLoad %7 %5
+%10 = OpLoad %3 %1
+%12 = OpSampledImage %11 %10 %9
+%8 = OpImageSampleExplicitLod %4 %12 %17 Lod %19
+)"};
+ case ValidTextureOverload::kSampleLevelDepthCubeArrayF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 Cube 1 1 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%11 = OpTypeSampledImage %3
+%13 = OpTypeVector %4 4
+%14 = OpTypeVector %4 3
+%15 = OpConstant %4 1
+%16 = OpConstant %4 2
+%17 = OpConstant %4 3
+%18 = OpConstantComposite %14 %15 %16 %17
+%23 = OpTypeInt 32 0
+%24 = OpConstant %23 4
+%26 = OpConstant %23 5
+)",
+ R"(
+%9 = OpLoad %7 %5
+%10 = OpLoad %3 %1
+%12 = OpSampledImage %11 %10 %9
+%19 = OpCompositeExtract %4 %18 0
+%20 = OpCompositeExtract %4 %18 1
+%21 = OpCompositeExtract %4 %18 2
+%22 = OpConvertUToF %4 %24
+%25 = OpCompositeConstruct %13 %19 %20 %21 %22
+%8 = OpImageSampleExplicitLod %4 %12 %25 Lod %26
+)"};
+ case ValidTextureOverload::kSampleGrad2dF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 2D 0 0 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%9 = OpTypeVector %4 4
+%12 = OpTypeSampledImage %3
+%14 = OpTypeVector %4 2
+%15 = OpConstant %4 1
+%16 = OpConstant %4 2
+%17 = OpConstantComposite %14 %15 %16
+%18 = OpConstant %4 3
+%19 = OpConstant %4 4
+%20 = OpConstantComposite %14 %18 %19
+%21 = OpConstant %4 5
+%22 = OpConstant %4 6
+%23 = OpConstantComposite %14 %21 %22
+)",
+ R"(
+%10 = OpLoad %7 %5
+%11 = OpLoad %3 %1
+%13 = OpSampledImage %12 %11 %10
+%8 = OpImageSampleExplicitLod %9 %13 %17 Grad %20 %23
+)"};
+ case ValidTextureOverload::kSampleGrad2dOffsetF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 2D 0 0 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%9 = OpTypeVector %4 4
+%12 = OpTypeSampledImage %3
+%14 = OpTypeVector %4 2
+%15 = OpConstant %4 1
+%16 = OpConstant %4 2
+%17 = OpConstantComposite %14 %15 %16
+%18 = OpConstant %4 3
+%19 = OpConstant %4 4
+%20 = OpConstantComposite %14 %18 %19
+%21 = OpConstant %4 5
+%22 = OpConstant %4 6
+%23 = OpConstantComposite %14 %21 %22
+%25 = OpTypeInt 32 1
+%24 = OpTypeVector %25 2
+%26 = OpConstant %25 7
+%27 = OpConstant %25 8
+%28 = OpConstantComposite %24 %26 %27
+)",
+ R"(
+%10 = OpLoad %7 %5
+%11 = OpLoad %3 %1
+%13 = OpSampledImage %12 %11 %10
+%8 = OpImageSampleExplicitLod %9 %13 %17 Grad|Offset %20 %23 %28
+)"};
+ case ValidTextureOverload::kSampleGrad2dArrayF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 2D 0 1 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%9 = OpTypeVector %4 4
+%12 = OpTypeSampledImage %3
+%14 = OpTypeVector %4 3
+%15 = OpTypeVector %4 2
+%16 = OpConstant %4 1
+%17 = OpConstant %4 2
+%18 = OpConstantComposite %15 %16 %17
+%22 = OpTypeInt 32 0
+%23 = OpConstant %22 3
+%25 = OpConstant %4 4
+%26 = OpConstant %4 5
+%27 = OpConstantComposite %15 %25 %26
+%28 = OpConstant %4 6
+%29 = OpConstant %4 7
+%30 = OpConstantComposite %15 %28 %29
+)",
+ R"(
+%10 = OpLoad %7 %5
+%11 = OpLoad %3 %1
+%13 = OpSampledImage %12 %11 %10
+%19 = OpCompositeExtract %4 %18 0
+%20 = OpCompositeExtract %4 %18 1
+%21 = OpConvertUToF %4 %23
+%24 = OpCompositeConstruct %14 %19 %20 %21
+%8 = OpImageSampleExplicitLod %9 %13 %24 Grad %27 %30
+)"};
+ case ValidTextureOverload::kSampleGrad2dArrayOffsetF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 2D 0 1 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%9 = OpTypeVector %4 4
+%12 = OpTypeSampledImage %3
+%14 = OpTypeVector %4 3
+%15 = OpTypeVector %4 2
+%16 = OpConstant %4 1
+%17 = OpConstant %4 2
+%18 = OpConstantComposite %15 %16 %17
+%22 = OpTypeInt 32 0
+%23 = OpConstant %22 3
+%25 = OpConstant %4 4
+%26 = OpConstant %4 5
+%27 = OpConstantComposite %15 %25 %26
+%28 = OpConstant %4 6
+%29 = OpConstant %4 7
+%30 = OpConstantComposite %15 %28 %29
+%32 = OpTypeInt 32 1
+%31 = OpTypeVector %32 2
+%33 = OpConstant %32 8
+%34 = OpConstant %32 9
+%35 = OpConstantComposite %31 %33 %34
+)",
+ R"(
+%10 = OpLoad %7 %5
+%11 = OpLoad %3 %1
+%13 = OpSampledImage %12 %11 %10
+%19 = OpCompositeExtract %4 %18 0
+%20 = OpCompositeExtract %4 %18 1
+%21 = OpConvertUToF %4 %23
+%24 = OpCompositeConstruct %14 %19 %20 %21
+%8 = OpImageSampleExplicitLod %9 %13 %24 Grad|Offset %27 %30 %35
+)"};
+ case ValidTextureOverload::kSampleGrad3dF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 3D 0 0 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%9 = OpTypeVector %4 4
+%12 = OpTypeSampledImage %3
+%14 = OpTypeVector %4 3
+%15 = OpConstant %4 1
+%16 = OpConstant %4 2
+%17 = OpConstant %4 3
+%18 = OpConstantComposite %14 %15 %16 %17
+%19 = OpConstant %4 4
+%20 = OpConstant %4 5
+%21 = OpConstant %4 6
+%22 = OpConstantComposite %14 %19 %20 %21
+%23 = OpConstant %4 7
+%24 = OpConstant %4 8
+%25 = OpConstant %4 9
+%26 = OpConstantComposite %14 %23 %24 %25
+)",
+ R"(
+%10 = OpLoad %7 %5
+%11 = OpLoad %3 %1
+%13 = OpSampledImage %12 %11 %10
+%8 = OpImageSampleExplicitLod %9 %13 %18 Grad %22 %26
+)"};
+ case ValidTextureOverload::kSampleGrad3dOffsetF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 3D 0 0 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%9 = OpTypeVector %4 4
+%12 = OpTypeSampledImage %3
+%14 = OpTypeVector %4 3
+%15 = OpConstant %4 1
+%16 = OpConstant %4 2
+%17 = OpConstant %4 3
+%18 = OpConstantComposite %14 %15 %16 %17
+%19 = OpConstant %4 4
+%20 = OpConstant %4 5
+%21 = OpConstant %4 6
+%22 = OpConstantComposite %14 %19 %20 %21
+%23 = OpConstant %4 7
+%24 = OpConstant %4 8
+%25 = OpConstant %4 9
+%26 = OpConstantComposite %14 %23 %24 %25
+%28 = OpTypeInt 32 1
+%27 = OpTypeVector %28 3
+%29 = OpConstant %28 10
+%30 = OpConstant %28 11
+%31 = OpConstant %28 12
+%32 = OpConstantComposite %27 %29 %30 %31
+)",
+ R"(
+%10 = OpLoad %7 %5
+%11 = OpLoad %3 %1
+%13 = OpSampledImage %12 %11 %10
+%8 = OpImageSampleExplicitLod %9 %13 %18 Grad|Offset %22 %26 %32
+)"};
+ case ValidTextureOverload::kSampleGradCubeF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 Cube 0 0 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%9 = OpTypeVector %4 4
+%12 = OpTypeSampledImage %3
+%14 = OpTypeVector %4 3
+%15 = OpConstant %4 1
+%16 = OpConstant %4 2
+%17 = OpConstant %4 3
+%18 = OpConstantComposite %14 %15 %16 %17
+%19 = OpConstant %4 4
+%20 = OpConstant %4 5
+%21 = OpConstant %4 6
+%22 = OpConstantComposite %14 %19 %20 %21
+%23 = OpConstant %4 7
+%24 = OpConstant %4 8
+%25 = OpConstant %4 9
+%26 = OpConstantComposite %14 %23 %24 %25
+)",
+ R"(
+%10 = OpLoad %7 %5
+%11 = OpLoad %3 %1
+%13 = OpSampledImage %12 %11 %10
+%8 = OpImageSampleExplicitLod %9 %13 %18 Grad %22 %26
+)"};
+ case ValidTextureOverload::kSampleGradCubeArrayF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 Cube 0 1 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%9 = OpTypeVector %4 4
+%12 = OpTypeSampledImage %3
+%14 = OpTypeVector %4 3
+%15 = OpConstant %4 1
+%16 = OpConstant %4 2
+%17 = OpConstant %4 3
+%18 = OpConstantComposite %14 %15 %16 %17
+%23 = OpTypeInt 32 0
+%24 = OpConstant %23 4
+%26 = OpConstant %4 5
+%27 = OpConstant %4 6
+%28 = OpConstant %4 7
+%29 = OpConstantComposite %14 %26 %27 %28
+%30 = OpConstant %4 8
+%31 = OpConstant %4 9
+%32 = OpConstant %4 10
+%33 = OpConstantComposite %14 %30 %31 %32
+)",
+ R"(
+%10 = OpLoad %7 %5
+%11 = OpLoad %3 %1
+%13 = OpSampledImage %12 %11 %10
+%19 = OpCompositeExtract %4 %18 0
+%20 = OpCompositeExtract %4 %18 1
+%21 = OpCompositeExtract %4 %18 2
+%22 = OpConvertUToF %4 %24
+%25 = OpCompositeConstruct %9 %19 %20 %21 %22
+%8 = OpImageSampleExplicitLod %9 %13 %25 Grad %29 %33
+)"};
+ case ValidTextureOverload::kSampleGradDepth2dF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 2D 1 0 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%11 = OpTypeSampledImage %3
+%13 = OpTypeVector %4 2
+%14 = OpConstant %4 1
+%15 = OpConstant %4 2
+%16 = OpConstantComposite %13 %14 %15
+%17 = OpConstant %4 3
+%18 = OpConstant %4 0
+)",
+ R"(
+%9 = OpLoad %7 %5
+%10 = OpLoad %3 %1
+%12 = OpSampledImage %11 %10 %9
+%8 = OpImageSampleDrefExplicitLod %4 %12 %16 %17 Lod %18
+)"};
+ case ValidTextureOverload::kSampleGradDepth2dOffsetF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 2D 1 0 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%11 = OpTypeSampledImage %3
+%13 = OpTypeVector %4 2
+%14 = OpConstant %4 1
+%15 = OpConstant %4 2
+%16 = OpConstantComposite %13 %14 %15
+%17 = OpConstant %4 3
+%18 = OpConstant %4 0
+%20 = OpTypeInt 32 1
+%19 = OpTypeVector %20 2
+%21 = OpConstant %20 4
+%22 = OpConstant %20 5
+%23 = OpConstantComposite %19 %21 %22
+)",
+ R"(
+%9 = OpLoad %7 %5
+%10 = OpLoad %3 %1
+%12 = OpSampledImage %11 %10 %9
+%8 = OpImageSampleDrefExplicitLod %4 %12 %16 %17 Lod|Offset %18 %23
+)"};
+ case ValidTextureOverload::kSampleGradDepth2dArrayF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 2D 1 1 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%11 = OpTypeSampledImage %3
+%13 = OpTypeVector %4 3
+%14 = OpTypeVector %4 2
+%15 = OpConstant %4 1
+%16 = OpConstant %4 2
+%17 = OpConstantComposite %14 %15 %16
+%21 = OpTypeInt 32 0
+%22 = OpConstant %21 4
+%24 = OpConstant %4 3
+%25 = OpConstant %4 0
+)",
+ R"(
+%9 = OpLoad %7 %5
+%10 = OpLoad %3 %1
+%12 = OpSampledImage %11 %10 %9
+%18 = OpCompositeExtract %4 %17 0
+%19 = OpCompositeExtract %4 %17 1
+%20 = OpConvertUToF %4 %22
+%23 = OpCompositeConstruct %13 %18 %19 %20
+%8 = OpImageSampleDrefExplicitLod %4 %12 %23 %24 Lod %25
+)"};
+ case ValidTextureOverload::kSampleGradDepth2dArrayOffsetF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 2D 1 1 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%11 = OpTypeSampledImage %3
+%13 = OpTypeVector %4 3
+%14 = OpTypeVector %4 2
+%15 = OpConstant %4 1
+%16 = OpConstant %4 2
+%17 = OpConstantComposite %14 %15 %16
+%21 = OpTypeInt 32 0
+%22 = OpConstant %21 4
+%24 = OpConstant %4 3
+%25 = OpConstant %4 0
+%27 = OpTypeInt 32 1
+%26 = OpTypeVector %27 2
+%28 = OpConstant %27 5
+%29 = OpConstant %27 6
+%30 = OpConstantComposite %26 %28 %29
+)",
+ R"(
+%9 = OpLoad %7 %5
+%10 = OpLoad %3 %1
+%12 = OpSampledImage %11 %10 %9
+%18 = OpCompositeExtract %4 %17 0
+%19 = OpCompositeExtract %4 %17 1
+%20 = OpConvertUToF %4 %22
+%23 = OpCompositeConstruct %13 %18 %19 %20
+%8 = OpImageSampleDrefExplicitLod %4 %12 %23 %24 Lod|Offset %25 %30
+)"};
+ case ValidTextureOverload::kSampleGradDepthCubeF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 Cube 1 0 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%11 = OpTypeSampledImage %3
+%13 = OpTypeVector %4 3
+%14 = OpConstant %4 1
+%15 = OpConstant %4 2
+%16 = OpConstant %4 3
+%17 = OpConstantComposite %13 %14 %15 %16
+%18 = OpConstant %4 4
+%19 = OpConstant %4 0
+)",
+ R"(
+%9 = OpLoad %7 %5
+%10 = OpLoad %3 %1
+%12 = OpSampledImage %11 %10 %9
+%8 = OpImageSampleDrefExplicitLod %4 %12 %17 %18 Lod %19
+)"};
+ case ValidTextureOverload::kSampleGradDepthCubeArrayF32:
+ return {
+ R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 Cube 1 1 0 1 Unknown
+%2 = OpTypePointer Private %3
+%1 = OpVariable %2 Private
+%7 = OpTypeSampler
+%6 = OpTypePointer Private %7
+%5 = OpVariable %6 Private
+%11 = OpTypeSampledImage %3
+%13 = OpTypeVector %4 4
+%14 = OpTypeVector %4 3
+%15 = OpConstant %4 1
+%16 = OpConstant %4 2
+%17 = OpConstant %4 3
+%18 = OpConstantComposite %14 %15 %16 %17
+%23 = OpTypeInt 32 0
+%24 = OpConstant %23 4
+%26 = OpConstant %4 5
+%27 = OpConstant %4 0
+)",
+ R"(
+%9 = OpLoad %7 %5
+%10 = OpLoad %3 %1
+%12 = OpSampledImage %11 %10 %9
+%19 = OpCompositeExtract %4 %18 0
+%20 = OpCompositeExtract %4 %18 1
+%21 = OpCompositeExtract %4 %18 2
+%22 = OpConvertUToF %4 %24
+%25 = OpCompositeConstruct %13 %19 %20 %21 %22
+%8 = OpImageSampleDrefExplicitLod %4 %12 %25 %26 Lod %27
+)"};
+ }
+ return {"<unmatched texture overload>", "<unmatched texture overload>"};
+} // NOLINT - Ignore the length of this function
+
+TEST_P(IntrinsicTextureTest, Call) {
+ auto param = GetParam();
+
+ b.push_function(Function{});
+
+ ast::type::Type* datatype = nullptr;
+ switch (param.texture_data_type) {
+ case ast::intrinsic::test::TextureDataType::kF32:
+ datatype = ty.f32;
+ break;
+ case ast::intrinsic::test::TextureDataType::kU32:
+ datatype = ty.u32;
+ break;
+ case ast::intrinsic::test::TextureDataType::kI32:
+ datatype = ty.i32;
+ break;
+ }
+
+ ast::type::SamplerType sampler_type{param.sampler_kind};
+ ast::Variable* tex = nullptr;
+ switch (param.texture_kind) {
+ case ast::intrinsic::test::TextureKind::kRegular:
+ tex = Var("texture", ast::StorageClass::kNone,
+ ctx->type_mgr().Get<ast::type::SampledTextureType>(
+ param.texture_dimension, datatype));
+ break;
+
+ case ast::intrinsic::test::TextureKind::kDepth:
+ tex = Var("texture", ast::StorageClass::kNone,
+ ctx->type_mgr().Get<ast::type::DepthTextureType>(
+ param.texture_dimension));
+ break;
+ }
+
+ auto* sampler = Var("sampler", ast::StorageClass::kNone, &sampler_type);
+
+ ASSERT_TRUE(b.GenerateGlobalVariable(tex)) << b.error();
+ ASSERT_TRUE(b.GenerateGlobalVariable(sampler)) << b.error();
+
+ ast::CallExpression call{Expr(param.function), param.args(this)};
+
+ EXPECT_TRUE(td.DetermineResultType(&call)) << td.error();
+ EXPECT_EQ(b.GenerateExpression(&call), 8u) << b.error();
+
+ auto expected = expected_texture_overload(param.overload);
+ EXPECT_EQ(expected.types, "\n" + DumpInstructions(b.types()));
+ EXPECT_EQ(expected.instructions,
+ "\n" + DumpInstructions(b.functions()[0].instructions()));
}
// This tests that we do not push OpTypeSampledImage and float_0 type twice.
@@ -894,23 +2220,23 @@
%7 = OpTypeSampler
%6 = OpTypePointer Private %7
%5 = OpVariable %6 Private
-%11 = OpTypeVector %4 2
-%12 = OpConstant %4 1
-%13 = OpConstant %4 2
-%14 = OpConstantComposite %11 %12 %13
-%15 = OpTypeSampledImage %3
+%11 = OpTypeSampledImage %3
+%13 = OpTypeVector %4 2
+%14 = OpConstant %4 1
+%15 = OpConstant %4 2
+%16 = OpConstantComposite %13 %14 %15
%17 = OpConstant %4 0
)");
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
- R"(%9 = OpLoad %3 %1
-%10 = OpLoad %7 %5
-%16 = OpSampledImage %15 %9 %10
-%8 = OpImageSampleDrefExplicitLod %4 %16 %14 %13 Lod %17
-%19 = OpLoad %3 %1
-%20 = OpLoad %7 %5
-%21 = OpSampledImage %15 %19 %20
-%18 = OpImageSampleDrefExplicitLod %4 %21 %14 %13 Lod %17
+ R"(%9 = OpLoad %7 %5
+%10 = OpLoad %3 %1
+%12 = OpSampledImage %11 %10 %9
+%8 = OpImageSampleDrefExplicitLod %4 %12 %16 %15 Lod %17
+%19 = OpLoad %7 %5
+%20 = OpLoad %3 %1
+%21 = OpSampledImage %11 %20 %19
+%18 = OpImageSampleDrefExplicitLod %4 %21 %16 %15 Lod %17
)");
}