From 0a68b365ebff6144228140eb00dd367f62e964ed Mon Sep 17 00:00:00 2001 From: Ben Clayton Date: Thu, 14 Jan 2021 18:11:17 +0000 Subject: [PATCH] Implement textureNumSamples() SPIR-V reader TODO Bug: tint:140 Bug: tint:437 Change-Id: Id95855660680b12e3ff49b6340ef966dfa49f8e4 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/37848 Commit-Queue: Ben Clayton Reviewed-by: David Neto Reviewed-by: dan sinclair --- src/ast/intrinsic.cc | 7 +++- src/ast/intrinsic.h | 1 + src/ast/intrinsic_texture_helper_test.cc | 20 +++++++++++ src/ast/intrinsic_texture_helper_test.h | 2 ++ src/type_determiner.cc | 4 +++ src/type_determiner_test.cc | 6 ++++ src/writer/hlsl/generator_impl.cc | 35 ++++++++++++------ .../generator_impl_intrinsic_texture_test.cc | 14 ++++++++ src/writer/msl/generator_impl.cc | 8 +++++ .../generator_impl_intrinsic_texture_test.cc | 3 ++ src/writer/spirv/builder.cc | 6 ++++ .../spirv/builder_intrinsic_texture_test.cc | 36 +++++++++++++++++++ 12 files changed, 131 insertions(+), 11 deletions(-) diff --git a/src/ast/intrinsic.cc b/src/ast/intrinsic.cc index 2282650927..6a16abbb9e 100644 --- a/src/ast/intrinsic.cc +++ b/src/ast/intrinsic.cc @@ -215,6 +215,9 @@ std::ostream& operator<<(std::ostream& out, Intrinsic i) { case Intrinsic::kTextureNumLevels: out << "textureNumLevels"; return out; + case Intrinsic::kTextureNumSamples: + out << "textureNumSamples"; + return out; case Intrinsic::kTextureSample: out << "textureSample"; return out; @@ -281,7 +284,9 @@ bool IsTextureIntrinsic(Intrinsic i) { bool IsImageQueryIntrinsic(Intrinsic i) { return i == ast::Intrinsic::kTextureDimensions || - i == Intrinsic::kTextureNumLayers || i == Intrinsic::kTextureNumLevels; + i == Intrinsic::kTextureNumLayers || + i == Intrinsic::kTextureNumLevels || + i == Intrinsic::kTextureNumSamples; } } // namespace intrinsic diff --git a/src/ast/intrinsic.h b/src/ast/intrinsic.h index bdf310e6dd..90477bc583 100644 --- a/src/ast/intrinsic.h +++ b/src/ast/intrinsic.h @@ -87,6 +87,7 @@ enum class Intrinsic { kTextureLoad, kTextureNumLayers, kTextureNumLevels, + kTextureNumSamples, kTextureSample, kTextureSampleBias, kTextureSampleCompare, diff --git a/src/ast/intrinsic_texture_helper_test.cc b/src/ast/intrinsic_texture_helper_test.cc index fbeae35a38..00a2d05c13 100644 --- a/src/ast/intrinsic_texture_helper_test.cc +++ b/src/ast/intrinsic_texture_helper_test.cc @@ -711,6 +711,26 @@ std::vector TextureOverloadCase::ValidCases() { "textureNumLevels", [](Builder* b) { return b->ExprList("texture"); }, }, + { + ValidTextureOverload::kNumSamplesMultisampled2d, + "textureNumSamples(t : texture_multisampled_2d) -> i32", + TextureKind::kMultisampled, + type::SamplerKind::kSampler, + type::TextureDimension::k2d, + TextureDataType::kF32, + "textureNumSamples", + [](Builder* b) { return b->ExprList("texture"); }, + }, + { + ValidTextureOverload::kNumSamplesMultisampled2dArray, + "textureNumSamples(t : texture_multisampled_2d_array) -> i32", + TextureKind::kMultisampled, + type::SamplerKind::kSampler, + type::TextureDimension::k2dArray, + TextureDataType::kF32, + "textureNumSamples", + [](Builder* b) { return b->ExprList("texture"); }, + }, { ValidTextureOverload::kSample1dF32, "textureSample(t : texture_1d,\n" diff --git a/src/ast/intrinsic_texture_helper_test.h b/src/ast/intrinsic_texture_helper_test.h index e78f9e0ff1..bd67b9fab4 100644 --- a/src/ast/intrinsic_texture_helper_test.h +++ b/src/ast/intrinsic_texture_helper_test.h @@ -86,6 +86,8 @@ enum class ValidTextureOverload { kNumLevelsDepth2dArray, kNumLevelsDepthCube, kNumLevelsDepthCubeArray, + kNumSamplesMultisampled2d, + kNumSamplesMultisampled2dArray, kSample1dF32, kSample1dArrayF32, kSample2dF32, diff --git a/src/type_determiner.cc b/src/type_determiner.cc index 84f9b6f501..70192025a9 100644 --- a/src/type_determiner.cc +++ b/src/type_determiner.cc @@ -568,6 +568,7 @@ bool TypeDeterminer::DetermineIntrinsic(ast::IdentifierExpression* ident, break; case ast::Intrinsic::kTextureNumLayers: case ast::Intrinsic::kTextureNumLevels: + case ast::Intrinsic::kTextureNumSamples: param.idx.texture = param.count++; break; case ast::Intrinsic::kTextureLoad: @@ -698,6 +699,7 @@ bool TypeDeterminer::DetermineIntrinsic(ast::IdentifierExpression* ident, } case ast::Intrinsic::kTextureNumLayers: case ast::Intrinsic::kTextureNumLevels: + case ast::Intrinsic::kTextureNumSamples: return_type = mod_->create(); break; case ast::Intrinsic::kTextureStore: @@ -1038,6 +1040,8 @@ bool TypeDeterminer::SetIntrinsicIfNeeded(ast::IdentifierExpression* ident) { ident->set_intrinsic(ast::Intrinsic::kTextureNumLayers); } else if (name == "textureNumLevels") { ident->set_intrinsic(ast::Intrinsic::kTextureNumLevels); + } else if (name == "textureNumSamples") { + ident->set_intrinsic(ast::Intrinsic::kTextureNumSamples); } else if (name == "textureLoad") { ident->set_intrinsic(ast::Intrinsic::kTextureLoad); } else if (name == "textureStore") { diff --git a/src/type_determiner_test.cc b/src/type_determiner_test.cc index 1a76ae4792..b05d2ee27f 100644 --- a/src/type_determiner_test.cc +++ b/src/type_determiner_test.cc @@ -1766,6 +1766,7 @@ INSTANTIATE_TEST_SUITE_P( IntrinsicData{"textureLoad", ast::Intrinsic::kTextureLoad}, IntrinsicData{"textureNumLayers", ast::Intrinsic::kTextureNumLayers}, IntrinsicData{"textureNumLevels", ast::Intrinsic::kTextureNumLevels}, + IntrinsicData{"textureNumSamples", ast::Intrinsic::kTextureNumSamples}, IntrinsicData{"textureSample", ast::Intrinsic::kTextureSample}, IntrinsicData{"textureSampleBias", ast::Intrinsic::kTextureSampleBias}, IntrinsicData{"textureSampleCompare", @@ -2949,6 +2950,9 @@ const char* expected_texture_overload( case ValidTextureOverload::kNumLevelsDepthCube: case ValidTextureOverload::kNumLevelsDepthCubeArray: return R"(textureNumLevels(texture))"; + case ValidTextureOverload::kNumSamplesMultisampled2d: + case ValidTextureOverload::kNumSamplesMultisampled2dArray: + return R"(textureNumSamples(texture))"; case ValidTextureOverload::kDimensions2dLevel: case ValidTextureOverload::kDimensions2dArrayLevel: case ValidTextureOverload::kDimensions3dLevel: @@ -3206,6 +3210,8 @@ TEST_P(TypeDeterminerTextureIntrinsicTest, Call) { 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) == "textureNumSamples") { + EXPECT_EQ(call->result_type(), ty.i32); } else if (std::string(param.function) == "textureStore") { EXPECT_EQ(call->result_type(), ty.void_); } else { diff --git a/src/writer/hlsl/generator_impl.cc b/src/writer/hlsl/generator_impl.cc index 187020d065..06791db227 100644 --- a/src/writer/hlsl/generator_impl.cc +++ b/src/writer/hlsl/generator_impl.cc @@ -698,15 +698,9 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& pre, switch (ident->intrinsic()) { case ast::Intrinsic::kTextureDimensions: case ast::Intrinsic::kTextureNumLayers: - case ast::Intrinsic::kTextureNumLevels: { - // Declare a variable to hold the queried texture info - auto dims = generate_name(kTempNamePrefix); - - std::stringstream texture_name; - if (!EmitExpression(pre, texture_name, texture)) { - return false; - } - + case ast::Intrinsic::kTextureNumLevels: + case ast::Intrinsic::kTextureNumSamples: { + // All of these intrinsics use the GetDimensions() method on the texture int num_dimensions = 0; const char* swizzle = ""; bool add_mip_level_in = false; @@ -783,18 +777,39 @@ bool GeneratorImpl::EmitTextureCall(std::ostream& pre, break; } break; + case ast::Intrinsic::kTextureNumSamples: + switch (texture_type->dim()) { + default: + error_ = "texture dimension does not support multisampling"; + return false; + case ast::type::TextureDimension::k2d: + num_dimensions = 3; + swizzle = ".z"; + break; + case ast::type::TextureDimension::k2dArray: + num_dimensions = 4; + swizzle = ".w"; + break; + } + break; default: error_ = "unexpected intrinsic"; return false; } + // Declare a variable to hold the queried texture info + auto dims = generate_name(kTempNamePrefix); + if (num_dimensions == 1) { pre << "int " << dims << ";\n"; } else { pre << "int" << num_dimensions << " " << dims << ";\n"; } - pre << texture_name.str() << ".GetDimensions("; + if (!EmitExpression(pre, pre, texture)) { + return false; + } + pre << ".GetDimensions("; if (pidx.level != kNotUsed) { pre << pidx.level << ", "; } else if (add_mip_level_in) { diff --git a/src/writer/hlsl/generator_impl_intrinsic_texture_test.cc b/src/writer/hlsl/generator_impl_intrinsic_texture_test.cc index bbc5401bf0..e0ec794721 100644 --- a/src/writer/hlsl/generator_impl_intrinsic_texture_test.cc +++ b/src/writer/hlsl/generator_impl_intrinsic_texture_test.cc @@ -178,6 +178,20 @@ ExpectedResult expected_texture_overload( "_tint_tmp.x, _tint_tmp.y, _tint_tmp.z, _tint_tmp.w);", "_tint_tmp.w", }; + case ValidTextureOverload::kNumSamplesMultisampled2d: + return { + "int3 _tint_tmp;\n" + "texture_tint_0." + "GetDimensions(_tint_tmp.x, _tint_tmp.y, _tint_tmp.z);", + "_tint_tmp.z", + }; + case ValidTextureOverload::kNumSamplesMultisampled2dArray: + return { + "int4 _tint_tmp;\n" + "texture_tint_0." + "GetDimensions(_tint_tmp.x, _tint_tmp.y, _tint_tmp.z, _tint_tmp.w);", + "_tint_tmp.w", + }; case ValidTextureOverload::kSample1dF32: return R"(texture_tint_0.Sample(sampler_tint_0, 1.0f))"; case ValidTextureOverload::kSample1dArrayF32: diff --git a/src/writer/msl/generator_impl.cc b/src/writer/msl/generator_impl.cc index f3a55e4f5f..aa91eefb57 100644 --- a/src/writer/msl/generator_impl.cc +++ b/src/writer/msl/generator_impl.cc @@ -687,6 +687,14 @@ bool GeneratorImpl::EmitTextureCall(ast::CallExpression* expr) { out_ << ".get_num_mip_levels())"; return true; } + case ast::Intrinsic::kTextureNumSamples: { + out_ << "int("; + if (!EmitExpression(params[pidx.texture])) { + return false; + } + out_ << ".get_num_samples())"; + return true; + } default: break; } diff --git a/src/writer/msl/generator_impl_intrinsic_texture_test.cc b/src/writer/msl/generator_impl_intrinsic_texture_test.cc index ded1bfb098..54c2a9ef46 100644 --- a/src/writer/msl/generator_impl_intrinsic_texture_test.cc +++ b/src/writer/msl/generator_impl_intrinsic_texture_test.cc @@ -90,6 +90,9 @@ std::string expected_texture_overload( case ValidTextureOverload::kNumLevelsDepthCube: case ValidTextureOverload::kNumLevelsDepthCubeArray: return R"(int(texture_tint_0.get_num_mip_levels()))"; + case ValidTextureOverload::kNumSamplesMultisampled2d: + case ValidTextureOverload::kNumSamplesMultisampled2dArray: + return R"(int(texture_tint_0.get_num_samples()))"; case ValidTextureOverload::kSample1dF32: return R"(texture_tint_0.sample(sampler_tint_0, 1.0f))"; case ValidTextureOverload::kSample1dArrayF32: diff --git a/src/writer/spirv/builder.cc b/src/writer/spirv/builder.cc index 7f913a5bbb..e6d11fd430 100644 --- a/src/writer/spirv/builder.cc +++ b/src/writer/spirv/builder.cc @@ -2251,6 +2251,12 @@ bool Builder::GenerateTextureIntrinsic(ast::IdentifierExpression* ident, spirv_params.emplace_back(gen_param(pidx.texture)); break; } + case ast::Intrinsic::kTextureNumSamples: { + op = spv::Op::OpImageQuerySamples; + append_result_type_and_id_to_spirv_params(); + spirv_params.emplace_back(gen_param(pidx.texture)); + break; + } case ast::Intrinsic::kTextureLoad: { op = texture_type->Is() ? spv::Op::OpImageRead diff --git a/src/writer/spirv/builder_intrinsic_texture_test.cc b/src/writer/spirv/builder_intrinsic_texture_test.cc index bf4c87f414..9c1e2513a1 100644 --- a/src/writer/spirv/builder_intrinsic_texture_test.cc +++ b/src/writer/spirv/builder_intrinsic_texture_test.cc @@ -1073,6 +1073,42 @@ OpCapability ImageQuery R"( OpCapability SampledCubeArray OpCapability ImageQuery +)"}; + case ValidTextureOverload::kNumSamplesMultisampled2d: + return {R"( +%4 = OpTypeFloat 32 +%3 = OpTypeImage %4 2D 0 0 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 +)", + R"( +%10 = OpLoad %3 %1 +%8 = OpImageQuerySamples %9 %10 +)", + R"( +OpCapability ImageQuery +)"}; + case ValidTextureOverload::kNumSamplesMultisampled2dArray: + 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 +)", + R"( +%10 = OpLoad %3 %1 +%8 = OpImageQuerySamples %9 %10 +)", + R"( +OpCapability ImageQuery )"}; case ValidTextureOverload::kSample1dF32: return {