Implement textureNumLevels()

SPIR-V reader TODO

Bug: tint:140
Bug: tint:437
Change-Id: Icd41b2ef84e62b304e446589eb2e37c38279af35
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/37846
Reviewed-by: David Neto <dneto@google.com>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
Commit-Queue: Ben Clayton <bclayton@google.com>
This commit is contained in:
Ben Clayton 2021-01-14 18:06:57 +00:00 committed by Commit Bot service account
parent c21f1f92a2
commit d97132028a
12 changed files with 452 additions and 87 deletions

View File

@ -212,6 +212,9 @@ std::ostream& operator<<(std::ostream& out, Intrinsic i) {
case Intrinsic::kTextureNumLayers: case Intrinsic::kTextureNumLayers:
out << "textureNumLayers"; out << "textureNumLayers";
return out; return out;
case Intrinsic::kTextureNumLevels:
out << "textureNumLevels";
return out;
case Intrinsic::kTextureSample: case Intrinsic::kTextureSample:
out << "textureSample"; out << "textureSample";
return out; return out;
@ -268,8 +271,8 @@ bool IsFloatClassificationIntrinsic(Intrinsic i) {
} }
bool IsTextureIntrinsic(Intrinsic i) { bool IsTextureIntrinsic(Intrinsic i) {
return i == Intrinsic::kTextureDimensions || i == Intrinsic::kTextureLoad || return IsImageQueryIntrinsic(i) || i == Intrinsic::kTextureLoad ||
i == Intrinsic::kTextureNumLayers || i == Intrinsic::kTextureSample || i == Intrinsic::kTextureSample ||
i == Intrinsic::kTextureSampleLevel || i == Intrinsic::kTextureSampleLevel ||
i == Intrinsic::kTextureSampleBias || i == Intrinsic::kTextureSampleBias ||
i == Intrinsic::kTextureSampleCompare || i == Intrinsic::kTextureSampleCompare ||
@ -278,7 +281,7 @@ 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; i == Intrinsic::kTextureNumLayers || i == Intrinsic::kTextureNumLevels;
} }
} // namespace intrinsic } // namespace intrinsic

View File

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

View File

@ -543,7 +543,7 @@ std::vector<TextureOverloadCase> TextureOverloadCase::ValidCases() {
}, },
{ {
ValidTextureOverload::kNumLayers1dArray, ValidTextureOverload::kNumLayers1dArray,
"textureNumLayers(t : texture_1d_array<T>) -> i32", "textureNumLayers(t : texture_1d_array<f32>) -> i32",
TextureKind::kRegular, TextureKind::kRegular,
type::SamplerKind::kSampler, type::SamplerKind::kSampler,
type::TextureDimension::k1dArray, type::TextureDimension::k1dArray,
@ -553,7 +553,7 @@ std::vector<TextureOverloadCase> TextureOverloadCase::ValidCases() {
}, },
{ {
ValidTextureOverload::kNumLayers2dArray, ValidTextureOverload::kNumLayers2dArray,
"textureNumLayers(t : texture_2d_array<T>) -> i32", "textureNumLayers(t : texture_2d_array<f32>) -> i32",
TextureKind::kRegular, TextureKind::kRegular,
type::SamplerKind::kSampler, type::SamplerKind::kSampler,
type::TextureDimension::k2dArray, type::TextureDimension::k2dArray,
@ -563,7 +563,7 @@ std::vector<TextureOverloadCase> TextureOverloadCase::ValidCases() {
}, },
{ {
ValidTextureOverload::kNumLayersCubeArray, ValidTextureOverload::kNumLayersCubeArray,
"textureNumLayers(t : texture_cube_array<T>) -> i32", "textureNumLayers(t : texture_cube_array<f32>) -> i32",
TextureKind::kRegular, TextureKind::kRegular,
type::SamplerKind::kSampler, type::SamplerKind::kSampler,
type::TextureDimension::kCubeArray, type::TextureDimension::kCubeArray,
@ -573,7 +573,7 @@ std::vector<TextureOverloadCase> TextureOverloadCase::ValidCases() {
}, },
{ {
ValidTextureOverload::kNumLayersMultisampled_2dArray, ValidTextureOverload::kNumLayersMultisampled_2dArray,
"textureNumLayers(t : texture_multisampled_2d_array<T>) -> i32", "textureNumLayers(t : texture_multisampled_2d_array<f32>) -> i32",
TextureKind::kMultisampled, TextureKind::kMultisampled,
type::SamplerKind::kSampler, type::SamplerKind::kSampler,
type::TextureDimension::k2dArray, type::TextureDimension::k2dArray,
@ -603,7 +603,7 @@ std::vector<TextureOverloadCase> TextureOverloadCase::ValidCases() {
}, },
{ {
ValidTextureOverload::kNumLayersStorageWO1dArray, ValidTextureOverload::kNumLayersStorageWO1dArray,
"textureNumLayers(t : texture_storage_1d_array<F>) -> i32", "textureNumLayers(t : texture_storage_1d_array<rgba32float>) -> i32",
ast::AccessControl::kWriteOnly, ast::AccessControl::kWriteOnly,
ast::type::ImageFormat::kRgba32Float, ast::type::ImageFormat::kRgba32Float,
type::TextureDimension::k1dArray, type::TextureDimension::k1dArray,
@ -613,7 +613,7 @@ std::vector<TextureOverloadCase> TextureOverloadCase::ValidCases() {
}, },
{ {
ValidTextureOverload::kNumLayersStorageWO2dArray, ValidTextureOverload::kNumLayersStorageWO2dArray,
"textureNumLayers(t : texture_storage_2d_array<F>) -> i32", "textureNumLayers(t : texture_storage_2d_array<rgba32float>) -> i32",
ast::AccessControl::kWriteOnly, ast::AccessControl::kWriteOnly,
ast::type::ImageFormat::kRgba32Float, ast::type::ImageFormat::kRgba32Float,
type::TextureDimension::k2dArray, type::TextureDimension::k2dArray,
@ -621,6 +621,96 @@ std::vector<TextureOverloadCase> TextureOverloadCase::ValidCases() {
"textureNumLayers", "textureNumLayers",
[](Builder* b) { return b->ExprList("texture"); }, [](Builder* b) { return b->ExprList("texture"); },
}, },
{
ValidTextureOverload::kNumLevels2d,
"textureNumLevels(t : texture_2d<f32>) -> i32",
TextureKind::kRegular,
type::SamplerKind::kSampler,
type::TextureDimension::k2d,
TextureDataType::kF32,
"textureNumLevels",
[](Builder* b) { return b->ExprList("texture"); },
},
{
ValidTextureOverload::kNumLevels2dArray,
"textureNumLevels(t : texture_2d_array<f32>) -> i32",
TextureKind::kRegular,
type::SamplerKind::kSampler,
type::TextureDimension::k2dArray,
TextureDataType::kF32,
"textureNumLevels",
[](Builder* b) { return b->ExprList("texture"); },
},
{
ValidTextureOverload::kNumLevels3d,
"textureNumLevels(t : texture_3d<f32>) -> i32",
TextureKind::kRegular,
type::SamplerKind::kSampler,
type::TextureDimension::k3d,
TextureDataType::kF32,
"textureNumLevels",
[](Builder* b) { return b->ExprList("texture"); },
},
{
ValidTextureOverload::kNumLevelsCube,
"textureNumLevels(t : texture_cube<f32>) -> i32",
TextureKind::kRegular,
type::SamplerKind::kSampler,
type::TextureDimension::kCube,
TextureDataType::kF32,
"textureNumLevels",
[](Builder* b) { return b->ExprList("texture"); },
},
{
ValidTextureOverload::kNumLevelsCubeArray,
"textureNumLevels(t : texture_cube_array<f32>) -> i32",
TextureKind::kRegular,
type::SamplerKind::kSampler,
type::TextureDimension::kCubeArray,
TextureDataType::kF32,
"textureNumLevels",
[](Builder* b) { return b->ExprList("texture"); },
},
{
ValidTextureOverload::kNumLevelsDepth2d,
"textureNumLevels(t : texture_depth_2d) -> i32",
TextureKind::kDepth,
type::SamplerKind::kSampler,
type::TextureDimension::k2d,
TextureDataType::kF32,
"textureNumLevels",
[](Builder* b) { return b->ExprList("texture"); },
},
{
ValidTextureOverload::kNumLevelsDepth2dArray,
"textureNumLevels(t : texture_depth_2d_array) -> i32",
TextureKind::kDepth,
type::SamplerKind::kSampler,
type::TextureDimension::k2dArray,
TextureDataType::kF32,
"textureNumLevels",
[](Builder* b) { return b->ExprList("texture"); },
},
{
ValidTextureOverload::kNumLevelsDepthCube,
"textureNumLevels(t : texture_depth_cube) -> i32",
TextureKind::kDepth,
type::SamplerKind::kSampler,
type::TextureDimension::kCube,
TextureDataType::kF32,
"textureNumLevels",
[](Builder* b) { return b->ExprList("texture"); },
},
{
ValidTextureOverload::kNumLevelsDepthCubeArray,
"textureNumLevels(t : texture_depth_cube_array) -> i32",
TextureKind::kDepth,
type::SamplerKind::kSampler,
type::TextureDimension::kCubeArray,
TextureDataType::kF32,
"textureNumLevels",
[](Builder* b) { return b->ExprList("texture"); },
},
{ {
ValidTextureOverload::kSample1dF32, ValidTextureOverload::kSample1dF32,
"textureSample(t : texture_1d<f32>,\n" "textureSample(t : texture_1d<f32>,\n"
@ -2413,7 +2503,7 @@ std::vector<TextureOverloadCase> TextureOverloadCase::ValidCases() {
}, },
{ {
ValidTextureOverload::kStoreWO1dRgba32float, ValidTextureOverload::kStoreWO1dRgba32float,
"textureStore(t : texture_storage_1d<F>,\n" "textureStore(t : texture_storage_1d<rgba32float>,\n"
" coords : i32,\n" " coords : i32,\n"
" value : vec4<T>) -> void", " value : vec4<T>) -> void",
ast::AccessControl::kWriteOnly, ast::AccessControl::kWriteOnly,
@ -2429,7 +2519,7 @@ std::vector<TextureOverloadCase> TextureOverloadCase::ValidCases() {
}, },
{ {
ValidTextureOverload::kStoreWO1dArrayRgba32float, ValidTextureOverload::kStoreWO1dArrayRgba32float,
"textureStore(t : texture_storage_1d_array<F>,\n" "textureStore(t : texture_storage_1d_array<rgba32float>,\n"
" coords : i32,\n" " coords : i32,\n"
" array_index : i32,\n" " array_index : i32,\n"
" value : vec4<T>) -> void", " value : vec4<T>) -> void",
@ -2447,7 +2537,7 @@ std::vector<TextureOverloadCase> TextureOverloadCase::ValidCases() {
}, },
{ {
ValidTextureOverload::kStoreWO2dRgba32float, ValidTextureOverload::kStoreWO2dRgba32float,
"textureStore(t : texture_storage_2d<F>,\n" "textureStore(t : texture_storage_2d<rgba32float>,\n"
" coords : vec2<i32>,\n" " coords : vec2<i32>,\n"
" value : vec4<T>) -> void", " value : vec4<T>) -> void",
ast::AccessControl::kWriteOnly, ast::AccessControl::kWriteOnly,
@ -2463,7 +2553,7 @@ std::vector<TextureOverloadCase> TextureOverloadCase::ValidCases() {
}, },
{ {
ValidTextureOverload::kStoreWO2dArrayRgba32float, ValidTextureOverload::kStoreWO2dArrayRgba32float,
"textureStore(t : texture_storage_2d_array<F>,\n" "textureStore(t : texture_storage_2d_array<rgba32float>,\n"
" coords : vec2<i32>,\n" " coords : vec2<i32>,\n"
" array_index : i32,\n" " array_index : i32,\n"
" value : vec4<T>) -> void", " value : vec4<T>) -> void",
@ -2481,7 +2571,7 @@ std::vector<TextureOverloadCase> TextureOverloadCase::ValidCases() {
}, },
{ {
ValidTextureOverload::kStoreWO3dRgba32float, ValidTextureOverload::kStoreWO3dRgba32float,
"textureStore(t : texture_storage_3d<F>,\n" "textureStore(t : texture_storage_3d<rgba32float>,\n"
" coords : vec3<i32>,\n" " coords : vec3<i32>,\n"
" value : vec4<T>) -> void", " value : vec4<T>) -> void",
ast::AccessControl::kWriteOnly, ast::AccessControl::kWriteOnly,

View File

@ -77,6 +77,15 @@ enum class ValidTextureOverload {
kNumLayersDepthCubeArray, kNumLayersDepthCubeArray,
kNumLayersStorageWO1dArray, kNumLayersStorageWO1dArray,
kNumLayersStorageWO2dArray, kNumLayersStorageWO2dArray,
kNumLevels2d,
kNumLevels2dArray,
kNumLevels3d,
kNumLevelsCube,
kNumLevelsCubeArray,
kNumLevelsDepth2d,
kNumLevelsDepth2dArray,
kNumLevelsDepthCube,
kNumLevelsDepthCubeArray,
kSample1dF32, kSample1dF32,
kSample1dArrayF32, kSample1dArrayF32,
kSample2dF32, kSample2dF32,

View File

@ -567,6 +567,7 @@ bool TypeDeterminer::DetermineIntrinsic(ast::IdentifierExpression* ident,
} }
break; break;
case ast::Intrinsic::kTextureNumLayers: case ast::Intrinsic::kTextureNumLayers:
case ast::Intrinsic::kTextureNumLevels:
param.idx.texture = param.count++; param.idx.texture = param.count++;
break; break;
case ast::Intrinsic::kTextureLoad: case ast::Intrinsic::kTextureLoad:
@ -696,6 +697,7 @@ bool TypeDeterminer::DetermineIntrinsic(ast::IdentifierExpression* ident,
break; break;
} }
case ast::Intrinsic::kTextureNumLayers: case ast::Intrinsic::kTextureNumLayers:
case ast::Intrinsic::kTextureNumLevels:
return_type = mod_->create<ast::type::I32>(); return_type = mod_->create<ast::type::I32>();
break; break;
case ast::Intrinsic::kTextureStore: case ast::Intrinsic::kTextureStore:
@ -1034,6 +1036,8 @@ bool TypeDeterminer::SetIntrinsicIfNeeded(ast::IdentifierExpression* ident) {
ident->set_intrinsic(ast::Intrinsic::kTextureDimensions); ident->set_intrinsic(ast::Intrinsic::kTextureDimensions);
} else if (name == "textureNumLayers") { } else if (name == "textureNumLayers") {
ident->set_intrinsic(ast::Intrinsic::kTextureNumLayers); ident->set_intrinsic(ast::Intrinsic::kTextureNumLayers);
} else if (name == "textureNumLevels") {
ident->set_intrinsic(ast::Intrinsic::kTextureNumLevels);
} 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

@ -1765,6 +1765,7 @@ INSTANTIATE_TEST_SUITE_P(
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{"textureNumLayers", ast::Intrinsic::kTextureNumLayers},
IntrinsicData{"textureNumLevels", ast::Intrinsic::kTextureNumLevels},
IntrinsicData{"textureSample", ast::Intrinsic::kTextureSample}, IntrinsicData{"textureSample", ast::Intrinsic::kTextureSample},
IntrinsicData{"textureSampleBias", ast::Intrinsic::kTextureSampleBias}, IntrinsicData{"textureSampleBias", ast::Intrinsic::kTextureSampleBias},
IntrinsicData{"textureSampleCompare", IntrinsicData{"textureSampleCompare",
@ -2938,6 +2939,16 @@ const char* expected_texture_overload(
case ValidTextureOverload::kNumLayersStorageWO1dArray: case ValidTextureOverload::kNumLayersStorageWO1dArray:
case ValidTextureOverload::kNumLayersStorageWO2dArray: case ValidTextureOverload::kNumLayersStorageWO2dArray:
return R"(textureNumLayers(texture))"; return R"(textureNumLayers(texture))";
case ValidTextureOverload::kNumLevels2d:
case ValidTextureOverload::kNumLevels2dArray:
case ValidTextureOverload::kNumLevels3d:
case ValidTextureOverload::kNumLevelsCube:
case ValidTextureOverload::kNumLevelsCubeArray:
case ValidTextureOverload::kNumLevelsDepth2d:
case ValidTextureOverload::kNumLevelsDepth2dArray:
case ValidTextureOverload::kNumLevelsDepthCube:
case ValidTextureOverload::kNumLevelsDepthCubeArray:
return R"(textureNumLevels(texture))";
case ValidTextureOverload::kDimensions2dLevel: case ValidTextureOverload::kDimensions2dLevel:
case ValidTextureOverload::kDimensions2dArrayLevel: case ValidTextureOverload::kDimensions2dArrayLevel:
case ValidTextureOverload::kDimensions3dLevel: case ValidTextureOverload::kDimensions3dLevel:
@ -3193,6 +3204,8 @@ TEST_P(TypeDeterminerTextureIntrinsicTest, Call) {
} }
} else if (std::string(param.function) == "textureNumLayers") { } else if (std::string(param.function) == "textureNumLayers") {
EXPECT_EQ(call->result_type(), ty.i32); EXPECT_EQ(call->result_type(), ty.i32);
} else if (std::string(param.function) == "textureNumLevels") {
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

@ -697,7 +697,8 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& pre,
switch (ident->intrinsic()) { switch (ident->intrinsic()) {
case ast::Intrinsic::kTextureDimensions: case ast::Intrinsic::kTextureDimensions:
case ast::Intrinsic::kTextureNumLayers: { case ast::Intrinsic::kTextureNumLayers:
case ast::Intrinsic::kTextureNumLevels: {
// Declare a variable to hold the queried texture info // Declare a variable to hold the queried texture info
auto dims = generate_name(kTempNamePrefix); auto dims = generate_name(kTempNamePrefix);
@ -706,85 +707,120 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& pre,
return false; return false;
} }
auto get_dimensions = [&](std::initializer_list<const char*>&& suffixes) { int num_dimensions = 0;
pre << texture_name.str() << ".GetDimensions("; const char* swizzle = "";
if (pidx.level != kNotUsed) { bool add_mip_level_in = false;
pre << pidx.level << ", ";
}
bool first = true;
for (auto* suffix : suffixes) {
if (!first) {
pre << ", ";
}
first = false;
pre << dims << suffix;
}
pre << ");";
};
const char* dims_swizzle = ""; switch (ident->intrinsic()) {
const char* num_els_swizzle = ""; case ast::Intrinsic::kTextureDimensions:
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"; num_dimensions = 1;
get_dimensions({""});
break; break;
case ast::type::TextureDimension::k1dArray: case ast::type::TextureDimension::k1dArray:
pre << "int2 " << dims << ";\n"; num_dimensions = 2;
get_dimensions({".x", ".y"}); swizzle = ".x";
dims_swizzle = ".x";
num_els_swizzle = ".y";
break; break;
case ast::type::TextureDimension::k2d: case ast::type::TextureDimension::k2d:
pre << "int2 " << dims << ";\n"; num_dimensions = 2;
get_dimensions({".x", ".y"});
break; break;
case ast::type::TextureDimension::k2dArray: case ast::type::TextureDimension::k2dArray:
pre << "int3 " << dims << ";\n"; num_dimensions = 3;
get_dimensions({".x", ".y", ".z"}); swizzle = ".xy";
dims_swizzle = ".xy";
num_els_swizzle = ".z";
break; break;
case ast::type::TextureDimension::k3d: case ast::type::TextureDimension::k3d:
pre << "int3 " << dims << ";\n"; num_dimensions = 3;
get_dimensions({".x", ".y", ".z"});
break; break;
case ast::type::TextureDimension::kCube: case ast::type::TextureDimension::kCube:
// 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 << "int2 " << dims << ";\n"; num_dimensions = 2;
get_dimensions({".x", ".y"}); swizzle = ".xyy"; // [width, height, height]
dims_swizzle = ".xyy"; // [width, height, height]
break; 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 << "int3 " << dims << ";\n"; num_dimensions = 3;
get_dimensions({".x", ".y", ".z"}); swizzle = ".xyy"; // [width, height, height]
dims_swizzle = ".xyy"; // [width, height, height]
num_els_swizzle = ".z";
break; break;
} }
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: case ast::Intrinsic::kTextureNumLayers:
out << dims << num_els_swizzle; switch (texture_type->dim()) {
return true;
default: default:
error_ = "Unhandled intrinsic"; error_ = "texture dimension is not arrayed";
return false;
case ast::type::TextureDimension::k1dArray:
num_dimensions = 2;
swizzle = ".y";
break;
case ast::type::TextureDimension::k2dArray:
case ast::type::TextureDimension::kCubeArray:
num_dimensions = 3;
swizzle = ".z";
break;
}
break;
case ast::Intrinsic::kTextureNumLevels:
add_mip_level_in = true;
switch (texture_type->dim()) {
default:
error_ = "texture dimension does not support mips";
return false;
case ast::type::TextureDimension::k2d:
case ast::type::TextureDimension::kCube:
num_dimensions = 3;
swizzle = ".z";
break;
case ast::type::TextureDimension::k2dArray:
case ast::type::TextureDimension::k3d:
case ast::type::TextureDimension::kCubeArray:
num_dimensions = 4;
swizzle = ".w";
break;
}
break;
default:
error_ = "unexpected intrinsic";
return false; return false;
} }
if (num_dimensions == 1) {
pre << "int " << dims << ";\n";
} else {
pre << "int" << num_dimensions << " " << dims << ";\n";
}
pre << texture_name.str() << ".GetDimensions(";
if (pidx.level != kNotUsed) {
pre << pidx.level << ", ";
} else if (add_mip_level_in) {
pre << "0, ";
}
if (num_dimensions == 1) {
pre << dims;
} else {
assert(num_dimensions > 0);
assert(num_dimensions <= 4);
static constexpr char xyzw[] = {'x', 'y', 'z', 'w'};
for (int i = 0; i < num_dimensions; i++) {
if (i > 0) {
pre << ", ";
}
pre << dims << "." << xyzw[i];
}
}
pre << ");";
// The out parameters of the GetDimensions() call is now in temporary
// `dims` variable. This may be packed with other data, so the final
// expression may require a swizzle.
out << dims << swizzle;
return true;
} }
default: default:
break; break;

View File

@ -157,6 +157,27 @@ ExpectedResult expected_texture_overload(
"GetDimensions(_tint_tmp.x, _tint_tmp.y, _tint_tmp.z);", "GetDimensions(_tint_tmp.x, _tint_tmp.y, _tint_tmp.z);",
"_tint_tmp.z", "_tint_tmp.z",
}; };
case ValidTextureOverload::kNumLevels2d:
case ValidTextureOverload::kNumLevelsCube:
case ValidTextureOverload::kNumLevelsDepth2d:
case ValidTextureOverload::kNumLevelsDepthCube:
return {
"int3 _tint_tmp;\n"
"texture_tint_0."
"GetDimensions(0, _tint_tmp.x, _tint_tmp.y, _tint_tmp.z);",
"_tint_tmp.z",
};
case ValidTextureOverload::kNumLevels2dArray:
case ValidTextureOverload::kNumLevels3d:
case ValidTextureOverload::kNumLevelsCubeArray:
case ValidTextureOverload::kNumLevelsDepth2dArray:
case ValidTextureOverload::kNumLevelsDepthCubeArray:
return {
"int4 _tint_tmp;\n"
"texture_tint_0.GetDimensions(0, "
"_tint_tmp.x, _tint_tmp.y, _tint_tmp.z, _tint_tmp.w);",
"_tint_tmp.w",
};
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

@ -679,6 +679,14 @@ bool GeneratorImpl::EmitTextureCall(ast::CallExpression* expr) {
out_ << ".get_array_size())"; out_ << ".get_array_size())";
return true; return true;
} }
case ast::Intrinsic::kTextureNumLevels: {
out_ << "int(";
if (!EmitExpression(params[pidx.texture])) {
return false;
}
out_ << ".get_num_mip_levels())";
return true;
}
default: default:
break; break;
} }

View File

@ -80,6 +80,16 @@ std::string expected_texture_overload(
case ValidTextureOverload::kNumLayersStorageWO1dArray: case ValidTextureOverload::kNumLayersStorageWO1dArray:
case ValidTextureOverload::kNumLayersStorageWO2dArray: case ValidTextureOverload::kNumLayersStorageWO2dArray:
return R"(int(texture_tint_0.get_array_size()))"; return R"(int(texture_tint_0.get_array_size()))";
case ValidTextureOverload::kNumLevels2d:
case ValidTextureOverload::kNumLevels2dArray:
case ValidTextureOverload::kNumLevels3d:
case ValidTextureOverload::kNumLevelsCube:
case ValidTextureOverload::kNumLevelsCubeArray:
case ValidTextureOverload::kNumLevelsDepth2d:
case ValidTextureOverload::kNumLevelsDepth2dArray:
case ValidTextureOverload::kNumLevelsDepthCube:
case ValidTextureOverload::kNumLevelsDepthCubeArray:
return R"(int(texture_tint_0.get_num_mip_levels()))";
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

@ -2245,6 +2245,12 @@ bool Builder::GenerateTextureIntrinsic(ast::IdentifierExpression* ident,
} }
break; break;
} }
case ast::Intrinsic::kTextureNumLevels: {
op = spv::Op::OpImageQueryLevels;
append_result_type_and_id_to_spirv_params();
spirv_params.emplace_back(gen_param(pidx.texture));
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

@ -909,6 +909,170 @@ OpCapability ImageQuery
)", )",
R"( R"(
OpCapability ImageQuery OpCapability ImageQuery
)"};
case ValidTextureOverload::kNumLevels2d:
return {R"(
%4 = OpTypeFloat 32
%3 = OpTypeImage %4 2D 0 0 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
)",
R"(
%10 = OpLoad %3 %1
%8 = OpImageQueryLevels %9 %10
)",
R"(
OpCapability ImageQuery
)"};
case ValidTextureOverload::kNumLevels2dArray:
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
)",
R"(
%10 = OpLoad %3 %1
%8 = OpImageQueryLevels %9 %10
)",
R"(
OpCapability ImageQuery
)"};
case ValidTextureOverload::kNumLevels3d:
return {R"(
%4 = OpTypeFloat 32
%3 = OpTypeImage %4 3D 0 0 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
)",
R"(
%10 = OpLoad %3 %1
%8 = OpImageQueryLevels %9 %10
)",
R"(
OpCapability ImageQuery
)"};
case ValidTextureOverload::kNumLevelsCube:
return {R"(
%4 = OpTypeFloat 32
%3 = OpTypeImage %4 Cube 0 0 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
)",
R"(
%10 = OpLoad %3 %1
%8 = OpImageQueryLevels %9 %10
)",
R"(
OpCapability ImageQuery
)"};
case ValidTextureOverload::kNumLevelsCubeArray:
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
)",
R"(
%10 = OpLoad %3 %1
%8 = OpImageQueryLevels %9 %10
)",
R"(
OpCapability SampledCubeArray
OpCapability ImageQuery
)"};
case ValidTextureOverload::kNumLevelsDepth2d:
return {R"(
%4 = OpTypeFloat 32
%3 = OpTypeImage %4 2D 1 0 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
)",
R"(
%10 = OpLoad %3 %1
%8 = OpImageQueryLevels %9 %10
)",
R"(
OpCapability ImageQuery
)"};
case ValidTextureOverload::kNumLevelsDepth2dArray:
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
)",
R"(
%10 = OpLoad %3 %1
%8 = OpImageQueryLevels %9 %10
)",
R"(
OpCapability ImageQuery
)"};
case ValidTextureOverload::kNumLevelsDepthCube:
return {R"(
%4 = OpTypeFloat 32
%3 = OpTypeImage %4 Cube 1 0 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
)",
R"(
%10 = OpLoad %3 %1
%8 = OpImageQueryLevels %9 %10
)",
R"(
OpCapability ImageQuery
)"};
case ValidTextureOverload::kNumLevelsDepthCubeArray:
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
)",
R"(
%10 = OpLoad %3 %1
%8 = OpImageQueryLevels %9 %10
)",
R"(
OpCapability SampledCubeArray
OpCapability ImageQuery
)"}; )"};
case ValidTextureOverload::kSample1dF32: case ValidTextureOverload::kSample1dF32:
return { return {