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>
This commit is contained in:
Ben Clayton 2021-01-14 16:50:07 +00:00 committed by Commit Bot service account
parent 0f4638b9e4
commit c21f1f92a2
12 changed files with 720 additions and 261 deletions

View File

@ -21,211 +21,220 @@ std::ostream& operator<<(std::ostream& out, Intrinsic i) {
/// The emitted name matches the spelling in the WGSL spec. /// The emitted name matches the spelling in the WGSL spec.
/// including case. /// including case.
switch (i) { switch (i) {
case Intrinsic::kNone:
return out;
case Intrinsic::kAbs: case Intrinsic::kAbs:
out << "abs"; out << "abs";
break; return out;
case Intrinsic::kAcos: case Intrinsic::kAcos:
out << "acos"; out << "acos";
break; return out;
case Intrinsic::kAll: case Intrinsic::kAll:
out << "all"; out << "all";
break; return out;
case Intrinsic::kAny: case Intrinsic::kAny:
out << "any"; out << "any";
break; return out;
case Intrinsic::kArrayLength: case Intrinsic::kArrayLength:
out << "arrayLength"; out << "arrayLength";
break; return out;
case Intrinsic::kAsin: case Intrinsic::kAsin:
out << "asin"; out << "asin";
break; return out;
case Intrinsic::kAtan: case Intrinsic::kAtan:
out << "atan"; out << "atan";
break; return out;
case Intrinsic::kAtan2: case Intrinsic::kAtan2:
out << "atan2"; out << "atan2";
break; return out;
case Intrinsic::kCeil: case Intrinsic::kCeil:
out << "ceil"; out << "ceil";
break; return out;
case Intrinsic::kClamp: case Intrinsic::kClamp:
out << "clamp"; out << "clamp";
break; return out;
case Intrinsic::kCos: case Intrinsic::kCos:
out << "cos"; out << "cos";
break; return out;
case Intrinsic::kCosh: case Intrinsic::kCosh:
out << "cosh"; out << "cosh";
break; return out;
case Intrinsic::kCountOneBits: case Intrinsic::kCountOneBits:
out << "countOneBits"; out << "countOneBits";
break; return out;
case Intrinsic::kCross: case Intrinsic::kCross:
out << "cross"; out << "cross";
break; return out;
case Intrinsic::kDeterminant: case Intrinsic::kDeterminant:
out << "determinant"; out << "determinant";
break; return out;
case Intrinsic::kDistance: case Intrinsic::kDistance:
out << "distance"; out << "distance";
break; return out;
case Intrinsic::kDot: case Intrinsic::kDot:
out << "dot"; out << "dot";
break; return out;
case Intrinsic::kDpdx: case Intrinsic::kDpdx:
out << "dpdx"; out << "dpdx";
break; return out;
case Intrinsic::kDpdxCoarse: case Intrinsic::kDpdxCoarse:
out << "dpdxCoarse"; out << "dpdxCoarse";
break; return out;
case Intrinsic::kDpdxFine: case Intrinsic::kDpdxFine:
out << "dpdxFine"; out << "dpdxFine";
break; return out;
case Intrinsic::kDpdy: case Intrinsic::kDpdy:
out << "dpdy"; out << "dpdy";
break; return out;
case Intrinsic::kDpdyCoarse: case Intrinsic::kDpdyCoarse:
out << "dpdyCoarse"; out << "dpdyCoarse";
break; return out;
case Intrinsic::kDpdyFine: case Intrinsic::kDpdyFine:
out << "dpdyFine"; out << "dpdyFine";
break; return out;
case Intrinsic::kExp: case Intrinsic::kExp:
out << "exp"; out << "exp";
break; return out;
case Intrinsic::kExp2: case Intrinsic::kExp2:
out << "exp2"; out << "exp2";
break; return out;
case Intrinsic::kFaceForward: case Intrinsic::kFaceForward:
out << "faceForward"; out << "faceForward";
break; return out;
case Intrinsic::kFloor: case Intrinsic::kFloor:
out << "floor"; out << "floor";
break; return out;
case Intrinsic::kFma: case Intrinsic::kFma:
out << "fma"; out << "fma";
break; return out;
case Intrinsic::kFract: case Intrinsic::kFract:
out << "fract"; out << "fract";
break; return out;
case Intrinsic::kFrexp: case Intrinsic::kFrexp:
out << "frexp"; out << "frexp";
break; return out;
case Intrinsic::kFwidth: case Intrinsic::kFwidth:
out << "fwidth"; out << "fwidth";
break; return out;
case Intrinsic::kFwidthCoarse: case Intrinsic::kFwidthCoarse:
out << "fwidthCoarse"; out << "fwidthCoarse";
break; return out;
case Intrinsic::kFwidthFine: case Intrinsic::kFwidthFine:
out << "fwidthFine"; out << "fwidthFine";
break; return out;
case Intrinsic::kInverseSqrt: case Intrinsic::kInverseSqrt:
out << "inverseSqrt"; out << "inverseSqrt";
break; return out;
case Intrinsic::kIsFinite: case Intrinsic::kIsFinite:
out << "isFinite"; out << "isFinite";
break; return out;
case Intrinsic::kIsInf: case Intrinsic::kIsInf:
out << "isInf"; out << "isInf";
break; return out;
case Intrinsic::kIsNan: case Intrinsic::kIsNan:
out << "isNan"; out << "isNan";
break; return out;
case Intrinsic::kIsNormal: case Intrinsic::kIsNormal:
out << "isNormal"; out << "isNormal";
break; return out;
case Intrinsic::kLdexp: case Intrinsic::kLdexp:
out << "ldexp"; out << "ldexp";
break; return out;
case Intrinsic::kLength: case Intrinsic::kLength:
out << "length"; out << "length";
break; return out;
case Intrinsic::kLog: case Intrinsic::kLog:
out << "log"; out << "log";
break; return out;
case Intrinsic::kLog2: case Intrinsic::kLog2:
out << "log2"; out << "log2";
break; return out;
case Intrinsic::kMax: case Intrinsic::kMax:
out << "max"; out << "max";
break; return out;
case Intrinsic::kMin: case Intrinsic::kMin:
out << "min"; out << "min";
break; return out;
case Intrinsic::kMix: case Intrinsic::kMix:
out << "mix"; out << "mix";
break; return out;
case Intrinsic::kModf: case Intrinsic::kModf:
out << "modf"; out << "modf";
break; return out;
case Intrinsic::kNormalize: case Intrinsic::kNormalize:
out << "normalize"; out << "normalize";
break; return out;
case Intrinsic::kPow: case Intrinsic::kPow:
out << "pow"; out << "pow";
break; return out;
case Intrinsic::kReflect: case Intrinsic::kReflect:
out << "reflect"; out << "reflect";
break; return out;
case Intrinsic::kReverseBits: case Intrinsic::kReverseBits:
out << "reverseBits"; out << "reverseBits";
break; return out;
case Intrinsic::kRound: case Intrinsic::kRound:
out << "round"; out << "round";
break; return out;
case Intrinsic::kSelect: case Intrinsic::kSelect:
out << "select"; out << "select";
break; return out;
case Intrinsic::kSign: case Intrinsic::kSign:
out << "sign"; out << "sign";
break; return out;
case Intrinsic::kSin: case Intrinsic::kSin:
out << "sin"; out << "sin";
break; return out;
case Intrinsic::kSinh: case Intrinsic::kSinh:
out << "sinh"; out << "sinh";
break; return out;
case Intrinsic::kSmoothStep: case Intrinsic::kSmoothStep:
out << "smoothStep"; out << "smoothStep";
break; return out;
case Intrinsic::kSqrt: case Intrinsic::kSqrt:
out << "sqrt"; out << "sqrt";
break; return out;
case Intrinsic::kStep: case Intrinsic::kStep:
out << "step"; out << "step";
break; return out;
case Intrinsic::kTan: case Intrinsic::kTan:
out << "tan"; out << "tan";
break; return out;
case Intrinsic::kTanh: case Intrinsic::kTanh:
out << "tanh"; out << "tanh";
break; return out;
case Intrinsic::kTextureDimensions:
out << "textureDimensions";
return out;
case Intrinsic::kTextureLoad: case Intrinsic::kTextureLoad:
out << "textureLoad"; out << "textureLoad";
break; return out;
case Intrinsic::kTextureNumLayers:
out << "textureNumLayers";
return out;
case Intrinsic::kTextureSample: case Intrinsic::kTextureSample:
out << "textureSample"; out << "textureSample";
break; return out;
case Intrinsic::kTextureSampleBias: case Intrinsic::kTextureSampleBias:
out << "textureSampleBias"; out << "textureSampleBias";
break; return out;
case Intrinsic::kTextureSampleCompare: case Intrinsic::kTextureSampleCompare:
out << "textureSampleCompare"; out << "textureSampleCompare";
break; return out;
case Intrinsic::kTextureSampleGrad: case Intrinsic::kTextureSampleGrad:
out << "textureSampleGrad"; out << "textureSampleGrad";
break; return out;
case Intrinsic::kTextureSampleLevel: case Intrinsic::kTextureSampleLevel:
out << "textureSampleLevel"; out << "textureSampleLevel";
break; return out;
case Intrinsic::kTextureStore:
out << "textureStore";
return out;
case Intrinsic::kTrunc: case Intrinsic::kTrunc:
out << "trunc"; out << "trunc";
break; return out;
default:
out << "Unknown";
break;
} }
out << "Unknown";
return out; return out;
} }
@ -260,7 +269,7 @@ bool IsFloatClassificationIntrinsic(Intrinsic i) {
bool IsTextureIntrinsic(Intrinsic i) { bool IsTextureIntrinsic(Intrinsic i) {
return i == Intrinsic::kTextureDimensions || i == Intrinsic::kTextureLoad || return i == Intrinsic::kTextureDimensions || i == Intrinsic::kTextureLoad ||
i == Intrinsic::kTextureSample || i == Intrinsic::kTextureNumLayers || i == Intrinsic::kTextureSample ||
i == Intrinsic::kTextureSampleLevel || i == Intrinsic::kTextureSampleLevel ||
i == Intrinsic::kTextureSampleBias || i == Intrinsic::kTextureSampleBias ||
i == Intrinsic::kTextureSampleCompare || i == Intrinsic::kTextureSampleCompare ||
@ -268,7 +277,8 @@ bool IsTextureIntrinsic(Intrinsic i) {
} }
bool IsImageQueryIntrinsic(Intrinsic i) { bool IsImageQueryIntrinsic(Intrinsic i) {
return i == ast::Intrinsic::kTextureDimensions; return i == ast::Intrinsic::kTextureDimensions ||
i == Intrinsic::kTextureNumLayers;
} }
} // namespace intrinsic } // namespace intrinsic

View File

@ -85,6 +85,7 @@ enum class Intrinsic {
kTanh, kTanh,
kTextureDimensions, kTextureDimensions,
kTextureLoad, kTextureLoad,
kTextureNumLayers,
kTextureSample, kTextureSample,
kTextureSampleBias, kTextureSampleBias,
kTextureSampleCompare, kTextureSampleCompare,

View File

@ -541,6 +541,86 @@ std::vector<TextureOverloadCase> TextureOverloadCase::ValidCases() {
"textureDimensions", "textureDimensions",
[](Builder* b) { return b->ExprList("texture"); }, [](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, ValidTextureOverload::kSample1dF32,
"textureSample(t : texture_1d<f32>,\n" "textureSample(t : texture_1d<f32>,\n"

View File

@ -69,6 +69,14 @@ enum class ValidTextureOverload {
kDimensionsStorageWO2d, kDimensionsStorageWO2d,
kDimensionsStorageWO2dArray, kDimensionsStorageWO2dArray,
kDimensionsStorageWO3d, kDimensionsStorageWO3d,
kNumLayers1dArray,
kNumLayers2dArray,
kNumLayersCubeArray,
kNumLayersMultisampled_2dArray,
kNumLayersDepth2dArray,
kNumLayersDepthCubeArray,
kNumLayersStorageWO1dArray,
kNumLayersStorageWO2dArray,
kSample1dF32, kSample1dF32,
kSample1dArrayF32, kSample1dArrayF32,
kSample2dF32, kSample2dF32,

View File

@ -566,6 +566,9 @@ bool TypeDeterminer::DetermineIntrinsic(ast::IdentifierExpression* ident,
param.idx.level = param.count++; param.idx.level = param.count++;
} }
break; break;
case ast::Intrinsic::kTextureNumLayers:
param.idx.texture = param.count++;
break;
case ast::Intrinsic::kTextureLoad: case ast::Intrinsic::kTextureLoad:
param.idx.texture = param.count++; param.idx.texture = param.count++;
param.idx.coords = param.count++; param.idx.coords = param.count++;
@ -669,7 +672,8 @@ bool TypeDeterminer::DetermineIntrinsic(ast::IdentifierExpression* ident,
// Set the function return type // Set the function return type
ast::type::Type* return_type = nullptr; ast::type::Type* return_type = nullptr;
if (ident->intrinsic() == ast::Intrinsic::kTextureDimensions) { switch (ident->intrinsic()) {
case ast::Intrinsic::kTextureDimensions: {
auto* i32 = mod_->create<ast::type::I32>(); auto* i32 = mod_->create<ast::type::I32>();
switch (texture->dim()) { switch (texture->dim()) {
default: default:
@ -689,9 +693,15 @@ bool TypeDeterminer::DetermineIntrinsic(ast::IdentifierExpression* ident,
return_type = mod_->create<ast::type::Vector>(i32, 3); return_type = mod_->create<ast::type::Vector>(i32, 3);
break; break;
} }
} else if (ident->intrinsic() == ast::Intrinsic::kTextureStore) { break;
}
case ast::Intrinsic::kTextureNumLayers:
return_type = mod_->create<ast::type::I32>();
break;
case ast::Intrinsic::kTextureStore:
return_type = mod_->create<ast::type::Void>(); return_type = mod_->create<ast::type::Void>();
} else { break;
default: {
if (texture->Is<ast::type::DepthTexture>()) { if (texture->Is<ast::type::DepthTexture>()) {
return_type = mod_->create<ast::type::F32>(); return_type = mod_->create<ast::type::F32>();
} else { } else {
@ -711,6 +721,7 @@ bool TypeDeterminer::DetermineIntrinsic(ast::IdentifierExpression* ident,
return_type = mod_->create<ast::type::Vector>(type, 4); return_type = mod_->create<ast::type::Vector>(type, 4);
} }
} }
}
expr->func()->set_result_type(return_type); expr->func()->set_result_type(return_type);
return true; return true;
@ -1021,6 +1032,8 @@ bool TypeDeterminer::SetIntrinsicIfNeeded(ast::IdentifierExpression* ident) {
ident->set_intrinsic(ast::Intrinsic::kTanh); ident->set_intrinsic(ast::Intrinsic::kTanh);
} else if (name == "textureDimensions") { } else if (name == "textureDimensions") {
ident->set_intrinsic(ast::Intrinsic::kTextureDimensions); ident->set_intrinsic(ast::Intrinsic::kTextureDimensions);
} else if (name == "textureNumLayers") {
ident->set_intrinsic(ast::Intrinsic::kTextureNumLayers);
} else if (name == "textureLoad") { } else if (name == "textureLoad") {
ident->set_intrinsic(ast::Intrinsic::kTextureLoad); ident->set_intrinsic(ast::Intrinsic::kTextureLoad);
} else if (name == "textureStore") { } else if (name == "textureStore") {

View File

@ -1764,6 +1764,7 @@ INSTANTIATE_TEST_SUITE_P(
IntrinsicData{"tanh", ast::Intrinsic::kTanh}, IntrinsicData{"tanh", ast::Intrinsic::kTanh},
IntrinsicData{"textureDimensions", ast::Intrinsic::kTextureDimensions}, IntrinsicData{"textureDimensions", ast::Intrinsic::kTextureDimensions},
IntrinsicData{"textureLoad", ast::Intrinsic::kTextureLoad}, IntrinsicData{"textureLoad", ast::Intrinsic::kTextureLoad},
IntrinsicData{"textureNumLayers", ast::Intrinsic::kTextureNumLayers},
IntrinsicData{"textureSample", ast::Intrinsic::kTextureSample}, IntrinsicData{"textureSample", ast::Intrinsic::kTextureSample},
IntrinsicData{"textureSampleBias", ast::Intrinsic::kTextureSampleBias}, IntrinsicData{"textureSampleBias", ast::Intrinsic::kTextureSampleBias},
IntrinsicData{"textureSampleCompare", IntrinsicData{"textureSampleCompare",
@ -2928,6 +2929,15 @@ const char* expected_texture_overload(
case ValidTextureOverload::kDimensionsStorageWO2dArray: case ValidTextureOverload::kDimensionsStorageWO2dArray:
case ValidTextureOverload::kDimensionsStorageWO3d: case ValidTextureOverload::kDimensionsStorageWO3d:
return R"(textureDimensions(texture))"; 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::kDimensions2dLevel:
case ValidTextureOverload::kDimensions2dArrayLevel: case ValidTextureOverload::kDimensions2dArrayLevel:
case ValidTextureOverload::kDimensions3dLevel: case ValidTextureOverload::kDimensions3dLevel:
@ -3181,6 +3191,8 @@ TEST_P(TypeDeterminerTextureIntrinsicTest, Call) {
ty.vec3<i32>()->type_name()); ty.vec3<i32>()->type_name());
break; break;
} }
} else if (std::string(param.function) == "textureNumLayers") {
EXPECT_EQ(call->result_type(), ty.i32);
} else if (std::string(param.function) == "textureStore") { } else if (std::string(param.function) == "textureStore") {
EXPECT_EQ(call->result_type(), ty.void_); EXPECT_EQ(call->result_type(), ty.void_);
} else { } else {

View File

@ -695,49 +695,99 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& pre,
auto* texture_type = auto* texture_type =
texture->result_type()->UnwrapAll()->As<ast::type::Texture>(); texture->result_type()->UnwrapAll()->As<ast::type::Texture>();
if (ident->intrinsic() == ast::Intrinsic::kTextureDimensions) { switch (ident->intrinsic()) {
// Declare a variable to hold the texture dimensions case ast::Intrinsic::kTextureDimensions:
case ast::Intrinsic::kTextureNumLayers: {
// Declare a variable to hold the queried texture info
auto dims = generate_name(kTempNamePrefix); auto dims = generate_name(kTempNamePrefix);
EmitType(pre, expr->result_type(), "");
pre << " " << dims << ";" << std::endl;
// Now call GetDimensions() on the texture object, populating the dims std::stringstream texture_name;
// variable. if (!EmitExpression(pre, texture_name, texture)) {
std::stringstream tex_out;
if (!EmitExpression(pre, tex_out, texture)) {
return false; return false;
} }
pre << tex_out.str() << ".GetDimensions(";
auto get_dimensions = [&](std::initializer_list<const char*>&& suffixes) {
pre << texture_name.str() << ".GetDimensions(";
if (pidx.level != kNotUsed) { if (pidx.level != kNotUsed) {
pre << pidx.level << ", "; 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()) { switch (texture_type->dim()) {
case ast::type::TextureDimension::kNone: case ast::type::TextureDimension::kNone:
error_ = "texture dimension is kNone"; error_ = "texture dimension is kNone";
return false; return false;
case ast::type::TextureDimension::k1d: case ast::type::TextureDimension::k1d:
pre << "int " << dims << ";\n";
get_dimensions({""});
break;
case ast::type::TextureDimension::k1dArray: case ast::type::TextureDimension::k1dArray:
pre << dims << ");"; pre << "int2 " << dims << ";\n";
get_dimensions({".x", ".y"});
dims_swizzle = ".x";
num_els_swizzle = ".y";
break; break;
case ast::type::TextureDimension::k2d: case ast::type::TextureDimension::k2d:
pre << "int2 " << dims << ";\n";
get_dimensions({".x", ".y"});
break;
case ast::type::TextureDimension::k2dArray: case ast::type::TextureDimension::k2dArray:
pre << dims << "[0], " << dims << "[1]);"; pre << "int3 " << dims << ";\n";
get_dimensions({".x", ".y", ".z"});
dims_swizzle = ".xy";
num_els_swizzle = ".z";
break; break;
case ast::type::TextureDimension::k3d: case ast::type::TextureDimension::k3d:
pre << dims << "[0], " << dims << "[1], " << dims << "[2]);"; pre << "int3 " << dims << ";\n";
get_dimensions({".x", ".y", ".z"});
break; break;
case ast::type::TextureDimension::kCube: 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: case ast::type::TextureDimension::kCubeArray:
// width == height == depth for cubes // width == height == depth for cubes
// See https://github.com/gpuweb/gpuweb/issues/1345 // See https://github.com/gpuweb/gpuweb/issues/1345
pre << dims << "[0], " << dims << "[1]);\n"; pre << "int3 " << dims << ";\n";
pre << dims << "[2] = " << dims << "[1];"; // dims[2] = dims[1] get_dimensions({".x", ".y", ".z"});
dims_swizzle = ".xyy"; // [width, height, height]
num_els_swizzle = ".z";
break; break;
} }
// The result of the textureDimensions() call is now the temporary variable. // The result of the textureDimensions() call is now in temporary
out << dims; // 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; 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)) if (!EmitExpression(pre, out, texture))

View File

@ -41,75 +41,121 @@ ExpectedResult expected_texture_overload(
using ValidTextureOverload = ast::intrinsic::test::ValidTextureOverload; using ValidTextureOverload = ast::intrinsic::test::ValidTextureOverload;
switch (overload) { switch (overload) {
case ValidTextureOverload::kDimensions1d: case ValidTextureOverload::kDimensions1d:
case ValidTextureOverload::kDimensions1dArray:
case ValidTextureOverload::kDimensionsStorageRO1d: case ValidTextureOverload::kDimensionsStorageRO1d:
case ValidTextureOverload::kDimensionsStorageRO1dArray:
case ValidTextureOverload::kDimensionsStorageWO1d: case ValidTextureOverload::kDimensionsStorageWO1d:
case ValidTextureOverload::kDimensionsStorageWO1dArray:
return { return {
"int _tint_tmp;\n" "int _tint_tmp;\n"
"texture_tint_0.GetDimensions(_tint_tmp);", "texture_tint_0.GetDimensions(_tint_tmp);",
"_tint_tmp", "_tint_tmp",
}; };
case ValidTextureOverload::kDimensions2d: case ValidTextureOverload::kDimensions1dArray:
case ValidTextureOverload::kDimensions2dArray: case ValidTextureOverload::kDimensionsStorageRO1dArray:
case ValidTextureOverload::kDimensionsMultisampled_2d: case ValidTextureOverload::kDimensionsStorageWO1dArray:
case ValidTextureOverload::kDimensionsMultisampled_2dArray:
case ValidTextureOverload::kDimensionsDepth2d:
case ValidTextureOverload::kDimensionsDepth2dArray:
case ValidTextureOverload::kDimensionsStorageRO2d:
case ValidTextureOverload::kDimensionsStorageRO2dArray:
case ValidTextureOverload::kDimensionsStorageWO2d:
case ValidTextureOverload::kDimensionsStorageWO2dArray:
return { return {
"int2 _tint_tmp;\n" "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", "_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::kDimensions3d:
case ValidTextureOverload::kDimensionsStorageRO3d: case ValidTextureOverload::kDimensionsStorageRO3d:
case ValidTextureOverload::kDimensionsStorageWO3d: case ValidTextureOverload::kDimensionsStorageWO3d:
return { return {
"int3 _tint_tmp;\n" "int3 _tint_tmp;\n"
"texture_tint_0.GetDimensions(_tint_tmp[0], _tint_tmp[1], " "texture_tint_0."
"_tint_tmp[2]);", "GetDimensions(_tint_tmp.x, _tint_tmp.y, _tint_tmp.z);",
"_tint_tmp", "_tint_tmp",
}; };
case ValidTextureOverload::kDimensionsCube: case ValidTextureOverload::kDimensionsCube:
case ValidTextureOverload::kDimensionsCubeArray:
case ValidTextureOverload::kDimensionsDepthCube: 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: case ValidTextureOverload::kDimensionsDepthCubeArray:
return { return {
"int3 _tint_tmp;\n" "int3 _tint_tmp;\n"
"texture_tint_0.GetDimensions(_tint_tmp[0], _tint_tmp[1]);\n" "texture_tint_0."
"_tint_tmp[2] = _tint_tmp[1];", "GetDimensions(_tint_tmp.x, _tint_tmp.y, _tint_tmp.z);",
"_tint_tmp", "_tint_tmp.xyy",
}; };
case ValidTextureOverload::kDimensions2dLevel: case ValidTextureOverload::kDimensions2dLevel:
case ValidTextureOverload::kDimensions2dArrayLevel:
case ValidTextureOverload::kDimensionsDepth2dLevel: case ValidTextureOverload::kDimensionsDepth2dLevel:
case ValidTextureOverload::kDimensionsDepth2dArrayLevel:
return { return {
"int2 _tint_tmp;\n" "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", "_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: case ValidTextureOverload::kDimensions3dLevel:
return { return {
"int3 _tint_tmp;\n" "int3 _tint_tmp;\n"
"texture_tint_0.GetDimensions(1, _tint_tmp[0], _tint_tmp[1], " "texture_tint_0."
"_tint_tmp[2]);", "GetDimensions(1, _tint_tmp.x, _tint_tmp.y, _tint_tmp.z);",
"_tint_tmp", "_tint_tmp",
}; };
case ValidTextureOverload::kDimensionsCubeLevel: case ValidTextureOverload::kDimensionsCubeLevel:
case ValidTextureOverload::kDimensionsCubeArrayLevel:
case ValidTextureOverload::kDimensionsDepthCubeLevel: 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: case ValidTextureOverload::kDimensionsDepthCubeArrayLevel:
return { return {
"int3 _tint_tmp;\n" "int3 _tint_tmp;\n"
"texture_tint_0.GetDimensions(1, _tint_tmp[0], _tint_tmp[1]);\n" "texture_tint_0."
"_tint_tmp[2] = _tint_tmp[1];", "GetDimensions(1, _tint_tmp.x, _tint_tmp.y, _tint_tmp.z);",
"_tint_tmp", "_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: case ValidTextureOverload::kSample1dF32:
return R"(texture_tint_0.Sample(sampler_tint_0, 1.0f))"; return R"(texture_tint_0.Sample(sampler_tint_0, 1.0f))";

View File

@ -616,7 +616,8 @@ bool GeneratorImpl::EmitTextureCall(ast::CallExpression* expr) {
->UnwrapAll() ->UnwrapAll()
->As<ast::type::Texture>(); ->As<ast::type::Texture>();
if (ident->intrinsic() == ast::Intrinsic::kTextureDimensions) { switch (ident->intrinsic()) {
case ast::Intrinsic::kTextureDimensions: {
std::vector<const char*> dims; std::vector<const char*> dims;
switch (texture_type->dim()) { switch (texture_type->dim()) {
case ast::type::TextureDimension::kNone: case ast::type::TextureDimension::kNone:
@ -654,7 +655,9 @@ bool GeneratorImpl::EmitTextureCall(ast::CallExpression* expr) {
}; };
if (dims.size() == 1) { if (dims.size() == 1) {
out_ << "int(";
get_dim(dims[0]); get_dim(dims[0]);
out_ << ")";
} else { } else {
EmitType(expr->result_type(), ""); EmitType(expr->result_type(), "");
out_ << "("; out_ << "(";
@ -668,6 +671,17 @@ bool GeneratorImpl::EmitTextureCall(ast::CallExpression* expr) {
} }
return true; return true;
} }
case ast::Intrinsic::kTextureNumLayers: {
out_ << "int(";
if (!EmitExpression(params[pidx.texture])) {
return false;
}
out_ << ".get_array_size())";
return true;
}
default:
break;
}
if (!EmitExpression(params[pidx.texture])) if (!EmitExpression(params[pidx.texture]))
return false; return false;

View File

@ -38,7 +38,7 @@ std::string expected_texture_overload(
case ValidTextureOverload::kDimensionsStorageRO1dArray: case ValidTextureOverload::kDimensionsStorageRO1dArray:
case ValidTextureOverload::kDimensionsStorageWO1d: case ValidTextureOverload::kDimensionsStorageWO1d:
case ValidTextureOverload::kDimensionsStorageWO1dArray: case ValidTextureOverload::kDimensionsStorageWO1dArray:
return R"(texture_tint_0.get_width())"; return R"(int(texture_tint_0.get_width()))";
case ValidTextureOverload::kDimensions2d: case ValidTextureOverload::kDimensions2d:
case ValidTextureOverload::kDimensions2dArray: case ValidTextureOverload::kDimensions2dArray:
case ValidTextureOverload::kDimensionsMultisampled_2d: case ValidTextureOverload::kDimensionsMultisampled_2d:
@ -71,6 +71,15 @@ std::string expected_texture_overload(
case ValidTextureOverload::kDimensionsDepthCubeLevel: case ValidTextureOverload::kDimensionsDepthCubeLevel:
case ValidTextureOverload::kDimensionsDepthCubeArrayLevel: case ValidTextureOverload::kDimensionsDepthCubeArrayLevel:
return R"(int3(texture_tint_0.get_width(1), texture_tint_0.get_height(1), texture_tint_0.get_height(1)))"; 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: case ValidTextureOverload::kSample1dF32:
return R"(texture_tint_0.sample(sampler_tint_0, 1.0f))"; return R"(texture_tint_0.sample(sampler_tint_0, 1.0f))";
case ValidTextureOverload::kSample1dArrayF32: case ValidTextureOverload::kSample1dArrayF32:

View File

@ -2073,6 +2073,49 @@ bool Builder::GenerateTextureIntrinsic(ast::IdentifierExpression* ident,
return true; 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 { auto append_coords_to_spirv_params = [&]() -> bool {
if (pidx.array_index != kNotUsed) { if (pidx.array_index != kNotUsed) {
// Array index needs to be appended to the coordinates. // Array index needs to be appended to the coordinates.
@ -2147,42 +2190,10 @@ bool Builder::GenerateTextureIntrinsic(ast::IdentifierExpression* ident,
break; break;
} }
if (swizzle.empty()) { if (!append_result_type_and_id_to_spirv_params_swizzled(spirv_dims,
append_result_type_and_id_to_spirv_params(); swizzle)) {
} 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; return false;
} }
spirv_params.emplace_back(Operand::Int(spirv_result_type_id));
spirv_params.emplace_back(spirv_result);
}
spirv_params.emplace_back(gen_param(pidx.texture)); spirv_params.emplace_back(gen_param(pidx.texture));
if (texture_type->Is<ast::type::MultisampledTexture>() || if (texture_type->Is<ast::type::MultisampledTexture>() ||
@ -2199,6 +2210,41 @@ bool Builder::GenerateTextureIntrinsic(ast::IdentifierExpression* ident,
} }
break; 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: { case ast::Intrinsic::kTextureLoad: {
op = texture_type->Is<ast::type::StorageTexture>() op = texture_type->Is<ast::type::StorageTexture>()
? spv::Op::OpImageRead ? spv::Op::OpImageRead

View File

@ -739,6 +739,176 @@ OpCapability ImageQuery
)", )",
R"( R"(
OpCapability ImageQuery 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: case ValidTextureOverload::kSample1dF32:
return { return {