tint/sem: Make BindingPoint optional

Reduces hops from sem -> ast, just to know whether the variable has a binding point.

Change-Id: I5620198e6f08b73d5a0171d95874f1a2dae5d93e
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/127060
Reviewed-by: James Price <jrprice@google.com>
Auto-Submit: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: James Price <jrprice@google.com>
This commit is contained in:
Ben Clayton 2023-04-19 13:24:27 +00:00 committed by Dawn LUCI CQ
parent d1aa1cb29a
commit 5f4847c23e
18 changed files with 99 additions and 93 deletions

View File

@ -36,12 +36,13 @@ writer::ExternalTextureOptions::BindingsMap GenerateExternalTextureBindings(
std::vector<sem::BindingPoint> ext_tex_bps; std::vector<sem::BindingPoint> ext_tex_bps;
for (auto* var : program->AST().GlobalVariables()) { for (auto* var : program->AST().GlobalVariables()) {
if (auto* sem_var = program->Sem().Get(var)->As<sem::GlobalVariable>()) { if (auto* sem_var = program->Sem().Get(var)->As<sem::GlobalVariable>()) {
auto bp = sem_var->BindingPoint(); if (auto bp = sem_var->BindingPoint()) {
auto& n = group_to_next_binding_number[bp.group]; auto& n = group_to_next_binding_number[bp->group];
n = std::max(n, bp.binding + 1); n = std::max(n, bp->binding + 1);
if (sem_var->Type()->UnwrapRef()->Is<type::ExternalTexture>()) { if (sem_var->Type()->UnwrapRef()->Is<type::ExternalTexture>()) {
ext_tex_bps.emplace_back(bp); ext_tex_bps.emplace_back(*bp);
}
} }
} }
} }

View File

@ -271,12 +271,13 @@ int CommonFuzzer::Run(const uint8_t* data, size_t size) {
std::vector<sem::BindingPoint> ext_tex_bps; std::vector<sem::BindingPoint> ext_tex_bps;
for (auto* var : program.AST().GlobalVariables()) { for (auto* var : program.AST().GlobalVariables()) {
if (auto* sem_var = program.Sem().Get(var)->As<sem::GlobalVariable>()) { if (auto* sem_var = program.Sem().Get(var)->As<sem::GlobalVariable>()) {
auto bp = sem_var->BindingPoint(); if (auto bp = sem_var->BindingPoint()) {
auto& n = group_to_next_binding_number[bp.group]; auto& n = group_to_next_binding_number[bp->group];
n = std::max(n, bp.binding + 1); n = std::max(n, bp->binding + 1);
if (sem_var->Type()->UnwrapRef()->Is<type::ExternalTexture>()) { if (sem_var->Type()->UnwrapRef()->Is<type::ExternalTexture>()) {
ext_tex_bps.emplace_back(bp); ext_tex_bps.emplace_back(*bp);
}
} }
} }
} }

View File

@ -531,8 +531,8 @@ std::vector<SamplerTexturePair> Inspector::GetSamplerTextureUses(
auto* texture = pair.first->As<sem::GlobalVariable>(); auto* texture = pair.first->As<sem::GlobalVariable>();
auto* sampler = pair.second ? pair.second->As<sem::GlobalVariable>() : nullptr; auto* sampler = pair.second ? pair.second->As<sem::GlobalVariable>() : nullptr;
SamplerTexturePair new_pair; SamplerTexturePair new_pair;
new_pair.sampler_binding_point = sampler ? sampler->BindingPoint() : placeholder; new_pair.sampler_binding_point = sampler ? *sampler->BindingPoint() : placeholder;
new_pair.texture_binding_point = texture->BindingPoint(); new_pair.texture_binding_point = *texture->BindingPoint();
new_pairs.push_back(new_pair); new_pairs.push_back(new_pair);
} }
return new_pairs; return new_pairs;
@ -834,8 +834,8 @@ void Inspector::GenerateSamplerTargets() {
GetOriginatingResources(std::array<const ast::Expression*, 2>{t, s}, GetOriginatingResources(std::array<const ast::Expression*, 2>{t, s},
[&](std::array<const sem::GlobalVariable*, 2> globals) { [&](std::array<const sem::GlobalVariable*, 2> globals) {
auto texture_binding_point = globals[0]->BindingPoint(); auto texture_binding_point = *globals[0]->BindingPoint();
auto sampler_binding_point = globals[1]->BindingPoint(); auto sampler_binding_point = *globals[1]->BindingPoint();
for (auto* entry_point : entry_points) { for (auto* entry_point : entry_points) {
const auto& ep_name = const auto& ep_name =

View File

@ -276,7 +276,7 @@ sem::Variable* Resolver::Let(const ast::Let* v, bool is_global) {
sem = builder_->create<sem::GlobalVariable>( sem = builder_->create<sem::GlobalVariable>(
v, ty, sem::EvaluationStage::kRuntime, builtin::AddressSpace::kUndefined, v, ty, sem::EvaluationStage::kRuntime, builtin::AddressSpace::kUndefined,
builtin::Access::kUndefined, builtin::Access::kUndefined,
/* constant_value */ nullptr, sem::BindingPoint{}, std::nullopt); /* constant_value */ nullptr, std::nullopt, std::nullopt);
} else { } else {
sem = builder_->create<sem::LocalVariable>(v, ty, sem::EvaluationStage::kRuntime, sem = builder_->create<sem::LocalVariable>(v, ty, sem::EvaluationStage::kRuntime,
builtin::AddressSpace::kUndefined, builtin::AddressSpace::kUndefined,
@ -336,7 +336,7 @@ sem::Variable* Resolver::Override(const ast::Override* v) {
auto* sem = builder_->create<sem::GlobalVariable>( auto* sem = builder_->create<sem::GlobalVariable>(
v, ty, sem::EvaluationStage::kOverride, builtin::AddressSpace::kUndefined, v, ty, sem::EvaluationStage::kOverride, builtin::AddressSpace::kUndefined,
builtin::Access::kUndefined, builtin::Access::kUndefined,
/* constant_value */ nullptr, sem::BindingPoint{}, std::nullopt); /* constant_value */ nullptr, std::nullopt, std::nullopt);
sem->SetInitializer(rhs); sem->SetInitializer(rhs);
if (auto* id_attr = ast::GetAttribute<ast::IdAttribute>(v->attributes)) { if (auto* id_attr = ast::GetAttribute<ast::IdAttribute>(v->attributes)) {
@ -430,7 +430,7 @@ sem::Variable* Resolver::Const(const ast::Const* c, bool is_global) {
auto* sem = is_global auto* sem = is_global
? static_cast<sem::Variable*>(builder_->create<sem::GlobalVariable>( ? static_cast<sem::Variable*>(builder_->create<sem::GlobalVariable>(
c, ty, sem::EvaluationStage::kConstant, builtin::AddressSpace::kUndefined, c, ty, sem::EvaluationStage::kConstant, builtin::AddressSpace::kUndefined,
builtin::Access::kUndefined, value, sem::BindingPoint{}, std::nullopt)) builtin::Access::kUndefined, value, std::nullopt, std::nullopt))
: static_cast<sem::Variable*>(builder_->create<sem::LocalVariable>( : static_cast<sem::Variable*>(builder_->create<sem::LocalVariable>(
c, ty, sem::EvaluationStage::kConstant, builtin::AddressSpace::kUndefined, c, ty, sem::EvaluationStage::kConstant, builtin::AddressSpace::kUndefined,
builtin::Access::kUndefined, current_statement_, value)); builtin::Access::kUndefined, current_statement_, value));
@ -528,7 +528,7 @@ sem::Variable* Resolver::Var(const ast::Var* var, bool is_global) {
sem::Variable* sem = nullptr; sem::Variable* sem = nullptr;
if (is_global) { if (is_global) {
sem::BindingPoint binding_point; std::optional<sem::BindingPoint> binding_point;
if (var->HasBindingPoint()) { if (var->HasBindingPoint()) {
uint32_t binding = 0; uint32_t binding = 0;
{ {
@ -640,8 +640,9 @@ sem::Parameter* Resolver::Parameter(const ast::Parameter* param, uint32_t index)
} }
} }
sem::BindingPoint binding_point; std::optional<sem::BindingPoint> binding_point;
if (param->HasBindingPoint()) { if (param->HasBindingPoint()) {
binding_point = sem::BindingPoint{};
{ {
ExprEvalStageConstraint constraint{sem::EvaluationStage::kConstant, "@binding value"}; ExprEvalStageConstraint constraint{sem::EvaluationStage::kConstant, "@binding value"};
TINT_SCOPED_ASSIGNMENT(expr_eval_stage_constraint_, constraint); TINT_SCOPED_ASSIGNMENT(expr_eval_stage_constraint_, constraint);
@ -651,7 +652,7 @@ sem::Parameter* Resolver::Parameter(const ast::Parameter* param, uint32_t index)
if (!materialized) { if (!materialized) {
return nullptr; return nullptr;
} }
binding_point.binding = materialized->ConstantValue()->ValueAs<u32>(); binding_point->binding = materialized->ConstantValue()->ValueAs<u32>();
} }
{ {
ExprEvalStageConstraint constraint{sem::EvaluationStage::kConstant, "@group value"}; ExprEvalStageConstraint constraint{sem::EvaluationStage::kConstant, "@group value"};
@ -662,7 +663,7 @@ sem::Parameter* Resolver::Parameter(const ast::Parameter* param, uint32_t index)
if (!materialized) { if (!materialized) {
return nullptr; return nullptr;
} }
binding_point.group = materialized->ConstantValue()->ValueAs<u32>(); binding_point->group = materialized->ConstantValue()->ValueAs<u32>();
} }
} }

View File

@ -1346,11 +1346,14 @@ bool Validator::EntryPoint(const sem::Function* func, ast::PipelineStage stage)
utils::Hashmap<sem::BindingPoint, const ast::Variable*, 8> binding_points; utils::Hashmap<sem::BindingPoint, const ast::Variable*, 8> binding_points;
for (auto* global : func->TransitivelyReferencedGlobals()) { for (auto* global : func->TransitivelyReferencedGlobals()) {
auto* var_decl = global->Declaration()->As<ast::Var>(); auto* var_decl = global->Declaration()->As<ast::Var>();
if (!var_decl || !var_decl->HasBindingPoint()) { if (!var_decl) {
continue; continue;
} }
auto bp = global->BindingPoint(); auto bp = global->BindingPoint();
if (auto added = binding_points.Add(bp, var_decl); if (!bp) {
continue;
}
if (auto added = binding_points.Add(*bp, var_decl);
!added && !added &&
IsValidationEnabled(decl->attributes, IsValidationEnabled(decl->attributes,
ast::DisabledValidation::kBindingPointCollision) && ast::DisabledValidation::kBindingPointCollision) &&
@ -1364,7 +1367,7 @@ bool Validator::EntryPoint(const sem::Function* func, ast::PipelineStage stage)
AddError( AddError(
"entry point '" + func_name + "entry point '" + func_name +
"' references multiple variables that use the same resource binding @group(" + "' references multiple variables that use the same resource binding @group(" +
std::to_string(bp.group) + "), @binding(" + std::to_string(bp.binding) + ")", std::to_string(bp->group) + "), @binding(" + std::to_string(bp->binding) + ")",
var_decl->source); var_decl->source);
AddNote("first resource binding usage declared here", (*added.value)->source); AddNote("first resource binding usage declared here", (*added.value)->source);
return false; return false;

View File

@ -60,8 +60,8 @@ Function::VariableBindings Function::TransitivelyReferencedUniformVariables() co
continue; continue;
} }
if (global->Declaration()->HasBindingPoint()) { if (auto bp = global->BindingPoint()) {
ret.push_back({global, global->BindingPoint()}); ret.push_back({global, *bp});
} }
} }
return ret; return ret;
@ -75,8 +75,8 @@ Function::VariableBindings Function::TransitivelyReferencedStorageBufferVariable
continue; continue;
} }
if (global->Declaration()->HasBindingPoint()) { if (auto bp = global->BindingPoint()) {
ret.push_back({global, global->BindingPoint()}); ret.push_back({global, *bp});
} }
} }
return ret; return ret;
@ -119,8 +119,8 @@ Function::VariableBindings Function::TransitivelyReferencedVariablesOfType(
for (auto* global : TransitivelyReferencedGlobals()) { for (auto* global : TransitivelyReferencedGlobals()) {
auto* unwrapped_type = global->Type()->UnwrapRef(); auto* unwrapped_type = global->Type()->UnwrapRef();
if (unwrapped_type->TypeInfo().Is(type)) { if (unwrapped_type->TypeInfo().Is(type)) {
if (global->Declaration()->HasBindingPoint()) { if (auto bp = global->BindingPoint()) {
ret.push_back({global, global->BindingPoint()}); ret.push_back({global, *bp});
} }
} }
} }
@ -147,8 +147,8 @@ Function::VariableBindings Function::TransitivelyReferencedSamplerVariablesImpl(
continue; continue;
} }
if (global->Declaration()->HasBindingPoint()) { if (auto bp = global->BindingPoint()) {
ret.push_back({global, global->BindingPoint()}); ret.push_back({global, *bp});
} }
} }
return ret; return ret;
@ -172,8 +172,8 @@ Function::VariableBindings Function::TransitivelyReferencedSampledTextureVariabl
continue; continue;
} }
if (global->Declaration()->HasBindingPoint()) { if (auto bp = global->BindingPoint()) {
ret.push_back({global, global->BindingPoint()}); ret.push_back({global, *bp});
} }
} }

View File

@ -61,7 +61,7 @@ GlobalVariable::GlobalVariable(const ast::Variable* declaration,
builtin::AddressSpace address_space, builtin::AddressSpace address_space,
builtin::Access access, builtin::Access access,
const constant::Value* constant_value, const constant::Value* constant_value,
sem::BindingPoint binding_point, std::optional<sem::BindingPoint> binding_point,
std::optional<uint32_t> location) std::optional<uint32_t> location)
: Base(declaration, type, stage, address_space, access, constant_value), : Base(declaration, type, stage, address_space, access, constant_value),
binding_point_(binding_point), binding_point_(binding_point),
@ -75,7 +75,7 @@ Parameter::Parameter(const ast::Parameter* declaration,
builtin::AddressSpace address_space, builtin::AddressSpace address_space,
builtin::Access access, builtin::Access access,
const ParameterUsage usage /* = ParameterUsage::kNone */, const ParameterUsage usage /* = ParameterUsage::kNone */,
sem::BindingPoint binding_point /* = {} */, std::optional<sem::BindingPoint> binding_point /* = {} */,
std::optional<uint32_t> location /* = std::nullopt */) std::optional<uint32_t> location /* = std::nullopt */)
: Base(declaration, type, EvaluationStage::kRuntime, address_space, access, nullptr), : Base(declaration, type, EvaluationStage::kRuntime, address_space, access, nullptr),
index_(index), index_(index),

View File

@ -165,14 +165,14 @@ class GlobalVariable final : public Castable<GlobalVariable, Variable> {
builtin::AddressSpace address_space, builtin::AddressSpace address_space,
builtin::Access access, builtin::Access access,
const constant::Value* constant_value, const constant::Value* constant_value,
sem::BindingPoint binding_point = {}, std::optional<sem::BindingPoint> binding_point = std::nullopt,
std::optional<uint32_t> location = std::nullopt); std::optional<uint32_t> location = std::nullopt);
/// Destructor /// Destructor
~GlobalVariable() override; ~GlobalVariable() override;
/// @returns the resource binding point for the variable /// @returns the resource binding point for the variable
sem::BindingPoint BindingPoint() const { return binding_point_; } std::optional<sem::BindingPoint> BindingPoint() const { return binding_point_; }
/// @param id the constant identifier to assign to this variable /// @param id the constant identifier to assign to this variable
void SetOverrideId(OverrideId id) { override_id_ = id; } void SetOverrideId(OverrideId id) { override_id_ = id; }
@ -184,7 +184,7 @@ class GlobalVariable final : public Castable<GlobalVariable, Variable> {
std::optional<uint32_t> Location() const { return location_; } std::optional<uint32_t> Location() const { return location_; }
private: private:
const sem::BindingPoint binding_point_; const std::optional<sem::BindingPoint> binding_point_;
tint::OverrideId override_id_; tint::OverrideId override_id_;
std::optional<uint32_t> location_; std::optional<uint32_t> location_;
@ -208,7 +208,7 @@ class Parameter final : public Castable<Parameter, Variable> {
builtin::AddressSpace address_space, builtin::AddressSpace address_space,
builtin::Access access, builtin::Access access,
const ParameterUsage usage = ParameterUsage::kNone, const ParameterUsage usage = ParameterUsage::kNone,
sem::BindingPoint binding_point = {}, std::optional<sem::BindingPoint> binding_point = {},
std::optional<uint32_t> location = std::nullopt); std::optional<uint32_t> location = std::nullopt);
/// Destructor /// Destructor
@ -239,7 +239,7 @@ class Parameter final : public Castable<Parameter, Variable> {
void SetShadows(const CastableBase* shadows) { shadows_ = shadows; } void SetShadows(const CastableBase* shadows) { shadows_ = shadows; }
/// @returns the resource binding point for the parameter /// @returns the resource binding point for the parameter
sem::BindingPoint BindingPoint() const { return binding_point_; } std::optional<sem::BindingPoint> BindingPoint() const { return binding_point_; }
/// @returns the location value for the parameter, if set /// @returns the location value for the parameter, if set
std::optional<uint32_t> Location() const { return location_; } std::optional<uint32_t> Location() const { return location_; }
@ -249,7 +249,7 @@ class Parameter final : public Castable<Parameter, Variable> {
const ParameterUsage usage_; const ParameterUsage usage_;
CallTarget const* owner_ = nullptr; CallTarget const* owner_ = nullptr;
const CastableBase* shadows_ = nullptr; const CastableBase* shadows_ = nullptr;
const sem::BindingPoint binding_point_; const std::optional<sem::BindingPoint> binding_point_;
const std::optional<uint32_t> location_; const std::optional<uint32_t> location_;
}; };

View File

@ -82,14 +82,15 @@ struct ArrayLengthFromUniform::State {
IterateArrayLengthOnStorageVar([&](const ast::CallExpression*, const sem::VariableUser*, IterateArrayLengthOnStorageVar([&](const ast::CallExpression*, const sem::VariableUser*,
const sem::GlobalVariable* var) { const sem::GlobalVariable* var) {
auto binding = var->BindingPoint(); if (auto binding = var->BindingPoint()) {
auto idx_itr = cfg->bindpoint_to_size_index.find(binding); auto idx_itr = cfg->bindpoint_to_size_index.find(*binding);
if (idx_itr == cfg->bindpoint_to_size_index.end()) { if (idx_itr == cfg->bindpoint_to_size_index.end()) {
return; return;
} }
if (idx_itr->second > max_buffer_size_index) { if (idx_itr->second > max_buffer_size_index) {
max_buffer_size_index = idx_itr->second; max_buffer_size_index = idx_itr->second;
} }
}
}); });
// Get (or create, on first call) the uniform buffer that will receive the // Get (or create, on first call) the uniform buffer that will receive the
@ -120,7 +121,10 @@ struct ArrayLengthFromUniform::State {
const sem::VariableUser* storage_buffer_sem, const sem::VariableUser* storage_buffer_sem,
const sem::GlobalVariable* var) { const sem::GlobalVariable* var) {
auto binding = var->BindingPoint(); auto binding = var->BindingPoint();
auto idx_itr = cfg->bindpoint_to_size_index.find(binding); if (!binding) {
return;
}
auto idx_itr = cfg->bindpoint_to_size_index.find(*binding);
if (idx_itr == cfg->bindpoint_to_size_index.end()) { if (idx_itr == cfg->bindpoint_to_size_index.end()) {
return; return;
} }

View File

@ -71,10 +71,8 @@ Transform::ApplyResult BindingRemapper::Apply(const Program* src,
auto* func = src->Sem().Get(func_ast); auto* func = src->Sem().Get(func_ast);
std::unordered_map<sem::BindingPoint, int> binding_point_counts; std::unordered_map<sem::BindingPoint, int> binding_point_counts;
for (auto* global : func->TransitivelyReferencedGlobals()) { for (auto* global : func->TransitivelyReferencedGlobals()) {
if (global->Declaration()->HasBindingPoint()) { if (auto from = global->BindingPoint()) {
BindingPoint from = global->BindingPoint(); auto bp_it = remappings->binding_points.find(*from);
auto bp_it = remappings->binding_points.find(from);
if (bp_it != remappings->binding_points.end()) { if (bp_it != remappings->binding_points.end()) {
// Remapped // Remapped
BindingPoint to = bp_it->second; BindingPoint to = bp_it->second;
@ -83,8 +81,8 @@ Transform::ApplyResult BindingRemapper::Apply(const Program* src,
} }
} else { } else {
// No remapping // No remapping
if (binding_point_counts[from]++) { if (binding_point_counts[*from]++) {
add_collision_attr.emplace(from); add_collision_attr.emplace(*from);
} }
} }
} }
@ -97,7 +95,7 @@ Transform::ApplyResult BindingRemapper::Apply(const Program* src,
auto* global_sem = src->Sem().Get<sem::GlobalVariable>(var); auto* global_sem = src->Sem().Get<sem::GlobalVariable>(var);
// The original binding point // The original binding point
BindingPoint from = global_sem->BindingPoint(); BindingPoint from = *global_sem->BindingPoint();
// The binding point after remapping // The binding point after remapping
BindingPoint bp = from; BindingPoint bp = from;

View File

@ -107,9 +107,9 @@ struct CombineSamplers::State {
const sem::Variable* sampler_var, const sem::Variable* sampler_var,
std::string name) { std::string name) {
SamplerTexturePair bp_pair; SamplerTexturePair bp_pair;
bp_pair.texture_binding_point = texture_var->As<sem::GlobalVariable>()->BindingPoint(); bp_pair.texture_binding_point = *texture_var->As<sem::GlobalVariable>()->BindingPoint();
bp_pair.sampler_binding_point = sampler_var bp_pair.sampler_binding_point =
? sampler_var->As<sem::GlobalVariable>()->BindingPoint() sampler_var ? *sampler_var->As<sem::GlobalVariable>()->BindingPoint()
: binding_info->placeholder_binding_point; : binding_info->placeholder_binding_point;
auto it = binding_info->binding_map.find(bp_pair); auto it = binding_info->binding_map.find(bp_pair);
if (it != binding_info->binding_map.end()) { if (it != binding_info->binding_map.end()) {
@ -161,9 +161,8 @@ struct CombineSamplers::State {
if (tint::IsAnyOf<type::Texture, type::Sampler>(type) && if (tint::IsAnyOf<type::Texture, type::Sampler>(type) &&
!type->Is<type::StorageTexture>()) { !type->Is<type::StorageTexture>()) {
ctx.Remove(ctx.src->AST().GlobalDeclarations(), global); ctx.Remove(ctx.src->AST().GlobalDeclarations(), global);
} else if (global->HasBindingPoint()) { } else if (auto binding_point = global_sem->BindingPoint()) {
auto binding_point = global_sem->BindingPoint(); if (binding_point->group == 0 && binding_point->binding == 0) {
if (binding_point.group == 0 && binding_point.binding == 0) {
auto* attribute = auto* attribute =
ctx.dst->Disable(ast::DisabledValidation::kBindingPointCollision); ctx.dst->Disable(ast::DisabledValidation::kBindingPointCollision);
ctx.InsertFront(global->attributes, attribute); ctx.InsertFront(global->attributes, attribute);

View File

@ -115,7 +115,7 @@ struct MultiplanarExternalTexture::State {
// The binding points for the newly introduced bindings must have been provided to this // The binding points for the newly introduced bindings must have been provided to this
// transform. We fetch the new binding points by providing the original texture_external // transform. We fetch the new binding points by providing the original texture_external
// binding points into the passed map. // binding points into the passed map.
sem::BindingPoint bp = sem_var->BindingPoint(); sem::BindingPoint bp = *sem_var->BindingPoint();
BindingsMap::const_iterator it = new_binding_points->bindings_map.find(bp); BindingsMap::const_iterator it = new_binding_points->bindings_map.find(bp);
if (it == new_binding_points->bindings_map.end()) { if (it == new_binding_points->bindings_map.end()) {

View File

@ -148,11 +148,10 @@ Transform::ApplyResult NumWorkgroupsFromUniform::Apply(const Program* src,
group = 0; group = 0;
for (auto* global : src->AST().GlobalVariables()) { for (auto* global : src->AST().GlobalVariables()) {
if (global->HasBindingPoint()) {
auto* global_sem = src->Sem().Get<sem::GlobalVariable>(global); auto* global_sem = src->Sem().Get<sem::GlobalVariable>(global);
auto binding_point = global_sem->BindingPoint(); if (auto bp = global_sem->BindingPoint()) {
if (binding_point.group >= group) { if (bp->group >= group) {
group = binding_point.group + 1; group = bp->group + 1;
} }
} }
} }

View File

@ -67,18 +67,18 @@ TEST_F(FlattenBindingsTest, NotFlat_SingleNamespace) {
auto* sem = flattened->Sem().Get<sem::GlobalVariable>(vars[0]); auto* sem = flattened->Sem().Get<sem::GlobalVariable>(vars[0]);
ASSERT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
EXPECT_EQ(sem->BindingPoint().group, 0u); EXPECT_EQ(sem->BindingPoint()->group, 0u);
EXPECT_EQ(sem->BindingPoint().binding, 0u); EXPECT_EQ(sem->BindingPoint()->binding, 0u);
sem = flattened->Sem().Get<sem::GlobalVariable>(vars[1]); sem = flattened->Sem().Get<sem::GlobalVariable>(vars[1]);
ASSERT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
EXPECT_EQ(sem->BindingPoint().group, 0u); EXPECT_EQ(sem->BindingPoint()->group, 0u);
EXPECT_EQ(sem->BindingPoint().binding, 1u); EXPECT_EQ(sem->BindingPoint()->binding, 1u);
sem = flattened->Sem().Get<sem::GlobalVariable>(vars[2]); sem = flattened->Sem().Get<sem::GlobalVariable>(vars[2]);
ASSERT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
EXPECT_EQ(sem->BindingPoint().group, 0u); EXPECT_EQ(sem->BindingPoint()->group, 0u);
EXPECT_EQ(sem->BindingPoint().binding, 2u); EXPECT_EQ(sem->BindingPoint()->binding, 2u);
} }
TEST_F(FlattenBindingsTest, NotFlat_MultipleNamespaces) { TEST_F(FlattenBindingsTest, NotFlat_MultipleNamespaces) {
@ -131,20 +131,20 @@ TEST_F(FlattenBindingsTest, NotFlat_MultipleNamespaces) {
for (size_t i = 0; i < num_buffers; ++i) { for (size_t i = 0; i < num_buffers; ++i) {
auto* sem = flattened->Sem().Get<sem::GlobalVariable>(vars[i]); auto* sem = flattened->Sem().Get<sem::GlobalVariable>(vars[i]);
ASSERT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
EXPECT_EQ(sem->BindingPoint().group, 0u); EXPECT_EQ(sem->BindingPoint()->group, 0u);
EXPECT_EQ(sem->BindingPoint().binding, i); EXPECT_EQ(sem->BindingPoint()->binding, i);
} }
for (size_t i = 0; i < num_samplers; ++i) { for (size_t i = 0; i < num_samplers; ++i) {
auto* sem = flattened->Sem().Get<sem::GlobalVariable>(vars[i + num_buffers]); auto* sem = flattened->Sem().Get<sem::GlobalVariable>(vars[i + num_buffers]);
ASSERT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
EXPECT_EQ(sem->BindingPoint().group, 0u); EXPECT_EQ(sem->BindingPoint()->group, 0u);
EXPECT_EQ(sem->BindingPoint().binding, i); EXPECT_EQ(sem->BindingPoint()->binding, i);
} }
for (size_t i = 0; i < num_textures; ++i) { for (size_t i = 0; i < num_textures; ++i) {
auto* sem = flattened->Sem().Get<sem::GlobalVariable>(vars[i + num_buffers + num_samplers]); auto* sem = flattened->Sem().Get<sem::GlobalVariable>(vars[i + num_buffers + num_samplers]);
ASSERT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
EXPECT_EQ(sem->BindingPoint().group, 0u); EXPECT_EQ(sem->BindingPoint()->group, 0u);
EXPECT_EQ(sem->BindingPoint().binding, i); EXPECT_EQ(sem->BindingPoint()->binding, i);
} }
} }

View File

@ -2031,7 +2031,7 @@ bool GeneratorImpl::EmitUniformVariable(const ast::Var* var, const sem::Variable
TINT_ICE(Writer, builder_.Diagnostics()) << "storage variable must be of struct type"; TINT_ICE(Writer, builder_.Diagnostics()) << "storage variable must be of struct type";
return false; return false;
} }
auto bp = sem->As<sem::GlobalVariable>()->BindingPoint(); auto bp = *sem->As<sem::GlobalVariable>()->BindingPoint();
{ {
auto out = line(); auto out = line();
out << "layout(binding = " << bp.binding << ", std140"; out << "layout(binding = " << bp.binding << ", std140";
@ -2052,7 +2052,7 @@ bool GeneratorImpl::EmitStorageVariable(const ast::Var* var, const sem::Variable
TINT_ICE(Writer, builder_.Diagnostics()) << "storage variable must be of struct type"; TINT_ICE(Writer, builder_.Diagnostics()) << "storage variable must be of struct type";
return false; return false;
} }
auto bp = sem->As<sem::GlobalVariable>()->BindingPoint(); auto bp = *sem->As<sem::GlobalVariable>()->BindingPoint();
line() << "layout(binding = " << bp.binding << ", std430) buffer " line() << "layout(binding = " << bp.binding << ", std430) buffer "
<< UniqueIdentifier(StructName(str) + "_ssbo") << " {"; << UniqueIdentifier(StructName(str) + "_ssbo") << " {";
EmitStructMembers(current_buffer_, str); EmitStructMembers(current_buffer_, str);

View File

@ -3066,7 +3066,7 @@ bool GeneratorImpl::EmitGlobalVariable(const ast::Variable* global) {
} }
bool GeneratorImpl::EmitUniformVariable(const ast::Var* var, const sem::Variable* sem) { bool GeneratorImpl::EmitUniformVariable(const ast::Var* var, const sem::Variable* sem) {
auto binding_point = sem->As<sem::GlobalVariable>()->BindingPoint(); auto binding_point = *sem->As<sem::GlobalVariable>()->BindingPoint();
auto* type = sem->Type()->UnwrapRef(); auto* type = sem->Type()->UnwrapRef();
auto name = var->name->symbol.Name(); auto name = var->name->symbol.Name();
line() << "cbuffer cbuffer_" << name << RegisterAndSpace('b', binding_point) << " {"; line() << "cbuffer cbuffer_" << name << RegisterAndSpace('b', binding_point) << " {";
@ -3095,7 +3095,7 @@ bool GeneratorImpl::EmitStorageVariable(const ast::Var* var, const sem::Variable
auto* global_sem = sem->As<sem::GlobalVariable>(); auto* global_sem = sem->As<sem::GlobalVariable>();
out << RegisterAndSpace(sem->Access() == builtin::Access::kRead ? 't' : 'u', out << RegisterAndSpace(sem->Access() == builtin::Access::kRead ? 't' : 'u',
global_sem->BindingPoint()) *global_sem->BindingPoint())
<< ";"; << ";";
return true; return true;
@ -3124,14 +3124,14 @@ bool GeneratorImpl::EmitHandleVariable(const ast::Var* var, const sem::Variable*
if (register_space) { if (register_space) {
auto bp = sem->As<sem::GlobalVariable>()->BindingPoint(); auto bp = sem->As<sem::GlobalVariable>()->BindingPoint();
out << " : register(" << register_space << bp.binding; out << " : register(" << register_space << bp->binding;
// Omit the space if it's 0, as it's the default. // Omit the space if it's 0, as it's the default.
// SM 5.0 doesn't support spaces, so we don't emit them if group is 0 for better // SM 5.0 doesn't support spaces, so we don't emit them if group is 0 for better
// compatibility. // compatibility.
if (bp.group == 0) { if (bp->group == 0) {
out << ")"; out << ")";
} else { } else {
out << ", space" << bp.group << ")"; out << ", space" << bp->group << ")";
} }
} }

View File

@ -1996,12 +1996,12 @@ bool GeneratorImpl::EmitEntryPointFunction(const ast::Function* func) {
} }
auto* param_sem = program_->Sem().Get<sem::Parameter>(param); auto* param_sem = program_->Sem().Get<sem::Parameter>(param);
auto bp = param_sem->BindingPoint(); auto bp = param_sem->BindingPoint();
if (TINT_UNLIKELY(bp.group != 0)) { if (TINT_UNLIKELY(bp->group != 0)) {
TINT_ICE(Writer, diagnostics_) << "encountered non-zero resource group index (use " TINT_ICE(Writer, diagnostics_) << "encountered non-zero resource group index (use "
"BindingRemapper to fix)"; "BindingRemapper to fix)";
return kInvalidBindingIndex; return kInvalidBindingIndex;
} }
return bp.binding; return bp->binding;
}; };
{ {

View File

@ -867,14 +867,14 @@ bool Builder::GenerateGlobalVariable(const ast::Variable* v) {
[&](const ast::BindingAttribute*) { [&](const ast::BindingAttribute*) {
auto bp = sem->BindingPoint(); auto bp = sem->BindingPoint();
push_annot(spv::Op::OpDecorate, {Operand(var_id), U32Operand(SpvDecorationBinding), push_annot(spv::Op::OpDecorate, {Operand(var_id), U32Operand(SpvDecorationBinding),
Operand(bp.binding)}); Operand(bp->binding)});
return true; return true;
}, },
[&](const ast::GroupAttribute*) { [&](const ast::GroupAttribute*) {
auto bp = sem->BindingPoint(); auto bp = sem->BindingPoint();
push_annot( push_annot(
spv::Op::OpDecorate, spv::Op::OpDecorate,
{Operand(var_id), U32Operand(SpvDecorationDescriptorSet), Operand(bp.group)}); {Operand(var_id), U32Operand(SpvDecorationDescriptorSet), Operand(bp->group)});
return true; return true;
}, },
[&](const ast::IdAttribute*) { [&](const ast::IdAttribute*) {