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;
for (auto* var : program->AST().GlobalVariables()) {
if (auto* sem_var = program->Sem().Get(var)->As<sem::GlobalVariable>()) {
auto bp = sem_var->BindingPoint();
auto& n = group_to_next_binding_number[bp.group];
n = std::max(n, bp.binding + 1);
if (auto bp = sem_var->BindingPoint()) {
auto& n = group_to_next_binding_number[bp->group];
n = std::max(n, bp->binding + 1);
if (sem_var->Type()->UnwrapRef()->Is<type::ExternalTexture>()) {
ext_tex_bps.emplace_back(bp);
if (sem_var->Type()->UnwrapRef()->Is<type::ExternalTexture>()) {
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;
for (auto* var : program.AST().GlobalVariables()) {
if (auto* sem_var = program.Sem().Get(var)->As<sem::GlobalVariable>()) {
auto bp = sem_var->BindingPoint();
auto& n = group_to_next_binding_number[bp.group];
n = std::max(n, bp.binding + 1);
if (auto bp = sem_var->BindingPoint()) {
auto& n = group_to_next_binding_number[bp->group];
n = std::max(n, bp->binding + 1);
if (sem_var->Type()->UnwrapRef()->Is<type::ExternalTexture>()) {
ext_tex_bps.emplace_back(bp);
if (sem_var->Type()->UnwrapRef()->Is<type::ExternalTexture>()) {
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* sampler = pair.second ? pair.second->As<sem::GlobalVariable>() : nullptr;
SamplerTexturePair new_pair;
new_pair.sampler_binding_point = sampler ? sampler->BindingPoint() : placeholder;
new_pair.texture_binding_point = texture->BindingPoint();
new_pair.sampler_binding_point = sampler ? *sampler->BindingPoint() : placeholder;
new_pair.texture_binding_point = *texture->BindingPoint();
new_pairs.push_back(new_pair);
}
return new_pairs;
@ -834,8 +834,8 @@ void Inspector::GenerateSamplerTargets() {
GetOriginatingResources(std::array<const ast::Expression*, 2>{t, s},
[&](std::array<const sem::GlobalVariable*, 2> globals) {
auto texture_binding_point = globals[0]->BindingPoint();
auto sampler_binding_point = globals[1]->BindingPoint();
auto texture_binding_point = *globals[0]->BindingPoint();
auto sampler_binding_point = *globals[1]->BindingPoint();
for (auto* entry_point : entry_points) {
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>(
v, ty, sem::EvaluationStage::kRuntime, builtin::AddressSpace::kUndefined,
builtin::Access::kUndefined,
/* constant_value */ nullptr, sem::BindingPoint{}, std::nullopt);
/* constant_value */ nullptr, std::nullopt, std::nullopt);
} else {
sem = builder_->create<sem::LocalVariable>(v, ty, sem::EvaluationStage::kRuntime,
builtin::AddressSpace::kUndefined,
@ -336,7 +336,7 @@ sem::Variable* Resolver::Override(const ast::Override* v) {
auto* sem = builder_->create<sem::GlobalVariable>(
v, ty, sem::EvaluationStage::kOverride, builtin::AddressSpace::kUndefined,
builtin::Access::kUndefined,
/* constant_value */ nullptr, sem::BindingPoint{}, std::nullopt);
/* constant_value */ nullptr, std::nullopt, std::nullopt);
sem->SetInitializer(rhs);
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
? static_cast<sem::Variable*>(builder_->create<sem::GlobalVariable>(
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>(
c, ty, sem::EvaluationStage::kConstant, builtin::AddressSpace::kUndefined,
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;
if (is_global) {
sem::BindingPoint binding_point;
std::optional<sem::BindingPoint> binding_point;
if (var->HasBindingPoint()) {
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()) {
binding_point = sem::BindingPoint{};
{
ExprEvalStageConstraint constraint{sem::EvaluationStage::kConstant, "@binding value"};
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) {
return nullptr;
}
binding_point.binding = materialized->ConstantValue()->ValueAs<u32>();
binding_point->binding = materialized->ConstantValue()->ValueAs<u32>();
}
{
ExprEvalStageConstraint constraint{sem::EvaluationStage::kConstant, "@group value"};
@ -662,7 +663,7 @@ sem::Parameter* Resolver::Parameter(const ast::Parameter* param, uint32_t index)
if (!materialized) {
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;
for (auto* global : func->TransitivelyReferencedGlobals()) {
auto* var_decl = global->Declaration()->As<ast::Var>();
if (!var_decl || !var_decl->HasBindingPoint()) {
if (!var_decl) {
continue;
}
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 &&
IsValidationEnabled(decl->attributes,
ast::DisabledValidation::kBindingPointCollision) &&
@ -1364,7 +1367,7 @@ bool Validator::EntryPoint(const sem::Function* func, ast::PipelineStage stage)
AddError(
"entry point '" + func_name +
"' 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);
AddNote("first resource binding usage declared here", (*added.value)->source);
return false;

View File

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

View File

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

View File

@ -165,14 +165,14 @@ class GlobalVariable final : public Castable<GlobalVariable, Variable> {
builtin::AddressSpace address_space,
builtin::Access access,
const constant::Value* constant_value,
sem::BindingPoint binding_point = {},
std::optional<sem::BindingPoint> binding_point = std::nullopt,
std::optional<uint32_t> location = std::nullopt);
/// Destructor
~GlobalVariable() override;
/// @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
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_; }
private:
const sem::BindingPoint binding_point_;
const std::optional<sem::BindingPoint> binding_point_;
tint::OverrideId override_id_;
std::optional<uint32_t> location_;
@ -208,7 +208,7 @@ class Parameter final : public Castable<Parameter, Variable> {
builtin::AddressSpace address_space,
builtin::Access access,
const ParameterUsage usage = ParameterUsage::kNone,
sem::BindingPoint binding_point = {},
std::optional<sem::BindingPoint> binding_point = {},
std::optional<uint32_t> location = std::nullopt);
/// Destructor
@ -239,7 +239,7 @@ class Parameter final : public Castable<Parameter, Variable> {
void SetShadows(const CastableBase* shadows) { shadows_ = shadows; }
/// @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
std::optional<uint32_t> Location() const { return location_; }
@ -249,7 +249,7 @@ class Parameter final : public Castable<Parameter, Variable> {
const ParameterUsage usage_;
CallTarget const* owner_ = nullptr;
const CastableBase* shadows_ = nullptr;
const sem::BindingPoint binding_point_;
const std::optional<sem::BindingPoint> binding_point_;
const std::optional<uint32_t> location_;
};

View File

@ -82,13 +82,14 @@ struct ArrayLengthFromUniform::State {
IterateArrayLengthOnStorageVar([&](const ast::CallExpression*, const sem::VariableUser*,
const sem::GlobalVariable* var) {
auto binding = var->BindingPoint();
auto idx_itr = cfg->bindpoint_to_size_index.find(binding);
if (idx_itr == cfg->bindpoint_to_size_index.end()) {
return;
}
if (idx_itr->second > max_buffer_size_index) {
max_buffer_size_index = idx_itr->second;
if (auto binding = var->BindingPoint()) {
auto idx_itr = cfg->bindpoint_to_size_index.find(*binding);
if (idx_itr == cfg->bindpoint_to_size_index.end()) {
return;
}
if (idx_itr->second > max_buffer_size_index) {
max_buffer_size_index = idx_itr->second;
}
}
});
@ -120,7 +121,10 @@ struct ArrayLengthFromUniform::State {
const sem::VariableUser* storage_buffer_sem,
const sem::GlobalVariable* var) {
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()) {
return;
}

View File

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

View File

@ -107,10 +107,10 @@ struct CombineSamplers::State {
const sem::Variable* sampler_var,
std::string name) {
SamplerTexturePair bp_pair;
bp_pair.texture_binding_point = texture_var->As<sem::GlobalVariable>()->BindingPoint();
bp_pair.sampler_binding_point = sampler_var
? sampler_var->As<sem::GlobalVariable>()->BindingPoint()
: binding_info->placeholder_binding_point;
bp_pair.texture_binding_point = *texture_var->As<sem::GlobalVariable>()->BindingPoint();
bp_pair.sampler_binding_point =
sampler_var ? *sampler_var->As<sem::GlobalVariable>()->BindingPoint()
: binding_info->placeholder_binding_point;
auto it = binding_info->binding_map.find(bp_pair);
if (it != binding_info->binding_map.end()) {
name = it->second;
@ -161,9 +161,8 @@ struct CombineSamplers::State {
if (tint::IsAnyOf<type::Texture, type::Sampler>(type) &&
!type->Is<type::StorageTexture>()) {
ctx.Remove(ctx.src->AST().GlobalDeclarations(), global);
} else if (global->HasBindingPoint()) {
auto binding_point = global_sem->BindingPoint();
if (binding_point.group == 0 && binding_point.binding == 0) {
} else if (auto binding_point = global_sem->BindingPoint()) {
if (binding_point->group == 0 && binding_point->binding == 0) {
auto* attribute =
ctx.dst->Disable(ast::DisabledValidation::kBindingPointCollision);
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
// transform. We fetch the new binding points by providing the original texture_external
// 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);
if (it == new_binding_points->bindings_map.end()) {

View File

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

View File

@ -67,18 +67,18 @@ TEST_F(FlattenBindingsTest, NotFlat_SingleNamespace) {
auto* sem = flattened->Sem().Get<sem::GlobalVariable>(vars[0]);
ASSERT_NE(sem, nullptr);
EXPECT_EQ(sem->BindingPoint().group, 0u);
EXPECT_EQ(sem->BindingPoint().binding, 0u);
EXPECT_EQ(sem->BindingPoint()->group, 0u);
EXPECT_EQ(sem->BindingPoint()->binding, 0u);
sem = flattened->Sem().Get<sem::GlobalVariable>(vars[1]);
ASSERT_NE(sem, nullptr);
EXPECT_EQ(sem->BindingPoint().group, 0u);
EXPECT_EQ(sem->BindingPoint().binding, 1u);
EXPECT_EQ(sem->BindingPoint()->group, 0u);
EXPECT_EQ(sem->BindingPoint()->binding, 1u);
sem = flattened->Sem().Get<sem::GlobalVariable>(vars[2]);
ASSERT_NE(sem, nullptr);
EXPECT_EQ(sem->BindingPoint().group, 0u);
EXPECT_EQ(sem->BindingPoint().binding, 2u);
EXPECT_EQ(sem->BindingPoint()->group, 0u);
EXPECT_EQ(sem->BindingPoint()->binding, 2u);
}
TEST_F(FlattenBindingsTest, NotFlat_MultipleNamespaces) {
@ -131,20 +131,20 @@ TEST_F(FlattenBindingsTest, NotFlat_MultipleNamespaces) {
for (size_t i = 0; i < num_buffers; ++i) {
auto* sem = flattened->Sem().Get<sem::GlobalVariable>(vars[i]);
ASSERT_NE(sem, nullptr);
EXPECT_EQ(sem->BindingPoint().group, 0u);
EXPECT_EQ(sem->BindingPoint().binding, i);
EXPECT_EQ(sem->BindingPoint()->group, 0u);
EXPECT_EQ(sem->BindingPoint()->binding, i);
}
for (size_t i = 0; i < num_samplers; ++i) {
auto* sem = flattened->Sem().Get<sem::GlobalVariable>(vars[i + num_buffers]);
ASSERT_NE(sem, nullptr);
EXPECT_EQ(sem->BindingPoint().group, 0u);
EXPECT_EQ(sem->BindingPoint().binding, i);
EXPECT_EQ(sem->BindingPoint()->group, 0u);
EXPECT_EQ(sem->BindingPoint()->binding, i);
}
for (size_t i = 0; i < num_textures; ++i) {
auto* sem = flattened->Sem().Get<sem::GlobalVariable>(vars[i + num_buffers + num_samplers]);
ASSERT_NE(sem, nullptr);
EXPECT_EQ(sem->BindingPoint().group, 0u);
EXPECT_EQ(sem->BindingPoint().binding, i);
EXPECT_EQ(sem->BindingPoint()->group, 0u);
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";
return false;
}
auto bp = sem->As<sem::GlobalVariable>()->BindingPoint();
auto bp = *sem->As<sem::GlobalVariable>()->BindingPoint();
{
auto out = line();
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";
return false;
}
auto bp = sem->As<sem::GlobalVariable>()->BindingPoint();
auto bp = *sem->As<sem::GlobalVariable>()->BindingPoint();
line() << "layout(binding = " << bp.binding << ", std430) buffer "
<< UniqueIdentifier(StructName(str) + "_ssbo") << " {";
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) {
auto binding_point = sem->As<sem::GlobalVariable>()->BindingPoint();
auto binding_point = *sem->As<sem::GlobalVariable>()->BindingPoint();
auto* type = sem->Type()->UnwrapRef();
auto name = var->name->symbol.Name();
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>();
out << RegisterAndSpace(sem->Access() == builtin::Access::kRead ? 't' : 'u',
global_sem->BindingPoint())
*global_sem->BindingPoint())
<< ";";
return true;
@ -3124,14 +3124,14 @@ bool GeneratorImpl::EmitHandleVariable(const ast::Var* var, const sem::Variable*
if (register_space) {
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.
// SM 5.0 doesn't support spaces, so we don't emit them if group is 0 for better
// compatibility.
if (bp.group == 0) {
if (bp->group == 0) {
out << ")";
} 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 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 "
"BindingRemapper to fix)";
return kInvalidBindingIndex;
}
return bp.binding;
return bp->binding;
};
{

View File

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