Implement textureNumLayers()
SPIR-V reader TODO
Bug: tint:140
Bug: tint:437
Change-Id: Id397f5f07a2f18f365dc9c2d588e619cea8f89dc
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/37844
Reviewed-by: dan sinclair <dsinclair@chromium.org>
Commit-Queue: Ben Clayton <bclayton@google.com>
diff --git a/src/ast/intrinsic.cc b/src/ast/intrinsic.cc
index 73f3ab3..3f6f8ac 100644
--- a/src/ast/intrinsic.cc
+++ b/src/ast/intrinsic.cc
@@ -21,211 +21,220 @@
/// The emitted name matches the spelling in the WGSL spec.
/// including case.
switch (i) {
+ case Intrinsic::kNone:
+ return out;
case Intrinsic::kAbs:
out << "abs";
- break;
+ return out;
case Intrinsic::kAcos:
out << "acos";
- break;
+ return out;
case Intrinsic::kAll:
out << "all";
- break;
+ return out;
case Intrinsic::kAny:
out << "any";
- break;
+ return out;
case Intrinsic::kArrayLength:
out << "arrayLength";
- break;
+ return out;
case Intrinsic::kAsin:
out << "asin";
- break;
+ return out;
case Intrinsic::kAtan:
out << "atan";
- break;
+ return out;
case Intrinsic::kAtan2:
out << "atan2";
- break;
+ return out;
case Intrinsic::kCeil:
out << "ceil";
- break;
+ return out;
case Intrinsic::kClamp:
out << "clamp";
- break;
+ return out;
case Intrinsic::kCos:
out << "cos";
- break;
+ return out;
case Intrinsic::kCosh:
out << "cosh";
- break;
+ return out;
case Intrinsic::kCountOneBits:
out << "countOneBits";
- break;
+ return out;
case Intrinsic::kCross:
out << "cross";
- break;
+ return out;
case Intrinsic::kDeterminant:
out << "determinant";
- break;
+ return out;
case Intrinsic::kDistance:
out << "distance";
- break;
+ return out;
case Intrinsic::kDot:
out << "dot";
- break;
+ return out;
case Intrinsic::kDpdx:
out << "dpdx";
- break;
+ return out;
case Intrinsic::kDpdxCoarse:
out << "dpdxCoarse";
- break;
+ return out;
case Intrinsic::kDpdxFine:
out << "dpdxFine";
- break;
+ return out;
case Intrinsic::kDpdy:
out << "dpdy";
- break;
+ return out;
case Intrinsic::kDpdyCoarse:
out << "dpdyCoarse";
- break;
+ return out;
case Intrinsic::kDpdyFine:
out << "dpdyFine";
- break;
+ return out;
case Intrinsic::kExp:
out << "exp";
- break;
+ return out;
case Intrinsic::kExp2:
out << "exp2";
- break;
+ return out;
case Intrinsic::kFaceForward:
out << "faceForward";
- break;
+ return out;
case Intrinsic::kFloor:
out << "floor";
- break;
+ return out;
case Intrinsic::kFma:
out << "fma";
- break;
+ return out;
case Intrinsic::kFract:
out << "fract";
- break;
+ return out;
case Intrinsic::kFrexp:
out << "frexp";
- break;
+ return out;
case Intrinsic::kFwidth:
out << "fwidth";
- break;
+ return out;
case Intrinsic::kFwidthCoarse:
out << "fwidthCoarse";
- break;
+ return out;
case Intrinsic::kFwidthFine:
out << "fwidthFine";
- break;
+ return out;
case Intrinsic::kInverseSqrt:
out << "inverseSqrt";
- break;
+ return out;
case Intrinsic::kIsFinite:
out << "isFinite";
- break;
+ return out;
case Intrinsic::kIsInf:
out << "isInf";
- break;
+ return out;
case Intrinsic::kIsNan:
out << "isNan";
- break;
+ return out;
case Intrinsic::kIsNormal:
out << "isNormal";
- break;
+ return out;
case Intrinsic::kLdexp:
out << "ldexp";
- break;
+ return out;
case Intrinsic::kLength:
out << "length";
- break;
+ return out;
case Intrinsic::kLog:
out << "log";
- break;
+ return out;
case Intrinsic::kLog2:
out << "log2";
- break;
+ return out;
case Intrinsic::kMax:
out << "max";
- break;
+ return out;
case Intrinsic::kMin:
out << "min";
- break;
+ return out;
case Intrinsic::kMix:
out << "mix";
- break;
+ return out;
case Intrinsic::kModf:
out << "modf";
- break;
+ return out;
case Intrinsic::kNormalize:
out << "normalize";
- break;
+ return out;
case Intrinsic::kPow:
out << "pow";
- break;
+ return out;
case Intrinsic::kReflect:
out << "reflect";
- break;
+ return out;
case Intrinsic::kReverseBits:
out << "reverseBits";
- break;
+ return out;
case Intrinsic::kRound:
out << "round";
- break;
+ return out;
case Intrinsic::kSelect:
out << "select";
- break;
+ return out;
case Intrinsic::kSign:
out << "sign";
- break;
+ return out;
case Intrinsic::kSin:
out << "sin";
- break;
+ return out;
case Intrinsic::kSinh:
out << "sinh";
- break;
+ return out;
case Intrinsic::kSmoothStep:
out << "smoothStep";
- break;
+ return out;
case Intrinsic::kSqrt:
out << "sqrt";
- break;
+ return out;
case Intrinsic::kStep:
out << "step";
- break;
+ return out;
case Intrinsic::kTan:
out << "tan";
- break;
+ return out;
case Intrinsic::kTanh:
out << "tanh";
- break;
+ return out;
+ case Intrinsic::kTextureDimensions:
+ out << "textureDimensions";
+ return out;
case Intrinsic::kTextureLoad:
out << "textureLoad";
- break;
+ return out;
+ case Intrinsic::kTextureNumLayers:
+ out << "textureNumLayers";
+ return out;
case Intrinsic::kTextureSample:
out << "textureSample";
- break;
+ return out;
case Intrinsic::kTextureSampleBias:
out << "textureSampleBias";
- break;
+ return out;
case Intrinsic::kTextureSampleCompare:
out << "textureSampleCompare";
- break;
+ return out;
case Intrinsic::kTextureSampleGrad:
out << "textureSampleGrad";
- break;
+ return out;
case Intrinsic::kTextureSampleLevel:
out << "textureSampleLevel";
- break;
+ return out;
+ case Intrinsic::kTextureStore:
+ out << "textureStore";
+ return out;
case Intrinsic::kTrunc:
out << "trunc";
- break;
- default:
- out << "Unknown";
- break;
+ return out;
}
+ out << "Unknown";
return out;
}
@@ -260,7 +269,7 @@
bool IsTextureIntrinsic(Intrinsic i) {
return i == Intrinsic::kTextureDimensions || i == Intrinsic::kTextureLoad ||
- i == Intrinsic::kTextureSample ||
+ i == Intrinsic::kTextureNumLayers || i == Intrinsic::kTextureSample ||
i == Intrinsic::kTextureSampleLevel ||
i == Intrinsic::kTextureSampleBias ||
i == Intrinsic::kTextureSampleCompare ||
@@ -268,7 +277,8 @@
}
bool IsImageQueryIntrinsic(Intrinsic i) {
- return i == ast::Intrinsic::kTextureDimensions;
+ return i == ast::Intrinsic::kTextureDimensions ||
+ i == Intrinsic::kTextureNumLayers;
}
} // namespace intrinsic
diff --git a/src/ast/intrinsic.h b/src/ast/intrinsic.h
index 9de55b1..36eb5ad 100644
--- a/src/ast/intrinsic.h
+++ b/src/ast/intrinsic.h
@@ -85,6 +85,7 @@
kTanh,
kTextureDimensions,
kTextureLoad,
+ kTextureNumLayers,
kTextureSample,
kTextureSampleBias,
kTextureSampleCompare,
diff --git a/src/ast/intrinsic_texture_helper_test.cc b/src/ast/intrinsic_texture_helper_test.cc
index 7d06193..ac3c61a 100644
--- a/src/ast/intrinsic_texture_helper_test.cc
+++ b/src/ast/intrinsic_texture_helper_test.cc
@@ -542,6 +542,86 @@
[](Builder* b) { return b->ExprList("texture"); },
},
{
+ ValidTextureOverload::kNumLayers1dArray,
+ "textureNumLayers(t : texture_1d_array<T>) -> i32",
+ TextureKind::kRegular,
+ type::SamplerKind::kSampler,
+ type::TextureDimension::k1dArray,
+ TextureDataType::kF32,
+ "textureNumLayers",
+ [](Builder* b) { return b->ExprList("texture"); },
+ },
+ {
+ ValidTextureOverload::kNumLayers2dArray,
+ "textureNumLayers(t : texture_2d_array<T>) -> i32",
+ TextureKind::kRegular,
+ type::SamplerKind::kSampler,
+ type::TextureDimension::k2dArray,
+ TextureDataType::kF32,
+ "textureNumLayers",
+ [](Builder* b) { return b->ExprList("texture"); },
+ },
+ {
+ ValidTextureOverload::kNumLayersCubeArray,
+ "textureNumLayers(t : texture_cube_array<T>) -> i32",
+ TextureKind::kRegular,
+ type::SamplerKind::kSampler,
+ type::TextureDimension::kCubeArray,
+ TextureDataType::kF32,
+ "textureNumLayers",
+ [](Builder* b) { return b->ExprList("texture"); },
+ },
+ {
+ ValidTextureOverload::kNumLayersMultisampled_2dArray,
+ "textureNumLayers(t : texture_multisampled_2d_array<T>) -> i32",
+ TextureKind::kMultisampled,
+ type::SamplerKind::kSampler,
+ type::TextureDimension::k2dArray,
+ TextureDataType::kF32,
+ "textureNumLayers",
+ [](Builder* b) { return b->ExprList("texture"); },
+ },
+ {
+ ValidTextureOverload::kNumLayersDepth2dArray,
+ "textureNumLayers(t : texture_depth_2d_array) -> i32",
+ TextureKind::kDepth,
+ type::SamplerKind::kSampler,
+ type::TextureDimension::k2dArray,
+ TextureDataType::kF32,
+ "textureNumLayers",
+ [](Builder* b) { return b->ExprList("texture"); },
+ },
+ {
+ ValidTextureOverload::kNumLayersDepthCubeArray,
+ "textureNumLayers(t : texture_depth_cube_array) -> i32",
+ TextureKind::kDepth,
+ type::SamplerKind::kSampler,
+ type::TextureDimension::kCubeArray,
+ TextureDataType::kF32,
+ "textureNumLayers",
+ [](Builder* b) { return b->ExprList("texture"); },
+ },
+ {
+ ValidTextureOverload::kNumLayersStorageWO1dArray,
+ "textureNumLayers(t : texture_storage_1d_array<F>) -> i32",
+ ast::AccessControl::kWriteOnly,
+ ast::type::ImageFormat::kRgba32Float,
+ type::TextureDimension::k1dArray,
+ TextureDataType::kF32,
+ "textureNumLayers",
+ [](Builder* b) { return b->ExprList("texture"); },
+ },
+ {
+ ValidTextureOverload::kNumLayersStorageWO2dArray,
+ "textureNumLayers(t : texture_storage_2d_array<F>) -> i32",
+ ast::AccessControl::kWriteOnly,
+ ast::type::ImageFormat::kRgba32Float,
+ type::TextureDimension::k2dArray,
+ TextureDataType::kF32,
+ "textureNumLayers",
+ [](Builder* b) { return b->ExprList("texture"); },
+ },
+ {
ValidTextureOverload::kSample1dF32,
"textureSample(t : texture_1d<f32>,\n"
" s : sampler,\n"
diff --git a/src/ast/intrinsic_texture_helper_test.h b/src/ast/intrinsic_texture_helper_test.h
index fae5a2a..ca0d655 100644
--- a/src/ast/intrinsic_texture_helper_test.h
+++ b/src/ast/intrinsic_texture_helper_test.h
@@ -69,6 +69,14 @@
kDimensionsStorageWO2d,
kDimensionsStorageWO2dArray,
kDimensionsStorageWO3d,
+ kNumLayers1dArray,
+ kNumLayers2dArray,
+ kNumLayersCubeArray,
+ kNumLayersMultisampled_2dArray,
+ kNumLayersDepth2dArray,
+ kNumLayersDepthCubeArray,
+ kNumLayersStorageWO1dArray,
+ kNumLayersStorageWO2dArray,
kSample1dF32,
kSample1dArrayF32,
kSample2dF32,
diff --git a/src/type_determiner.cc b/src/type_determiner.cc
index 8f3f64b..57ba101 100644
--- a/src/type_determiner.cc
+++ b/src/type_determiner.cc
@@ -566,6 +566,9 @@
param.idx.level = param.count++;
}
break;
+ case ast::Intrinsic::kTextureNumLayers:
+ param.idx.texture = param.count++;
+ break;
case ast::Intrinsic::kTextureLoad:
param.idx.texture = param.count++;
param.idx.coords = param.count++;
@@ -669,46 +672,54 @@
// Set the function return type
ast::type::Type* return_type = nullptr;
- if (ident->intrinsic() == ast::Intrinsic::kTextureDimensions) {
- auto* i32 = mod_->create<ast::type::I32>();
- switch (texture->dim()) {
- default:
- set_error(expr->source(), "invalid texture dimensions");
- break;
- case ast::type::TextureDimension::k1d:
- case ast::type::TextureDimension::k1dArray:
- return_type = i32;
- break;
- case ast::type::TextureDimension::k2d:
- case ast::type::TextureDimension::k2dArray:
- return_type = mod_->create<ast::type::Vector>(i32, 2);
- break;
- case ast::type::TextureDimension::k3d:
- case ast::type::TextureDimension::kCube:
- case ast::type::TextureDimension::kCubeArray:
- return_type = mod_->create<ast::type::Vector>(i32, 3);
- break;
- }
- } else if (ident->intrinsic() == ast::Intrinsic::kTextureStore) {
- return_type = mod_->create<ast::type::Void>();
- } else {
- if (texture->Is<ast::type::DepthTexture>()) {
- return_type = mod_->create<ast::type::F32>();
- } else {
- ast::type::Type* type = nullptr;
- if (auto* storage = texture->As<ast::type::StorageTexture>()) {
- type = storage->type();
- } else if (auto* sampled = texture->As<ast::type::SampledTexture>()) {
- type = sampled->type();
- } else if (auto* msampled =
- texture->As<ast::type::MultisampledTexture>()) {
- type = msampled->type();
- } else {
- set_error(expr->source(),
- "unknown texture type for texture sampling");
- return false;
+ switch (ident->intrinsic()) {
+ case ast::Intrinsic::kTextureDimensions: {
+ auto* i32 = mod_->create<ast::type::I32>();
+ switch (texture->dim()) {
+ default:
+ set_error(expr->source(), "invalid texture dimensions");
+ break;
+ case ast::type::TextureDimension::k1d:
+ case ast::type::TextureDimension::k1dArray:
+ return_type = i32;
+ break;
+ case ast::type::TextureDimension::k2d:
+ case ast::type::TextureDimension::k2dArray:
+ return_type = mod_->create<ast::type::Vector>(i32, 2);
+ break;
+ case ast::type::TextureDimension::k3d:
+ case ast::type::TextureDimension::kCube:
+ case ast::type::TextureDimension::kCubeArray:
+ return_type = mod_->create<ast::type::Vector>(i32, 3);
+ break;
}
- return_type = mod_->create<ast::type::Vector>(type, 4);
+ break;
+ }
+ case ast::Intrinsic::kTextureNumLayers:
+ return_type = mod_->create<ast::type::I32>();
+ break;
+ case ast::Intrinsic::kTextureStore:
+ return_type = mod_->create<ast::type::Void>();
+ break;
+ default: {
+ if (texture->Is<ast::type::DepthTexture>()) {
+ return_type = mod_->create<ast::type::F32>();
+ } else {
+ ast::type::Type* type = nullptr;
+ if (auto* storage = texture->As<ast::type::StorageTexture>()) {
+ type = storage->type();
+ } else if (auto* sampled = texture->As<ast::type::SampledTexture>()) {
+ type = sampled->type();
+ } else if (auto* msampled =
+ texture->As<ast::type::MultisampledTexture>()) {
+ type = msampled->type();
+ } else {
+ set_error(expr->source(),
+ "unknown texture type for texture sampling");
+ return false;
+ }
+ return_type = mod_->create<ast::type::Vector>(type, 4);
+ }
}
}
expr->func()->set_result_type(return_type);
@@ -1021,6 +1032,8 @@
ident->set_intrinsic(ast::Intrinsic::kTanh);
} else if (name == "textureDimensions") {
ident->set_intrinsic(ast::Intrinsic::kTextureDimensions);
+ } else if (name == "textureNumLayers") {
+ ident->set_intrinsic(ast::Intrinsic::kTextureNumLayers);
} else if (name == "textureLoad") {
ident->set_intrinsic(ast::Intrinsic::kTextureLoad);
} else if (name == "textureStore") {
diff --git a/src/type_determiner_test.cc b/src/type_determiner_test.cc
index 300cc99..dcd3519 100644
--- a/src/type_determiner_test.cc
+++ b/src/type_determiner_test.cc
@@ -1764,6 +1764,7 @@
IntrinsicData{"tanh", ast::Intrinsic::kTanh},
IntrinsicData{"textureDimensions", ast::Intrinsic::kTextureDimensions},
IntrinsicData{"textureLoad", ast::Intrinsic::kTextureLoad},
+ IntrinsicData{"textureNumLayers", ast::Intrinsic::kTextureNumLayers},
IntrinsicData{"textureSample", ast::Intrinsic::kTextureSample},
IntrinsicData{"textureSampleBias", ast::Intrinsic::kTextureSampleBias},
IntrinsicData{"textureSampleCompare",
@@ -2928,6 +2929,15 @@
case ValidTextureOverload::kDimensionsStorageWO2dArray:
case ValidTextureOverload::kDimensionsStorageWO3d:
return R"(textureDimensions(texture))";
+ case ValidTextureOverload::kNumLayers1dArray:
+ case ValidTextureOverload::kNumLayers2dArray:
+ case ValidTextureOverload::kNumLayersCubeArray:
+ case ValidTextureOverload::kNumLayersMultisampled_2dArray:
+ case ValidTextureOverload::kNumLayersDepth2dArray:
+ case ValidTextureOverload::kNumLayersDepthCubeArray:
+ case ValidTextureOverload::kNumLayersStorageWO1dArray:
+ case ValidTextureOverload::kNumLayersStorageWO2dArray:
+ return R"(textureNumLayers(texture))";
case ValidTextureOverload::kDimensions2dLevel:
case ValidTextureOverload::kDimensions2dArrayLevel:
case ValidTextureOverload::kDimensions3dLevel:
@@ -3181,6 +3191,8 @@
ty.vec3<i32>()->type_name());
break;
}
+ } else if (std::string(param.function) == "textureNumLayers") {
+ EXPECT_EQ(call->result_type(), ty.i32);
} else if (std::string(param.function) == "textureStore") {
EXPECT_EQ(call->result_type(), ty.void_);
} else {
diff --git a/src/writer/hlsl/generator_impl.cc b/src/writer/hlsl/generator_impl.cc
index e1a5737..a750271 100644
--- a/src/writer/hlsl/generator_impl.cc
+++ b/src/writer/hlsl/generator_impl.cc
@@ -695,49 +695,99 @@
auto* texture_type =
texture->result_type()->UnwrapAll()->As<ast::type::Texture>();
- if (ident->intrinsic() == ast::Intrinsic::kTextureDimensions) {
- // Declare a variable to hold the texture dimensions
- auto dims = generate_name(kTempNamePrefix);
- EmitType(pre, expr->result_type(), "");
- pre << " " << dims << ";" << std::endl;
+ switch (ident->intrinsic()) {
+ case ast::Intrinsic::kTextureDimensions:
+ case ast::Intrinsic::kTextureNumLayers: {
+ // Declare a variable to hold the queried texture info
+ auto dims = generate_name(kTempNamePrefix);
- // Now call GetDimensions() on the texture object, populating the dims
- // variable.
- std::stringstream tex_out;
- if (!EmitExpression(pre, tex_out, texture)) {
- return false;
- }
- pre << tex_out.str() << ".GetDimensions(";
- if (pidx.level != kNotUsed) {
- pre << pidx.level << ", ";
- }
- switch (texture_type->dim()) {
- case ast::type::TextureDimension::kNone:
- error_ = "texture dimension is kNone";
+ std::stringstream texture_name;
+ if (!EmitExpression(pre, texture_name, texture)) {
return false;
- case ast::type::TextureDimension::k1d:
- case ast::type::TextureDimension::k1dArray:
- pre << dims << ");";
- break;
- case ast::type::TextureDimension::k2d:
- case ast::type::TextureDimension::k2dArray:
- pre << dims << "[0], " << dims << "[1]);";
- break;
- case ast::type::TextureDimension::k3d:
- pre << dims << "[0], " << dims << "[1], " << dims << "[2]);";
- break;
- case ast::type::TextureDimension::kCube:
- case ast::type::TextureDimension::kCubeArray:
- // width == height == depth for cubes
- // See https://github.com/gpuweb/gpuweb/issues/1345
- pre << dims << "[0], " << dims << "[1]);\n";
- pre << dims << "[2] = " << dims << "[1];"; // dims[2] = dims[1]
- break;
- }
+ }
- // The result of the textureDimensions() call is now the temporary variable.
- out << dims;
- return true;
+ auto get_dimensions = [&](std::initializer_list<const char*>&& suffixes) {
+ pre << texture_name.str() << ".GetDimensions(";
+ if (pidx.level != kNotUsed) {
+ pre << pidx.level << ", ";
+ }
+ bool first = true;
+ for (auto* suffix : suffixes) {
+ if (!first) {
+ pre << ", ";
+ }
+ first = false;
+ pre << dims << suffix;
+ }
+ pre << ");";
+ };
+
+ const char* dims_swizzle = "";
+ const char* num_els_swizzle = "";
+
+ std::stringstream ss;
+ switch (texture_type->dim()) {
+ case ast::type::TextureDimension::kNone:
+ error_ = "texture dimension is kNone";
+ return false;
+ case ast::type::TextureDimension::k1d:
+ pre << "int " << dims << ";\n";
+ get_dimensions({""});
+ break;
+ case ast::type::TextureDimension::k1dArray:
+ pre << "int2 " << dims << ";\n";
+ get_dimensions({".x", ".y"});
+ dims_swizzle = ".x";
+ num_els_swizzle = ".y";
+ break;
+ case ast::type::TextureDimension::k2d:
+ pre << "int2 " << dims << ";\n";
+ get_dimensions({".x", ".y"});
+ break;
+ case ast::type::TextureDimension::k2dArray:
+ pre << "int3 " << dims << ";\n";
+ get_dimensions({".x", ".y", ".z"});
+ dims_swizzle = ".xy";
+ num_els_swizzle = ".z";
+ break;
+ case ast::type::TextureDimension::k3d:
+ pre << "int3 " << dims << ";\n";
+ get_dimensions({".x", ".y", ".z"});
+ break;
+ case ast::type::TextureDimension::kCube:
+ // width == height == depth for cubes
+ // See https://github.com/gpuweb/gpuweb/issues/1345
+ pre << "int2 " << dims << ";\n";
+ get_dimensions({".x", ".y"});
+ dims_swizzle = ".xyy"; // [width, height, height]
+ break;
+ case ast::type::TextureDimension::kCubeArray:
+ // width == height == depth for cubes
+ // See https://github.com/gpuweb/gpuweb/issues/1345
+ pre << "int3 " << dims << ";\n";
+ get_dimensions({".x", ".y", ".z"});
+ dims_swizzle = ".xyy"; // [width, height, height]
+ num_els_swizzle = ".z";
+ break;
+ }
+
+ // The result of the textureDimensions() call is now in temporary
+ // variable. This may be packed with other data, so the final expression
+ // may require a swizzle.
+ switch (ident->intrinsic()) {
+ case ast::Intrinsic::kTextureDimensions:
+ out << dims << dims_swizzle;
+ return true;
+ case ast::Intrinsic::kTextureNumLayers:
+ out << dims << num_els_swizzle;
+ return true;
+ default:
+ error_ = "Unhandled intrinsic";
+ return false;
+ }
+ }
+ default:
+ break;
}
if (!EmitExpression(pre, out, texture))
diff --git a/src/writer/hlsl/generator_impl_intrinsic_texture_test.cc b/src/writer/hlsl/generator_impl_intrinsic_texture_test.cc
index e5b5ee2..972283c 100644
--- a/src/writer/hlsl/generator_impl_intrinsic_texture_test.cc
+++ b/src/writer/hlsl/generator_impl_intrinsic_texture_test.cc
@@ -41,75 +41,121 @@
using ValidTextureOverload = ast::intrinsic::test::ValidTextureOverload;
switch (overload) {
case ValidTextureOverload::kDimensions1d:
- case ValidTextureOverload::kDimensions1dArray:
case ValidTextureOverload::kDimensionsStorageRO1d:
- case ValidTextureOverload::kDimensionsStorageRO1dArray:
case ValidTextureOverload::kDimensionsStorageWO1d:
- case ValidTextureOverload::kDimensionsStorageWO1dArray:
return {
"int _tint_tmp;\n"
"texture_tint_0.GetDimensions(_tint_tmp);",
"_tint_tmp",
};
- case ValidTextureOverload::kDimensions2d:
- case ValidTextureOverload::kDimensions2dArray:
- case ValidTextureOverload::kDimensionsMultisampled_2d:
- case ValidTextureOverload::kDimensionsMultisampled_2dArray:
- case ValidTextureOverload::kDimensionsDepth2d:
- case ValidTextureOverload::kDimensionsDepth2dArray:
- case ValidTextureOverload::kDimensionsStorageRO2d:
- case ValidTextureOverload::kDimensionsStorageRO2dArray:
- case ValidTextureOverload::kDimensionsStorageWO2d:
- case ValidTextureOverload::kDimensionsStorageWO2dArray:
+ case ValidTextureOverload::kDimensions1dArray:
+ case ValidTextureOverload::kDimensionsStorageRO1dArray:
+ case ValidTextureOverload::kDimensionsStorageWO1dArray:
return {
"int2 _tint_tmp;\n"
- "texture_tint_0.GetDimensions(_tint_tmp[0], _tint_tmp[1]);",
+ "texture_tint_0.GetDimensions(_tint_tmp.x, _tint_tmp.y);",
+ "_tint_tmp.x",
+ };
+ case ValidTextureOverload::kDimensions2d:
+ case ValidTextureOverload::kDimensionsMultisampled_2d:
+ case ValidTextureOverload::kDimensionsDepth2d:
+ case ValidTextureOverload::kDimensionsStorageRO2d:
+ case ValidTextureOverload::kDimensionsStorageWO2d:
+ return {
+ "int2 _tint_tmp;\n"
+ "texture_tint_0.GetDimensions(_tint_tmp.x, _tint_tmp.y);",
"_tint_tmp",
};
+ case ValidTextureOverload::kDimensions2dArray:
+ case ValidTextureOverload::kDimensionsMultisampled_2dArray:
+ case ValidTextureOverload::kDimensionsDepth2dArray:
+ case ValidTextureOverload::kDimensionsStorageRO2dArray:
+ case ValidTextureOverload::kDimensionsStorageWO2dArray:
+ return {
+ "int3 _tint_tmp;\n"
+ "texture_tint_0."
+ "GetDimensions(_tint_tmp.x, _tint_tmp.y, _tint_tmp.z);",
+ "_tint_tmp.xy",
+ };
case ValidTextureOverload::kDimensions3d:
case ValidTextureOverload::kDimensionsStorageRO3d:
case ValidTextureOverload::kDimensionsStorageWO3d:
return {
"int3 _tint_tmp;\n"
- "texture_tint_0.GetDimensions(_tint_tmp[0], _tint_tmp[1], "
- "_tint_tmp[2]);",
+ "texture_tint_0."
+ "GetDimensions(_tint_tmp.x, _tint_tmp.y, _tint_tmp.z);",
"_tint_tmp",
};
case ValidTextureOverload::kDimensionsCube:
- case ValidTextureOverload::kDimensionsCubeArray:
case ValidTextureOverload::kDimensionsDepthCube:
+ return {
+ "int2 _tint_tmp;\n"
+ "texture_tint_0.GetDimensions(_tint_tmp.x, _tint_tmp.y);",
+ "_tint_tmp.xyy",
+ };
+ case ValidTextureOverload::kDimensionsCubeArray:
case ValidTextureOverload::kDimensionsDepthCubeArray:
return {
"int3 _tint_tmp;\n"
- "texture_tint_0.GetDimensions(_tint_tmp[0], _tint_tmp[1]);\n"
- "_tint_tmp[2] = _tint_tmp[1];",
- "_tint_tmp",
+ "texture_tint_0."
+ "GetDimensions(_tint_tmp.x, _tint_tmp.y, _tint_tmp.z);",
+ "_tint_tmp.xyy",
};
case ValidTextureOverload::kDimensions2dLevel:
- case ValidTextureOverload::kDimensions2dArrayLevel:
case ValidTextureOverload::kDimensionsDepth2dLevel:
- case ValidTextureOverload::kDimensionsDepth2dArrayLevel:
return {
"int2 _tint_tmp;\n"
- "texture_tint_0.GetDimensions(1, _tint_tmp[0], _tint_tmp[1]);",
+ "texture_tint_0.GetDimensions(1, _tint_tmp.x, _tint_tmp.y);",
"_tint_tmp",
};
+ case ValidTextureOverload::kDimensions2dArrayLevel:
+ case ValidTextureOverload::kDimensionsDepth2dArrayLevel:
+ return {
+ "int3 _tint_tmp;\n"
+ "texture_tint_0."
+ "GetDimensions(1, _tint_tmp.x, _tint_tmp.y, _tint_tmp.z);",
+ "_tint_tmp.xy",
+ };
case ValidTextureOverload::kDimensions3dLevel:
return {
"int3 _tint_tmp;\n"
- "texture_tint_0.GetDimensions(1, _tint_tmp[0], _tint_tmp[1], "
- "_tint_tmp[2]);",
+ "texture_tint_0."
+ "GetDimensions(1, _tint_tmp.x, _tint_tmp.y, _tint_tmp.z);",
"_tint_tmp",
};
case ValidTextureOverload::kDimensionsCubeLevel:
- case ValidTextureOverload::kDimensionsCubeArrayLevel:
case ValidTextureOverload::kDimensionsDepthCubeLevel:
+ return {
+ "int2 _tint_tmp;\n"
+ "texture_tint_0.GetDimensions(1, _tint_tmp.x, _tint_tmp.y);",
+ "_tint_tmp.xyy",
+ };
+ case ValidTextureOverload::kDimensionsCubeArrayLevel:
case ValidTextureOverload::kDimensionsDepthCubeArrayLevel:
return {
"int3 _tint_tmp;\n"
- "texture_tint_0.GetDimensions(1, _tint_tmp[0], _tint_tmp[1]);\n"
- "_tint_tmp[2] = _tint_tmp[1];",
- "_tint_tmp",
+ "texture_tint_0."
+ "GetDimensions(1, _tint_tmp.x, _tint_tmp.y, _tint_tmp.z);",
+ "_tint_tmp.xyy",
+ };
+ case ValidTextureOverload::kNumLayers1dArray:
+ case ValidTextureOverload::kNumLayersStorageWO1dArray:
+ return {
+ "int2 _tint_tmp;\n"
+ "texture_tint_0.GetDimensions(_tint_tmp.x, _tint_tmp.y);",
+ "_tint_tmp.y",
+ };
+ case ValidTextureOverload::kNumLayers2dArray:
+ case ValidTextureOverload::kNumLayersMultisampled_2dArray:
+ case ValidTextureOverload::kNumLayersDepth2dArray:
+ case ValidTextureOverload::kNumLayersCubeArray:
+ case ValidTextureOverload::kNumLayersDepthCubeArray:
+ case ValidTextureOverload::kNumLayersStorageWO2dArray:
+ return {
+ "int3 _tint_tmp;\n"
+ "texture_tint_0."
+ "GetDimensions(_tint_tmp.x, _tint_tmp.y, _tint_tmp.z);",
+ "_tint_tmp.z",
};
case ValidTextureOverload::kSample1dF32:
return R"(texture_tint_0.Sample(sampler_tint_0, 1.0f))";
diff --git a/src/writer/msl/generator_impl.cc b/src/writer/msl/generator_impl.cc
index 7efe837..30c1887 100644
--- a/src/writer/msl/generator_impl.cc
+++ b/src/writer/msl/generator_impl.cc
@@ -616,57 +616,71 @@
->UnwrapAll()
->As<ast::type::Texture>();
- if (ident->intrinsic() == ast::Intrinsic::kTextureDimensions) {
- std::vector<const char*> dims;
- switch (texture_type->dim()) {
- case ast::type::TextureDimension::kNone:
- error_ = "texture dimension is kNone";
- return false;
- case ast::type::TextureDimension::k1d:
- case ast::type::TextureDimension::k1dArray:
- dims = {"width"};
- break;
- case ast::type::TextureDimension::k2d:
- case ast::type::TextureDimension::k2dArray:
- dims = {"width", "height"};
- break;
- case ast::type::TextureDimension::k3d:
- dims = {"width", "height", "depth"};
- break;
- case ast::type::TextureDimension::kCube:
- case ast::type::TextureDimension::kCubeArray:
- // width == height == depth for cubes
- // See https://github.com/gpuweb/gpuweb/issues/1345
- dims = {"width", "height", "height"};
- break;
- }
+ switch (ident->intrinsic()) {
+ case ast::Intrinsic::kTextureDimensions: {
+ std::vector<const char*> dims;
+ switch (texture_type->dim()) {
+ case ast::type::TextureDimension::kNone:
+ error_ = "texture dimension is kNone";
+ return false;
+ case ast::type::TextureDimension::k1d:
+ case ast::type::TextureDimension::k1dArray:
+ dims = {"width"};
+ break;
+ case ast::type::TextureDimension::k2d:
+ case ast::type::TextureDimension::k2dArray:
+ dims = {"width", "height"};
+ break;
+ case ast::type::TextureDimension::k3d:
+ dims = {"width", "height", "depth"};
+ break;
+ case ast::type::TextureDimension::kCube:
+ case ast::type::TextureDimension::kCubeArray:
+ // width == height == depth for cubes
+ // See https://github.com/gpuweb/gpuweb/issues/1345
+ dims = {"width", "height", "height"};
+ break;
+ }
- auto get_dim = [&](const char* name) {
+ auto get_dim = [&](const char* name) {
+ if (!EmitExpression(params[pidx.texture])) {
+ return false;
+ }
+ out_ << ".get_" << name << "(";
+ if (pidx.level != kNotUsed) {
+ out_ << pidx.level;
+ }
+ out_ << ")";
+ return true;
+ };
+
+ if (dims.size() == 1) {
+ out_ << "int(";
+ get_dim(dims[0]);
+ out_ << ")";
+ } else {
+ EmitType(expr->result_type(), "");
+ out_ << "(";
+ for (size_t i = 0; i < dims.size(); i++) {
+ if (i > 0) {
+ out_ << ", ";
+ }
+ get_dim(dims[i]);
+ }
+ out_ << ")";
+ }
+ return true;
+ }
+ case ast::Intrinsic::kTextureNumLayers: {
+ out_ << "int(";
if (!EmitExpression(params[pidx.texture])) {
return false;
}
- out_ << ".get_" << name << "(";
- if (pidx.level != kNotUsed) {
- out_ << pidx.level;
- }
- out_ << ")";
+ out_ << ".get_array_size())";
return true;
- };
-
- if (dims.size() == 1) {
- get_dim(dims[0]);
- } else {
- EmitType(expr->result_type(), "");
- out_ << "(";
- for (size_t i = 0; i < dims.size(); i++) {
- if (i > 0) {
- out_ << ", ";
- }
- get_dim(dims[i]);
- }
- out_ << ")";
}
- return true;
+ default:
+ break;
}
if (!EmitExpression(params[pidx.texture]))
diff --git a/src/writer/msl/generator_impl_intrinsic_texture_test.cc b/src/writer/msl/generator_impl_intrinsic_texture_test.cc
index 3955bed..67bbdc7 100644
--- a/src/writer/msl/generator_impl_intrinsic_texture_test.cc
+++ b/src/writer/msl/generator_impl_intrinsic_texture_test.cc
@@ -38,7 +38,7 @@
case ValidTextureOverload::kDimensionsStorageRO1dArray:
case ValidTextureOverload::kDimensionsStorageWO1d:
case ValidTextureOverload::kDimensionsStorageWO1dArray:
- return R"(texture_tint_0.get_width())";
+ return R"(int(texture_tint_0.get_width()))";
case ValidTextureOverload::kDimensions2d:
case ValidTextureOverload::kDimensions2dArray:
case ValidTextureOverload::kDimensionsMultisampled_2d:
@@ -71,6 +71,15 @@
case ValidTextureOverload::kDimensionsDepthCubeLevel:
case ValidTextureOverload::kDimensionsDepthCubeArrayLevel:
return R"(int3(texture_tint_0.get_width(1), texture_tint_0.get_height(1), texture_tint_0.get_height(1)))";
+ case ValidTextureOverload::kNumLayers1dArray:
+ case ValidTextureOverload::kNumLayers2dArray:
+ case ValidTextureOverload::kNumLayersCubeArray:
+ case ValidTextureOverload::kNumLayersMultisampled_2dArray:
+ case ValidTextureOverload::kNumLayersDepth2dArray:
+ case ValidTextureOverload::kNumLayersDepthCubeArray:
+ case ValidTextureOverload::kNumLayersStorageWO1dArray:
+ case ValidTextureOverload::kNumLayersStorageWO2dArray:
+ return R"(int(texture_tint_0.get_array_size()))";
case ValidTextureOverload::kSample1dF32:
return R"(texture_tint_0.sample(sampler_tint_0, 1.0f))";
case ValidTextureOverload::kSample1dArrayF32:
diff --git a/src/writer/spirv/builder.cc b/src/writer/spirv/builder.cc
index 0bc1565..8887d63 100644
--- a/src/writer/spirv/builder.cc
+++ b/src/writer/spirv/builder.cc
@@ -2073,6 +2073,49 @@
return true;
};
+ // Appends a result type and id to `spirv_params`, by first swizzling the
+ // result of the op with `swizzle`.
+ auto append_result_type_and_id_to_spirv_params_swizzled =
+ [&](uint32_t spirv_result_width, std::vector<uint32_t> swizzle) {
+ if (swizzle.empty()) {
+ append_result_type_and_id_to_spirv_params();
+ } else {
+ // Assign post_emission to swizzle the result of the call to
+ // OpImageQuerySize[Lod].
+ auto* element_type = ElementTypeOf(call->result_type());
+ auto spirv_result = result_op();
+ auto* spirv_result_type =
+ mod_->create<ast::type::Vector>(element_type, spirv_result_width);
+ if (swizzle.size() > 1) {
+ post_emission = [=] {
+ OperandList operands{
+ result_type,
+ result_id,
+ spirv_result,
+ spirv_result,
+ };
+ for (auto idx : swizzle) {
+ operands.emplace_back(Operand::Int(idx));
+ }
+ return push_function_inst(spv::Op::OpVectorShuffle, operands);
+ };
+ } else {
+ post_emission = [=] {
+ return push_function_inst(spv::Op::OpCompositeExtract,
+ {result_type, result_id, spirv_result,
+ Operand::Int(swizzle[0])});
+ };
+ }
+ auto spirv_result_type_id = GenerateTypeIfNeeded(spirv_result_type);
+ if (spirv_result_type_id == 0) {
+ return false;
+ }
+ spirv_params.emplace_back(Operand::Int(spirv_result_type_id));
+ spirv_params.emplace_back(spirv_result);
+ }
+ return true;
+ };
+
auto append_coords_to_spirv_params = [&]() -> bool {
if (pidx.array_index != kNotUsed) {
// Array index needs to be appended to the coordinates.
@@ -2147,41 +2190,9 @@
break;
}
- if (swizzle.empty()) {
- append_result_type_and_id_to_spirv_params();
- } else {
- // Assign post_emission to swizzle the result of the call to
- // OpImageQuerySize[Lod].
- auto* element_type = ElementTypeOf(call->result_type());
- auto spirv_result = result_op();
- auto* spirv_result_type =
- mod_->create<ast::type::Vector>(element_type, spirv_dims);
- if (swizzle.size() > 1) {
- post_emission = [=] {
- OperandList operands{
- result_type,
- result_id,
- spirv_result,
- spirv_result,
- };
- for (auto idx : swizzle) {
- operands.emplace_back(Operand::Int(idx));
- }
- return push_function_inst(spv::Op::OpVectorShuffle, operands);
- };
- } else {
- post_emission = [=] {
- return push_function_inst(spv::Op::OpCompositeExtract,
- {result_type, result_id, spirv_result,
- Operand::Int(swizzle[0])});
- };
- }
- auto spirv_result_type_id = GenerateTypeIfNeeded(spirv_result_type);
- if (spirv_result_type_id == 0) {
- return false;
- }
- spirv_params.emplace_back(Operand::Int(spirv_result_type_id));
- spirv_params.emplace_back(spirv_result);
+ if (!append_result_type_and_id_to_spirv_params_swizzled(spirv_dims,
+ swizzle)) {
+ return false;
}
spirv_params.emplace_back(gen_param(pidx.texture));
@@ -2199,6 +2210,41 @@
}
break;
}
+ case ast::Intrinsic::kTextureNumLayers: {
+ uint32_t spirv_dims = 0;
+ switch (texture_type->dim()) {
+ default:
+ error_ = "texture is not arrayed";
+ return false;
+ case ast::type::TextureDimension::k1dArray:
+ spirv_dims = 2;
+ break;
+ case ast::type::TextureDimension::k2dArray:
+ case ast::type::TextureDimension::kCubeArray:
+ spirv_dims = 3;
+ break;
+ }
+
+ // OpImageQuerySize[Lod] packs the array count as the last element of the
+ // returned vector. Extract this.
+ if (!append_result_type_and_id_to_spirv_params_swizzled(
+ spirv_dims, {spirv_dims - 1})) {
+ return false;
+ }
+
+ spirv_params.emplace_back(gen_param(pidx.texture));
+
+ if (texture_type->Is<ast::type::MultisampledTexture>() ||
+ texture_type->Is<ast::type::StorageTexture>()) {
+ op = spv::Op::OpImageQuerySize;
+ } else {
+ ast::SintLiteral i32_0(Source{}, mod_->create<ast::type::I32>(), 0);
+ op = spv::Op::OpImageQuerySizeLod;
+ spirv_params.emplace_back(
+ Operand::Int(GenerateLiteralIfNeeded(nullptr, &i32_0)));
+ }
+ break;
+ }
case ast::Intrinsic::kTextureLoad: {
op = texture_type->Is<ast::type::StorageTexture>()
? spv::Op::OpImageRead
diff --git a/src/writer/spirv/builder_intrinsic_texture_test.cc b/src/writer/spirv/builder_intrinsic_texture_test.cc
index c65fb96..abb588f 100644
--- a/src/writer/spirv/builder_intrinsic_texture_test.cc
+++ b/src/writer/spirv/builder_intrinsic_texture_test.cc
@@ -740,6 +740,176 @@
R"(
OpCapability ImageQuery
)"};
+
+ case ValidTextureOverload::kNumLayers1dArray:
+ return {R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 1D 0 1 0 1 Unknown
+%2 = OpTypePointer UniformConstant %3
+%1 = OpVariable %2 UniformConstant
+%7 = OpTypeSampler
+%6 = OpTypePointer UniformConstant %7
+%5 = OpVariable %6 UniformConstant
+%9 = OpTypeInt 32 1
+%11 = OpTypeVector %9 2
+%13 = OpConstant %9 0
+)",
+ R"(
+%12 = OpLoad %3 %1
+%10 = OpImageQuerySizeLod %11 %12 %13
+%8 = OpCompositeExtract %9 %10 1
+)",
+ R"(
+OpCapability Sampled1D
+OpCapability ImageQuery
+)"};
+ case ValidTextureOverload::kNumLayers2dArray:
+ return {R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 2D 0 1 0 1 Unknown
+%2 = OpTypePointer UniformConstant %3
+%1 = OpVariable %2 UniformConstant
+%7 = OpTypeSampler
+%6 = OpTypePointer UniformConstant %7
+%5 = OpVariable %6 UniformConstant
+%9 = OpTypeInt 32 1
+%11 = OpTypeVector %9 3
+%13 = OpConstant %9 0
+)",
+ R"(
+%12 = OpLoad %3 %1
+%10 = OpImageQuerySizeLod %11 %12 %13
+%8 = OpCompositeExtract %9 %10 2
+)",
+ R"(
+OpCapability ImageQuery
+)"};
+ case ValidTextureOverload::kNumLayersCubeArray:
+ return {R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 Cube 0 1 0 1 Unknown
+%2 = OpTypePointer UniformConstant %3
+%1 = OpVariable %2 UniformConstant
+%7 = OpTypeSampler
+%6 = OpTypePointer UniformConstant %7
+%5 = OpVariable %6 UniformConstant
+%9 = OpTypeInt 32 1
+%11 = OpTypeVector %9 3
+%13 = OpConstant %9 0
+)",
+ R"(
+%12 = OpLoad %3 %1
+%10 = OpImageQuerySizeLod %11 %12 %13
+%8 = OpCompositeExtract %9 %10 2
+)",
+ R"(
+OpCapability SampledCubeArray
+OpCapability ImageQuery
+)"};
+ case ValidTextureOverload::kNumLayersMultisampled_2dArray:
+ return {R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 2D 0 1 1 1 Unknown
+%2 = OpTypePointer UniformConstant %3
+%1 = OpVariable %2 UniformConstant
+%7 = OpTypeSampler
+%6 = OpTypePointer UniformConstant %7
+%5 = OpVariable %6 UniformConstant
+%9 = OpTypeInt 32 1
+%11 = OpTypeVector %9 3
+)",
+ R"(
+%12 = OpLoad %3 %1
+%10 = OpImageQuerySize %11 %12
+%8 = OpCompositeExtract %9 %10 2
+)",
+ R"(
+OpCapability ImageQuery
+)"};
+ case ValidTextureOverload::kNumLayersDepth2dArray:
+ return {R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 2D 1 1 0 1 Unknown
+%2 = OpTypePointer UniformConstant %3
+%1 = OpVariable %2 UniformConstant
+%7 = OpTypeSampler
+%6 = OpTypePointer UniformConstant %7
+%5 = OpVariable %6 UniformConstant
+%9 = OpTypeInt 32 1
+%11 = OpTypeVector %9 3
+%13 = OpConstant %9 0
+)",
+ R"(
+%12 = OpLoad %3 %1
+%10 = OpImageQuerySizeLod %11 %12 %13
+%8 = OpCompositeExtract %9 %10 2
+)",
+ R"(
+OpCapability ImageQuery
+)"};
+ case ValidTextureOverload::kNumLayersDepthCubeArray:
+ return {R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 Cube 1 1 0 1 Unknown
+%2 = OpTypePointer UniformConstant %3
+%1 = OpVariable %2 UniformConstant
+%7 = OpTypeSampler
+%6 = OpTypePointer UniformConstant %7
+%5 = OpVariable %6 UniformConstant
+%9 = OpTypeInt 32 1
+%11 = OpTypeVector %9 3
+%13 = OpConstant %9 0
+)",
+ R"(
+%12 = OpLoad %3 %1
+%10 = OpImageQuerySizeLod %11 %12 %13
+%8 = OpCompositeExtract %9 %10 2
+)",
+ R"(
+OpCapability SampledCubeArray
+OpCapability ImageQuery
+)"};
+ case ValidTextureOverload::kNumLayersStorageWO1dArray:
+ return {R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 1D 0 1 0 2 Rgba32f
+%2 = OpTypePointer UniformConstant %3
+%1 = OpVariable %2 UniformConstant
+%7 = OpTypeSampler
+%6 = OpTypePointer UniformConstant %7
+%5 = OpVariable %6 UniformConstant
+%9 = OpTypeInt 32 1
+%11 = OpTypeVector %9 2
+)",
+ R"(
+%12 = OpLoad %3 %1
+%10 = OpImageQuerySize %11 %12
+%8 = OpCompositeExtract %9 %10 1
+)",
+ R"(
+OpCapability Image1D
+OpCapability ImageQuery
+)"};
+ case ValidTextureOverload::kNumLayersStorageWO2dArray:
+ return {R"(
+%4 = OpTypeFloat 32
+%3 = OpTypeImage %4 2D 0 1 0 2 Rgba32f
+%2 = OpTypePointer UniformConstant %3
+%1 = OpVariable %2 UniformConstant
+%7 = OpTypeSampler
+%6 = OpTypePointer UniformConstant %7
+%5 = OpVariable %6 UniformConstant
+%9 = OpTypeInt 32 1
+%11 = OpTypeVector %9 3
+)",
+ R"(
+%12 = OpLoad %3 %1
+%10 = OpImageQuerySize %11 %12
+%8 = OpCompositeExtract %9 %10 2
+)",
+ R"(
+OpCapability ImageQuery
+)"};
case ValidTextureOverload::kSample1dF32:
return {
R"(