diff --git a/BUILD.gn b/BUILD.gn index 0a47cd7841..529bc6023d 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -755,6 +755,8 @@ source_set("tint_unittests_core_src") { "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 56cda30dcb..cc59d62bba 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -364,6 +364,8 @@ set(TINT_TEST_SRCS 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 af08b69eba..4c6ac31a46 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 #include +#include #include "src/ast/expression.h" #include "src/ast/intrinsic.h" @@ -45,6 +47,17 @@ class IdentifierExpression : public Expression { 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 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 @@ class IdentifierExpression : public Expression { IdentifierExpression(const IdentifierExpression&) = delete; Intrinsic intrinsic_ = Intrinsic::kNone; + std::unique_ptr intrinsic_sig_; std::string name_; }; diff --git a/src/ast/intrinsic.cc b/src/ast/intrinsic.cc index 14fdeefe54..dc6c60a15c 100644 --- a/src/ast/intrinsic.cc +++ b/src/ast/intrinsic.cc @@ -216,6 +216,9 @@ std::ostream& operator<<(std::ostream& out, Intrinsic i) { case Intrinsic::kTextureSampleCompare: out << "textureSampleCompare"; break; + case Intrinsic::kTextureSampleGrad: + out << "textureSampleGrad"; + break; case Intrinsic::kTextureSampleLevel: out << "textureSampleLevel"; break; @@ -231,6 +234,12 @@ std::ostream& operator<<(std::ostream& out, Intrinsic i) { 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 @@ bool IsTextureIntrinsic(ast::Intrinsic i) { 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 9eb160048f..a122ad30c8 100644 --- a/src/ast/intrinsic.h +++ b/src/ast/intrinsic.h @@ -89,6 +89,7 @@ enum class Intrinsic { kTextureSample, kTextureSampleBias, kTextureSampleCompare, + kTextureSampleGrad, kTextureSampleLevel, kTrunc }; @@ -99,6 +100,64 @@ std::ostream& operator<<(std::ostream& out, Intrinsic i); 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(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 0000000000..5e1587ccaf --- /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 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::ValidCases() { + return {{ + ValidTextureOverload::kSample1dF32, + "textureSample(t : texture_1d,\n" + " s : sampler,\n" + " coords : f32) -> vec4", + 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,\n" + " s : sampler,\n" + " coords : f32,\n" + " array_index : u32) -> vec4", + 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,\n" + " s : sampler,\n" + " coords : vec2) -> vec4", + 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(1.f, 2.f)); // coords + }, + }, + { + ValidTextureOverload::kSample2dOffsetF32, + "textureSample(t : texture_2d,\n" + " s : sampler,\n" + " coords : vec2\n" + " offset : vec2) -> vec4", + 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(1.f, 2.f), // coords + b->vec2(3, 4)); // offset + }, + }, + { + ValidTextureOverload::kSample2dArrayF32, + "textureSample(t : texture_2d_array,\n" + " s : sampler,\n" + " coords : vec2,\n" + " array_index : u32) -> vec4", + 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(1.f, 2.f), // coords + 3u); // array_index + }, + }, + { + ValidTextureOverload::kSample2dArrayOffsetF32, + "textureSample(t : texture_2d_array,\n" + " s : sampler,\n" + " coords : vec2,\n" + " array_index : u32\n" + " offset : vec2) -> vec4", + 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(1.f, 2.f), // coords + 3u, // array_index + b->vec2(4, 5)); // offset + }, + }, + { + ValidTextureOverload::kSample3dF32, + "textureSample(t : texture_3d,\n" + " s : sampler,\n" + " coords : vec3) -> vec4", + 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(1.f, 2.f, 3.f)); // coords + }, + }, + { + ValidTextureOverload::kSample3dOffsetF32, + "textureSample(t : texture_3d,\n" + " s : sampler,\n" + " coords : vec3\n" + " offset : vec3) -> vec4", + 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(1.f, 2.f, 3.f), // coords + b->vec3(4, 5, 6)); // offset + }, + }, + { + ValidTextureOverload::kSampleCubeF32, + "textureSample(t : texture_cube,\n" + " s : sampler,\n" + " coords : vec3) -> vec4", + 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(1.f, 2.f, 3.f)); // coords + }, + }, + { + ValidTextureOverload::kSampleCubeArrayF32, + "textureSample(t : texture_cube_array,\n" + " s : sampler,\n" + " coords : vec3,\n" + " array_index : u32) -> vec4", + 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(1.f, 2.f, 3.f), // coords + 4u); // array_index + }, + }, + { + ValidTextureOverload::kSampleDepth2dF32, + "textureSample(t : texture_depth_2d,\n" + " s : sampler,\n" + " coords : vec2) -> 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(1.f, 2.f)); // coords + }, + }, + { + ValidTextureOverload::kSampleDepth2dOffsetF32, + "textureSample(t : texture_depth_2d,\n" + " s : sampler,\n" + " coords : vec2\n" + " offset : vec2) -> 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(1.f, 2.f), // coords + b->vec2(3, 4)); // offset + }, + }, + { + ValidTextureOverload::kSampleDepth2dArrayF32, + "textureSample(t : texture_depth_2d_array,\n" + " s : sampler,\n" + " coords : vec2,\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(1.f, 2.f), // coords + 3u); // array_index + }, + }, + { + ValidTextureOverload::kSampleDepth2dArrayOffsetF32, + "textureSample(t : texture_depth_2d_array,\n" + " s : sampler,\n" + " coords : vec2,\n" + " array_index : u32\n" + " offset : vec2) -> 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(1.f, 2.f), // coords + 3u, // array_index + b->vec2(4, 5)); // offset + }, + }, + { + ValidTextureOverload::kSampleDepthCubeF32, + "textureSample(t : texture_depth_cube,\n" + " s : sampler,\n" + " coords : vec3) -> 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(1.f, 2.f, 3.f)); // coords + }, + }, + { + ValidTextureOverload::kSampleDepthCubeArrayF32, + "textureSample(t : texture_depth_cube_array,\n" + " s : sampler,\n" + " coords : vec3,\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(1.f, 2.f, 3.f), // coords + 4u); // array_index + }, + }, + { + ValidTextureOverload::kSampleBias2dF32, + "textureSampleBias(t : texture_2d,\n" + " s : sampler,\n" + " coords : vec2,\n" + " bias : f32) -> vec4", + 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(1.f, 2.f), // coords + 3.f); // bias + }, + }, + { + ValidTextureOverload::kSampleBias2dOffsetF32, + "textureSampleBias(t : texture_2d,\n" + " s : sampler,\n" + " coords : vec2,\n" + " bias : f32,\n" + " offset : vec2) -> vec4", + 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(1.f, 2.f), // coords + 3.f, // bias + b->vec2(4, 5)); // offset + }, + }, + { + ValidTextureOverload::kSampleBias2dArrayF32, + "textureSampleBias(t : texture_2d_array,\n" + " s : sampler,\n" + " coords : vec2,\n" + " array_index : u32,\n" + " bias : f32) -> vec4", + 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(1.f, 2.f), // coords + 4u, // array_index + 3.f); // bias + }, + }, + { + ValidTextureOverload::kSampleBias2dArrayOffsetF32, + "textureSampleBias(t : texture_2d_array,\n" + " s : sampler,\n" + " coords : vec2,\n" + " array_index : u32,\n" + " bias : f32,\n" + " offset : vec2) -> vec4", + 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(1.f, 2.f), // coords + 3u, // array_index + 4.f, // bias + b->vec2(5, 6)); // offset + }, + }, + { + ValidTextureOverload::kSampleBias3dF32, + "textureSampleBias(t : texture_3d,\n" + " s : sampler,\n" + " coords : vec3,\n" + " bias : f32) -> vec4", + 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(1.f, 2.f, 3.f), // coords + 4.f); // bias + }, + }, + { + ValidTextureOverload::kSampleBias3dOffsetF32, + "textureSampleBias(t : texture_3d,\n" + " s : sampler,\n" + " coords : vec3,\n" + " bias : f32,\n" + " offset : vec3) -> vec4", + 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(1.f, 2.f, 3.f), // coords + 4.f, // bias + b->vec3(5, 6, 7)); // offset + }, + }, + { + ValidTextureOverload::kSampleBiasCubeF32, + "textureSampleBias(t : texture_cube,\n" + " s : sampler,\n" + " coords : vec3,\n" + " bias : f32) -> vec4", + 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(1.f, 2.f, 3.f), // coords + 4.f); // bias + }, + }, + { + ValidTextureOverload::kSampleBiasCubeArrayF32, + "textureSampleBias(t : texture_cube_array,\n" + " s : sampler,\n" + " coords : vec3,\n" + " array_index : u32,\n" + " bias : f32) -> vec4", + 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(1.f, 2.f, 3.f), // coords + 3u, // array_index + 4.f); // bias + }, + }, + { + ValidTextureOverload::kSampleLevel2dF32, + "textureSampleLevel(t : texture_2d,\n" + " s : sampler,\n" + " coords : vec2,\n" + " level : f32) -> vec4", + 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(1.f, 2.f), // coords + 3.f); // level + }, + }, + { + ValidTextureOverload::kSampleLevel2dOffsetF32, + "textureSampleLevel(t : texture_2d,\n" + " s : sampler,\n" + " coords : vec2,\n" + " level : f32,\n" + " offset : vec2) -> vec4", + 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(1.f, 2.f), // coords + 3.f, // level + b->vec2(4, 5)); // offset + }, + }, + { + ValidTextureOverload::kSampleLevel2dArrayF32, + "textureSampleLevel(t : texture_2d_array,\n" + " s : sampler,\n" + " coords : vec2,\n" + " array_index : u32,\n" + " level : f32) -> vec4", + 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(1.f, 2.f), // coords + 3u, // array_index + 4.f); // level + }, + }, + { + ValidTextureOverload::kSampleLevel2dArrayOffsetF32, + "textureSampleLevel(t : texture_2d_array,\n" + " s : sampler,\n" + " coords : vec2,\n" + " array_index : u32,\n" + " level : f32,\n" + " offset : vec2) -> vec4", + 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(1.f, 2.f), // coords + 3u, // array_index + 4.f, // level + b->vec2(5, 6)); // offset + }, + }, + { + ValidTextureOverload::kSampleLevel3dF32, + "textureSampleLevel(t : texture_3d,\n" + " s : sampler,\n" + " coords : vec3,\n" + " level : f32) -> vec4", + 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(1.f, 2.f, 3.f), // coords + 4.f); // level + }, + }, + { + ValidTextureOverload::kSampleLevel3dOffsetF32, + "textureSampleLevel(t : texture_3d,\n" + " s : sampler,\n" + " coords : vec3,\n" + " level : f32,\n" + " offset : vec3) -> vec4", + 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(1.f, 2.f, 3.f), // coords + 4.f, // level + b->vec3(5, 6, 7)); // offset + }, + }, + { + ValidTextureOverload::kSampleLevelCubeF32, + "textureSampleLevel(t : texture_cube,\n" + " s : sampler,\n" + " coords : vec3,\n" + " level : f32) -> vec4", + 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(1.f, 2.f, 3.f), // coords + 4.f); // level + }, + }, + { + ValidTextureOverload::kSampleLevelCubeArrayF32, + "textureSampleLevel(t : texture_cube_array,\n" + " s : sampler,\n" + " coords : vec3,\n" + " array_index : u32,\n" + " level : f32) -> vec4", + 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(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,\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(1.f, 2.f), // coords + 3u); // level + }, + }, + { + ValidTextureOverload::kSampleLevelDepth2dOffsetF32, + "textureSampleLevel(t : texture_depth_2d,\n" + " s : sampler,\n" + " coords : vec2,\n" + " level : u32,\n" + " offset : vec2) -> 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(1.f, 2.f), // coords + 3u, // level + b->vec2(4, 5)); // offset + }, + }, + { + ValidTextureOverload::kSampleLevelDepth2dArrayF32, + "textureSampleLevel(t : texture_depth_2d_array,\n" + " s : sampler,\n" + " coords : vec2,\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(1.f, 2.f), // coords + 3u, // array_index + 4u); // level + }, + }, + { + ValidTextureOverload::kSampleLevelDepth2dArrayOffsetF32, + "textureSampleLevel(t : texture_depth_2d_array,\n" + " s : sampler,\n" + " coords : vec2,\n" + " array_index : u32,\n" + " level : u32,\n" + " offset : vec2) -> 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(1.f, 2.f), // coords + 3u, // array_index + 4u, // level + b->vec2(5, 6)); // offset + }, + }, + { + ValidTextureOverload::kSampleLevelDepthCubeF32, + "textureSampleLevel(t : texture_depth_cube,\n" + " s : sampler,\n" + " coords : vec3,\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(1.f, 2.f, 3.f), // coords + 4u); // level + }, + }, + { + ValidTextureOverload::kSampleLevelDepthCubeArrayF32, + "textureSampleLevel(t : texture_depth_cube_array,\n" + " s : sampler,\n" + " coords : vec3,\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(1.f, 2.f, 3.f), // coords + 4u, // array_index + 5u); // level + }, + }, + { + ValidTextureOverload::kSampleGrad2dF32, + "textureSampleGrad(t : texture_2d,\n" + " s : sampler,\n" + " coords : vec2\n" + " ddx : vec2,\n" + " ddy : vec2) -> vec4", + 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(1.0f, 2.0f), // coords + b->vec2(3.0f, 4.0f), // ddx + b->vec2(5.0f, 6.0f)); // ddy + }, + }, + { + ValidTextureOverload::kSampleGrad2dOffsetF32, + "textureSampleGrad(t : texture_2d,\n" + " s : sampler,\n" + " coords : vec2,\n" + " ddx : vec2,\n" + " ddy : vec2,\n" + " offset : vec2) -> vec4", + 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(1.f, 2.f), // coords + b->vec2(3.f, 4.f), // ddx + b->vec2(5.f, 6.f), // ddy + b->vec2(7, 8)); // offset + }, + }, + { + ValidTextureOverload::kSampleGrad2dArrayF32, + "textureSampleGrad(t : texture_2d_array,\n" + " s : sampler,\n" + " coords : vec2,\n" + " array_index : u32,\n" + " ddx : vec2,\n" + " ddy : vec2) -> vec4", + 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(1.f, 2.f), // coords + 3u, // array_index + b->vec2(4.f, 5.f), // ddx + b->vec2(6.f, 7.f)); // ddy + }, + }, + { + ValidTextureOverload::kSampleGrad2dArrayOffsetF32, + "textureSampleGrad(t : texture_2d_array,\n" + " s : sampler,\n" + " coords : vec2,\n" + " array_index : u32,\n" + " ddx : vec2,\n" + " ddy : vec2,\n" + " offset : vec2) -> vec4", + 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(1.f, 2.f), // coords + 3u, // array_index + b->vec2(4.f, 5.f), // ddx + b->vec2(6.f, 7.f), // ddy + b->vec2(8, 9)); // offset + }, + }, + { + ValidTextureOverload::kSampleGrad3dF32, + "textureSampleGrad(t : texture_3d,\n" + " s : sampler,\n" + " coords : vec3,\n" + " ddx : vec3,\n" + " ddy : vec3) -> vec4", + 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(1.f, 2.f, 3.f), // coords + b->vec3(4.f, 5.f, 6.f), // ddx + b->vec3(7.f, 8.f, 9.f)); // ddy + }, + }, + { + ValidTextureOverload::kSampleGrad3dOffsetF32, + "textureSampleGrad(t : texture_3d,\n" + " s : sampler,\n" + " coords : vec3,\n" + " ddx : vec3,\n" + " ddy : vec3,\n" + " offset : vec3) -> vec4", + 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(1.f, 2.f, 3.f), // coords + b->vec3(4.f, 5.f, 6.f), // ddx + b->vec3(7.f, 8.f, 9.f), // ddy + b->vec3(10, 11, 12)); // offset + }, + }, + { + ValidTextureOverload::kSampleGradCubeF32, + "textureSampleGrad(t : texture_cube,\n" + " s : sampler,\n" + " coords : vec3,\n" + " ddx : vec3,\n" + " ddy : vec3) -> vec4", + 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(1.f, 2.f, 3.f), // coords + b->vec3(4.f, 5.f, 6.f), // ddx + b->vec3(7.f, 8.f, 9.f)); // ddy + }, + }, + { + ValidTextureOverload::kSampleGradCubeArrayF32, + "textureSampleGrad(t : texture_cube_array,\n" + " s : sampler,\n" + " coords : vec3,\n" + " array_index : u32,\n" + " ddx : vec3,\n" + " ddy : vec3) -> vec4", + 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(1.f, 2.f, 3.f), // coords + 4u, // array_index + b->vec3(5.f, 6.f, 7.f), // ddx + b->vec3(8.f, 9.f, 10.f)); // ddy + }, + }, + { + ValidTextureOverload::kSampleGradDepth2dF32, + "textureSampleCompare(t : texture_depth_2d,\n" + " s : sampler_comparison,\n" + " coords : vec2,\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(1.f, 2.f), // coords + 3.f); // depth_ref + }, + }, + { + ValidTextureOverload::kSampleGradDepth2dOffsetF32, + "textureSampleCompare(t : texture_depth_2d,\n" + " s : sampler_comparison,\n" + " coords : vec2,\n" + " depth_ref : f32,\n" + " offset : vec2) -> 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(1.f, 2.f), // coords + 3.f, // depth_ref + b->vec2(4, 5)); // offset + }, + }, + { + ValidTextureOverload::kSampleGradDepth2dArrayF32, + "textureSampleCompare(t : texture_depth_2d_array,\n" + " s : sampler_comparison,\n" + " coords : vec2,\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(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,\n" + " array_index : u32,\n" + " depth_ref : f32,\n" + " offset : vec2) -> 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(1.f, 2.f), // coords + 4u, // array_index + 3.f, // depth_ref + b->vec2(5, 6)); // offset + }, + }, + { + ValidTextureOverload::kSampleGradDepthCubeF32, + "textureSampleCompare(t : texture_depth_cube,\n" + " s : sampler_comparison,\n" + " coords : vec3,\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(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,\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(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 0000000000..5e7da8aaf8 --- /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 +#include + +#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); + /// Copy constructor + TextureOverloadCase(const TextureOverloadCase&); + /// Destructor + ~TextureOverloadCase(); + + /// @return a vector containing a large number of valid texture overloads + static std::vector 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 args; +}; + +inline std::ostream& operator<<(std::ostream& out, + const TextureOverloadCase& data) { + out << "TextureOverloadCase" << static_cast(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 d1d39e6e00..eb2a3a00f9 100644 --- a/src/inspector/inspector_test.cc +++ b/src/inspector/inspector_test.cc @@ -529,6 +529,44 @@ class InspectorHelper { 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(); + + auto* call_result = create( + "sampler_result", ast::StorageClass::kFunction, vec_type(base_type, 4)); + body->append(create(call_result)); + + ast::ExpressionList call_params; + call_params.push_back(create(texture_name)); + call_params.push_back(create(sampler_name)); + call_params.push_back(create(coords_name)); + call_params.push_back(create(array_index)); + auto* call_expr = create( + create("textureSample"), call_params); + + body->append(create( + create("sampler_result"), call_expr)); + body->append(create()); + + return create(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 @@ class InspectorGetComparisonSamplerResourceBindingsTest 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 @@ struct GetSampledTextureTestParams { class InspectorGetSampledTextureResourceBindingsTestWithParam : public InspectorHelper, public testing::TestWithParam {}; - +class InspectorGetSampledArrayTextureResourceBindingsTestWithParam + : public InspectorHelper, + public testing::TestWithParam {}; class InspectorGetMultisampledTextureResourceBindingsTest : public InspectorHelper, public testing::Test {}; +class InspectorGetMultisampledArrayTextureResourceBindingsTest + : public InspectorHelper, + public testing::Test {}; typedef GetSampledTextureTestParams GetMultisampledTextureTestParams; +class InspectorGetMultisampledArrayTextureResourceBindingsTestWithParam + : public InspectorHelper, + public testing::TestWithParam {}; class InspectorGetMultisampledTextureResourceBindingsTestWithParam : public InspectorHelper, public testing::TestWithParam {}; @@ -2008,18 +2057,6 @@ INSTANTIATE_TEST_SUITE_P( ast::type::TextureDimension::k1d, 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, @@ -2032,18 +2069,6 @@ INSTANTIATE_TEST_SUITE_P( ast::type::TextureDimension::k2d, 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, @@ -2067,6 +2092,65 @@ INSTANTIATE_TEST_SUITE_P( 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::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 @@ INSTANTIATE_TEST_SUITE_P( inspector::ResourceBinding::TextureDimension::kCubeArray, inspector::ResourceBinding::SampledKind::kUInt})); -TEST_F(InspectorGetMultisampledTextureResourceBindingsTest, Empty) { - auto* foo = MakeEmptyBodyFunction("foo"); - foo->add_decoration( - create(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( @@ -2138,18 +2210,6 @@ INSTANTIATE_TEST_SUITE_P( ast::type::TextureDimension::k1d, 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, @@ -2161,6 +2221,65 @@ INSTANTIATE_TEST_SUITE_P( 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::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::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 a4d2382132..6208feff6d 100644 --- a/src/type_determiner.cc +++ b/src/type_determiner.cc @@ -552,26 +552,7 @@ bool TypeDeterminer::DetermineIntrinsic(ast::IdentifierExpression* ident, 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())); - return true; - } + ast::intrinsic::TextureSignature::Parameters param; auto* texture_param = expr->params()[0]; if (!texture_param->result_type()->UnwrapPtrIfNeeded()->IsTexture()) { @@ -581,6 +562,115 @@ bool TypeDeterminer::DetermineIntrinsic(ast::IdentifierExpression* ident, 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(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(param)); + + if (texture->IsDepth()) { + expr->func()->set_result_type( + ctx_.type_mgr().Get(std::make_unique())); + return true; + } + if (!texture->IsStorage() && !(texture->IsSampled() || texture->IsMultisampled())) { set_error(expr->source(), "invalid texture for " + ident->name()); @@ -925,6 +1015,8 @@ bool TypeDeterminer::SetIntrinsicIfNeeded(ast::IdentifierExpression* ident) { 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 c12c0d2fcb..66094a283f 100644 --- a/src/type_determiner_test.cc +++ b/src/type_determiner_test.cc @@ -14,6 +14,7 @@ #include "src/type_determiner.h" +#include #include #include #include @@ -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 @@ class FakeExpr : public ast::Expression { void to_str(std::ostream&, size_t) const override {} }; -class TypeDeterminerHelper { +class TypeDeterminerHelper : public ast::BuilderWithContextAndModule { public: - TypeDeterminerHelper() - : td_(std::make_unique(&ctx_, &mod_)) {} + TypeDeterminerHelper() : td_(std::make_unique(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 - T* create(ARGS&&... args) { - return mod_.create(std::forward(args)...); - } private: - Context ctx_; - ast::Module mod_; + void OnVariableBuilt(ast::Variable* var) override { + td_->RegisterVariableForTesting(var); + } + std::unique_ptr td_; }; @@ -350,7 +343,7 @@ TEST_F(TypeDeterminerTest, Stmt_Call) { ast::VariableList params; auto* func = create("my_func", params, &f32, create()); - mod()->AddFunction(func); + mod->AddFunction(func); // Register the function EXPECT_TRUE(td()->Determine()); @@ -379,12 +372,12 @@ TEST_F(TypeDeterminerTest, Stmt_Call_undeclared) { main_body->append(create(call_expr)); main_body->append(create()); auto* func_main = create("main", params0, &f32, main_body); - mod()->AddFunction(func_main); + mod->AddFunction(func_main); auto* body = create(); body->append(create()); auto* func = create("func", params0, &f32, body); - mod()->AddFunction(func); + mod->AddFunction(func); EXPECT_FALSE(td()->Determine()) << td()->error(); EXPECT_EQ(td()->error(), @@ -412,7 +405,7 @@ TEST_F(TypeDeterminerTest, Stmt_VariableDecl_ModuleScope) { create(&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 @@ TEST_F(TypeDeterminerTest, Expr_ArrayAccessor_Array) { create(&i32, 2)); auto* var = create("my_var", ast::StorageClass::kFunction, &ary); - mod()->AddGlobalVariable(var); + mod->AddGlobalVariable(var); // Register the global EXPECT_TRUE(td()->Determine()); @@ -461,7 +454,7 @@ TEST_F(TypeDeterminerTest, Expr_ArrayAccessor_Alias_Array) { create(&i32, 2)); auto* var = create("my_var", ast::StorageClass::kFunction, &aary); - mod()->AddGlobalVariable(var); + mod->AddGlobalVariable(var); // Register the global EXPECT_TRUE(td()->Determine()); @@ -486,7 +479,7 @@ TEST_F(TypeDeterminerTest, Expr_ArrayAccessor_Array_Constant) { auto* var = create("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 @@ TEST_F(TypeDeterminerTest, Expr_ArrayAccessor_Matrix) { auto* idx = create( create(&i32, 2)); auto* var = create("my_var", ast::StorageClass::kNone, &mat); - mod()->AddGlobalVariable(var); + mod->AddGlobalVariable(var); // Register the global EXPECT_TRUE(td()->Determine()); @@ -532,7 +525,7 @@ TEST_F(TypeDeterminerTest, Expr_ArrayAccessor_Matrix_BothDimensions) { auto* idx2 = create( create(&i32, 1)); auto* var = create("my_var", ast::StorageClass::kNone, &mat); - mod()->AddGlobalVariable(var); + mod->AddGlobalVariable(var); // Register the global EXPECT_TRUE(td()->Determine()); @@ -558,7 +551,7 @@ TEST_F(TypeDeterminerTest, Expr_ArrayAccessor_Vector) { auto* idx = create( create(&i32, 2)); auto* var = create("my_var", ast::StorageClass::kNone, &vec); - mod()->AddGlobalVariable(var); + mod->AddGlobalVariable(var); // Register the global EXPECT_TRUE(td()->Determine()); @@ -592,7 +585,7 @@ TEST_F(TypeDeterminerTest, Expr_Call) { ast::VariableList params; auto* func = create("my_func", params, &f32, create()); - mod()->AddFunction(func); + mod->AddFunction(func); // Register the function EXPECT_TRUE(td()->Determine()); @@ -611,7 +604,7 @@ TEST_F(TypeDeterminerTest, Expr_Call_WithParams) { ast::VariableList params; auto* func = create("my_func", params, &f32, create()); - mod()->AddFunction(func); + mod->AddFunction(func); // Register the function EXPECT_TRUE(td()->Determine()); @@ -695,7 +688,7 @@ TEST_F(TypeDeterminerTest, Expr_Constructor_Type) { TEST_F(TypeDeterminerTest, Expr_Identifier_GlobalVariable) { ast::type::F32Type f32; auto* var = create("my_var", ast::StorageClass::kNone, &f32); - mod()->AddGlobalVariable(var); + mod->AddGlobalVariable(var); // Register the global EXPECT_TRUE(td()->Determine()); @@ -711,7 +704,7 @@ TEST_F(TypeDeterminerTest, Expr_Identifier_GlobalConstant) { ast::type::F32Type f32; auto* var = create("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 @@ TEST_F(TypeDeterminerTest, Expr_Identifier_Function) { ast::VariableList params; auto* func = create("my_func", params, &f32, create()); - mod()->AddFunction(func); + mod->AddFunction(func); // Register the function EXPECT_TRUE(td()->Determine()); @@ -822,11 +815,11 @@ TEST_F(TypeDeterminerTest, Function_RegisterInputOutputVariables) { auto* priv_var = create("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(); @@ -844,7 +837,7 @@ TEST_F(TypeDeterminerTest, Function_RegisterInputOutputVariables) { create("priv_var"))); auto* func = create("my_func", params, &f32, body); - mod()->AddFunction(func); + mod->AddFunction(func); // Register the function EXPECT_TRUE(td()->Determine()); @@ -872,11 +865,11 @@ TEST_F(TypeDeterminerTest, Function_RegisterInputOutputVariables_SubFunction) { auto* priv_var = create("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(); body->append(create( @@ -894,7 +887,7 @@ TEST_F(TypeDeterminerTest, Function_RegisterInputOutputVariables_SubFunction) { ast::VariableList params; auto* func = create("my_func", params, &f32, body); - mod()->AddFunction(func); + mod->AddFunction(func); body = create(); body->append(create( @@ -903,7 +896,7 @@ TEST_F(TypeDeterminerTest, Function_RegisterInputOutputVariables_SubFunction) { ast::ExpressionList{}))); auto* func2 = create("func", params, &f32, body); - mod()->AddFunction(func2); + mod->AddFunction(func2); // Register the function EXPECT_TRUE(td()->Determine()); @@ -933,7 +926,7 @@ TEST_F(TypeDeterminerTest, Function_NotRegisterFunctionVariable) { ast::VariableList params; auto* func = create("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 @@ TEST_F(TypeDeterminerTest, Expr_MemberAccessor_Struct) { auto* var = create("my_struct", ast::StorageClass::kNone, &st); - mod()->AddGlobalVariable(var); + mod->AddGlobalVariable(var); // Register the global EXPECT_TRUE(td()->Determine()); @@ -993,7 +986,7 @@ TEST_F(TypeDeterminerTest, Expr_MemberAccessor_Struct_Alias) { auto* var = create("my_struct", ast::StorageClass::kNone, &alias); - mod()->AddGlobalVariable(var); + mod->AddGlobalVariable(var); // Register the global EXPECT_TRUE(td()->Determine()); @@ -1015,7 +1008,7 @@ TEST_F(TypeDeterminerTest, Expr_MemberAccessor_VectorSwizzle) { ast::type::VectorType vec3(&f32, 3); auto* var = create("my_vec", ast::StorageClass::kNone, &vec3); - mod()->AddGlobalVariable(var); + mod->AddGlobalVariable(var); // Register the global EXPECT_TRUE(td()->Determine()); @@ -1036,7 +1029,7 @@ TEST_F(TypeDeterminerTest, Expr_MemberAccessor_VectorSwizzle_SingleElement) { ast::type::VectorType vec3(&f32, 3); auto* var = create("my_vec", ast::StorageClass::kNone, &vec3); - mod()->AddGlobalVariable(var); + mod->AddGlobalVariable(var); // Register the global EXPECT_TRUE(td()->Determine()); @@ -1100,7 +1093,7 @@ TEST_F(TypeDeterminerTest, Expr_Accessor_MultiLevel) { ast::type::StructType stA("A", strctA); auto* var = create("c", ast::StorageClass::kNone, &stA); - mod()->AddGlobalVariable(var); + mod->AddGlobalVariable(var); // Register the global EXPECT_TRUE(td()->Determine()); @@ -1133,7 +1126,7 @@ TEST_P(Expr_Binary_BitwiseTest, Scalar) { ast::type::I32Type i32; auto* var = create("val", ast::StorageClass::kNone, &i32); - mod()->AddGlobalVariable(var); + mod->AddGlobalVariable(var); // Register the global ASSERT_TRUE(td()->Determine()) << td()->error(); @@ -1153,7 +1146,7 @@ TEST_P(Expr_Binary_BitwiseTest, Vector) { ast::type::VectorType vec3(&i32, 3); auto* var = create("val", ast::StorageClass::kNone, &vec3); - mod()->AddGlobalVariable(var); + mod->AddGlobalVariable(var); // Register the global ASSERT_TRUE(td()->Determine()) << td()->error(); @@ -1187,7 +1180,7 @@ TEST_P(Expr_Binary_LogicalTest, Scalar) { auto* var = create("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 @@ TEST_P(Expr_Binary_LogicalTest, Vector) { ast::type::VectorType vec3(&bool_type, 3); auto* var = create("val", ast::StorageClass::kNone, &vec3); - mod()->AddGlobalVariable(var); + mod->AddGlobalVariable(var); // Register the global ASSERT_TRUE(td()->Determine()) << td()->error(); @@ -1233,7 +1226,7 @@ TEST_P(Expr_Binary_CompareTest, Scalar) { ast::type::I32Type i32; auto* var = create("val", ast::StorageClass::kNone, &i32); - mod()->AddGlobalVariable(var); + mod->AddGlobalVariable(var); // Register the global ASSERT_TRUE(td()->Determine()) << td()->error(); @@ -1253,7 +1246,7 @@ TEST_P(Expr_Binary_CompareTest, Vector) { ast::type::VectorType vec3(&i32, 3); auto* var = create("val", ast::StorageClass::kNone, &vec3); - mod()->AddGlobalVariable(var); + mod->AddGlobalVariable(var); // Register the global ASSERT_TRUE(td()->Determine()) << td()->error(); @@ -1280,7 +1273,7 @@ TEST_F(TypeDeterminerTest, Expr_Binary_Multiply_Scalar_Scalar) { ast::type::I32Type i32; auto* var = create("val", ast::StorageClass::kNone, &i32); - mod()->AddGlobalVariable(var); + mod->AddGlobalVariable(var); // Register the global ASSERT_TRUE(td()->Determine()) << td()->error(); @@ -1302,8 +1295,8 @@ TEST_F(TypeDeterminerTest, Expr_Binary_Multiply_Vector_Scalar) { create("scalar", ast::StorageClass::kNone, &f32); auto* vector = create("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 @@ TEST_F(TypeDeterminerTest, Expr_Binary_Multiply_Scalar_Vector) { create("scalar", ast::StorageClass::kNone, &f32); auto* vector = create("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 @@ TEST_F(TypeDeterminerTest, Expr_Binary_Multiply_Vector_Vector) { auto* vector = create("vector", ast::StorageClass::kNone, &vec3); - mod()->AddGlobalVariable(vector); + mod->AddGlobalVariable(vector); // Register the global ASSERT_TRUE(td()->Determine()) << td()->error(); @@ -1374,8 +1367,8 @@ TEST_F(TypeDeterminerTest, Expr_Binary_Multiply_Matrix_Scalar) { create("scalar", ast::StorageClass::kNone, &f32); auto* matrix = create("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 @@ TEST_F(TypeDeterminerTest, Expr_Binary_Multiply_Scalar_Matrix) { create("scalar", ast::StorageClass::kNone, &f32); auto* matrix = create("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 @@ TEST_F(TypeDeterminerTest, Expr_Binary_Multiply_Matrix_Vector) { create("vector", ast::StorageClass::kNone, &vec3); auto* matrix = create("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 @@ TEST_F(TypeDeterminerTest, Expr_Binary_Multiply_Vector_Matrix) { create("vector", ast::StorageClass::kNone, &vec3); auto* matrix = create("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 @@ TEST_F(TypeDeterminerTest, Expr_Binary_Multiply_Matrix_Matrix) { create("mat4x3", ast::StorageClass::kNone, &mat4x3); auto* matrix2 = create("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 @@ TEST_P(IntrinsicDerivativeTest, Scalar) { ast::type::F32Type f32; auto* var = create("ident", ast::StorageClass::kNone, &f32); - mod()->AddGlobalVariable(var); + mod->AddGlobalVariable(var); // Register the global EXPECT_TRUE(td()->Determine()); @@ -1533,7 +1526,7 @@ TEST_P(IntrinsicDerivativeTest, Vector) { ast::type::VectorType vec4(&f32, 4); auto* var = create("ident", ast::StorageClass::kNone, &vec4); - mod()->AddGlobalVariable(var); + mod->AddGlobalVariable(var); // Register the global EXPECT_TRUE(td()->Determine()); @@ -1575,8 +1568,8 @@ TEST_P(IntrinsicDerivativeTest, ToomManyParams) { auto* var1 = create("ident1", ast::StorageClass::kNone, &vec4); auto* var2 = create("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 @@ TEST_P(Intrinsic, Test) { ast::type::VectorType vec3(&bool_type, 3); auto* var = create("my_var", ast::StorageClass::kNone, &vec3); - mod()->AddGlobalVariable(var); + mod->AddGlobalVariable(var); ast::ExpressionList call_params; call_params.push_back(create("my_var")); @@ -1637,7 +1630,7 @@ TEST_P(Intrinsic_FloatMethod, Vector) { ast::type::VectorType vec3(&f32, 3); auto* var = create("my_var", ast::StorageClass::kNone, &vec3); - mod()->AddGlobalVariable(var); + mod->AddGlobalVariable(var); ast::ExpressionList call_params; call_params.push_back(create("my_var")); @@ -1661,7 +1654,7 @@ TEST_P(Intrinsic_FloatMethod, Scalar) { ast::type::F32Type f32; auto* var = create("my_var", ast::StorageClass::kNone, &f32); - mod()->AddGlobalVariable(var); + mod->AddGlobalVariable(var); ast::ExpressionList call_params; call_params.push_back(create("my_var")); @@ -1682,7 +1675,7 @@ TEST_P(Intrinsic_FloatMethod, MissingParam) { ast::type::F32Type f32; auto* var = create("my_var", ast::StorageClass::kNone, &f32); - mod()->AddGlobalVariable(var); + mod->AddGlobalVariable(var); ast::ExpressionList call_params; ast::CallExpression expr(create(name), @@ -1700,7 +1693,7 @@ TEST_P(Intrinsic_FloatMethod, TooManyParams) { ast::type::F32Type f32; auto* var = create("my_var", ast::StorageClass::kNone, &f32); - mod()->AddGlobalVariable(var); + mod->AddGlobalVariable(var); ast::ExpressionList call_params; call_params.push_back(create("my_var")); @@ -1769,7 +1762,7 @@ class Intrinsic_TextureOperation ast::type::Type* type, ast::ExpressionList* call_params) { auto* var = create(name, ast::StorageClass::kNone, type); - mod()->AddGlobalVariable(var); + mod->AddGlobalVariable(var); call_params->push_back(create(name)); } @@ -1794,7 +1787,7 @@ TEST_P(Intrinsic_StorageTextureOperation, TextureLoadRo) { auto coords_type = get_coords_type(dim, &i32); ast::type::Type* texture_type = - ctx()->type_mgr().Get(std::make_unique( + ctx->type_mgr().Get(std::make_unique( dim, ast::AccessControl::kReadOnly, format)); ast::ExpressionList call_params; @@ -1891,184 +1884,9 @@ TEST_P(Intrinsic_SampledTextureOperation, TextureLoadSampled) { 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::SamplerKind::kSampler); - auto coords_type = get_coords_type(dim, &f32); - auto texture_type = - std::make_unique(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("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::SamplerKind::kSampler); - auto coords_type = get_coords_type(dim, &f32); - auto texture_type = - std::make_unique(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("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::SamplerKind::kSampler); - auto coords_type = get_coords_type(dim, &f32); - auto texture_type = - std::make_unique(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("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::SamplerKind::kComparisonSampler); - auto coords_type = get_coords_type(dim, &f32); - auto texture_type = std::make_unique(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("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 @@ TEST_F(TypeDeterminerTest, Intrinsic_Dot) { ast::type::VectorType vec3(&f32, 3); auto* var = create("my_var", ast::StorageClass::kNone, &vec3); - mod()->AddGlobalVariable(var); + mod->AddGlobalVariable(var); ast::ExpressionList call_params; call_params.push_back(create("my_var")); @@ -2105,8 +1923,8 @@ TEST_F(TypeDeterminerTest, Intrinsic_Select) { auto* var = create("my_var", ast::StorageClass::kNone, &vec3); auto* bool_var = create("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("my_var")); @@ -2130,7 +1948,7 @@ TEST_F(TypeDeterminerTest, Intrinsic_Select_TooFewParams) { ast::type::VectorType vec3(&f32, 3); auto* var = create("v", ast::StorageClass::kNone, &vec3); - mod()->AddGlobalVariable(var); + mod->AddGlobalVariable(var); ast::ExpressionList call_params; call_params.push_back(create("v")); @@ -2150,7 +1968,7 @@ TEST_F(TypeDeterminerTest, Intrinsic_Select_TooManyParams) { ast::type::VectorType vec3(&f32, 3); auto* var = create("v", ast::StorageClass::kNone, &vec3); - mod()->AddGlobalVariable(var); + mod->AddGlobalVariable(var); ast::ExpressionList call_params; call_params.push_back(create("v")); @@ -2175,8 +1993,8 @@ TEST_F(TypeDeterminerTest, Intrinsic_OuterProduct) { auto* var1 = create("v3", ast::StorageClass::kNone, &vec3); auto* var2 = create("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("v3")); @@ -2204,7 +2022,7 @@ TEST_F(TypeDeterminerTest, Intrinsic_OuterProduct_TooFewParams) { ast::type::VectorType vec2(&f32, 2); auto* var2 = create("v2", ast::StorageClass::kNone, &vec2); - mod()->AddGlobalVariable(var2); + mod->AddGlobalVariable(var2); ast::ExpressionList call_params; call_params.push_back(create("v2")); @@ -2224,7 +2042,7 @@ TEST_F(TypeDeterminerTest, Intrinsic_OuterProduct_TooManyParams) { ast::type::VectorType vec2(&f32, 2); auto* var2 = create("v2", ast::StorageClass::kNone, &vec2); - mod()->AddGlobalVariable(var2); + mod->AddGlobalVariable(var2); ast::ExpressionList call_params; call_params.push_back(create("v2")); @@ -2249,7 +2067,7 @@ TEST_P(UnaryOpExpressionTest, Expr_UnaryOp) { ast::type::VectorType vec4(&f32, 4); auto* var = create("ident", ast::StorageClass::kNone, &vec4); - mod()->AddGlobalVariable(var); + mod->AddGlobalVariable(var); // Register the global EXPECT_TRUE(td()->Determine()); @@ -2276,7 +2094,7 @@ TEST_F(TypeDeterminerTest, StorageClass_SetsIfMissing) { body->append(stmt); auto* func = create("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 @@ TEST_F(TypeDeterminerTest, StorageClass_DoesNotSetOnConst) { body->append(stmt); auto* func = create("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 @@ TEST_F(TypeDeterminerTest, StorageClass_NonFunctionClassError) { body->append(stmt); auto* func = create("func", ast::VariableList{}, &i32, body); - mod()->AddFunction(func); + mod->AddFunction(func); EXPECT_FALSE(td()->Determine()); EXPECT_EQ(td()->error(), @@ -2403,6 +2221,7 @@ INSTANTIATE_TEST_SUITE_P( 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 @@ TEST_F(TypeDeterminerTest, ImportData_GLSL_Determinant) { ast::type::MatrixType mat(&f32, 3, 3); auto* var = create("var", ast::StorageClass::kFunction, &mat); - mod()->AddGlobalVariable(var); + mod->AddGlobalVariable(var); // Register the global ASSERT_TRUE(td()->Determine()) << td()->error(); @@ -4383,7 +4202,7 @@ TEST_P(ImportData_Matrix_OneParam_Test, Error_Float) { ast::type::F32Type f32; auto* var = create("var", ast::StorageClass::kFunction, &f32); - mod()->AddGlobalVariable(var); + mod->AddGlobalVariable(var); // Register the global ASSERT_TRUE(td()->Determine()) << td()->error(); @@ -4419,7 +4238,7 @@ TEST_P(ImportData_Matrix_OneParam_Test, TooManyParams) { ast::type::MatrixType mat(&f32, 3, 3); auto* var = create("var", ast::StorageClass::kFunction, &mat); - mod()->AddGlobalVariable(var); + mod->AddGlobalVariable(var); // Register the global ASSERT_TRUE(td()->Determine()) << td()->error(); @@ -4495,21 +4314,21 @@ TEST_F(TypeDeterminerTest, Function_EntryPoints_StageDecoration) { ep_2->add_decoration( create(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("first", ast::StorageClass::kPrivate, &f32)); - mod()->AddGlobalVariable( + mod->AddGlobalVariable( create("second", ast::StorageClass::kPrivate, &f32)); - mod()->AddGlobalVariable( + mod->AddGlobalVariable( create("call_a", ast::StorageClass::kPrivate, &f32)); - mod()->AddGlobalVariable( + mod->AddGlobalVariable( create("call_b", ast::StorageClass::kPrivate, &f32)); - mod()->AddGlobalVariable( + mod->AddGlobalVariable( create("call_c", ast::StorageClass::kPrivate, &f32)); // Register the functions and calculate the callers @@ -4533,5 +4352,238 @@ TEST_F(TypeDeterminerTest, Function_EntryPoints_StageDecoration) { EXPECT_TRUE(ep_2->ancestor_entry_points().empty()); } +using TypeDeterminerTextureIntrinsicTest = + TypeDeterminerTestWithParam; + +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 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 ""; +} + +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( + param.texture_dimension, datatype)); + break; + + case ast::intrinsic::test::TextureKind::kDepth: + Var("texture", ast::StorageClass::kNone, + ctx->type_mgr().Get( + 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( + 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 518e9cedff..081a3a2bd3 100644 --- a/src/writer/spirv/builder.cc +++ b/src/writer/spirv/builder.cc @@ -1749,9 +1749,15 @@ uint32_t Builder::GenerateIntrinsic(ast::IdentifierExpression* ident, 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 @@ uint32_t Builder::GenerateIntrinsic(ast::IdentifierExpression* ident, 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 @@ uint32_t Builder::GenerateIntrinsic(ast::IdentifierExpression* ident, 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 @@ uint32_t Builder::GenerateIntrinsic(ast::IdentifierExpression* ident, 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 @@ uint32_t Builder::GenerateIntrinsic(ast::IdentifierExpression* ident, 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( + 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 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 dd0d20daa8..ac3f452561 100644 --- a/src/writer/spirv/builder.h +++ b/src/writer/spirv/builder.h @@ -231,7 +231,7 @@ class Builder { 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 @@ class Builder { /// 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 3b056376c7..e41cc8a34b 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_TextureLoad_Multisampled_2d) { )"); } -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; - 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(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 @@ TEST_F(IntrinsicBuilderTest, Call_TextureSampleLevel_1d) { %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(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 @@ TEST_F(IntrinsicBuilderTest, Call_TextureSampleLevel_2d) { %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(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(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 {"", ""}; +} // 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( + param.texture_dimension, datatype)); + break; + + case ast::intrinsic::test::TextureKind::kDepth: + tex = Var("texture", ast::StorageClass::kNone, + ctx->type_mgr().Get( + 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 @@ TEST_F(IntrinsicBuilderTest, Call_TextureSampleCompare_Twice) { %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 )"); }