[inspector] Extract storage-buffer information
BUG=tint:257 Change-Id: Ib85d76a3b972226b401e57ba2a632d6252e95f8f Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/31080 Commit-Queue: Ryan Harrison <rharrison@chromium.org> Reviewed-by: dan sinclair <dsinclair@chromium.org>
This commit is contained in:
parent
57694c8dab
commit
fcbc6efa8f
|
@ -34,15 +34,15 @@ bool ArrayType::IsArray() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t ArrayType::MinBufferBindingSize() const {
|
uint64_t ArrayType::MinBufferBindingSize() const {
|
||||||
if (IsRuntimeArray()) {
|
// RTAs have a size_ = 0, but the value that is wanted from this call is the
|
||||||
return array_stride();
|
// minimum size, so assuming atleast 1 element in the RTA.
|
||||||
}
|
uint32_t size = IsRuntimeArray() ? 1 : size_;
|
||||||
|
|
||||||
if (has_array_stride()) {
|
if (has_array_stride()) {
|
||||||
return size_ * array_stride();
|
return size * array_stride();
|
||||||
}
|
}
|
||||||
|
|
||||||
return size_ * type()->MinBufferBindingSize();
|
return size * type()->MinBufferBindingSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ArrayType::array_stride() const {
|
uint32_t ArrayType::array_stride() const {
|
||||||
|
|
|
@ -137,14 +137,8 @@ std::map<uint32_t, Scalar> Inspector::GetConstantIDs() {
|
||||||
|
|
||||||
std::vector<ResourceBinding> Inspector::GetUniformBufferResourceBindings(
|
std::vector<ResourceBinding> Inspector::GetUniformBufferResourceBindings(
|
||||||
const std::string& entry_point) {
|
const std::string& entry_point) {
|
||||||
auto* func = module_.FindFunctionByName(entry_point);
|
auto* func = FindEntryPointByName(entry_point);
|
||||||
if (!func) {
|
if (!func) {
|
||||||
error_ += entry_point + " was not found!";
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!func->IsEntryPoint()) {
|
|
||||||
error_ += entry_point + " is not an entry point!";
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,5 +167,53 @@ std::vector<ResourceBinding> Inspector::GetUniformBufferResourceBindings(
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<ResourceBinding> Inspector::GetStorageBufferResourceBindings(
|
||||||
|
const std::string& entry_point) {
|
||||||
|
auto* func = FindEntryPointByName(entry_point);
|
||||||
|
if (!func) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<ResourceBinding> result;
|
||||||
|
for (auto& ruv : func->referenced_storagebuffer_variables()) {
|
||||||
|
ResourceBinding entry;
|
||||||
|
ast::Variable* var = nullptr;
|
||||||
|
ast::Function::BindingInfo binding_info;
|
||||||
|
std::tie(var, binding_info) = ruv;
|
||||||
|
if (!var->type()->IsStruct()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry.bind_group = binding_info.set->value();
|
||||||
|
entry.binding = binding_info.binding->value();
|
||||||
|
entry.min_buffer_binding_size = var->type()->MinBufferBindingSize();
|
||||||
|
|
||||||
|
result.push_back(std::move(entry));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<ResourceBinding>
|
||||||
|
Inspector::GetReadOnlyStorageBufferResourceBindings(const std::string&) {
|
||||||
|
error_ += "GetReadOnlyStorageBufferResourceBindings is not implemented!";
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
ast::Function* Inspector::FindEntryPointByName(const std::string& name) {
|
||||||
|
auto* func = module_.FindFunctionByName(name);
|
||||||
|
if (!func) {
|
||||||
|
error_ += name + " was not found!";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!func->IsEntryPoint()) {
|
||||||
|
error_ += name + " is not an entry point!";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return func;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace inspector
|
} // namespace inspector
|
||||||
} // namespace tint
|
} // namespace tint
|
||||||
|
|
|
@ -59,13 +59,31 @@ class Inspector {
|
||||||
std::map<uint32_t, Scalar> GetConstantIDs();
|
std::map<uint32_t, Scalar> GetConstantIDs();
|
||||||
|
|
||||||
/// @param entry_point name of the entry point to get information about.
|
/// @param entry_point name of the entry point to get information about.
|
||||||
/// @returns vector of all of the bindings for Uniform buffers.
|
/// @returns vector of all of the bindings for uniform buffers.
|
||||||
std::vector<ResourceBinding> GetUniformBufferResourceBindings(
|
std::vector<ResourceBinding> GetUniformBufferResourceBindings(
|
||||||
const std::string& entry_point);
|
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 storage buffers.
|
||||||
|
std::vector<ResourceBinding> GetStorageBufferResourceBindings(
|
||||||
|
const std::string& entry_point);
|
||||||
|
|
||||||
|
// TODO(rharrison): Implement once
|
||||||
|
// https://dawn-review.googlesource.com/c/tint/+/31060 lands.
|
||||||
|
/// @param entry_point name of the entry point to get information about.
|
||||||
|
/// @returns an empty vector and sets the error string. In the future it will
|
||||||
|
/// return of all of the bindings for read-only storage buffers.
|
||||||
|
std::vector<ResourceBinding> GetReadOnlyStorageBufferResourceBindings(
|
||||||
|
const std::string& entry_point);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const ast::Module& module_;
|
const ast::Module& module_;
|
||||||
std::string error_;
|
std::string error_;
|
||||||
|
|
||||||
|
/// @param name name of the entry point to find
|
||||||
|
/// @returns a pointer to the entry point if it exists, otherwise returns
|
||||||
|
/// nullptr and sets the error string.
|
||||||
|
ast::Function* FindEntryPointByName(const std::string& name);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace inspector
|
} // namespace inspector
|
||||||
|
|
|
@ -254,14 +254,16 @@ class InspectorHelper {
|
||||||
return std::to_string(idx) + type->type_name();
|
return std::to_string(idx) + type->type_name();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generates a struct type appropriate for using in an uniform buffer
|
/// Generates a struct type
|
||||||
/// @param name name for the type
|
/// @param name name for the type
|
||||||
/// @param members_info a vector of {type, offset} where each entry is the
|
/// @param members_info a vector of {type, offset} where each entry is the
|
||||||
/// type and offset of a member of the struct
|
/// type and offset of a member of the struct
|
||||||
/// @returns a struct type suitable to use for an uniform buffer
|
/// @param is_block whether or not to decorate as a Block
|
||||||
std::unique_ptr<ast::type::StructType> MakeUniformBufferStructType(
|
/// @returns a struct type
|
||||||
|
std::unique_ptr<ast::type::StructType> MakeStructType(
|
||||||
const std::string& name,
|
const std::string& name,
|
||||||
std::vector<std::tuple<ast::type::Type*, uint32_t>> members_info) {
|
std::vector<std::tuple<ast::type::Type*, uint32_t>> members_info,
|
||||||
|
bool is_block) {
|
||||||
ast::StructMemberList members;
|
ast::StructMemberList members;
|
||||||
for (auto& member_info : members_info) {
|
for (auto& member_info : members_info) {
|
||||||
ast::type::Type* type;
|
ast::type::Type* type;
|
||||||
|
@ -275,8 +277,11 @@ class InspectorHelper {
|
||||||
members.push_back(std::make_unique<ast::StructMember>(
|
members.push_back(std::make_unique<ast::StructMember>(
|
||||||
StructMemberName(members.size(), type), type, std::move(deco)));
|
StructMemberName(members.size(), type), type, std::move(deco)));
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::StructDecorationList decos;
|
ast::StructDecorationList decos;
|
||||||
decos.push_back(ast::StructDecoration::kBlock);
|
if (is_block) {
|
||||||
|
decos.push_back(ast::StructDecoration::kBlock);
|
||||||
|
}
|
||||||
|
|
||||||
auto str =
|
auto str =
|
||||||
std::make_unique<ast::Struct>(std::move(decos), std::move(members));
|
std::make_unique<ast::Struct>(std::move(decos), std::move(members));
|
||||||
|
@ -284,6 +289,50 @@ class InspectorHelper {
|
||||||
return std::make_unique<ast::type::StructType>(name, std::move(str));
|
return std::make_unique<ast::type::StructType>(name, std::move(str));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Generates a struct type appropriate for using in an uniform buffer
|
||||||
|
/// @param name name for the type
|
||||||
|
/// @param members_info a vector of {type, offset} where each entry is the
|
||||||
|
/// type and offset of a member of the struct
|
||||||
|
/// @returns a struct type suitable to use for an uniform buffer
|
||||||
|
std::unique_ptr<ast::type::StructType> MakeUniformBufferStructType(
|
||||||
|
const std::string& name,
|
||||||
|
std::vector<std::tuple<ast::type::Type*, uint32_t>> members_info) {
|
||||||
|
return MakeStructType(name, members_info, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generates a struct type appropriate for using in an storage buffer
|
||||||
|
/// @param name name for the type
|
||||||
|
/// @param members_info a vector of {type, offset} where each entry is the
|
||||||
|
/// type and offset of a member of the struct
|
||||||
|
/// @returns a struct type suitable to use for an uniform buffer
|
||||||
|
std::unique_ptr<ast::type::StructType> MakeStorageBufferStructType(
|
||||||
|
const std::string& name,
|
||||||
|
std::vector<std::tuple<ast::type::Type*, uint32_t>> members_info) {
|
||||||
|
return MakeStructType(name, members_info, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adds a binding variable with a struct type to the module
|
||||||
|
/// @param name the name of the variable
|
||||||
|
/// @param struct_type the type to use
|
||||||
|
/// @param storage_class the storage class to use
|
||||||
|
/// @param set the binding group/set to use for the uniform buffer
|
||||||
|
/// @param binding the binding number to use for the uniform buffer
|
||||||
|
void AddStructBinding(const std::string& name,
|
||||||
|
ast::type::StructType* struct_type,
|
||||||
|
ast::StorageClass storage_class,
|
||||||
|
uint32_t set,
|
||||||
|
uint32_t binding) {
|
||||||
|
auto var = std::make_unique<ast::DecoratedVariable>(
|
||||||
|
std::make_unique<ast::Variable>(name, storage_class, struct_type));
|
||||||
|
ast::VariableDecorationList decorations;
|
||||||
|
|
||||||
|
decorations.push_back(std::make_unique<ast::BindingDecoration>(binding));
|
||||||
|
decorations.push_back(std::make_unique<ast::SetDecoration>(set));
|
||||||
|
var->set_decorations(std::move(decorations));
|
||||||
|
|
||||||
|
mod()->AddGlobalVariable(std::move(var));
|
||||||
|
}
|
||||||
|
|
||||||
/// Adds an uniform buffer variable to the module
|
/// Adds an uniform buffer variable to the module
|
||||||
/// @param name the name of the variable
|
/// @param name the name of the variable
|
||||||
/// @param struct_type the type to use
|
/// @param struct_type the type to use
|
||||||
|
@ -293,26 +342,31 @@ class InspectorHelper {
|
||||||
ast::type::StructType* struct_type,
|
ast::type::StructType* struct_type,
|
||||||
uint32_t set,
|
uint32_t set,
|
||||||
uint32_t binding) {
|
uint32_t binding) {
|
||||||
auto var = std::make_unique<ast::DecoratedVariable>(
|
AddStructBinding(name, struct_type, ast::StorageClass::kUniform, set,
|
||||||
std::make_unique<ast::Variable>(name, ast::StorageClass::kUniform,
|
binding);
|
||||||
struct_type));
|
|
||||||
ast::VariableDecorationList decorations;
|
|
||||||
|
|
||||||
decorations.push_back(std::make_unique<ast::BindingDecoration>(binding));
|
|
||||||
decorations.push_back(std::make_unique<ast::SetDecoration>(set));
|
|
||||||
var->set_decorations(std::move(decorations));
|
|
||||||
|
|
||||||
mod()->AddGlobalVariable(std::move(var));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generates a function that references a specific uniform buffer
|
/// Adds an storage buffer variable to the module
|
||||||
|
/// @param name the name of the variable
|
||||||
|
/// @param struct_type the type to use
|
||||||
|
/// @param set the binding group/set to use for the storage buffer
|
||||||
|
/// @param binding the binding number to use for the storage buffer
|
||||||
|
void AddStorageBuffer(const std::string& name,
|
||||||
|
ast::type::StructType* struct_type,
|
||||||
|
uint32_t set,
|
||||||
|
uint32_t binding) {
|
||||||
|
AddStructBinding(name, struct_type, ast::StorageClass::kStorageBuffer, set,
|
||||||
|
binding);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generates a function that references a specific struct variable
|
||||||
/// @param func_name name of the function created
|
/// @param func_name name of the function created
|
||||||
/// @param ub_name name of the uniform buffer to be accessed
|
/// @param struct_name name of the struct variabler to be accessed
|
||||||
/// @param members list of members to access, by index and type
|
/// @param members list of members to access, by index and type
|
||||||
/// @returns a function that references all of the ub members specified
|
/// @returns a function that references all of the members specified
|
||||||
std::unique_ptr<ast::Function> MakeUniformBufferReferenceBodyFunction(
|
std::unique_ptr<ast::Function> MakeStructVariableReferenceBodyFunction(
|
||||||
std::string func_name,
|
std::string func_name,
|
||||||
std::string ub_name,
|
std::string struct_name,
|
||||||
std::vector<std::tuple<size_t, ast::type::Type*>> members) {
|
std::vector<std::tuple<size_t, ast::type::Type*>> members) {
|
||||||
auto body = std::make_unique<ast::BlockStatement>();
|
auto body = std::make_unique<ast::BlockStatement>();
|
||||||
|
|
||||||
|
@ -334,7 +388,7 @@ class InspectorHelper {
|
||||||
body->append(std::make_unique<ast::AssignmentStatement>(
|
body->append(std::make_unique<ast::AssignmentStatement>(
|
||||||
std::make_unique<ast::IdentifierExpression>("local" + member_name),
|
std::make_unique<ast::IdentifierExpression>("local" + member_name),
|
||||||
std::make_unique<ast::MemberAccessorExpression>(
|
std::make_unique<ast::MemberAccessorExpression>(
|
||||||
std::make_unique<ast::IdentifierExpression>(ub_name),
|
std::make_unique<ast::IdentifierExpression>(struct_name),
|
||||||
std::make_unique<ast::IdentifierExpression>(member_name))));
|
std::make_unique<ast::IdentifierExpression>(member_name))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -381,6 +435,7 @@ class InspectorTest : public InspectorHelper, public testing::Test {};
|
||||||
class InspectorGetEntryPointTest : public InspectorTest {};
|
class InspectorGetEntryPointTest : public InspectorTest {};
|
||||||
class InspectorGetConstantIDsTest : public InspectorTest {};
|
class InspectorGetConstantIDsTest : public InspectorTest {};
|
||||||
class InspectorGetUniformBufferResourceBindings : public InspectorTest {};
|
class InspectorGetUniformBufferResourceBindings : public InspectorTest {};
|
||||||
|
class InspectorGetStorageBufferResourceBindings : public InspectorTest {};
|
||||||
|
|
||||||
TEST_F(InspectorGetEntryPointTest, NoFunctions) {
|
TEST_F(InspectorGetEntryPointTest, NoFunctions) {
|
||||||
auto result = inspector()->GetEntryPoints();
|
auto result = inspector()->GetEntryPoints();
|
||||||
|
@ -801,8 +856,8 @@ TEST_F(InspectorGetUniformBufferResourceBindings, NonEntryPointFunc) {
|
||||||
auto foo_type = MakeUniformBufferStructType("foo_type", {{i32_type(), 0}});
|
auto foo_type = MakeUniformBufferStructType("foo_type", {{i32_type(), 0}});
|
||||||
AddUniformBuffer("foo_ub", foo_type.get(), 0, 0);
|
AddUniformBuffer("foo_ub", foo_type.get(), 0, 0);
|
||||||
|
|
||||||
auto ub_func = MakeUniformBufferReferenceBodyFunction("ub_func", "foo_ub",
|
auto ub_func = MakeStructVariableReferenceBodyFunction("ub_func", "foo_ub",
|
||||||
{{0, i32_type()}});
|
{{0, i32_type()}});
|
||||||
mod()->AddFunction(std::move(ub_func));
|
mod()->AddFunction(std::move(ub_func));
|
||||||
|
|
||||||
auto ep_func = MakeCallerBodyFunction("ep_func", "ub_func");
|
auto ep_func = MakeCallerBodyFunction("ep_func", "ub_func");
|
||||||
|
@ -835,8 +890,8 @@ TEST_F(InspectorGetUniformBufferResourceBindings, MissingBlockDeco) {
|
||||||
|
|
||||||
AddUniformBuffer("foo_ub", foo_type.get(), 0, 0);
|
AddUniformBuffer("foo_ub", foo_type.get(), 0, 0);
|
||||||
|
|
||||||
auto ub_func = MakeUniformBufferReferenceBodyFunction("ub_func", "foo_ub",
|
auto ub_func = MakeStructVariableReferenceBodyFunction("ub_func", "foo_ub",
|
||||||
{{0, i32_type()}});
|
{{0, i32_type()}});
|
||||||
mod()->AddFunction(std::move(ub_func));
|
mod()->AddFunction(std::move(ub_func));
|
||||||
|
|
||||||
auto ep_func = MakeCallerBodyFunction("ep_func", "ub_func");
|
auto ep_func = MakeCallerBodyFunction("ep_func", "ub_func");
|
||||||
|
@ -855,8 +910,8 @@ TEST_F(InspectorGetUniformBufferResourceBindings, Simple) {
|
||||||
auto foo_type = MakeUniformBufferStructType("foo_type", {{i32_type(), 0}});
|
auto foo_type = MakeUniformBufferStructType("foo_type", {{i32_type(), 0}});
|
||||||
AddUniformBuffer("foo_ub", foo_type.get(), 0, 0);
|
AddUniformBuffer("foo_ub", foo_type.get(), 0, 0);
|
||||||
|
|
||||||
auto ub_func = MakeUniformBufferReferenceBodyFunction("ub_func", "foo_ub",
|
auto ub_func = MakeStructVariableReferenceBodyFunction("ub_func", "foo_ub",
|
||||||
{{0, i32_type()}});
|
{{0, i32_type()}});
|
||||||
mod()->AddFunction(std::move(ub_func));
|
mod()->AddFunction(std::move(ub_func));
|
||||||
|
|
||||||
auto ep_func = MakeCallerBodyFunction("ep_func", "ub_func");
|
auto ep_func = MakeCallerBodyFunction("ep_func", "ub_func");
|
||||||
|
@ -880,7 +935,7 @@ TEST_F(InspectorGetUniformBufferResourceBindings, MultipleMembers) {
|
||||||
"foo_type", {{i32_type(), 0}, {u32_type(), 4}, {f32_type(), 8}});
|
"foo_type", {{i32_type(), 0}, {u32_type(), 4}, {f32_type(), 8}});
|
||||||
AddUniformBuffer("foo_ub", foo_type.get(), 0, 0);
|
AddUniformBuffer("foo_ub", foo_type.get(), 0, 0);
|
||||||
|
|
||||||
auto ub_func = MakeUniformBufferReferenceBodyFunction(
|
auto ub_func = MakeStructVariableReferenceBodyFunction(
|
||||||
"ub_func", "foo_ub", {{0, i32_type()}, {1, u32_type()}, {2, f32_type()}});
|
"ub_func", "foo_ub", {{0, i32_type()}, {1, u32_type()}, {2, f32_type()}});
|
||||||
mod()->AddFunction(std::move(ub_func));
|
mod()->AddFunction(std::move(ub_func));
|
||||||
|
|
||||||
|
@ -900,7 +955,7 @@ TEST_F(InspectorGetUniformBufferResourceBindings, MultipleMembers) {
|
||||||
EXPECT_EQ(12u, result[0].min_buffer_binding_size);
|
EXPECT_EQ(12u, result[0].min_buffer_binding_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(InspectorGetUniformBufferResourceBindings, MultipleUniformBufferS) {
|
TEST_F(InspectorGetUniformBufferResourceBindings, MultipleUniformBuffers) {
|
||||||
auto ub_type = MakeUniformBufferStructType(
|
auto ub_type = MakeUniformBufferStructType(
|
||||||
"ub_type", {{i32_type(), 0}, {u32_type(), 4}, {f32_type(), 8}});
|
"ub_type", {{i32_type(), 0}, {u32_type(), 4}, {f32_type(), 8}});
|
||||||
AddUniformBuffer("ub_foo", ub_type.get(), 0, 0);
|
AddUniformBuffer("ub_foo", ub_type.get(), 0, 0);
|
||||||
|
@ -909,7 +964,7 @@ TEST_F(InspectorGetUniformBufferResourceBindings, MultipleUniformBufferS) {
|
||||||
|
|
||||||
auto AddReferenceFunc = [this](const std::string& func_name,
|
auto AddReferenceFunc = [this](const std::string& func_name,
|
||||||
const std::string& var_name) {
|
const std::string& var_name) {
|
||||||
auto ub_func = MakeUniformBufferReferenceBodyFunction(
|
auto ub_func = MakeStructVariableReferenceBodyFunction(
|
||||||
func_name, var_name,
|
func_name, var_name,
|
||||||
{{0, i32_type()}, {1, u32_type()}, {2, f32_type()}});
|
{{0, i32_type()}, {1, u32_type()}, {2, f32_type()}});
|
||||||
mod()->AddFunction(std::move(ub_func));
|
mod()->AddFunction(std::move(ub_func));
|
||||||
|
@ -963,8 +1018,8 @@ TEST_F(InspectorGetUniformBufferResourceBindings, ContainingArray) {
|
||||||
"foo_type", {{i32_type(), 0}, {u32_array_type(4), 4}});
|
"foo_type", {{i32_type(), 0}, {u32_array_type(4), 4}});
|
||||||
AddUniformBuffer("foo_ub", foo_type.get(), 0, 0);
|
AddUniformBuffer("foo_ub", foo_type.get(), 0, 0);
|
||||||
|
|
||||||
auto ub_func = MakeUniformBufferReferenceBodyFunction("ub_func", "foo_ub",
|
auto ub_func = MakeStructVariableReferenceBodyFunction("ub_func", "foo_ub",
|
||||||
{{0, i32_type()}});
|
{{0, i32_type()}});
|
||||||
mod()->AddFunction(std::move(ub_func));
|
mod()->AddFunction(std::move(ub_func));
|
||||||
|
|
||||||
auto ep_func = MakeCallerBodyFunction("ep_func", "ub_func");
|
auto ep_func = MakeCallerBodyFunction("ep_func", "ub_func");
|
||||||
|
@ -983,6 +1038,163 @@ TEST_F(InspectorGetUniformBufferResourceBindings, ContainingArray) {
|
||||||
EXPECT_EQ(20u, result[0].min_buffer_binding_size);
|
EXPECT_EQ(20u, result[0].min_buffer_binding_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(InspectorGetStorageBufferResourceBindings, Simple) {
|
||||||
|
auto foo_type = MakeStorageBufferStructType("foo_type", {{i32_type(), 0}});
|
||||||
|
AddStorageBuffer("foo_sb", foo_type.get(), 0, 0);
|
||||||
|
|
||||||
|
auto sb_func = MakeStructVariableReferenceBodyFunction("sb_func", "foo_sb",
|
||||||
|
{{0, i32_type()}});
|
||||||
|
mod()->AddFunction(std::move(sb_func));
|
||||||
|
|
||||||
|
auto ep_func = MakeCallerBodyFunction("ep_func", "sb_func");
|
||||||
|
ep_func->add_decoration(
|
||||||
|
std::make_unique<ast::StageDecoration>(ast::PipelineStage::kVertex));
|
||||||
|
mod()->AddFunction(std::move(ep_func));
|
||||||
|
|
||||||
|
ASSERT_TRUE(td()->Determine()) << td()->error();
|
||||||
|
|
||||||
|
auto result = inspector()->GetStorageBufferResourceBindings("ep_func");
|
||||||
|
ASSERT_FALSE(inspector()->has_error());
|
||||||
|
ASSERT_EQ(1u, result.size());
|
||||||
|
|
||||||
|
EXPECT_EQ(0u, result[0].bind_group);
|
||||||
|
EXPECT_EQ(0u, result[0].binding);
|
||||||
|
EXPECT_EQ(4u, result[0].min_buffer_binding_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(InspectorGetStorageBufferResourceBindings, MultipleMembers) {
|
||||||
|
auto foo_type = MakeStorageBufferStructType(
|
||||||
|
"foo_type", {{i32_type(), 0}, {u32_type(), 4}, {f32_type(), 8}});
|
||||||
|
AddStorageBuffer("foo_sb", foo_type.get(), 0, 0);
|
||||||
|
|
||||||
|
auto sb_func = MakeStructVariableReferenceBodyFunction(
|
||||||
|
"sb_func", "foo_sb", {{0, i32_type()}, {1, u32_type()}, {2, f32_type()}});
|
||||||
|
mod()->AddFunction(std::move(sb_func));
|
||||||
|
|
||||||
|
auto ep_func = MakeCallerBodyFunction("ep_func", "sb_func");
|
||||||
|
ep_func->add_decoration(
|
||||||
|
std::make_unique<ast::StageDecoration>(ast::PipelineStage::kVertex));
|
||||||
|
mod()->AddFunction(std::move(ep_func));
|
||||||
|
|
||||||
|
ASSERT_TRUE(td()->Determine()) << td()->error();
|
||||||
|
|
||||||
|
auto result = inspector()->GetStorageBufferResourceBindings("ep_func");
|
||||||
|
ASSERT_FALSE(inspector()->has_error());
|
||||||
|
ASSERT_EQ(1u, result.size());
|
||||||
|
|
||||||
|
EXPECT_EQ(0u, result[0].bind_group);
|
||||||
|
EXPECT_EQ(0u, result[0].binding);
|
||||||
|
EXPECT_EQ(12u, result[0].min_buffer_binding_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(InspectorGetStorageBufferResourceBindings, MultipleStorageBuffers) {
|
||||||
|
auto sb_type = MakeStorageBufferStructType(
|
||||||
|
"sb_type", {{i32_type(), 0}, {u32_type(), 4}, {f32_type(), 8}});
|
||||||
|
AddStorageBuffer("sb_foo", sb_type.get(), 0, 0);
|
||||||
|
AddStorageBuffer("sb_bar", sb_type.get(), 0, 1);
|
||||||
|
AddStorageBuffer("sb_baz", sb_type.get(), 2, 0);
|
||||||
|
|
||||||
|
auto AddReferenceFunc = [this](const std::string& func_name,
|
||||||
|
const std::string& var_name) {
|
||||||
|
auto sb_func = MakeStructVariableReferenceBodyFunction(
|
||||||
|
func_name, var_name,
|
||||||
|
{{0, i32_type()}, {1, u32_type()}, {2, f32_type()}});
|
||||||
|
mod()->AddFunction(std::move(sb_func));
|
||||||
|
};
|
||||||
|
AddReferenceFunc("sb_foo_func", "sb_foo");
|
||||||
|
AddReferenceFunc("sb_bar_func", "sb_bar");
|
||||||
|
AddReferenceFunc("sb_baz_func", "sb_baz");
|
||||||
|
|
||||||
|
auto AddFuncCall = [](ast::BlockStatement* body, const std::string& callee) {
|
||||||
|
auto ident_expr = std::make_unique<ast::IdentifierExpression>(callee);
|
||||||
|
auto call_expr = std::make_unique<ast::CallExpression>(
|
||||||
|
std::move(ident_expr), ast::ExpressionList());
|
||||||
|
body->append(std::make_unique<ast::CallStatement>(std::move(call_expr)));
|
||||||
|
};
|
||||||
|
auto body = std::make_unique<ast::BlockStatement>();
|
||||||
|
|
||||||
|
AddFuncCall(body.get(), "sb_foo_func");
|
||||||
|
AddFuncCall(body.get(), "sb_bar_func");
|
||||||
|
AddFuncCall(body.get(), "sb_baz_func");
|
||||||
|
|
||||||
|
body->append(std::make_unique<ast::ReturnStatement>());
|
||||||
|
std::unique_ptr<ast::Function> func = std::make_unique<ast::Function>(
|
||||||
|
"ep_func", ast::VariableList(), void_type());
|
||||||
|
func->set_body(std::move(body));
|
||||||
|
|
||||||
|
func->add_decoration(
|
||||||
|
std::make_unique<ast::StageDecoration>(ast::PipelineStage::kVertex));
|
||||||
|
mod()->AddFunction(std::move(func));
|
||||||
|
|
||||||
|
ASSERT_TRUE(td()->Determine()) << td()->error();
|
||||||
|
|
||||||
|
auto result = inspector()->GetStorageBufferResourceBindings("ep_func");
|
||||||
|
ASSERT_FALSE(inspector()->has_error());
|
||||||
|
ASSERT_EQ(3u, result.size());
|
||||||
|
|
||||||
|
EXPECT_EQ(0u, result[0].bind_group);
|
||||||
|
EXPECT_EQ(0u, result[0].binding);
|
||||||
|
EXPECT_EQ(12u, result[0].min_buffer_binding_size);
|
||||||
|
|
||||||
|
EXPECT_EQ(0u, result[1].bind_group);
|
||||||
|
EXPECT_EQ(1u, result[1].binding);
|
||||||
|
EXPECT_EQ(12u, result[1].min_buffer_binding_size);
|
||||||
|
|
||||||
|
EXPECT_EQ(2u, result[2].bind_group);
|
||||||
|
EXPECT_EQ(0u, result[2].binding);
|
||||||
|
EXPECT_EQ(12u, result[2].min_buffer_binding_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(InspectorGetStorageBufferResourceBindings, ContainingArray) {
|
||||||
|
auto foo_type = MakeStorageBufferStructType(
|
||||||
|
"foo_type", {{i32_type(), 0}, {u32_array_type(4), 4}});
|
||||||
|
AddStorageBuffer("foo_sb", foo_type.get(), 0, 0);
|
||||||
|
|
||||||
|
auto sb_func = MakeStructVariableReferenceBodyFunction("sb_func", "foo_sb",
|
||||||
|
{{0, i32_type()}});
|
||||||
|
mod()->AddFunction(std::move(sb_func));
|
||||||
|
|
||||||
|
auto ep_func = MakeCallerBodyFunction("ep_func", "sb_func");
|
||||||
|
ep_func->add_decoration(
|
||||||
|
std::make_unique<ast::StageDecoration>(ast::PipelineStage::kVertex));
|
||||||
|
mod()->AddFunction(std::move(ep_func));
|
||||||
|
|
||||||
|
ASSERT_TRUE(td()->Determine()) << td()->error();
|
||||||
|
|
||||||
|
auto result = inspector()->GetStorageBufferResourceBindings("ep_func");
|
||||||
|
ASSERT_FALSE(inspector()->has_error());
|
||||||
|
ASSERT_EQ(1u, result.size());
|
||||||
|
|
||||||
|
EXPECT_EQ(0u, result[0].bind_group);
|
||||||
|
EXPECT_EQ(0u, result[0].binding);
|
||||||
|
EXPECT_EQ(20u, result[0].min_buffer_binding_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(InspectorGetStorageBufferResourceBindings, ContainingRuntimeArray) {
|
||||||
|
auto foo_type = MakeStorageBufferStructType(
|
||||||
|
"foo_type", {{i32_type(), 0}, {u32_array_type(0), 4}});
|
||||||
|
AddStorageBuffer("foo_sb", foo_type.get(), 0, 0);
|
||||||
|
|
||||||
|
auto sb_func = MakeStructVariableReferenceBodyFunction("sb_func", "foo_sb",
|
||||||
|
{{0, i32_type()}});
|
||||||
|
mod()->AddFunction(std::move(sb_func));
|
||||||
|
|
||||||
|
auto ep_func = MakeCallerBodyFunction("ep_func", "sb_func");
|
||||||
|
ep_func->add_decoration(
|
||||||
|
std::make_unique<ast::StageDecoration>(ast::PipelineStage::kVertex));
|
||||||
|
mod()->AddFunction(std::move(ep_func));
|
||||||
|
|
||||||
|
ASSERT_TRUE(td()->Determine()) << td()->error();
|
||||||
|
|
||||||
|
auto result = inspector()->GetStorageBufferResourceBindings("ep_func");
|
||||||
|
ASSERT_FALSE(inspector()->has_error());
|
||||||
|
ASSERT_EQ(1u, result.size());
|
||||||
|
|
||||||
|
EXPECT_EQ(0u, result[0].bind_group);
|
||||||
|
EXPECT_EQ(0u, result[0].binding);
|
||||||
|
EXPECT_EQ(8u, result[0].min_buffer_binding_size);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace inspector
|
} // namespace inspector
|
||||||
} // namespace tint
|
} // namespace tint
|
||||||
|
|
Loading…
Reference in New Issue