mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-21 18:59:21 +00:00
Convert @location to store expression internally.
This CL updates the internal storage for a `@location` attribute to store the `Expression` instead of a raw `uint32_t`. The current parser is updated to generate an `IntLiteralExpression` so we still parse as a `uint32_t` at the moment. Bug: tint:1633 Change-Id: I2b9684754a657b39554160c81727cf1541bee96c Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/101461 Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: Ben Clayton <bclayton@google.com> Commit-Queue: Dan Sinclair <dsinclair@chromium.org>
This commit is contained in:
committed by
Dawn LUCI CQ
parent
145337f309
commit
f9eeed6106
@@ -37,21 +37,32 @@ CanonicalizeEntryPointIO::~CanonicalizeEntryPointIO() = default;
|
||||
|
||||
namespace {
|
||||
|
||||
// Comparison function used to reorder struct members such that all members with
|
||||
// location attributes appear first (ordered by location slot), followed by
|
||||
// those with builtin attributes.
|
||||
bool StructMemberComparator(const ast::StructMember* a, const ast::StructMember* b) {
|
||||
auto* a_loc = ast::GetAttribute<ast::LocationAttribute>(a->attributes);
|
||||
auto* b_loc = ast::GetAttribute<ast::LocationAttribute>(b->attributes);
|
||||
auto* a_blt = ast::GetAttribute<ast::BuiltinAttribute>(a->attributes);
|
||||
auto* b_blt = ast::GetAttribute<ast::BuiltinAttribute>(b->attributes);
|
||||
/// Info for a struct member
|
||||
struct MemberInfo {
|
||||
/// The struct member item
|
||||
const ast::StructMember* member;
|
||||
/// The struct member location if provided
|
||||
std::optional<uint32_t> location;
|
||||
};
|
||||
|
||||
/// Comparison function used to reorder struct members such that all members with
|
||||
/// location attributes appear first (ordered by location slot), followed by
|
||||
/// those with builtin attributes.
|
||||
/// @param a a struct member
|
||||
/// @param b another struct member
|
||||
/// @returns true if a comes before b
|
||||
bool StructMemberComparator(const MemberInfo& a, const MemberInfo& b) {
|
||||
auto* a_loc = ast::GetAttribute<ast::LocationAttribute>(a.member->attributes);
|
||||
auto* b_loc = ast::GetAttribute<ast::LocationAttribute>(b.member->attributes);
|
||||
auto* a_blt = ast::GetAttribute<ast::BuiltinAttribute>(a.member->attributes);
|
||||
auto* b_blt = ast::GetAttribute<ast::BuiltinAttribute>(b.member->attributes);
|
||||
if (a_loc) {
|
||||
if (!b_loc) {
|
||||
// `a` has location attribute and `b` does not: `a` goes first.
|
||||
return true;
|
||||
}
|
||||
// Both have location attributes: smallest goes first.
|
||||
return a_loc->value < b_loc->value;
|
||||
return a.location < b.location;
|
||||
} else {
|
||||
if (b_loc) {
|
||||
// `b` has location attribute and `a` does not: `b` goes first.
|
||||
@@ -88,6 +99,8 @@ struct CanonicalizeEntryPointIO::State {
|
||||
utils::Vector<const ast::Attribute*, 2> attributes;
|
||||
/// The value itself.
|
||||
const ast::Expression* value;
|
||||
/// The output location.
|
||||
std::optional<uint32_t> location;
|
||||
};
|
||||
|
||||
/// The clone context.
|
||||
@@ -101,14 +114,15 @@ struct CanonicalizeEntryPointIO::State {
|
||||
|
||||
/// The new entry point wrapper function's parameters.
|
||||
utils::Vector<const ast::Parameter*, 8> wrapper_ep_parameters;
|
||||
|
||||
/// The members of the wrapper function's struct parameter.
|
||||
utils::Vector<const ast::StructMember*, 8> wrapper_struct_param_members;
|
||||
utils::Vector<MemberInfo, 8> wrapper_struct_param_members;
|
||||
/// The name of the wrapper function's struct parameter.
|
||||
Symbol wrapper_struct_param_name;
|
||||
/// The parameters that will be passed to the original function.
|
||||
utils::Vector<const ast::Expression*, 8> inner_call_parameters;
|
||||
/// The members of the wrapper function's struct return type.
|
||||
utils::Vector<const ast::StructMember*, 8> wrapper_struct_output_members;
|
||||
utils::Vector<MemberInfo, 8> wrapper_struct_output_members;
|
||||
/// The wrapper function output values.
|
||||
utils::Vector<OutputValue, 8> wrapper_output_values;
|
||||
/// The body of the wrapper function.
|
||||
@@ -153,10 +167,12 @@ struct CanonicalizeEntryPointIO::State {
|
||||
/// Add a shader input to the entry point.
|
||||
/// @param name the name of the shader input
|
||||
/// @param type the type of the shader input
|
||||
/// @param location the location if provided
|
||||
/// @param attributes the attributes to apply to the shader input
|
||||
/// @returns an expression which evaluates to the value of the shader input
|
||||
const ast::Expression* AddInput(std::string name,
|
||||
const sem::Type* type,
|
||||
std::optional<uint32_t> location,
|
||||
utils::Vector<const ast::Attribute*, 8> attributes) {
|
||||
auto* ast_type = CreateASTTypeFor(ctx, type);
|
||||
if (cfg.shader_style == ShaderStyle::kSpirv || cfg.shader_style == ShaderStyle::kGlsl) {
|
||||
@@ -214,7 +230,7 @@ struct CanonicalizeEntryPointIO::State {
|
||||
Symbol symbol = input_names.emplace(name).second ? ctx.dst->Symbols().Register(name)
|
||||
: ctx.dst->Symbols().New(name);
|
||||
wrapper_struct_param_members.Push(
|
||||
ctx.dst->Member(symbol, ast_type, std::move(attributes)));
|
||||
{ctx.dst->Member(symbol, ast_type, std::move(attributes)), location});
|
||||
return ctx.dst->MemberAccessor(InputStructSymbol(), symbol);
|
||||
}
|
||||
}
|
||||
@@ -222,10 +238,12 @@ struct CanonicalizeEntryPointIO::State {
|
||||
/// Add a shader output to the entry point.
|
||||
/// @param name the name of the shader output
|
||||
/// @param type the type of the shader output
|
||||
/// @param location the location if provided
|
||||
/// @param attributes the attributes to apply to the shader output
|
||||
/// @param value the value of the shader output
|
||||
void AddOutput(std::string name,
|
||||
const sem::Type* type,
|
||||
std::optional<uint32_t> location,
|
||||
utils::Vector<const ast::Attribute*, 8> attributes,
|
||||
const ast::Expression* value) {
|
||||
// Vulkan requires that integer user-defined vertex outputs are always decorated with
|
||||
@@ -256,6 +274,7 @@ struct CanonicalizeEntryPointIO::State {
|
||||
output.type = CreateASTTypeFor(ctx, type);
|
||||
output.attributes = std::move(attributes);
|
||||
output.value = value;
|
||||
output.location = location;
|
||||
wrapper_output_values.Push(output);
|
||||
}
|
||||
|
||||
@@ -280,7 +299,7 @@ struct CanonicalizeEntryPointIO::State {
|
||||
}
|
||||
|
||||
auto name = ctx.src->Symbols().NameFor(param->Declaration()->symbol);
|
||||
auto* input_expr = AddInput(name, param->Type(), std::move(attributes));
|
||||
auto* input_expr = AddInput(name, param->Type(), param->Location(), std::move(attributes));
|
||||
inner_call_parameters.Push(input_expr);
|
||||
}
|
||||
|
||||
@@ -308,7 +327,8 @@ struct CanonicalizeEntryPointIO::State {
|
||||
auto name = ctx.src->Symbols().NameFor(member_ast->symbol);
|
||||
|
||||
auto attributes = CloneShaderIOAttributes(member_ast->attributes, do_interpolate);
|
||||
auto* input_expr = AddInput(name, member->Type(), std::move(attributes));
|
||||
auto* input_expr =
|
||||
AddInput(name, member->Type(), member->Location(), std::move(attributes));
|
||||
inner_struct_values.Push(input_expr);
|
||||
}
|
||||
|
||||
@@ -337,7 +357,7 @@ struct CanonicalizeEntryPointIO::State {
|
||||
auto attributes = CloneShaderIOAttributes(member_ast->attributes, do_interpolate);
|
||||
|
||||
// Extract the original structure member.
|
||||
AddOutput(name, member->Type(), std::move(attributes),
|
||||
AddOutput(name, member->Type(), member->Location(), std::move(attributes),
|
||||
ctx.dst->MemberAccessor(original_result, name));
|
||||
}
|
||||
} else if (!inner_ret_type->Is<sem::Void>()) {
|
||||
@@ -345,8 +365,8 @@ struct CanonicalizeEntryPointIO::State {
|
||||
CloneShaderIOAttributes(func_ast->return_type_attributes, do_interpolate);
|
||||
|
||||
// Propagate the non-struct return value as is.
|
||||
AddOutput("value", func_sem->ReturnType(), std::move(attributes),
|
||||
ctx.dst->Expr(original_result));
|
||||
AddOutput("value", func_sem->ReturnType(), func_sem->ReturnLocation(),
|
||||
std::move(attributes), ctx.dst->Expr(original_result));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -365,7 +385,7 @@ struct CanonicalizeEntryPointIO::State {
|
||||
|
||||
// No existing sample mask builtin was found, so create a new output value
|
||||
// using the fixed sample mask.
|
||||
AddOutput("fixed_sample_mask", ctx.dst->create<sem::U32>(),
|
||||
AddOutput("fixed_sample_mask", ctx.dst->create<sem::U32>(), std::nullopt,
|
||||
{ctx.dst->Builtin(ast::BuiltinValue::kSampleMask)},
|
||||
ctx.dst->Expr(u32(cfg.fixed_sample_mask)));
|
||||
}
|
||||
@@ -373,7 +393,7 @@ struct CanonicalizeEntryPointIO::State {
|
||||
/// Add a point size builtin to the wrapper function output.
|
||||
void AddVertexPointSize() {
|
||||
// Create a new output value and assign it a literal 1.0 value.
|
||||
AddOutput("vertex_point_size", ctx.dst->create<sem::F32>(),
|
||||
AddOutput("vertex_point_size", ctx.dst->create<sem::F32>(), std::nullopt,
|
||||
{ctx.dst->Builtin(ast::BuiltinValue::kPointSize)}, ctx.dst->Expr(1_f));
|
||||
}
|
||||
|
||||
@@ -392,10 +412,14 @@ struct CanonicalizeEntryPointIO::State {
|
||||
std::sort(wrapper_struct_param_members.begin(), wrapper_struct_param_members.end(),
|
||||
StructMemberComparator);
|
||||
|
||||
utils::Vector<const ast::StructMember*, 8> members;
|
||||
for (auto& mem : wrapper_struct_param_members) {
|
||||
members.Push(mem.member);
|
||||
}
|
||||
|
||||
// Create the new struct type.
|
||||
auto struct_name = ctx.dst->Sym();
|
||||
auto* in_struct =
|
||||
ctx.dst->create<ast::Struct>(struct_name, wrapper_struct_param_members, utils::Empty);
|
||||
auto* in_struct = ctx.dst->create<ast::Struct>(struct_name, members, utils::Empty);
|
||||
ctx.InsertBefore(ctx.src->AST().GlobalDeclarations(), func_ast, in_struct);
|
||||
|
||||
// Create a new function parameter using this struct type.
|
||||
@@ -423,7 +447,8 @@ struct CanonicalizeEntryPointIO::State {
|
||||
member_names.insert(ctx.dst->Symbols().NameFor(name));
|
||||
|
||||
wrapper_struct_output_members.Push(
|
||||
ctx.dst->Member(name, outval.type, std::move(outval.attributes)));
|
||||
{ctx.dst->Member(name, outval.type, std::move(outval.attributes)),
|
||||
outval.location});
|
||||
assignments.Push(
|
||||
ctx.dst->Assign(ctx.dst->MemberAccessor(wrapper_result, name), outval.value));
|
||||
}
|
||||
@@ -432,9 +457,13 @@ struct CanonicalizeEntryPointIO::State {
|
||||
std::sort(wrapper_struct_output_members.begin(), wrapper_struct_output_members.end(),
|
||||
StructMemberComparator);
|
||||
|
||||
utils::Vector<const ast::StructMember*, 8> members;
|
||||
for (auto& mem : wrapper_struct_output_members) {
|
||||
members.Push(mem.member);
|
||||
}
|
||||
|
||||
// Create the new struct type.
|
||||
auto* out_struct = ctx.dst->create<ast::Struct>(
|
||||
ctx.dst->Sym(), wrapper_struct_output_members, utils::Empty);
|
||||
auto* out_struct = ctx.dst->create<ast::Struct>(ctx.dst->Sym(), members, utils::Empty);
|
||||
ctx.InsertBefore(ctx.src->AST().GlobalDeclarations(), func_ast, out_struct);
|
||||
|
||||
// Create the output struct object, assign its members, and return it.
|
||||
|
||||
@@ -692,7 +692,7 @@ struct State {
|
||||
/// @param func the entry point function
|
||||
/// @param param the parameter to process
|
||||
void ProcessNonStructParameter(const ast::Function* func, const ast::Parameter* param) {
|
||||
if (auto* location = ast::GetAttribute<ast::LocationAttribute>(param->attributes)) {
|
||||
if (ast::HasAttribute<ast::LocationAttribute>(param->attributes)) {
|
||||
// Create a function-scope variable to replace the parameter.
|
||||
auto func_var_sym = ctx.Clone(param->symbol);
|
||||
auto* func_var_type = ctx.Clone(param->type);
|
||||
@@ -701,8 +701,15 @@ struct State {
|
||||
// Capture mapping from location to the new variable.
|
||||
LocationInfo info;
|
||||
info.expr = [this, func_var]() { return ctx.dst->Expr(func_var); };
|
||||
info.type = ctx.src->Sem().Get(param)->Type();
|
||||
location_info[location->value] = info;
|
||||
|
||||
auto* sem = ctx.src->Sem().Get<sem::Parameter>(param);
|
||||
info.type = sem->Type();
|
||||
|
||||
if (!sem->Location().has_value()) {
|
||||
TINT_ICE(Transform, ctx.dst->Diagnostics()) << "Location missing value";
|
||||
return;
|
||||
}
|
||||
location_info[sem->Location().value()] = info;
|
||||
} else if (auto* builtin = ast::GetAttribute<ast::BuiltinAttribute>(param->attributes)) {
|
||||
// Check for existing vertex_index and instance_index builtins.
|
||||
if (builtin->builtin == ast::BuiltinValue::kVertexIndex) {
|
||||
@@ -742,12 +749,16 @@ struct State {
|
||||
return ctx.dst->MemberAccessor(param_sym, member_sym);
|
||||
};
|
||||
|
||||
if (auto* location = ast::GetAttribute<ast::LocationAttribute>(member->attributes)) {
|
||||
if (ast::HasAttribute<ast::LocationAttribute>(member->attributes)) {
|
||||
// Capture mapping from location to struct member.
|
||||
LocationInfo info;
|
||||
info.expr = member_expr;
|
||||
info.type = ctx.src->Sem().Get(member)->Type();
|
||||
location_info[location->value] = info;
|
||||
|
||||
auto* sem = ctx.src->Sem().Get(member);
|
||||
info.type = sem->Type();
|
||||
|
||||
TINT_ASSERT(Transform, sem->Location().has_value());
|
||||
location_info[sem->Location().value()] = info;
|
||||
has_locations = true;
|
||||
} else if (auto* builtin =
|
||||
ast::GetAttribute<ast::BuiltinAttribute>(member->attributes)) {
|
||||
|
||||
Reference in New Issue
Block a user