From dbcc1e0e804ed19596f43d2c2663a5b11b9977de Mon Sep 17 00:00:00 2001 From: Ryan Harrison Date: Tue, 10 Nov 2020 22:30:56 +0000 Subject: [PATCH] [inspector] Extract Sampled Texture data BUG=tint:257 Change-Id: I146591d052edfc959df33ccf235ea466cb59e59d Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/32260 Reviewed-by: dan sinclair Commit-Queue: Ryan Harrison --- src/ast/function.cc | 31 +++++++++ src/ast/function.h | 13 ++-- src/inspector/inspector.cc | 51 ++++++++++++++ src/inspector/inspector.h | 29 +++++++- src/inspector/inspector_test.cc | 115 +++++++++++++++++++++++++++++--- 5 files changed, 224 insertions(+), 15 deletions(-) diff --git a/src/ast/function.cc b/src/ast/function.cc index a90b0858bc..1c4d948d50 100644 --- a/src/ast/function.cc +++ b/src/ast/function.cc @@ -18,6 +18,7 @@ #include "src/ast/decorated_variable.h" #include "src/ast/stage_decoration.h" +#include "src/ast/type/texture_type.h" #include "src/ast/workgroup_decoration.h" namespace tint { @@ -177,6 +178,36 @@ Function::referenced_comparison_sampler_variables() const { return ReferencedSamplerVariablesImpl(type::SamplerKind::kComparisonSampler); } +const std::vector> +Function::referenced_sampled_texture_variables() const { + std::vector> ret; + + for (auto* var : referenced_module_variables()) { + auto* unwrapped_type = var->type()->UnwrapIfNeeded(); + if (!var->IsDecorated() || !unwrapped_type->IsTexture() || + !unwrapped_type->AsTexture()->IsSampled()) { + continue; + } + + BindingDecoration* binding = nullptr; + SetDecoration* set = nullptr; + for (const auto& deco : var->AsDecorated()->decorations()) { + if (deco->IsBinding()) { + binding = deco->AsBinding(); + } else if (deco->IsSet()) { + set = deco->AsSet(); + } + } + if (binding == nullptr || set == nullptr) { + continue; + } + + ret.push_back({var, BindingInfo{binding, set}}); + } + + return ret; +} + void Function::add_ancestor_entry_point(const std::string& ep) { for (const auto& point : ancestor_entry_points_) { if (point == ep) { diff --git a/src/ast/function.h b/src/ast/function.h index e07658f42b..8ed17c7177 100644 --- a/src/ast/function.h +++ b/src/ast/function.h @@ -129,26 +129,31 @@ class Function : public Node { /// @returns the pair. const std::vector> referenced_builtin_variables() const; - /// Retrieves any referenced uniform variables. Note, the uniform must be + /// Retrieves any referenced uniform variables. Note, the variables must be /// decorated with both binding and set decorations. /// @returns the referenced uniforms const std::vector> referenced_uniform_variables() const; - /// Retrieves any referenced storagebuffer variables. Note, the storagebuffer + /// Retrieves any referenced storagebuffer variables. Note, the variables /// must be decorated with both binding and set decorations. /// @returns the referenced storagebuffers const std::vector> referenced_storagebuffer_variables() const; /// Retrieves any referenced regular Sampler variables. Note, the - /// storagebuffer must be decorated with both binding and set decorations. + /// variables must be decorated with both binding and set decorations. /// @returns the referenced storagebuffers const std::vector> referenced_sampler_variables() const; /// Retrieves any referenced comparison Sampler variables. Note, the - /// storagebuffer must be decorated with both binding and set decorations. + /// variables must be decorated with both binding and set decorations. /// @returns the referenced storagebuffers const std::vector> referenced_comparison_sampler_variables() const; + /// Retrieves any referenced sampled textures variables. Note, the + /// variables must be decorated with both binding and set decorations. + /// @returns the referenced sampled textures + const std::vector> + referenced_sampled_texture_variables() const; /// Adds an ancestor entry point /// @param ep the entry point ancestor diff --git a/src/inspector/inspector.cc b/src/inspector/inspector.cc index ed278af23c..b170d87165 100644 --- a/src/inspector/inspector.cc +++ b/src/inspector/inspector.cc @@ -28,6 +28,7 @@ #include "src/ast/sint_literal.h" #include "src/ast/type/access_control_type.h" #include "src/ast/type/struct_type.h" +#include "src/ast/type/texture_type.h" #include "src/ast/type/type.h" #include "src/ast/uint_literal.h" #include "src/namer.h" @@ -237,6 +238,56 @@ std::vector Inspector::GetComparisonSamplerResourceBindings( return result; } +std::vector Inspector::GetSampledTextureResourceBindings( + const std::string& entry_point) { + auto* func = FindEntryPointByName(entry_point); + if (!func) { + return {}; + } + + std::vector result; + + for (auto& rcs : func->referenced_sampled_texture_variables()) { + ResourceBinding entry; + ast::Variable* var = nullptr; + ast::Function::BindingInfo binding_info; + std::tie(var, binding_info) = rcs; + + entry.bind_group = binding_info.set->value(); + entry.binding = binding_info.binding->value(); + + switch (var->type()->UnwrapIfNeeded()->AsTexture()->dim()) { + case ast::type::TextureDimension::k1d: + entry.dim = ResourceBinding::TextureDimension::k1d; + break; + case ast::type::TextureDimension::k1dArray: + entry.dim = ResourceBinding::TextureDimension::k1dArray; + break; + case ast::type::TextureDimension::k2d: + entry.dim = ResourceBinding::TextureDimension::k2d; + break; + case ast::type::TextureDimension::k2dArray: + entry.dim = ResourceBinding::TextureDimension::k2dArray; + break; + case ast::type::TextureDimension::k3d: + entry.dim = ResourceBinding::TextureDimension::k3d; + break; + case ast::type::TextureDimension::kCube: + entry.dim = ResourceBinding::TextureDimension::kCube; + break; + case ast::type::TextureDimension::kCubeArray: + entry.dim = ResourceBinding::TextureDimension::kCubeArray; + break; + default: + entry.dim = ResourceBinding::TextureDimension::kNone; + break; + } + result.push_back(std::move(entry)); + } + + return result; +} + ast::Function* Inspector::FindEntryPointByName(const std::string& name) { auto* func = module_.FindFunctionByName(name); if (!func) { diff --git a/src/inspector/inspector.h b/src/inspector/inspector.h index 7034a8a956..da49ff1382 100644 --- a/src/inspector/inspector.h +++ b/src/inspector/inspector.h @@ -31,12 +31,34 @@ namespace inspector { /// Container for information about how a resource is bound struct ResourceBinding { + /// The dimensionality of a texture + enum class TextureDimension { + /// Invalid texture + kNone = -1, + /// 1 dimensional texture + k1d, + /// 1 dimenstional array texture + k1dArray, + /// 2 dimensional texture + k2d, + /// 2 dimensional array texture + k2dArray, + /// 3 dimensional texture + k3d, + /// cube texture + kCube, + /// cube array texture + kCubeArray, + }; + /// Bind group the binding belongs uint32_t bind_group; /// Identifier to identify this binding within the bind group uint32_t binding; - /// Minimum size required for this binding, in bytes. + /// Minimum size required for this binding, in bytes, if defined. uint64_t min_buffer_binding_size; + /// Dimensionality of this binding, if defined. + TextureDimension dim; }; /// Extracts information from a module @@ -83,6 +105,11 @@ class Inspector { std::vector GetComparisonSamplerResourceBindings( const std::string& entry_point); + /// @param entry_point name of the entry point to get information about. + /// @returns vector of all of the bindings for sampled textures. + std::vector GetSampledTextureResourceBindings( + const std::string& entry_point); + private: const ast::Module& module_; std::string error_; diff --git a/src/inspector/inspector_test.cc b/src/inspector/inspector_test.cc index d52001c8a7..822aeeef1a 100644 --- a/src/inspector/inspector_test.cc +++ b/src/inspector/inspector_test.cc @@ -480,6 +480,11 @@ class InspectorHelper { name, ast::StorageClass::kUniformConstant, f32_type())); } + void AddF32Vec(const std::string& name, uint32_t count) { + mod()->AddGlobalVariable(std::make_unique( + name, ast::StorageClass::kUniformConstant, f32_vec_type(count))); + } + /// Adds a depth texture variable to the module /// @param name the name of the variable /// @param type the type to use @@ -504,7 +509,7 @@ class InspectorHelper { auto body = std::make_unique(); auto call_result = std::make_unique( - "sampler_result", ast::StorageClass::kFunction, f32_type()); + "sampler_result", ast::StorageClass::kFunction, f32_vec_type(4)); body->append( std::make_unique(std::move(call_result))); @@ -577,6 +582,22 @@ class InspectorHelper { return func; } + /// Gets an appropriate type for the coords parameter depending the the + /// dimensionality of the texture being sampled. + /// @param dim dimensionality of the texture being sampled. + /// @returns a pointer to a type appropriate for the coord param + ast::type::Type* GetCoordsType(ast::type::TextureDimension dim) { + if (dim == ast::type::TextureDimension::k1d) { + f32_type(); + } else if (dim == ast::type::TextureDimension::k1dArray || + dim == ast::type::TextureDimension::k2d) { + return f32_vec_type(2); + } else if (dim == ast::type::TextureDimension::kCubeArray) { + return f32_vec_type(4); + } + return f32_vec_type(3); + } + ast::Module* mod() { return &mod_; } TypeDeterminer* td() { return td_.get(); } Inspector* inspector() { return inspector_.get(); } @@ -595,6 +616,13 @@ class InspectorHelper { } return array_type_memo_[count].get(); } + ast::type::VectorType* f32_vec_type(uint32_t count) { + if (vector_type_memo_.find(count) == vector_type_memo_.end()) { + vector_type_memo_[count] = + std::make_unique(u32_type(), count); + } + return vector_type_memo_[count].get(); + } ast::type::VoidType* void_type() { return &void_type_; } ast::type::SamplerType* sampler_type() { return &sampler_type_; } ast::type::SamplerType* comparison_sampler_type() { @@ -615,19 +643,35 @@ class InspectorHelper { ast::type::SamplerType sampler_type_; ast::type::SamplerType comparison_sampler_type_; std::map> array_type_memo_; + std::map> vector_type_memo_; }; -class InspectorTest : public InspectorHelper, public testing::Test {}; - -class InspectorGetEntryPointTest : public InspectorTest {}; -class InspectorGetConstantIDsTest : public InspectorTest {}; -class InspectorGetUniformBufferResourceBindingsTest : public InspectorTest {}; -class InspectorGetStorageBufferResourceBindingsTest : public InspectorTest {}; +class InspectorGetEntryPointTest : public InspectorHelper, + public testing::Test {}; +class InspectorGetConstantIDsTest : public InspectorHelper, + public testing::Test {}; +class InspectorGetUniformBufferResourceBindingsTest : public InspectorHelper, + public testing::Test {}; +class InspectorGetStorageBufferResourceBindingsTest : public InspectorHelper, + public testing::Test {}; class InspectorGetReadOnlyStorageBufferResourceBindingsTest - : public InspectorTest {}; -class InspectorGetSamplerResourceBindingsTest : public InspectorTest {}; -class InspectorGetComparisonSamplerResourceBindingsTest : public InspectorTest { + : public InspectorHelper, + public testing::Test {}; +class InspectorGetSamplerResourceBindingsTest : public InspectorHelper, + public testing::Test {}; +class InspectorGetComparisonSamplerResourceBindingsTest + : public InspectorHelper, + public testing::Test {}; + +class InspectorGetSampledTextureResourceBindingsTest : public InspectorHelper, + public testing::Test {}; +struct GetSampledTextureTestParams { + ast::type::TextureDimension type_dim; + inspector::ResourceBinding::TextureDimension inspector_dim; }; +class InspectorGetSampledTextureResourceBindingsTestWithParam + : public InspectorHelper, + public testing::TestWithParam {}; TEST_F(InspectorGetEntryPointTest, NoFunctions) { auto result = inspector()->GetEntryPoints(); @@ -1816,6 +1860,57 @@ TEST_F(InspectorGetComparisonSamplerResourceBindingsTest, SkipsSamplers) { ASSERT_EQ(0u, result.size()); } +TEST_P(InspectorGetSampledTextureResourceBindingsTestWithParam, Simple) { + auto* coord_type = GetCoordsType(GetParam().type_dim); + auto sampled_texture_type = + MakeSampledTextureType(GetParam().type_dim, coord_type); + AddSampledTexture("foo_texture", sampled_texture_type.get(), 0, 0); + AddSampler("foo_sampler", 0, 1); + AddF32("foo_coords"); + + auto func = MakeSamplerReferenceBodyFunction("ep", "foo_texture", + "foo_sampler", "foo_coords"); + func->add_decoration(std::make_unique( + ast::PipelineStage::kVertex, Source{})); + mod()->AddFunction(std::move(func)); + + ASSERT_TRUE(td()->Determine()) << td()->error(); + + auto result = inspector()->GetSampledTextureResourceBindings("ep"); + ASSERT_FALSE(inspector()->has_error()) << inspector()->error(); + + ASSERT_EQ(1u, result.size()); + EXPECT_EQ(0u, result[0].bind_group); + EXPECT_EQ(0u, result[0].binding); + EXPECT_EQ(GetParam().inspector_dim, result[0].dim); +} + +INSTANTIATE_TEST_SUITE_P( + InspectorGetSampledTextureResourceBindingsTest, + InspectorGetSampledTextureResourceBindingsTestWithParam, + testing::Values( + GetSampledTextureTestParams{ + ast::type::TextureDimension::k1d, + inspector::ResourceBinding::TextureDimension::k1d}, + GetSampledTextureTestParams{ + ast::type::TextureDimension::k1dArray, + inspector::ResourceBinding::TextureDimension::k1dArray}, + GetSampledTextureTestParams{ + ast::type::TextureDimension::k2d, + inspector::ResourceBinding::TextureDimension::k2d}, + GetSampledTextureTestParams{ + ast::type::TextureDimension::k2dArray, + inspector::ResourceBinding::TextureDimension::k2dArray}, + GetSampledTextureTestParams{ + ast::type::TextureDimension::k3d, + inspector::ResourceBinding::TextureDimension::k3d}, + GetSampledTextureTestParams{ + ast::type::TextureDimension::kCube, + inspector::ResourceBinding::TextureDimension::kCube}, + GetSampledTextureTestParams{ + ast::type::TextureDimension::kCubeArray, + inspector::ResourceBinding::TextureDimension::kCubeArray})); + } // namespace } // namespace inspector } // namespace tint