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>
This commit is contained in:
David Neto 2021-02-01 22:47:54 +00:00 committed by Commit Bot service account
parent 4d098a7b75
commit 1d2bcb99d6
2 changed files with 490 additions and 4 deletions

View File

@ -4376,15 +4376,20 @@ bool FunctionEmitter::EmitImageQuery(const spvtools::opt::Instruction& inst) {
const auto opcode = inst.opcode(); const auto opcode = inst.opcode();
switch (opcode) { switch (opcode) {
case SpvOpImageQuerySize: { case SpvOpImageQuerySize:
case SpvOpImageQuerySizeLod: {
ast::ExpressionList exprs; ast::ExpressionList exprs;
// Invoke textureDimensions. // Invoke textureDimensions.
// If the texture is arrayed, combine with the result from // If the texture is arrayed, combine with the result from
// textureNumLayers. // textureNumLayers.
auto* dims_ident = create<ast::IdentifierExpression>( auto* dims_ident = create<ast::IdentifierExpression>(
Source{}, builder_.Symbols().Register("textureDimensions")); Source{}, builder_.Symbols().Register("textureDimensions"));
exprs.push_back(create<ast::CallExpression>( ast::ExpressionList dims_args{GetImageExpression(inst)};
Source{}, dims_ident, ast::ExpressionList{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())) { if (type::IsTextureArray(texture_type->dim())) {
auto* layers_ident = create<ast::IdentifierExpression>( auto* layers_ident = create<ast::IdentifierExpression>(
Source{}, builder_.Symbols().Register("textureNumLayers")); Source{}, builder_.Symbols().Register("textureNumLayers"));
@ -4401,7 +4406,6 @@ bool FunctionEmitter::EmitImageQuery(const spvtools::opt::Instruction& inst) {
return Fail() << "WGSL does not support querying the level of detail of " return Fail() << "WGSL does not support querying the level of detail of "
"an image: " "an image: "
<< inst.PrettyPrint(); << inst.PrettyPrint();
case SpvOpImageQuerySizeLod: // TODO(dneto)
case SpvOpImageQueryLevels: // TODO(dneto) case SpvOpImageQueryLevels: // TODO(dneto)
case SpvOpImageQuerySamples: // TODO(dneto) case SpvOpImageQuerySamples: // TODO(dneto)
default: default:

View File

@ -3924,6 +3924,488 @@ INSTANTIATE_TEST_SUITE_P(
} }
})"}})); })"}}));
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 { struct ImageCoordsCase {
// SPIR-V image type, excluding result ID and opcode // SPIR-V image type, excluding result ID and opcode
std::string spirv_image_type_details; std::string spirv_image_type_details;