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:
parent
652d40a3d1
commit
d086c147d0
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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*>>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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_ << ", ";
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue