spirv-reader: support OpImageQueryLevels
Bug: tint:109
Change-Id: I1bb7bbdca2322df28e7b22225e4b1bfdb74dbf73
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/39720
Commit-Queue: David Neto <dneto@google.com>
Auto-Submit: David Neto <dneto@google.com>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
diff --git a/src/reader/spirv/function.cc b/src/reader/spirv/function.cc
index 2a0a872..ddc2c14 100644
--- a/src/reader/spirv/function.cc
+++ b/src/reader/spirv/function.cc
@@ -4365,6 +4365,7 @@
}
bool FunctionEmitter::EmitImageQuery(const spvtools::opt::Instruction& inst) {
+ // TODO(dneto): Reject cases that are valid in Vulkan but invalid in WGSL.
const spvtools::opt::Instruction* image = GetImage(inst);
if (!image) {
return false;
@@ -4406,7 +4407,22 @@
return Fail() << "WGSL does not support querying the level of detail of "
"an image: "
<< inst.PrettyPrint();
- case SpvOpImageQueryLevels: // TODO(dneto)
+ case SpvOpImageQueryLevels: {
+ auto* levels_ident = create<ast::IdentifierExpression>(
+ Source{}, builder_.Symbols().Register("textureNumLevels"));
+ ast::Expression* ast_expr = create<ast::CallExpression>(
+ Source{}, levels_ident,
+ ast::ExpressionList{GetImageExpression(inst)});
+ auto* result_type = parser_impl_.ConvertType(inst.type_id());
+ // The SPIR-V result type must be integer scalar. The WGSL bulitin
+ // returns i32. If they aren't the same then convert the result.
+ if (result_type != i32_) {
+ ast_expr = create<ast::TypeConstructorExpression>(
+ Source{}, result_type, ast::ExpressionList{ast_expr});
+ }
+ TypedExpression expr{result_type, ast_expr};
+ return EmitConstDefOrWriteToHoistedVar(inst, expr);
+ }
case SpvOpImageQuerySamples: // TODO(dneto)
default:
break;
diff --git a/src/reader/spirv/parser_impl_handle_test.cc b/src/reader/spirv/parser_impl_handle_test.cc
index e8206d5..6c5a7ec 100644
--- a/src/reader/spirv/parser_impl_handle_test.cc
+++ b/src/reader/spirv/parser_impl_handle_test.cc
@@ -4406,6 +4406,293 @@
}
})"}}));
+INSTANTIATE_TEST_SUITE_P(
+ ImageQueryLevels_SignedResult,
+ SpvParserTest_SampledImageAccessTest,
+ ::testing::ValuesIn(std::vector<ImageAccessCase>{
+ // In Vulkan:
+ // Dim must be 1D, 2D, 3D, Cube
+ // WGSL allows 2d, 2d_array, 3d, cube, cube_array
+ // depth_2d, depth_2d_array, depth_cube, depth_cube_array
+
+ // 2D
+ {"%float 2D 0 0 0 1 Unknown", "%99 = OpImageQueryLevels %int %im\n",
+ R"(Variable{
+ Decorations{
+ GroupDecoration{2}
+ BindingDecoration{1}
+ }
+ x_20
+ uniform_constant
+ __sampled_texture_2d__f32
+ })",
+ R"(VariableDeclStatement{
+ VariableConst{
+ x_99
+ none
+ __i32
+ {
+ Call[not set]{
+ Identifier[not set]{textureNumLevels}
+ (
+ Identifier[not set]{x_20}
+ )
+ }
+ }
+ }
+ })"},
+
+ // 2D array
+ {"%float 2D 0 1 0 1 Unknown", "%99 = OpImageQueryLevels %int %im\n",
+ R"(Variable{
+ Decorations{
+ GroupDecoration{2}
+ BindingDecoration{1}
+ }
+ x_20
+ uniform_constant
+ __sampled_texture_2d_array__f32
+ })",
+ R"(VariableDeclStatement{
+ VariableConst{
+ x_99
+ none
+ __i32
+ {
+ Call[not set]{
+ Identifier[not set]{textureNumLevels}
+ (
+ Identifier[not set]{x_20}
+ )
+ }
+ }
+ }
+ })"},
+
+ // 3D
+ {"%float 3D 0 0 0 1 Unknown", "%99 = OpImageQueryLevels %int %im\n",
+ R"(Variable{
+ Decorations{
+ GroupDecoration{2}
+ BindingDecoration{1}
+ }
+ x_20
+ uniform_constant
+ __sampled_texture_3d__f32
+ })",
+ R"(VariableDeclStatement{
+ VariableConst{
+ x_99
+ none
+ __i32
+ {
+ Call[not set]{
+ Identifier[not set]{textureNumLevels}
+ (
+ Identifier[not set]{x_20}
+ )
+ }
+ }
+ }
+ })"},
+
+ // Cube
+ {"%float Cube 0 0 0 1 Unknown", "%99 = OpImageQueryLevels %int %im\n",
+ R"(Variable{
+ Decorations{
+ GroupDecoration{2}
+ BindingDecoration{1}
+ }
+ x_20
+ uniform_constant
+ __sampled_texture_cube__f32
+ })",
+ R"(VariableDeclStatement{
+ VariableConst{
+ x_99
+ none
+ __i32
+ {
+ Call[not set]{
+ Identifier[not set]{textureNumLevels}
+ (
+ Identifier[not set]{x_20}
+ )
+ }
+ }
+ }
+ })"},
+
+ // Cube array
+ {"%float Cube 0 1 0 1 Unknown", "%99 = OpImageQueryLevels %int %im\n",
+ R"(Variable{
+ Decorations{
+ GroupDecoration{2}
+ BindingDecoration{1}
+ }
+ x_20
+ uniform_constant
+ __sampled_texture_cube_array__f32
+ })",
+ R"(VariableDeclStatement{
+ VariableConst{
+ x_99
+ none
+ __i32
+ {
+ Call[not set]{
+ Identifier[not set]{textureNumLevels}
+ (
+ Identifier[not set]{x_20}
+ )
+ }
+ }
+ }
+ })"},
+
+ // depth 2d
+ {"%float 2D 1 0 0 1 Unknown", "%99 = OpImageQueryLevels %int %im\n",
+ R"(Variable{
+ Decorations{
+ GroupDecoration{2}
+ BindingDecoration{1}
+ }
+ x_20
+ uniform_constant
+ __depth_texture_2d
+ })",
+ R"(VariableDeclStatement{
+ VariableConst{
+ x_99
+ none
+ __i32
+ {
+ Call[not set]{
+ Identifier[not set]{textureNumLevels}
+ (
+ Identifier[not set]{x_20}
+ )
+ }
+ }
+ }
+ })"},
+
+ // depth 2d array
+ {"%float 2D 1 1 0 1 Unknown", "%99 = OpImageQueryLevels %int %im\n",
+ R"(Variable{
+ Decorations{
+ GroupDecoration{2}
+ BindingDecoration{1}
+ }
+ x_20
+ uniform_constant
+ __depth_texture_2d_array
+ })",
+ R"(VariableDeclStatement{
+ VariableConst{
+ x_99
+ none
+ __i32
+ {
+ Call[not set]{
+ Identifier[not set]{textureNumLevels}
+ (
+ Identifier[not set]{x_20}
+ )
+ }
+ }
+ }
+ })"},
+
+ // depth cube
+ {"%float Cube 1 0 0 1 Unknown", "%99 = OpImageQueryLevels %int %im\n",
+ R"(Variable{
+ Decorations{
+ GroupDecoration{2}
+ BindingDecoration{1}
+ }
+ x_20
+ uniform_constant
+ __depth_texture_cube
+ })",
+ R"(VariableDeclStatement{
+ VariableConst{
+ x_99
+ none
+ __i32
+ {
+ Call[not set]{
+ Identifier[not set]{textureNumLevels}
+ (
+ Identifier[not set]{x_20}
+ )
+ }
+ }
+ }
+ })"},
+
+ // depth cube array
+ {"%float Cube 1 1 0 1 Unknown", "%99 = OpImageQueryLevels %int %im\n",
+ R"(Variable{
+ Decorations{
+ GroupDecoration{2}
+ BindingDecoration{1}
+ }
+ x_20
+ uniform_constant
+ __depth_texture_cube_array
+ })",
+ R"(VariableDeclStatement{
+ VariableConst{
+ x_99
+ none
+ __i32
+ {
+ Call[not set]{
+ Identifier[not set]{textureNumLevels}
+ (
+ Identifier[not set]{x_20}
+ )
+ }
+ }
+ }
+ })"}}));
+
+INSTANTIATE_TEST_SUITE_P(
+ // Spot check that a type conversion is inserted when SPIR-V asks for
+ // an unsigned int result.
+ ImageQueryLevels_UnsignedResult,
+ SpvParserTest_SampledImageAccessTest,
+ ::testing::ValuesIn(std::vector<ImageAccessCase>{
+ {"%float 2D 0 0 0 1 Unknown", "%99 = OpImageQueryLevels %uint %im\n",
+ R"(Variable{
+ Decorations{
+ GroupDecoration{2}
+ BindingDecoration{1}
+ }
+ x_20
+ uniform_constant
+ __sampled_texture_2d__f32
+ })",
+ R"(VariableDeclStatement{
+ VariableConst{
+ x_99
+ none
+ __u32
+ {
+ TypeConstructor[not set]{
+ __u32
+ Call[not set]{
+ Identifier[not set]{textureNumLevels}
+ (
+ Identifier[not set]{x_20}
+ )
+ }
+ }
+ }
+ }
+ })"}}));
+
struct ImageCoordsCase {
// SPIR-V image type, excluding result ID and opcode
std::string spirv_image_type_details;