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>
This commit is contained in:
Ryan Harrison 2021-02-16 15:10:23 +00:00 committed by Commit Bot service account
parent 652d40a3d1
commit d086c147d0
7 changed files with 322 additions and 11 deletions

View File

@ -332,6 +332,18 @@ std::vector<ResourceBinding> Inspector::GetMultisampledTextureResourceBindings(
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 @@ std::vector<ResourceBinding> Inspector::GetStorageBufferResourceBindingsImpl(
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 @@ std::vector<ResourceBinding> Inspector::GetSampledTextureResourceBindingsImpl(
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

View File

@ -63,7 +63,9 @@ struct ResourceBinding {
kSampler,
kComparisonSampler,
kSampledTexture,
kMulitsampledTexture
kMulitsampledTexture,
kReadOnlyStorageTexture,
kWriteOnlyStorageTexture,
};
/// Type of resource that is bound.
@ -146,6 +148,16 @@ class Inspector {
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 @@ class Inspector {
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 @@ class Inspector {
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

View File

@ -601,6 +601,85 @@ class InspectorHelper : public ProgramBuilder {
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 InspectorGetMultisampledArrayTextureResourceBindingsTestWithParam
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 @@ INSTANTIATE_TEST_SUITE_P(
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

View File

@ -95,7 +95,7 @@ class Function : public Castable<Function, CallTarget> {
/// 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 @@ class Function : public Castable<Function, CallTarget> {
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*>>

View File

@ -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 @@ Function::ReferencedUniformVariables() const {
}
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 @@ Function::ReferencedMultisampledTextureVariables() const {
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;

View File

@ -1626,7 +1626,7 @@ bool GeneratorImpl::EmitEntryPointData(
}
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;

View File

@ -546,7 +546,7 @@ bool GeneratorImpl::EmitCall(ast::CallExpression* expr) {
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 @@ bool GeneratorImpl::EmitFunctionInternal(ast::Function* func,
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 @@ bool GeneratorImpl::EmitEntryPointFunction(ast::Function* func) {
<< " [[buffer(" << binding->value() << ")]]";
}
for (auto data : func_sem->ReferencedStoragebufferVariables()) {
for (auto data : func_sem->ReferencedStorageBufferVariables()) {
if (!first) {
out_ << ", ";
}