Add support fo extracting information about Storage Textures
BUG=tint:489
Change-Id: I28e4b0e568aea463971e9d2f5a04f04e942e2564
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/41600
Auto-Submit: Ryan Harrison <rharrison@chromium.org>
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Reviewed-by: Ben Clayton <bclayton@google.com>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
diff --git a/src/inspector/inspector.cc b/src/inspector/inspector.cc
index e41d2b3..95f8565 100644
--- a/src/inspector/inspector.cc
+++ b/src/inspector/inspector.cc
@@ -332,6 +332,18 @@
return GetSampledTextureResourceBindingsImpl(entry_point, true);
}
+std::vector<ResourceBinding>
+Inspector::GetReadOnlyStorageTextureResourceBindings(
+ const std::string& entry_point) {
+ return GetStorageTextureResourceBindingsImpl(entry_point, true);
+}
+
+std::vector<ResourceBinding>
+Inspector::GetWriteOnlyStorageTextureResourceBindings(
+ const std::string& entry_point) {
+ return GetStorageTextureResourceBindingsImpl(entry_point, false);
+}
+
ast::Function* Inspector::FindEntryPointByName(const std::string& name) {
auto* func = program_->AST().Functions().Find(program_->Symbols().Get(name));
if (!func) {
@@ -357,7 +369,7 @@
auto* func_sem = program_->Sem().Get(func);
std::vector<ResourceBinding> result;
- for (auto& rsv : func_sem->ReferencedStoragebufferVariables()) {
+ for (auto& rsv : func_sem->ReferencedStorageBufferVariables()) {
auto* var = rsv.first;
auto* decl = var->Declaration();
auto binding_info = rsv.second;
@@ -477,5 +489,42 @@
return result;
}
+std::vector<ResourceBinding> Inspector::GetStorageTextureResourceBindingsImpl(
+ const std::string& entry_point,
+ bool read_only) {
+ auto* func = FindEntryPointByName(entry_point);
+ if (!func) {
+ return {};
+ }
+
+ auto* func_sem = program_->Sem().Get(func);
+ std::vector<ResourceBinding> result;
+ for (auto& ref : func_sem->ReferencedStorageTextureVariables()) {
+ auto* var = ref.first;
+ auto* decl = var->Declaration();
+ auto binding_info = ref.second;
+
+ auto* ac_type = decl->type()->As<type::AccessControl>();
+ if (ac_type == nullptr) {
+ continue;
+ }
+
+ if (read_only != ac_type->IsReadOnly()) {
+ continue;
+ }
+
+ ResourceBinding entry;
+ entry.resource_type =
+ read_only ? ResourceBinding::ResourceType::kReadOnlyStorageTexture
+ : ResourceBinding::ResourceType::kWriteOnlyStorageTexture;
+ entry.bind_group = binding_info.group->value();
+ entry.binding = binding_info.binding->value();
+
+ result.push_back(entry);
+ }
+
+ return result;
+}
+
} // namespace inspector
} // namespace tint
diff --git a/src/inspector/inspector.h b/src/inspector/inspector.h
index 8e09e3f..38e59a1 100644
--- a/src/inspector/inspector.h
+++ b/src/inspector/inspector.h
@@ -63,7 +63,9 @@
kSampler,
kComparisonSampler,
kSampledTexture,
- kMulitsampledTexture
+ kMulitsampledTexture,
+ kReadOnlyStorageTexture,
+ kWriteOnlyStorageTexture,
};
/// Type of resource that is bound.
@@ -146,6 +148,16 @@
std::vector<ResourceBinding> GetMultisampledTextureResourceBindings(
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 read-only storage textures.
+ std::vector<ResourceBinding> GetReadOnlyStorageTextureResourceBindings(
+ 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 write-only storage textures.
+ std::vector<ResourceBinding> GetWriteOnlyStorageTextureResourceBindings(
+ const std::string& entry_point);
+
private:
const Program* program_;
std::string error_;
@@ -156,9 +168,9 @@
ast::Function* FindEntryPointByName(const std::string& name);
/// @param entry_point name of the entry point to get information about.
- /// @param read_only get only read only if true, otherwise get everything
- /// else.
- /// @returns vector of all of the bindings for the request storage buffers.
+ /// @param read_only if true get only read-only bindings, if false get
+ /// write-only bindings.
+ /// @returns vector of all of the bindings for the requested storage buffers.
std::vector<ResourceBinding> GetStorageBufferResourceBindingsImpl(
const std::string& entry_point,
bool read_only);
@@ -170,6 +182,14 @@
std::vector<ResourceBinding> GetSampledTextureResourceBindingsImpl(
const std::string& entry_point,
bool multisampled_only);
+
+ /// @param entry_point name of the entry point to get information about.
+ /// @param read_only if true get only read-only bindings, otherwise get
+ /// write-only bindings.
+ /// @returns vector of all of the bindings for the requested storage textures.
+ std::vector<ResourceBinding> GetStorageTextureResourceBindingsImpl(
+ const std::string& entry_point,
+ bool read_only);
};
} // namespace inspector
diff --git a/src/inspector/inspector_test.cc b/src/inspector/inspector_test.cc
index 982e12e..f52e688 100644
--- a/src/inspector/inspector_test.cc
+++ b/src/inspector/inspector_test.cc
@@ -601,6 +601,85 @@
return nullptr;
}
+ /// Generates appropriate types for a StorageTexture
+ /// @param dim the texture dimension of the storage texture
+ /// @param format the image format of the storage texture
+ /// @returns the storage texture type and subtype
+ std::tuple<type::StorageTexture*, type::Type*> MakeStorageTextureTypes(
+ type::TextureDimension dim,
+ type::ImageFormat format) {
+ type::Type* subtype = type::StorageTexture::SubtypeFor(format, Types());
+ return {create<type::StorageTexture>(dim, format, subtype), subtype};
+ }
+
+ /// Generates appropriate types for a Read-Only StorageTexture
+ /// @param dim the texture dimension of the storage texture
+ /// @param format the image format of the storage texture
+ /// @param read_only should the access type be read only, otherwise write only
+ /// @returns the storage texture type, subtype & access control type
+ std::tuple<type::StorageTexture*, type::Type*, type::AccessControl*>
+ MakeStorageTextureTypes(type::TextureDimension dim,
+ type::ImageFormat format,
+ bool read_only) {
+ type::StorageTexture* texture_type;
+ type::Type* subtype;
+ std::tie(texture_type, subtype) = MakeStorageTextureTypes(dim, format);
+ auto* access_control =
+ create<type::AccessControl>(read_only ? ast::AccessControl::kReadOnly
+ : ast::AccessControl::kWriteOnly,
+ texture_type);
+ return {texture_type, subtype, access_control};
+ }
+
+ /// Generates appropriate types for a Write-Only StorageTexture
+ /// @param dim the texture dimension of the storage texture
+ /// @param format the image format of the storage texture
+ /// @returns the storage texture type, subtype & access control type
+ std::tuple<type::StorageTexture*, type::Type*, type::AccessControl*>
+ MakeWriteOnlyStorageTextureTypes(type::TextureDimension dim,
+ type::ImageFormat format) {
+ type::StorageTexture* texture_type;
+ type::Type* subtype;
+ std::tie(texture_type, subtype) = MakeStorageTextureTypes(dim, format);
+ auto* access_control = create<type::AccessControl>(
+ ast::AccessControl::kWriteOnly, texture_type);
+ return {texture_type, subtype, access_control};
+ }
+
+ /// Adds a storage texture variable to the program
+ /// @param name the name of the variable
+ /// @param type the type to use
+ /// @param group the binding/group to use for the sampled texture
+ /// @param binding the binding number to use for the sampled texture
+ void AddStorageTexture(const std::string& name,
+ type::Type* type,
+ uint32_t group,
+ uint32_t binding) {
+ AddBinding(name, type, ast::StorageClass::kUniformConstant, group, binding);
+ }
+
+ /// Generates a function that references a storage texture variable.
+ /// @param func_name name of the function created
+ /// @param st_name name of the storage texture to use
+ /// @param dim_type type expected by textureDimensons to return
+ /// @param decorations the function decorations
+ /// @returns a function that references all of the values specified
+ ast::Function* MakeStorageTextureBodyFunction(
+ const std::string& func_name,
+ const std::string& st_name,
+ type::Type* dim_type,
+ ast::FunctionDecorationList decorations) {
+ ast::StatementList stmts;
+
+ stmts.emplace_back(create<ast::VariableDeclStatement>(
+ Var("dim", ast::StorageClass::kFunction, dim_type)));
+ stmts.emplace_back(create<ast::AssignmentStatement>(
+ Expr("dim"), Call("textureDimensions", st_name)));
+ stmts.emplace_back(create<ast::ReturnStatement>());
+
+ return Func(func_name, ast::VariableList(), ty.void_(), stmts, decorations);
+ }
+
Inspector& Build() {
if (inspector_) {
return *inspector_;
@@ -694,6 +773,13 @@
class InspectorGetMultisampledTextureResourceBindingsTestWithParam
: public InspectorHelper,
public testing::TestWithParam<GetMultisampledTextureTestParams> {};
+class InspectorGetStorageTextureResourceBindingsTest : public InspectorHelper,
+ public testing::Test {};
+typedef std::tuple<bool, type::TextureDimension, type::ImageFormat>
+ GetStorageTextureTestParams;
+class InspectorGetStorageTextureResourceBindingsTestWithParam
+ : public InspectorHelper,
+ public testing::TestWithParam<GetStorageTextureTestParams> {};
TEST_F(InspectorGetEntryPointTest, NoFunctions) {
Inspector& inspector = Build();
@@ -2417,6 +2503,126 @@
inspector::ResourceBinding::TextureDimension::k2dArray,
inspector::ResourceBinding::SampledKind::kUInt}));
+TEST_F(InspectorGetStorageTextureResourceBindingsTest, Empty) {
+ MakeEmptyBodyFunction(
+ "ep", ast::FunctionDecorationList{
+ create<ast::StageDecoration>(ast::PipelineStage::kVertex),
+ });
+
+ Inspector& inspector = Build();
+
+ auto result = inspector.GetReadOnlyStorageTextureResourceBindings("ep");
+ ASSERT_FALSE(inspector.has_error()) << inspector.error();
+ EXPECT_EQ(0u, result.size());
+
+ result = inspector.GetWriteOnlyStorageTextureResourceBindings("ep");
+ ASSERT_FALSE(inspector.has_error()) << inspector.error();
+ EXPECT_EQ(0u, result.size());
+}
+
+TEST_P(InspectorGetStorageTextureResourceBindingsTestWithParam, Simple) {
+ bool read_only;
+ type::TextureDimension dim;
+ type::ImageFormat format;
+ std::tie(read_only, dim, format) = GetParam();
+
+ type::StorageTexture* st_type;
+ type::Type* st_subtype;
+ type::AccessControl* ac;
+ std::tie(st_type, st_subtype, ac) =
+ MakeStorageTextureTypes(dim, format, read_only);
+ AddStorageTexture("st_var", ac, 0, 0);
+
+ type::Type* dim_type = nullptr;
+ switch (dim) {
+ case type::TextureDimension::k1d:
+ case type::TextureDimension::k1dArray:
+ dim_type = ty.i32();
+ break;
+ case type::TextureDimension::k2d:
+ case type::TextureDimension::k2dArray:
+ dim_type = ty.vec2<i32>();
+ break;
+ case type::TextureDimension::k3d:
+ dim_type = ty.vec3<i32>();
+ break;
+ default:
+ break;
+ }
+
+ ASSERT_FALSE(dim_type == nullptr);
+
+ MakeStorageTextureBodyFunction(
+ "ep", "st_var", dim_type,
+ ast::FunctionDecorationList{
+ create<ast::StageDecoration>(ast::PipelineStage::kVertex)});
+
+ Inspector& inspector = Build();
+
+ auto result =
+ read_only ? inspector.GetReadOnlyStorageTextureResourceBindings("ep")
+ : inspector.GetWriteOnlyStorageTextureResourceBindings("ep");
+ ASSERT_FALSE(inspector.has_error()) << inspector.error();
+ ASSERT_EQ(1u, result.size());
+
+ EXPECT_EQ(read_only ? ResourceBinding::ResourceType::kReadOnlyStorageTexture
+ : ResourceBinding::ResourceType::kWriteOnlyStorageTexture,
+ result[0].resource_type);
+ EXPECT_EQ(0u, result[0].bind_group);
+ EXPECT_EQ(0u, result[0].binding);
+
+ result = read_only
+ ? inspector.GetWriteOnlyStorageTextureResourceBindings("ep")
+ : inspector.GetReadOnlyStorageTextureResourceBindings("ep");
+ ASSERT_FALSE(inspector.has_error()) << inspector.error();
+ ASSERT_EQ(0u, result.size());
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ InspectorGetStorageTextureResourceBindingsTest,
+ InspectorGetStorageTextureResourceBindingsTestWithParam,
+ testing::Combine(testing::Bool(),
+ testing::Values(type::TextureDimension::k1d,
+ type::TextureDimension::k1dArray,
+ type::TextureDimension::k2d,
+ type::TextureDimension::k2dArray,
+ type::TextureDimension::k3d),
+ testing::Values(type::ImageFormat::kR8Uint,
+ type::ImageFormat::kR16Uint,
+ type::ImageFormat::kRg8Uint,
+ type::ImageFormat::kR32Uint,
+ type::ImageFormat::kRg16Uint,
+ type::ImageFormat::kRgba8Uint,
+ type::ImageFormat::kRg32Uint,
+ type::ImageFormat::kRgba16Uint,
+ type::ImageFormat::kRgba32Uint,
+ type::ImageFormat::kR8Sint,
+ type::ImageFormat::kR16Sint,
+ type::ImageFormat::kRg8Sint,
+ type::ImageFormat::kR32Sint,
+ type::ImageFormat::kRg16Sint,
+ type::ImageFormat::kRgba8Sint,
+ type::ImageFormat::kRg32Sint,
+ type::ImageFormat::kRgba16Sint,
+ type::ImageFormat::kRgba32Sint,
+ type::ImageFormat::kR8Unorm,
+ type::ImageFormat::kRg8Unorm,
+ type::ImageFormat::kRgba8Unorm,
+ type::ImageFormat::kRgba8UnormSrgb,
+ type::ImageFormat::kBgra8Unorm,
+ type::ImageFormat::kBgra8UnormSrgb,
+ type::ImageFormat::kRgb10A2Unorm,
+ type::ImageFormat::kR8Snorm,
+ type::ImageFormat::kRg8Snorm,
+ type::ImageFormat::kRgba8Snorm,
+ type::ImageFormat::kR16Float,
+ type::ImageFormat::kR32Float,
+ type::ImageFormat::kRg16Float,
+ type::ImageFormat::kRg11B10Float,
+ type::ImageFormat::kRg32Float,
+ type::ImageFormat::kRgba16Float,
+ type::ImageFormat::kRgba32Float)));
+
} // namespace
} // namespace inspector
} // namespace tint
diff --git a/src/semantic/function.h b/src/semantic/function.h
index 652e14d..9dc200f 100644
--- a/src/semantic/function.h
+++ b/src/semantic/function.h
@@ -95,7 +95,7 @@
/// must be decorated with both binding and group decorations.
/// @returns the referenced storagebuffers
const std::vector<std::pair<const Variable*, BindingInfo>>
- ReferencedStoragebufferVariables() const;
+ ReferencedStorageBufferVariables() const;
/// Retrieves any referenced regular Sampler variables. Note, the
/// variables must be decorated with both binding and group decorations.
@@ -121,6 +121,12 @@
const std::vector<std::pair<const Variable*, BindingInfo>>
ReferencedMultisampledTextureVariables() const;
+ /// Retrieves any referenced storage texture variables. Note, the variables
+ /// must be decorated with both binding and group decorations.
+ /// @returns the referenced storage textures
+ const std::vector<std::pair<const Variable*, BindingInfo>>
+ ReferencedStorageTextureVariables() const;
+
/// Retrieves any locally referenced builtin variables
/// @returns the <variable, decoration> pairs.
const std::vector<std::pair<const Variable*, ast::BuiltinDecoration*>>
diff --git a/src/semantic/sem_function.cc b/src/semantic/sem_function.cc
index 2ebf820..9862075 100644
--- a/src/semantic/sem_function.cc
+++ b/src/semantic/sem_function.cc
@@ -24,6 +24,7 @@
#include "src/semantic/variable.h"
#include "src/type/multisampled_texture_type.h"
#include "src/type/sampled_texture_type.h"
+#include "src/type/storage_texture_type.h"
#include "src/type/texture_type.h"
TINT_INSTANTIATE_CLASS_ID(tint::semantic::Function);
@@ -98,7 +99,7 @@
}
const std::vector<std::pair<const Variable*, Function::BindingInfo>>
-Function::ReferencedStoragebufferVariables() const {
+Function::ReferencedStorageBufferVariables() const {
std::vector<std::pair<const Variable*, Function::BindingInfo>> ret;
for (auto* var : ReferencedModuleVariables()) {
@@ -159,6 +160,35 @@
return ReferencedSampledTextureVariablesImpl(true);
}
+const std::vector<std::pair<const Variable*, Function::BindingInfo>>
+Function::ReferencedStorageTextureVariables() const {
+ std::vector<std::pair<const Variable*, Function::BindingInfo>> ret;
+
+ for (auto* var : ReferencedModuleVariables()) {
+ auto* unwrapped_type = var->Declaration()->type()->UnwrapIfNeeded();
+ auto* storage_texture = unwrapped_type->As<type::StorageTexture>();
+ if (storage_texture == nullptr) {
+ continue;
+ }
+
+ ast::BindingDecoration* binding = nullptr;
+ ast::GroupDecoration* group = nullptr;
+ for (auto* deco : var->Declaration()->decorations()) {
+ if (auto* b = deco->As<ast::BindingDecoration>()) {
+ binding = b;
+ } else if (auto* s = deco->As<ast::GroupDecoration>()) {
+ group = s;
+ }
+ }
+ if (binding == nullptr || group == nullptr) {
+ continue;
+ }
+
+ ret.push_back({var, BindingInfo{binding, group}});
+ }
+ return ret;
+}
+
const std::vector<std::pair<const Variable*, ast::BuiltinDecoration*>>
Function::LocalReferencedBuiltinVariables() const {
std::vector<std::pair<const Variable*, ast::BuiltinDecoration*>> ret;
diff --git a/src/writer/hlsl/generator_impl.cc b/src/writer/hlsl/generator_impl.cc
index b170fbd..f1d34e0 100644
--- a/src/writer/hlsl/generator_impl.cc
+++ b/src/writer/hlsl/generator_impl.cc
@@ -1626,7 +1626,7 @@
}
bool emitted_storagebuffer = false;
- for (auto data : func_sem->ReferencedStoragebufferVariables()) {
+ for (auto data : func_sem->ReferencedStorageBufferVariables()) {
auto* var = data.first;
auto* decl = var->Declaration();
auto* binding = data.second.binding;
diff --git a/src/writer/msl/generator_impl.cc b/src/writer/msl/generator_impl.cc
index 5421a64..7fb6803 100644
--- a/src/writer/msl/generator_impl.cc
+++ b/src/writer/msl/generator_impl.cc
@@ -546,7 +546,7 @@
out_ << program_->Symbols().NameFor(var->Declaration()->symbol());
}
- for (const auto& data : func_sem->ReferencedStoragebufferVariables()) {
+ for (const auto& data : func_sem->ReferencedStorageBufferVariables()) {
auto* var = data.first;
if (!first) {
out_ << ", ";
@@ -1384,7 +1384,7 @@
out_ << "& " << program_->Symbols().NameFor(var->Declaration()->symbol());
}
- for (const auto& data : func_sem->ReferencedStoragebufferVariables()) {
+ for (const auto& data : func_sem->ReferencedStorageBufferVariables()) {
auto* var = data.first;
if (!first) {
out_ << ", ";
@@ -1551,7 +1551,7 @@
<< " [[buffer(" << binding->value() << ")]]";
}
- for (auto data : func_sem->ReferencedStoragebufferVariables()) {
+ for (auto data : func_sem->ReferencedStorageBufferVariables()) {
if (!first) {
out_ << ", ";
}