spirv-reader: support OpImageQuerySizeLod
It queries the dimensions and array levels of a sampled image.
Bug: tint:109
Fixed: tint:423
Change-Id: Ia9ac0ee84b0282dbde8729a1698c9b21943723d2
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/39682
Commit-Queue: David Neto <dneto@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Auto-Submit: David Neto <dneto@google.com>
diff --git a/src/reader/spirv/function.cc b/src/reader/spirv/function.cc
index 15e9988..2a0a872 100644
--- a/src/reader/spirv/function.cc
+++ b/src/reader/spirv/function.cc
@@ -4376,15 +4376,20 @@
const auto opcode = inst.opcode();
switch (opcode) {
- case SpvOpImageQuerySize: {
+ case SpvOpImageQuerySize:
+ case SpvOpImageQuerySizeLod: {
ast::ExpressionList exprs;
// Invoke textureDimensions.
// If the texture is arrayed, combine with the result from
// textureNumLayers.
auto* dims_ident = create<ast::IdentifierExpression>(
Source{}, builder_.Symbols().Register("textureDimensions"));
- exprs.push_back(create<ast::CallExpression>(
- Source{}, dims_ident, ast::ExpressionList{GetImageExpression(inst)}));
+ ast::ExpressionList dims_args{GetImageExpression(inst)};
+ if (opcode == SpvOpImageQuerySizeLod) {
+ dims_args.push_back(ToI32(MakeOperand(inst, 1)).expr);
+ }
+ exprs.push_back(
+ create<ast::CallExpression>(Source{}, dims_ident, dims_args));
if (type::IsTextureArray(texture_type->dim())) {
auto* layers_ident = create<ast::IdentifierExpression>(
Source{}, builder_.Symbols().Register("textureNumLayers"));
@@ -4401,7 +4406,6 @@
return Fail() << "WGSL does not support querying the level of detail of "
"an image: "
<< inst.PrettyPrint();
- case SpvOpImageQuerySizeLod: // TODO(dneto)
case SpvOpImageQueryLevels: // TODO(dneto)
case SpvOpImageQuerySamples: // TODO(dneto)
default:
diff --git a/src/reader/spirv/parser_impl_handle_test.cc b/src/reader/spirv/parser_impl_handle_test.cc
index de34c44..e8206d5 100644
--- a/src/reader/spirv/parser_impl_handle_test.cc
+++ b/src/reader/spirv/parser_impl_handle_test.cc
@@ -3924,6 +3924,488 @@
}
})"}}));
+INSTANTIATE_TEST_SUITE_P(
+ ImageQuerySizeLod_NonArrayed_SignedResult_SignedLevel,
+ // ImageQuerySize requires storage image or multisampled
+ // For storage image, use another instruction to indicate whether it
+ // is readonly or writeonly.
+ SpvParserTest_SampledImageAccessTest,
+ ::testing::ValuesIn(std::vector<ImageAccessCase>{
+
+ // 1D
+ {"%float 1D 0 0 0 1 Unknown",
+ "%99 = OpImageQuerySizeLod %int %im %i1\n",
+ R"(Variable{
+ Decorations{
+ GroupDecoration{2}
+ BindingDecoration{1}
+ }
+ x_20
+ uniform_constant
+ __sampled_texture_1d__f32
+ })",
+ R"(VariableDeclStatement{
+ VariableConst{
+ x_99
+ none
+ __i32
+ {
+ TypeConstructor[not set]{
+ __i32
+ Call[not set]{
+ Identifier[not set]{textureDimensions}
+ (
+ Identifier[not set]{x_20}
+ Identifier[not set]{i1}
+ )
+ }
+ }
+ }
+ }
+ })"},
+
+ // 2D
+ {"%float 2D 0 0 0 1 Unknown",
+ "%99 = OpImageQuerySizeLod %v2int %im %i1\n",
+ R"(Variable{
+ Decorations{
+ GroupDecoration{2}
+ BindingDecoration{1}
+ }
+ x_20
+ uniform_constant
+ __sampled_texture_2d__f32
+ })",
+ R"(VariableDeclStatement{
+ VariableConst{
+ x_99
+ none
+ __vec_2__i32
+ {
+ TypeConstructor[not set]{
+ __vec_2__i32
+ Call[not set]{
+ Identifier[not set]{textureDimensions}
+ (
+ Identifier[not set]{x_20}
+ Identifier[not set]{i1}
+ )
+ }
+ }
+ }
+ }
+ })"},
+
+ // 3D
+ {"%float 3D 0 0 0 1 Unknown",
+ "%99 = OpImageQuerySizeLod %v3int %im %i1\n",
+ R"(Variable{
+ Decorations{
+ GroupDecoration{2}
+ BindingDecoration{1}
+ }
+ x_20
+ uniform_constant
+ __sampled_texture_3d__f32
+ })",
+ R"(VariableDeclStatement{
+ VariableConst{
+ x_99
+ none
+ __vec_3__i32
+ {
+ TypeConstructor[not set]{
+ __vec_3__i32
+ Call[not set]{
+ Identifier[not set]{textureDimensions}
+ (
+ Identifier[not set]{x_20}
+ Identifier[not set]{i1}
+ )
+ }
+ }
+ }
+ }
+ })"},
+
+ // Cube
+ {"%float Cube 0 0 0 1 Unknown",
+ "%99 = OpImageQuerySizeLod %v3int %im %i1\n",
+ R"(Variable{
+ Decorations{
+ GroupDecoration{2}
+ BindingDecoration{1}
+ }
+ x_20
+ uniform_constant
+ __sampled_texture_cube__f32
+ })",
+ R"(VariableDeclStatement{
+ VariableConst{
+ x_99
+ none
+ __vec_3__i32
+ {
+ TypeConstructor[not set]{
+ __vec_3__i32
+ Call[not set]{
+ Identifier[not set]{textureDimensions}
+ (
+ Identifier[not set]{x_20}
+ Identifier[not set]{i1}
+ )
+ }
+ }
+ }
+ }
+ })"},
+
+ // Depth 2D
+ {"%float 2D 1 0 0 1 Unknown",
+ "%99 = OpImageQuerySizeLod %v2int %im %i1\n",
+ R"(Variable{
+ Decorations{
+ GroupDecoration{2}
+ BindingDecoration{1}
+ }
+ x_20
+ uniform_constant
+ __depth_texture_2d
+ })",
+ R"(VariableDeclStatement{
+ VariableConst{
+ x_99
+ none
+ __vec_2__i32
+ {
+ TypeConstructor[not set]{
+ __vec_2__i32
+ Call[not set]{
+ Identifier[not set]{textureDimensions}
+ (
+ Identifier[not set]{x_20}
+ Identifier[not set]{i1}
+ )
+ }
+ }
+ }
+ }
+ })"},
+
+ // Depth Cube
+ {"%float Cube 1 0 0 1 Unknown",
+ "%99 = OpImageQuerySizeLod %v3int %im %i1\n",
+ R"(Variable{
+ Decorations{
+ GroupDecoration{2}
+ BindingDecoration{1}
+ }
+ x_20
+ uniform_constant
+ __depth_texture_cube
+ })",
+ R"(VariableDeclStatement{
+ VariableConst{
+ x_99
+ none
+ __vec_3__i32
+ {
+ TypeConstructor[not set]{
+ __vec_3__i32
+ Call[not set]{
+ Identifier[not set]{textureDimensions}
+ (
+ Identifier[not set]{x_20}
+ Identifier[not set]{i1}
+ )
+ }
+ }
+ }
+ }
+ })"}}));
+
+INSTANTIATE_TEST_SUITE_P(
+ ImageQuerySizeLod_Arrayed_SignedResult_SignedLevel,
+ // ImageQuerySize requires storage image or multisampled
+ // For storage image, use another instruction to indicate whether it
+ // is readonly or writeonly.
+ SpvParserTest_SampledImageAccessTest,
+ ::testing::ValuesIn(std::vector<ImageAccessCase>{
+
+ // 1D arrayed
+ {"%float 1D 0 1 0 1 Unknown",
+ "%99 = OpImageQuerySizeLod %v2int %im %i1\n",
+ R"(Variable{
+ Decorations{
+ GroupDecoration{2}
+ BindingDecoration{1}
+ }
+ x_20
+ uniform_constant
+ __sampled_texture_1d_array__f32
+ })",
+ R"(VariableDeclStatement{
+ VariableConst{
+ x_99
+ none
+ __vec_2__i32
+ {
+ TypeConstructor[not set]{
+ __vec_2__i32
+ Call[not set]{
+ Identifier[not set]{textureDimensions}
+ (
+ Identifier[not set]{x_20}
+ Identifier[not set]{i1}
+ )
+ }
+ Call[not set]{
+ Identifier[not set]{textureNumLayers}
+ (
+ Identifier[not set]{x_20}
+ )
+ }
+ }
+ }
+ }
+ })"},
+
+ // 2D array
+ {"%float 2D 0 1 0 1 Unknown",
+ "%99 = OpImageQuerySizeLod %v3int %im %i1\n",
+ R"(Variable{
+ Decorations{
+ GroupDecoration{2}
+ BindingDecoration{1}
+ }
+ x_20
+ uniform_constant
+ __sampled_texture_2d_array__f32
+ })",
+ R"(VariableDeclStatement{
+ VariableConst{
+ x_99
+ none
+ __vec_3__i32
+ {
+ TypeConstructor[not set]{
+ __vec_3__i32
+ Call[not set]{
+ Identifier[not set]{textureDimensions}
+ (
+ Identifier[not set]{x_20}
+ Identifier[not set]{i1}
+ )
+ }
+ Call[not set]{
+ Identifier[not set]{textureNumLayers}
+ (
+ Identifier[not set]{x_20}
+ )
+ }
+ }
+ }
+ }
+ })"},
+
+ // There is no 3D array
+
+ // Cube array
+ {"%float Cube 0 1 0 1 Unknown",
+ "%99 = OpImageQuerySizeLod %v4int %im %i1\n",
+ R"(Variable{
+ Decorations{
+ GroupDecoration{2}
+ BindingDecoration{1}
+ }
+ x_20
+ uniform_constant
+ __sampled_texture_cube_array__f32
+ })",
+ R"(VariableDeclStatement{
+ VariableConst{
+ x_99
+ none
+ __vec_4__i32
+ {
+ TypeConstructor[not set]{
+ __vec_4__i32
+ Call[not set]{
+ Identifier[not set]{textureDimensions}
+ (
+ Identifier[not set]{x_20}
+ Identifier[not set]{i1}
+ )
+ }
+ Call[not set]{
+ Identifier[not set]{textureNumLayers}
+ (
+ Identifier[not set]{x_20}
+ )
+ }
+ }
+ }
+ }
+ })"},
+
+ // Depth 2D array
+ {"%float 2D 1 1 0 1 Unknown",
+ "%99 = OpImageQuerySizeLod %v3int %im %i1\n",
+ R"(Variable{
+ Decorations{
+ GroupDecoration{2}
+ BindingDecoration{1}
+ }
+ x_20
+ uniform_constant
+ __depth_texture_2d_array
+ })",
+ R"(VariableDeclStatement{
+ VariableConst{
+ x_99
+ none
+ __vec_3__i32
+ {
+ TypeConstructor[not set]{
+ __vec_3__i32
+ Call[not set]{
+ Identifier[not set]{textureDimensions}
+ (
+ Identifier[not set]{x_20}
+ Identifier[not set]{i1}
+ )
+ }
+ Call[not set]{
+ Identifier[not set]{textureNumLayers}
+ (
+ Identifier[not set]{x_20}
+ )
+ }
+ }
+ }
+ }
+ })"},
+
+ // Depth Cube Array
+ {"%float Cube 1 1 0 1 Unknown",
+ "%99 = OpImageQuerySizeLod %v4int %im %i1\n",
+ R"(Variable{
+ Decorations{
+ GroupDecoration{2}
+ BindingDecoration{1}
+ }
+ x_20
+ uniform_constant
+ __depth_texture_cube_array
+ })",
+ R"(VariableDeclStatement{
+ VariableConst{
+ x_99
+ none
+ __vec_4__i32
+ {
+ TypeConstructor[not set]{
+ __vec_4__i32
+ Call[not set]{
+ Identifier[not set]{textureDimensions}
+ (
+ Identifier[not set]{x_20}
+ Identifier[not set]{i1}
+ )
+ }
+ Call[not set]{
+ Identifier[not set]{textureNumLayers}
+ (
+ Identifier[not set]{x_20}
+ )
+ }
+ }
+ }
+ }
+ })"}}));
+
+INSTANTIATE_TEST_SUITE_P(
+ // When the level-of-detail value is given as an unsigned
+ // integer, we must convert it before using it as an argument
+ // to textureDimensions.
+ ImageQuerySizeLod_NonArrayed_SignedResult_UnsignedLevel,
+ SpvParserTest_SampledImageAccessTest,
+ ::testing::ValuesIn(std::vector<ImageAccessCase>{
+
+ {"%float 1D 0 0 0 1 Unknown",
+ "%99 = OpImageQuerySizeLod %int %im %u1\n",
+ R"(Variable{
+ Decorations{
+ GroupDecoration{2}
+ BindingDecoration{1}
+ }
+ x_20
+ uniform_constant
+ __sampled_texture_1d__f32
+ })",
+ R"(VariableDeclStatement{
+ VariableConst{
+ x_99
+ none
+ __i32
+ {
+ TypeConstructor[not set]{
+ __i32
+ Call[not set]{
+ Identifier[not set]{textureDimensions}
+ (
+ Identifier[not set]{x_20}
+ TypeConstructor[not set]{
+ __i32
+ Identifier[not set]{u1}
+ }
+ )
+ }
+ }
+ }
+ }
+ })"}}));
+
+INSTANTIATE_TEST_SUITE_P(
+ // When SPIR-V wants the result type to be unsigned, we have to
+ // insert a type constructor or bitcast for WGSL to do the type
+ // coercion. But the algorithm already does that as a matter
+ // of course.
+ ImageQuerySizeLod_NonArrayed_UnsignedResult_SignedLevel,
+ SpvParserTest_SampledImageAccessTest,
+ ::testing::ValuesIn(std::vector<ImageAccessCase>{
+
+ {"%float 1D 0 0 0 1 Unknown",
+ "%99 = OpImageQuerySizeLod %uint %im %i1\n",
+ R"(Variable{
+ Decorations{
+ GroupDecoration{2}
+ BindingDecoration{1}
+ }
+ x_20
+ uniform_constant
+ __sampled_texture_1d__f32
+ })",
+ R"(VariableDeclStatement{
+ VariableConst{
+ x_99
+ none
+ __u32
+ {
+ TypeConstructor[not set]{
+ __u32
+ Call[not set]{
+ Identifier[not set]{textureDimensions}
+ (
+ Identifier[not set]{x_20}
+ Identifier[not set]{i1}
+ )
+ }
+ }
+ }
+ }
+ })"}}));
+
struct ImageCoordsCase {
// SPIR-V image type, excluding result ID and opcode
std::string spirv_image_type_details;