|
|
|
@ -24,17 +24,27 @@
|
|
|
|
|
#include "src/ast/float_literal.h"
|
|
|
|
|
#include "src/ast/function.h"
|
|
|
|
|
#include "src/ast/identifier_expression.h"
|
|
|
|
|
#include "src/ast/member_accessor_expression.h"
|
|
|
|
|
#include "src/ast/null_literal.h"
|
|
|
|
|
#include "src/ast/pipeline_stage.h"
|
|
|
|
|
#include "src/ast/return_statement.h"
|
|
|
|
|
#include "src/ast/scalar_constructor_expression.h"
|
|
|
|
|
#include "src/ast/sint_literal.h"
|
|
|
|
|
#include "src/ast/stage_decoration.h"
|
|
|
|
|
#include "src/ast/struct_decoration.h"
|
|
|
|
|
#include "src/ast/struct_member.h"
|
|
|
|
|
#include "src/ast/struct_member_decoration.h"
|
|
|
|
|
#include "src/ast/struct_member_offset_decoration.h"
|
|
|
|
|
#include "src/ast/type/array_type.h"
|
|
|
|
|
#include "src/ast/type/bool_type.h"
|
|
|
|
|
#include "src/ast/type/f32_type.h"
|
|
|
|
|
#include "src/ast/type/i32_type.h"
|
|
|
|
|
#include "src/ast/type/matrix_type.h"
|
|
|
|
|
#include "src/ast/type/pointer_type.h"
|
|
|
|
|
#include "src/ast/type/struct_type.h"
|
|
|
|
|
#include "src/ast/type/type.h"
|
|
|
|
|
#include "src/ast/type/u32_type.h"
|
|
|
|
|
#include "src/ast/type/vector_type.h"
|
|
|
|
|
#include "src/ast/type/void_type.h"
|
|
|
|
|
#include "src/ast/uint_literal.h"
|
|
|
|
|
#include "src/ast/variable_decl_statement.h"
|
|
|
|
@ -58,7 +68,7 @@ class InspectorHelper {
|
|
|
|
|
/// Generates an empty function
|
|
|
|
|
/// @param name name of the function created
|
|
|
|
|
/// @returns a function object
|
|
|
|
|
std::unique_ptr<ast::Function> GenerateEmptyBodyFunction(std::string name) {
|
|
|
|
|
std::unique_ptr<ast::Function> MakeEmptyBodyFunction(std::string name) {
|
|
|
|
|
auto body = std::make_unique<ast::BlockStatement>();
|
|
|
|
|
body->append(std::make_unique<ast::ReturnStatement>());
|
|
|
|
|
std::unique_ptr<ast::Function> func =
|
|
|
|
@ -71,9 +81,8 @@ class InspectorHelper {
|
|
|
|
|
/// @param caller name of the function created
|
|
|
|
|
/// @param callee name of the function to be called
|
|
|
|
|
/// @returns a function object
|
|
|
|
|
std::unique_ptr<ast::Function> GenerateCallerBodyFunction(
|
|
|
|
|
std::string caller,
|
|
|
|
|
std::string callee) {
|
|
|
|
|
std::unique_ptr<ast::Function> MakeCallerBodyFunction(std::string caller,
|
|
|
|
|
std::string callee) {
|
|
|
|
|
auto body = std::make_unique<ast::BlockStatement>();
|
|
|
|
|
auto ident_expr = std::make_unique<ast::IdentifierExpression>(callee);
|
|
|
|
|
auto call_expr = std::make_unique<ast::CallExpression>(
|
|
|
|
@ -89,7 +98,7 @@ class InspectorHelper {
|
|
|
|
|
/// Add In/Out variables to the global variables
|
|
|
|
|
/// @param inout_vars tuples of {in, out} that will be added as entries to the
|
|
|
|
|
/// global variables
|
|
|
|
|
void CreateInOutVariables(
|
|
|
|
|
void AddInOutVariables(
|
|
|
|
|
std::vector<std::tuple<std::string, std::string>> inout_vars) {
|
|
|
|
|
for (auto inout : inout_vars) {
|
|
|
|
|
std::string in, out;
|
|
|
|
@ -108,7 +117,7 @@ class InspectorHelper {
|
|
|
|
|
/// @param inout_vars tuples of {in, out} that will be converted into out = in
|
|
|
|
|
/// calls in the function body
|
|
|
|
|
/// @returns a function object
|
|
|
|
|
std::unique_ptr<ast::Function> GenerateInOutVariableBodyFunction(
|
|
|
|
|
std::unique_ptr<ast::Function> MakeInOutVariableBodyFunction(
|
|
|
|
|
std::string name,
|
|
|
|
|
std::vector<std::tuple<std::string, std::string>> inout_vars) {
|
|
|
|
|
auto body = std::make_unique<ast::BlockStatement>();
|
|
|
|
@ -133,7 +142,7 @@ class InspectorHelper {
|
|
|
|
|
/// @param inout_vars tuples of {in, out} that will be converted into out = in
|
|
|
|
|
/// calls in the function body
|
|
|
|
|
/// @returns a function object
|
|
|
|
|
std::unique_ptr<ast::Function> GenerateInOutVariableCallerBodyFunction(
|
|
|
|
|
std::unique_ptr<ast::Function> MakeInOutVariableCallerBodyFunction(
|
|
|
|
|
std::string caller,
|
|
|
|
|
std::string callee,
|
|
|
|
|
std::vector<std::tuple<std::string, std::string>> inout_vars) {
|
|
|
|
@ -163,10 +172,10 @@ class InspectorHelper {
|
|
|
|
|
/// @param val value to initialize the variable with, if NULL no initializer
|
|
|
|
|
/// will be added.
|
|
|
|
|
template <class T>
|
|
|
|
|
void CreateConstantID(std::string name,
|
|
|
|
|
uint32_t id,
|
|
|
|
|
ast::type::Type* type,
|
|
|
|
|
T* val) {
|
|
|
|
|
void AddConstantID(std::string name,
|
|
|
|
|
uint32_t id,
|
|
|
|
|
ast::type::Type* type,
|
|
|
|
|
T* val) {
|
|
|
|
|
auto dvar = std::make_unique<ast::DecoratedVariable>(
|
|
|
|
|
std::make_unique<ast::Variable>(name, ast::StorageClass::kNone, type));
|
|
|
|
|
dvar->set_is_const(true);
|
|
|
|
@ -180,35 +189,53 @@ class InspectorHelper {
|
|
|
|
|
mod()->AddGlobalVariable(std::move(dvar));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Generates an ast::Literal for the given value
|
|
|
|
|
/// @tparam T C++ type of the literal, must agree with type
|
|
|
|
|
/// @returns a Literal of the expected type and value
|
|
|
|
|
template <class T>
|
|
|
|
|
std::unique_ptr<ast::Literal> MakeLiteral(ast::type::Type*, T*) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// @param type AST type of the literal, must resolve to BoolLiteral
|
|
|
|
|
/// @param val scalar value for the literal to contain
|
|
|
|
|
/// @returns a Literal of the expected type and value
|
|
|
|
|
template <>
|
|
|
|
|
std::unique_ptr<ast::Literal> MakeLiteral<bool>(ast::type::Type* type,
|
|
|
|
|
bool* val) {
|
|
|
|
|
return std::make_unique<ast::BoolLiteral>(type, *val);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// @param type AST type of the literal, must resolve to UIntLiteral
|
|
|
|
|
/// @param val scalar value for the literal to contain
|
|
|
|
|
/// @returns a Literal of the expected type and value
|
|
|
|
|
template <>
|
|
|
|
|
std::unique_ptr<ast::Literal> MakeLiteral<uint32_t>(ast::type::Type* type,
|
|
|
|
|
uint32_t* val) {
|
|
|
|
|
return std::make_unique<ast::UintLiteral>(type, *val);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// @param type AST type of the literal, must resolve to IntLiteral
|
|
|
|
|
/// @param val scalar value for the literal to contain
|
|
|
|
|
/// @returns a Literal of the expected type and value
|
|
|
|
|
template <>
|
|
|
|
|
std::unique_ptr<ast::Literal> MakeLiteral<int32_t>(ast::type::Type* type,
|
|
|
|
|
int32_t* val) {
|
|
|
|
|
return std::make_unique<ast::SintLiteral>(type, *val);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// @param type AST type of the literal, must resolve to FloattLiteral
|
|
|
|
|
/// @param val scalar value for the literal to contain
|
|
|
|
|
/// @returns a Literal of the expected type and value
|
|
|
|
|
template <>
|
|
|
|
|
std::unique_ptr<ast::Literal> MakeLiteral<float>(ast::type::Type* type,
|
|
|
|
|
float* val) {
|
|
|
|
|
return std::make_unique<ast::FloatLiteral>(type, *val);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// @param vec Vector of strings to be searched
|
|
|
|
|
/// @param str String to be searching for
|
|
|
|
|
/// @returns true if str is in vec, otherwise false
|
|
|
|
|
bool ContainsString(const std::vector<std::string>& vec,
|
|
|
|
|
const std::string& str) {
|
|
|
|
|
for (auto& s : vec) {
|
|
|
|
@ -219,6 +246,105 @@ class InspectorHelper {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Builds a string for accessing a member in a generated struct
|
|
|
|
|
/// @param idx index of member
|
|
|
|
|
/// @param type type of member
|
|
|
|
|
/// @returns a string for the member
|
|
|
|
|
std::string StructMemberName(size_t idx, ast::type::Type* type) {
|
|
|
|
|
return std::to_string(idx) + type->type_name();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Generates a struct type appropriate for using in a UBO
|
|
|
|
|
/// @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 a UBO
|
|
|
|
|
std::unique_ptr<ast::type::StructType> MakeUBOStructType(
|
|
|
|
|
const std::string& name,
|
|
|
|
|
std::vector<std::tuple<ast::type::Type*, uint32_t>> members_info) {
|
|
|
|
|
ast::StructMemberList members;
|
|
|
|
|
for (auto& member_info : members_info) {
|
|
|
|
|
ast::type::Type* type;
|
|
|
|
|
uint32_t offset;
|
|
|
|
|
std::tie(type, offset) = member_info;
|
|
|
|
|
|
|
|
|
|
ast::StructMemberDecorationList deco;
|
|
|
|
|
deco.push_back(
|
|
|
|
|
std::make_unique<ast::StructMemberOffsetDecoration>(offset));
|
|
|
|
|
|
|
|
|
|
members.push_back(std::make_unique<ast::StructMember>(
|
|
|
|
|
StructMemberName(members.size(), type), type, std::move(deco)));
|
|
|
|
|
}
|
|
|
|
|
ast::StructDecorationList decos;
|
|
|
|
|
decos.push_back(ast::StructDecoration::kBlock);
|
|
|
|
|
|
|
|
|
|
auto str =
|
|
|
|
|
std::make_unique<ast::Struct>(std::move(decos), std::move(members));
|
|
|
|
|
|
|
|
|
|
return std::make_unique<ast::type::StructType>(name, std::move(str));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Adds a UBO 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 UBO
|
|
|
|
|
/// @param binding the binding number to use for the UBO
|
|
|
|
|
void AddUBO(const std::string& name,
|
|
|
|
|
ast::type::StructType* struct_type,
|
|
|
|
|
uint32_t set,
|
|
|
|
|
uint32_t binding) {
|
|
|
|
|
auto var = std::make_unique<ast::DecoratedVariable>(
|
|
|
|
|
std::make_unique<ast::Variable>(name, ast::StorageClass::kUniform,
|
|
|
|
|
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 UBO
|
|
|
|
|
/// @param func_name name of the function created
|
|
|
|
|
/// @param ubo_name name of the UBO to be accessed
|
|
|
|
|
/// @param member_idx index of the member to access
|
|
|
|
|
/// @returns a function that references all of the UBO members specified
|
|
|
|
|
std::unique_ptr<ast::Function> MakeUBOReferenceBodyFunction(
|
|
|
|
|
std::string func_name,
|
|
|
|
|
std::string ubo_name,
|
|
|
|
|
std::vector<std::tuple<size_t, ast::type::Type*>> members) {
|
|
|
|
|
auto body = std::make_unique<ast::BlockStatement>();
|
|
|
|
|
|
|
|
|
|
for (auto member : members) {
|
|
|
|
|
size_t member_idx;
|
|
|
|
|
ast::type::Type* member_type;
|
|
|
|
|
std::tie(member_idx, member_type) = member;
|
|
|
|
|
std::string member_name = StructMemberName(member_idx, member_type);
|
|
|
|
|
body->append(std::make_unique<ast::VariableDeclStatement>(
|
|
|
|
|
std::make_unique<ast::Variable>(
|
|
|
|
|
"local" + member_name, ast::StorageClass::kNone, member_type)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (auto member : members) {
|
|
|
|
|
size_t member_idx;
|
|
|
|
|
ast::type::Type* member_type;
|
|
|
|
|
std::tie(member_idx, member_type) = member;
|
|
|
|
|
std::string member_name = StructMemberName(member_idx, member_type);
|
|
|
|
|
body->append(std::make_unique<ast::AssignmentStatement>(
|
|
|
|
|
std::make_unique<ast::IdentifierExpression>("local" + member_name),
|
|
|
|
|
std::make_unique<ast::MemberAccessorExpression>(
|
|
|
|
|
std::make_unique<ast::IdentifierExpression>(ubo_name),
|
|
|
|
|
std::make_unique<ast::IdentifierExpression>(member_name))));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
body->append(std::make_unique<ast::ReturnStatement>());
|
|
|
|
|
auto func = std::make_unique<ast::Function>(func_name, ast::VariableList(),
|
|
|
|
|
void_type());
|
|
|
|
|
func->set_body(std::move(body));
|
|
|
|
|
return func;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ast::Module* mod() { return &mod_; }
|
|
|
|
|
TypeDeterminer* td() { return td_.get(); }
|
|
|
|
|
Inspector* inspector() { return inspector_.get(); }
|
|
|
|
@ -227,6 +353,14 @@ class InspectorHelper {
|
|
|
|
|
ast::type::F32Type* f32_type() { return &f32_type_; }
|
|
|
|
|
ast::type::I32Type* i32_type() { return &i32_type_; }
|
|
|
|
|
ast::type::U32Type* u32_type() { return &u32_type_; }
|
|
|
|
|
ast::type::ArrayType* u32_array_type(uint32_t count) {
|
|
|
|
|
static std::map<uint32_t, std::unique_ptr<ast::type::ArrayType>> memo;
|
|
|
|
|
if (memo.find(count) == memo.end()) {
|
|
|
|
|
memo[count] = std::make_unique<ast::type::ArrayType>(u32_type(), count);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return memo[count].get();
|
|
|
|
|
}
|
|
|
|
|
ast::type::VoidType* void_type() { return &void_type_; }
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
@ -245,6 +379,8 @@ class InspectorHelper {
|
|
|
|
|
class InspectorTest : public InspectorHelper, public testing::Test {};
|
|
|
|
|
|
|
|
|
|
class InspectorGetEntryPointTest : public InspectorTest {};
|
|
|
|
|
class InspectorGetConstantIDsTest : public InspectorTest {};
|
|
|
|
|
class InspectorGetUniformBufferResourceBindings : public InspectorTest {};
|
|
|
|
|
|
|
|
|
|
TEST_F(InspectorGetEntryPointTest, NoFunctions) {
|
|
|
|
|
auto result = inspector()->GetEntryPoints();
|
|
|
|
@ -254,7 +390,7 @@ TEST_F(InspectorGetEntryPointTest, NoFunctions) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(InspectorGetEntryPointTest, NoEntryPoints) {
|
|
|
|
|
mod()->AddFunction(GenerateEmptyBodyFunction("foo"));
|
|
|
|
|
mod()->AddFunction(MakeEmptyBodyFunction("foo"));
|
|
|
|
|
|
|
|
|
|
auto result = inspector()->GetEntryPoints();
|
|
|
|
|
ASSERT_FALSE(inspector()->has_error());
|
|
|
|
@ -263,7 +399,7 @@ TEST_F(InspectorGetEntryPointTest, NoEntryPoints) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(InspectorGetEntryPointTest, OneEntryPoint) {
|
|
|
|
|
auto foo = GenerateEmptyBodyFunction("foo");
|
|
|
|
|
auto foo = MakeEmptyBodyFunction("foo");
|
|
|
|
|
foo->add_decoration(
|
|
|
|
|
std::make_unique<ast::StageDecoration>(ast::PipelineStage::kVertex));
|
|
|
|
|
mod()->AddFunction(std::move(foo));
|
|
|
|
@ -277,12 +413,12 @@ TEST_F(InspectorGetEntryPointTest, OneEntryPoint) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(InspectorGetEntryPointTest, MultipleEntryPoints) {
|
|
|
|
|
auto foo = GenerateEmptyBodyFunction("foo");
|
|
|
|
|
auto foo = MakeEmptyBodyFunction("foo");
|
|
|
|
|
foo->add_decoration(
|
|
|
|
|
std::make_unique<ast::StageDecoration>(ast::PipelineStage::kVertex));
|
|
|
|
|
mod()->AddFunction(std::move(foo));
|
|
|
|
|
|
|
|
|
|
auto bar = GenerateEmptyBodyFunction("bar");
|
|
|
|
|
auto bar = MakeEmptyBodyFunction("bar");
|
|
|
|
|
bar->add_decoration(
|
|
|
|
|
std::make_unique<ast::StageDecoration>(ast::PipelineStage::kCompute));
|
|
|
|
|
mod()->AddFunction(std::move(bar));
|
|
|
|
@ -298,15 +434,15 @@ TEST_F(InspectorGetEntryPointTest, MultipleEntryPoints) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(InspectorGetEntryPointTest, MixFunctionsAndEntryPoints) {
|
|
|
|
|
auto func = GenerateEmptyBodyFunction("func");
|
|
|
|
|
auto func = MakeEmptyBodyFunction("func");
|
|
|
|
|
mod()->AddFunction(std::move(func));
|
|
|
|
|
|
|
|
|
|
auto foo = GenerateCallerBodyFunction("foo", "func");
|
|
|
|
|
auto foo = MakeCallerBodyFunction("foo", "func");
|
|
|
|
|
foo->add_decoration(
|
|
|
|
|
std::make_unique<ast::StageDecoration>(ast::PipelineStage::kVertex));
|
|
|
|
|
mod()->AddFunction(std::move(foo));
|
|
|
|
|
|
|
|
|
|
auto bar = GenerateCallerBodyFunction("bar", "func");
|
|
|
|
|
auto bar = MakeCallerBodyFunction("bar", "func");
|
|
|
|
|
bar->add_decoration(
|
|
|
|
|
std::make_unique<ast::StageDecoration>(ast::PipelineStage::kFragment));
|
|
|
|
|
mod()->AddFunction(std::move(bar));
|
|
|
|
@ -322,7 +458,7 @@ TEST_F(InspectorGetEntryPointTest, MixFunctionsAndEntryPoints) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(InspectorGetEntryPointTest, DefaultWorkgroupSize) {
|
|
|
|
|
auto foo = GenerateCallerBodyFunction("foo", "func");
|
|
|
|
|
auto foo = MakeCallerBodyFunction("foo", "func");
|
|
|
|
|
foo->add_decoration(
|
|
|
|
|
std::make_unique<ast::StageDecoration>(ast::PipelineStage::kVertex));
|
|
|
|
|
mod()->AddFunction(std::move(foo));
|
|
|
|
@ -339,7 +475,7 @@ TEST_F(InspectorGetEntryPointTest, DefaultWorkgroupSize) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(InspectorGetEntryPointTest, NonDefaultWorkgroupSize) {
|
|
|
|
|
auto foo = GenerateEmptyBodyFunction("foo");
|
|
|
|
|
auto foo = MakeEmptyBodyFunction("foo");
|
|
|
|
|
foo->add_decoration(
|
|
|
|
|
std::make_unique<ast::StageDecoration>(ast::PipelineStage::kCompute));
|
|
|
|
|
foo->add_decoration(std::make_unique<ast::WorkgroupDecoration>(8u, 2u, 1u));
|
|
|
|
@ -357,10 +493,10 @@ TEST_F(InspectorGetEntryPointTest, NonDefaultWorkgroupSize) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(InspectorGetEntryPointTest, NoInOutVariables) {
|
|
|
|
|
auto func = GenerateEmptyBodyFunction("func");
|
|
|
|
|
auto func = MakeEmptyBodyFunction("func");
|
|
|
|
|
mod()->AddFunction(std::move(func));
|
|
|
|
|
|
|
|
|
|
auto foo = GenerateCallerBodyFunction("foo", "func");
|
|
|
|
|
auto foo = MakeCallerBodyFunction("foo", "func");
|
|
|
|
|
foo->add_decoration(
|
|
|
|
|
std::make_unique<ast::StageDecoration>(ast::PipelineStage::kVertex));
|
|
|
|
|
mod()->AddFunction(std::move(foo));
|
|
|
|
@ -374,9 +510,9 @@ TEST_F(InspectorGetEntryPointTest, NoInOutVariables) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(InspectorGetEntryPointTest, EntryPointInOutVariables) {
|
|
|
|
|
CreateInOutVariables({{"in_var", "out_var"}});
|
|
|
|
|
AddInOutVariables({{"in_var", "out_var"}});
|
|
|
|
|
|
|
|
|
|
auto foo = GenerateInOutVariableBodyFunction("foo", {{"in_var", "out_var"}});
|
|
|
|
|
auto foo = MakeInOutVariableBodyFunction("foo", {{"in_var", "out_var"}});
|
|
|
|
|
foo->add_decoration(
|
|
|
|
|
std::make_unique<ast::StageDecoration>(ast::PipelineStage::kVertex));
|
|
|
|
|
mod()->AddFunction(std::move(foo));
|
|
|
|
@ -395,13 +531,12 @@ TEST_F(InspectorGetEntryPointTest, EntryPointInOutVariables) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(InspectorGetEntryPointTest, FunctionInOutVariables) {
|
|
|
|
|
CreateInOutVariables({{"in_var", "out_var"}});
|
|
|
|
|
AddInOutVariables({{"in_var", "out_var"}});
|
|
|
|
|
|
|
|
|
|
auto func =
|
|
|
|
|
GenerateInOutVariableBodyFunction("func", {{"in_var", "out_var"}});
|
|
|
|
|
auto func = MakeInOutVariableBodyFunction("func", {{"in_var", "out_var"}});
|
|
|
|
|
mod()->AddFunction(std::move(func));
|
|
|
|
|
|
|
|
|
|
auto foo = GenerateCallerBodyFunction("foo", "func");
|
|
|
|
|
auto foo = MakeCallerBodyFunction("foo", "func");
|
|
|
|
|
foo->add_decoration(
|
|
|
|
|
std::make_unique<ast::StageDecoration>(ast::PipelineStage::kVertex));
|
|
|
|
|
mod()->AddFunction(std::move(foo));
|
|
|
|
@ -420,14 +555,13 @@ TEST_F(InspectorGetEntryPointTest, FunctionInOutVariables) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(InspectorGetEntryPointTest, RepeatedInOutVariables) {
|
|
|
|
|
CreateInOutVariables({{"in_var", "out_var"}});
|
|
|
|
|
AddInOutVariables({{"in_var", "out_var"}});
|
|
|
|
|
|
|
|
|
|
auto func =
|
|
|
|
|
GenerateInOutVariableBodyFunction("func", {{"in_var", "out_var"}});
|
|
|
|
|
auto func = MakeInOutVariableBodyFunction("func", {{"in_var", "out_var"}});
|
|
|
|
|
mod()->AddFunction(std::move(func));
|
|
|
|
|
|
|
|
|
|
auto foo = GenerateInOutVariableCallerBodyFunction("foo", "func",
|
|
|
|
|
{{"in_var", "out_var"}});
|
|
|
|
|
auto foo = MakeInOutVariableCallerBodyFunction("foo", "func",
|
|
|
|
|
{{"in_var", "out_var"}});
|
|
|
|
|
foo->add_decoration(
|
|
|
|
|
std::make_unique<ast::StageDecoration>(ast::PipelineStage::kVertex));
|
|
|
|
|
mod()->AddFunction(std::move(foo));
|
|
|
|
@ -446,9 +580,9 @@ TEST_F(InspectorGetEntryPointTest, RepeatedInOutVariables) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(InspectorGetEntryPointTest, EntryPointMultipleInOutVariables) {
|
|
|
|
|
CreateInOutVariables({{"in_var", "out_var"}, {"in2_var", "out2_var"}});
|
|
|
|
|
AddInOutVariables({{"in_var", "out_var"}, {"in2_var", "out2_var"}});
|
|
|
|
|
|
|
|
|
|
auto foo = GenerateInOutVariableBodyFunction(
|
|
|
|
|
auto foo = MakeInOutVariableBodyFunction(
|
|
|
|
|
"foo", {{"in_var", "out_var"}, {"in2_var", "out2_var"}});
|
|
|
|
|
foo->add_decoration(
|
|
|
|
|
std::make_unique<ast::StageDecoration>(ast::PipelineStage::kVertex));
|
|
|
|
@ -470,13 +604,13 @@ TEST_F(InspectorGetEntryPointTest, EntryPointMultipleInOutVariables) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(InspectorGetEntryPointTest, FunctionMultipleInOutVariables) {
|
|
|
|
|
CreateInOutVariables({{"in_var", "out_var"}, {"in2_var", "out2_var"}});
|
|
|
|
|
AddInOutVariables({{"in_var", "out_var"}, {"in2_var", "out2_var"}});
|
|
|
|
|
|
|
|
|
|
auto func = GenerateInOutVariableBodyFunction(
|
|
|
|
|
auto func = MakeInOutVariableBodyFunction(
|
|
|
|
|
"func", {{"in_var", "out_var"}, {"in2_var", "out2_var"}});
|
|
|
|
|
mod()->AddFunction(std::move(func));
|
|
|
|
|
|
|
|
|
|
auto foo = GenerateCallerBodyFunction("foo", "func");
|
|
|
|
|
auto foo = MakeCallerBodyFunction("foo", "func");
|
|
|
|
|
foo->add_decoration(
|
|
|
|
|
std::make_unique<ast::StageDecoration>(ast::PipelineStage::kVertex));
|
|
|
|
|
mod()->AddFunction(std::move(foo));
|
|
|
|
@ -497,14 +631,14 @@ TEST_F(InspectorGetEntryPointTest, FunctionMultipleInOutVariables) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(InspectorGetEntryPointTest, MultipleEntryPointsInOutVariables) {
|
|
|
|
|
CreateInOutVariables({{"in_var", "out_var"}, {"in2_var", "out2_var"}});
|
|
|
|
|
AddInOutVariables({{"in_var", "out_var"}, {"in2_var", "out2_var"}});
|
|
|
|
|
|
|
|
|
|
auto foo = GenerateInOutVariableBodyFunction("foo", {{"in_var", "out2_var"}});
|
|
|
|
|
auto foo = MakeInOutVariableBodyFunction("foo", {{"in_var", "out2_var"}});
|
|
|
|
|
foo->add_decoration(
|
|
|
|
|
std::make_unique<ast::StageDecoration>(ast::PipelineStage::kVertex));
|
|
|
|
|
mod()->AddFunction(std::move(foo));
|
|
|
|
|
|
|
|
|
|
auto bar = GenerateInOutVariableBodyFunction("bar", {{"in2_var", "out_var"}});
|
|
|
|
|
auto bar = MakeInOutVariableBodyFunction("bar", {{"in2_var", "out_var"}});
|
|
|
|
|
bar->add_decoration(
|
|
|
|
|
std::make_unique<ast::StageDecoration>(ast::PipelineStage::kCompute));
|
|
|
|
|
mod()->AddFunction(std::move(bar));
|
|
|
|
@ -530,19 +664,18 @@ TEST_F(InspectorGetEntryPointTest, MultipleEntryPointsInOutVariables) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(InspectorGetEntryPointTest, MultipleEntryPointsSharedInOutVariables) {
|
|
|
|
|
CreateInOutVariables({{"in_var", "out_var"}, {"in2_var", "out2_var"}});
|
|
|
|
|
AddInOutVariables({{"in_var", "out_var"}, {"in2_var", "out2_var"}});
|
|
|
|
|
|
|
|
|
|
auto func =
|
|
|
|
|
GenerateInOutVariableBodyFunction("func", {{"in2_var", "out2_var"}});
|
|
|
|
|
auto func = MakeInOutVariableBodyFunction("func", {{"in2_var", "out2_var"}});
|
|
|
|
|
mod()->AddFunction(std::move(func));
|
|
|
|
|
|
|
|
|
|
auto foo = GenerateInOutVariableCallerBodyFunction("foo", "func",
|
|
|
|
|
{{"in_var", "out_var"}});
|
|
|
|
|
auto foo = MakeInOutVariableCallerBodyFunction("foo", "func",
|
|
|
|
|
{{"in_var", "out_var"}});
|
|
|
|
|
foo->add_decoration(
|
|
|
|
|
std::make_unique<ast::StageDecoration>(ast::PipelineStage::kVertex));
|
|
|
|
|
mod()->AddFunction(std::move(foo));
|
|
|
|
|
|
|
|
|
|
auto bar = GenerateCallerBodyFunction("bar", "func");
|
|
|
|
|
auto bar = MakeCallerBodyFunction("bar", "func");
|
|
|
|
|
bar->add_decoration(
|
|
|
|
|
std::make_unique<ast::StageDecoration>(ast::PipelineStage::kCompute));
|
|
|
|
|
mod()->AddFunction(std::move(bar));
|
|
|
|
@ -569,12 +702,12 @@ TEST_F(InspectorGetEntryPointTest, MultipleEntryPointsSharedInOutVariables) {
|
|
|
|
|
EXPECT_EQ("out2_var", result[1].output_variables[0]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(InspectorGetEntryPointTest, BoolConstantIDs) {
|
|
|
|
|
TEST_F(InspectorGetConstantIDsTest, Bool) {
|
|
|
|
|
bool val_true = true;
|
|
|
|
|
bool val_false = false;
|
|
|
|
|
CreateConstantID<bool>("foo", 1, bool_type(), nullptr);
|
|
|
|
|
CreateConstantID<bool>("bar", 20, bool_type(), &val_true);
|
|
|
|
|
CreateConstantID<bool>("baz", 300, bool_type(), &val_false);
|
|
|
|
|
AddConstantID<bool>("foo", 1, bool_type(), nullptr);
|
|
|
|
|
AddConstantID<bool>("bar", 20, bool_type(), &val_true);
|
|
|
|
|
AddConstantID<bool>("baz", 300, bool_type(), &val_false);
|
|
|
|
|
|
|
|
|
|
auto result = inspector()->GetConstantIDs();
|
|
|
|
|
ASSERT_EQ(3u, result.size());
|
|
|
|
@ -591,10 +724,10 @@ TEST_F(InspectorGetEntryPointTest, BoolConstantIDs) {
|
|
|
|
|
EXPECT_FALSE(result[300].AsBool());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(InspectorGetEntryPointTest, U32ConstantIDs) {
|
|
|
|
|
TEST_F(InspectorGetConstantIDsTest, U32) {
|
|
|
|
|
uint32_t val = 42;
|
|
|
|
|
CreateConstantID<uint32_t>("foo", 1, u32_type(), nullptr);
|
|
|
|
|
CreateConstantID<uint32_t>("bar", 20, u32_type(), &val);
|
|
|
|
|
AddConstantID<uint32_t>("foo", 1, u32_type(), nullptr);
|
|
|
|
|
AddConstantID<uint32_t>("bar", 20, u32_type(), &val);
|
|
|
|
|
|
|
|
|
|
auto result = inspector()->GetConstantIDs();
|
|
|
|
|
ASSERT_EQ(2u, result.size());
|
|
|
|
@ -607,12 +740,12 @@ TEST_F(InspectorGetEntryPointTest, U32ConstantIDs) {
|
|
|
|
|
EXPECT_EQ(42u, result[20].AsU32());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(InspectorGetEntryPointTest, I32ConstantIDs) {
|
|
|
|
|
TEST_F(InspectorGetConstantIDsTest, I32) {
|
|
|
|
|
int32_t val_neg = -42;
|
|
|
|
|
int32_t val_pos = 42;
|
|
|
|
|
CreateConstantID<int32_t>("foo", 1, i32_type(), nullptr);
|
|
|
|
|
CreateConstantID<int32_t>("bar", 20, i32_type(), &val_neg);
|
|
|
|
|
CreateConstantID<int32_t>("baz", 300, i32_type(), &val_pos);
|
|
|
|
|
AddConstantID<int32_t>("foo", 1, i32_type(), nullptr);
|
|
|
|
|
AddConstantID<int32_t>("bar", 20, i32_type(), &val_neg);
|
|
|
|
|
AddConstantID<int32_t>("baz", 300, i32_type(), &val_pos);
|
|
|
|
|
|
|
|
|
|
auto result = inspector()->GetConstantIDs();
|
|
|
|
|
ASSERT_EQ(3u, result.size());
|
|
|
|
@ -629,14 +762,14 @@ TEST_F(InspectorGetEntryPointTest, I32ConstantIDs) {
|
|
|
|
|
EXPECT_EQ(42, result[300].AsI32());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(InspectorGetEntryPointTest, FloatConstantIDs) {
|
|
|
|
|
TEST_F(InspectorGetConstantIDsTest, Float) {
|
|
|
|
|
float val_zero = 0.0f;
|
|
|
|
|
float val_neg = -10.0f;
|
|
|
|
|
float val_pos = 15.0f;
|
|
|
|
|
CreateConstantID<float>("foo", 1, f32_type(), nullptr);
|
|
|
|
|
CreateConstantID<float>("bar", 20, f32_type(), &val_zero);
|
|
|
|
|
CreateConstantID<float>("baz", 300, f32_type(), &val_neg);
|
|
|
|
|
CreateConstantID<float>("x", 4000, f32_type(), &val_pos);
|
|
|
|
|
AddConstantID<float>("foo", 1, f32_type(), nullptr);
|
|
|
|
|
AddConstantID<float>("bar", 20, f32_type(), &val_zero);
|
|
|
|
|
AddConstantID<float>("baz", 300, f32_type(), &val_neg);
|
|
|
|
|
AddConstantID<float>("x", 4000, f32_type(), &val_pos);
|
|
|
|
|
|
|
|
|
|
auto result = inspector()->GetConstantIDs();
|
|
|
|
|
ASSERT_EQ(4u, result.size());
|
|
|
|
@ -657,6 +790,200 @@ TEST_F(InspectorGetEntryPointTest, FloatConstantIDs) {
|
|
|
|
|
EXPECT_FLOAT_EQ(15.0, result[4000].AsFloat());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(InspectorGetUniformBufferResourceBindings, MissingEntryPoint) {
|
|
|
|
|
auto result = inspector()->GetUniformBufferResourceBindings("ep_func");
|
|
|
|
|
ASSERT_TRUE(inspector()->has_error());
|
|
|
|
|
std::string error = inspector()->error();
|
|
|
|
|
EXPECT_TRUE(error.find("not found") != std::string::npos);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(InspectorGetUniformBufferResourceBindings, NonEntryPointFunc) {
|
|
|
|
|
auto foo_type = MakeUBOStructType("foo_type", {{i32_type(), 0}});
|
|
|
|
|
AddUBO("foo_ubo", foo_type.get(), 0, 0);
|
|
|
|
|
|
|
|
|
|
auto ubo_func =
|
|
|
|
|
MakeUBOReferenceBodyFunction("ubo_func", "foo_ubo", {{0, i32_type()}});
|
|
|
|
|
mod()->AddFunction(std::move(ubo_func));
|
|
|
|
|
|
|
|
|
|
auto ep_func = MakeCallerBodyFunction("ep_func", "ubo_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()->GetUniformBufferResourceBindings("ubo_func");
|
|
|
|
|
std::string error = inspector()->error();
|
|
|
|
|
EXPECT_TRUE(error.find("not an entry point") != std::string::npos);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(InspectorGetUniformBufferResourceBindings, MissingBlockDeco) {
|
|
|
|
|
ast::StructMemberList members;
|
|
|
|
|
ast::StructMemberDecorationList deco;
|
|
|
|
|
deco.push_back(std::make_unique<ast::StructMemberOffsetDecoration>(0));
|
|
|
|
|
|
|
|
|
|
members.push_back(std::make_unique<ast::StructMember>(
|
|
|
|
|
StructMemberName(members.size(), i32_type()), i32_type(),
|
|
|
|
|
std::move(deco)));
|
|
|
|
|
|
|
|
|
|
ast::StructDecorationList decos;
|
|
|
|
|
|
|
|
|
|
auto str =
|
|
|
|
|
std::make_unique<ast::Struct>(std::move(decos), std::move(members));
|
|
|
|
|
auto foo_type =
|
|
|
|
|
std::make_unique<ast::type::StructType>("foo_type", std::move(str));
|
|
|
|
|
|
|
|
|
|
AddUBO("foo_ubo", foo_type.get(), 0, 0);
|
|
|
|
|
|
|
|
|
|
auto ubo_func =
|
|
|
|
|
MakeUBOReferenceBodyFunction("ubo_func", "foo_ubo", {{0, i32_type()}});
|
|
|
|
|
mod()->AddFunction(std::move(ubo_func));
|
|
|
|
|
|
|
|
|
|
auto ep_func = MakeCallerBodyFunction("ep_func", "ubo_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()->GetUniformBufferResourceBindings("ep_func");
|
|
|
|
|
ASSERT_FALSE(inspector()->has_error());
|
|
|
|
|
EXPECT_EQ(0u, result.size());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(InspectorGetUniformBufferResourceBindings, Simple) {
|
|
|
|
|
auto foo_type = MakeUBOStructType("foo_type", {{i32_type(), 0}});
|
|
|
|
|
AddUBO("foo_ubo", foo_type.get(), 0, 0);
|
|
|
|
|
|
|
|
|
|
auto ubo_func =
|
|
|
|
|
MakeUBOReferenceBodyFunction("ubo_func", "foo_ubo", {{0, i32_type()}});
|
|
|
|
|
mod()->AddFunction(std::move(ubo_func));
|
|
|
|
|
|
|
|
|
|
auto ep_func = MakeCallerBodyFunction("ep_func", "ubo_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()->GetUniformBufferResourceBindings("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(InspectorGetUniformBufferResourceBindings, MultipleMembers) {
|
|
|
|
|
auto foo_type = MakeUBOStructType(
|
|
|
|
|
"foo_type", {{i32_type(), 0}, {u32_type(), 4}, {f32_type(), 8}});
|
|
|
|
|
AddUBO("foo_ubo", foo_type.get(), 0, 0);
|
|
|
|
|
|
|
|
|
|
auto ubo_func = MakeUBOReferenceBodyFunction(
|
|
|
|
|
"ubo_func", "foo_ubo",
|
|
|
|
|
{{0, i32_type()}, {1, u32_type()}, {2, f32_type()}});
|
|
|
|
|
mod()->AddFunction(std::move(ubo_func));
|
|
|
|
|
|
|
|
|
|
auto ep_func = MakeCallerBodyFunction("ep_func", "ubo_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()->GetUniformBufferResourceBindings("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(InspectorGetUniformBufferResourceBindings, MultipleUBOs) {
|
|
|
|
|
auto ubo_type = MakeUBOStructType(
|
|
|
|
|
"ubo_type", {{i32_type(), 0}, {u32_type(), 4}, {f32_type(), 8}});
|
|
|
|
|
AddUBO("ubo_foo", ubo_type.get(), 0, 0);
|
|
|
|
|
AddUBO("ubo_bar", ubo_type.get(), 0, 1);
|
|
|
|
|
AddUBO("ubo_baz", ubo_type.get(), 2, 0);
|
|
|
|
|
|
|
|
|
|
auto AddReferenceFunc = [this](const std::string& func_name,
|
|
|
|
|
const std::string& var_name) {
|
|
|
|
|
auto ubo_func = MakeUBOReferenceBodyFunction(
|
|
|
|
|
func_name, var_name,
|
|
|
|
|
{{0, i32_type()}, {1, u32_type()}, {2, f32_type()}});
|
|
|
|
|
mod()->AddFunction(std::move(ubo_func));
|
|
|
|
|
};
|
|
|
|
|
AddReferenceFunc("ubo_foo_func", "ubo_foo");
|
|
|
|
|
AddReferenceFunc("ubo_bar_func", "ubo_bar");
|
|
|
|
|
AddReferenceFunc("ubo_baz_func", "ubo_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(), "ubo_foo_func");
|
|
|
|
|
AddFuncCall(body.get(), "ubo_bar_func");
|
|
|
|
|
AddFuncCall(body.get(), "ubo_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()->GetUniformBufferResourceBindings("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(InspectorGetUniformBufferResourceBindings, ContainingArray) {
|
|
|
|
|
auto foo_type =
|
|
|
|
|
MakeUBOStructType("foo_type", {{i32_type(), 0}, {u32_array_type(4), 4}});
|
|
|
|
|
AddUBO("foo_ubo", foo_type.get(), 0, 0);
|
|
|
|
|
|
|
|
|
|
auto ubo_func =
|
|
|
|
|
MakeUBOReferenceBodyFunction("ubo_func", "foo_ubo", {{0, i32_type()}});
|
|
|
|
|
mod()->AddFunction(std::move(ubo_func));
|
|
|
|
|
|
|
|
|
|
auto ep_func = MakeCallerBodyFunction("ep_func", "ubo_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()->GetUniformBufferResourceBindings("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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
} // namespace inspector
|
|
|
|
|
} // namespace tint
|
|
|
|
|