spirv-reader: Refactor decoration-getting for vars

Bug: tint:508
Change-Id: Ib176eb5e0dfdd6901635a9dd627aa9c7316f0a80
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/49301
Commit-Queue: David Neto <dneto@google.com>
Auto-Submit: David Neto <dneto@google.com>
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
This commit is contained in:
David Neto 2021-05-12 17:02:51 +00:00 committed by Commit Bot service account
parent bd65d8ecbd
commit 884a4e2172
2 changed files with 50 additions and 28 deletions

View File

@ -1365,32 +1365,44 @@ ast::Variable* ParserImpl::MakeVariable(uint32_t id,
sc = ast::StorageClass::kNone; sc = ast::StorageClass::kNone;
} }
if (!ConvertDecorationsForVariable(id, &type, &decorations)) {
return nullptr;
}
std::string name = namer_.Name(id);
return create<ast::Variable>(Source{}, builder_.Symbols().Register(name), sc,
type->Build(builder_), is_const, constructor,
decorations);
}
bool ParserImpl::ConvertDecorationsForVariable(
uint32_t id,
const Type** type,
ast::DecorationList* decorations) {
for (auto& deco : GetDecorationsFor(id)) { for (auto& deco : GetDecorationsFor(id)) {
if (deco.empty()) { if (deco.empty()) {
Fail() << "malformed decoration on ID " << id << ": it is empty"; return Fail() << "malformed decoration on ID " << id << ": it is empty";
return nullptr;
} }
if (deco[0] == SpvDecorationBuiltIn) { if (deco[0] == SpvDecorationBuiltIn) {
if (deco.size() == 1) { if (deco.size() == 1) {
Fail() << "malformed BuiltIn decoration on ID " << id return Fail() << "malformed BuiltIn decoration on ID " << id
<< ": has no operand"; << ": has no operand";
return nullptr;
} }
const auto spv_builtin = static_cast<SpvBuiltIn>(deco[1]); const auto spv_builtin = static_cast<SpvBuiltIn>(deco[1]);
switch (spv_builtin) { switch (spv_builtin) {
case SpvBuiltInPointSize: case SpvBuiltInPointSize:
special_builtins_[id] = spv_builtin; special_builtins_[id] = spv_builtin;
return nullptr; return false; // This is not an error
case SpvBuiltInSampleId: case SpvBuiltInSampleId:
case SpvBuiltInVertexIndex: case SpvBuiltInVertexIndex:
case SpvBuiltInInstanceIndex: case SpvBuiltInInstanceIndex:
// The SPIR-V variable is likely to be signed (because GLSL // The SPIR-V variable is likely to be signed (because GLSL
// requires signed), but WGSL requires unsigned. Handle specially // requires signed), but WGSL requires unsigned. Handle specially
// so we always perform the conversion at load and store. // so we always perform the conversion at load and store.
if (auto* forced_type = UnsignedTypeFor(type)) { if (auto* forced_type = UnsignedTypeFor(*type)) {
// Requires conversion and special handling in code generation. // Requires conversion and special handling in code generation.
special_builtins_[id] = spv_builtin; special_builtins_[id] = spv_builtin;
type = forced_type; *type = forced_type;
} }
break; break;
case SpvBuiltInSampleMask: { case SpvBuiltInSampleMask: {
@ -1404,7 +1416,7 @@ ast::Variable* ParserImpl::MakeVariable(uint32_t id,
"SampleMask must be an array of 1 element."; "SampleMask must be an array of 1 element.";
} }
special_builtins_[id] = spv_builtin; special_builtins_[id] = spv_builtin;
type = ty_.U32(); *type = ty_.U32();
break; break;
} }
default: default:
@ -1412,43 +1424,38 @@ ast::Variable* ParserImpl::MakeVariable(uint32_t id,
} }
auto ast_builtin = enum_converter_.ToBuiltin(spv_builtin); auto ast_builtin = enum_converter_.ToBuiltin(spv_builtin);
if (ast_builtin == ast::Builtin::kNone) { if (ast_builtin == ast::Builtin::kNone) {
return nullptr; // A diagnostic has already been emitted.
return false;
} }
decorations.emplace_back( decorations->emplace_back(
create<ast::BuiltinDecoration>(Source{}, ast_builtin)); create<ast::BuiltinDecoration>(Source{}, ast_builtin));
} }
if (deco[0] == SpvDecorationLocation) { if (deco[0] == SpvDecorationLocation) {
if (deco.size() != 2) { if (deco.size() != 2) {
Fail() << "malformed Location decoration on ID " << id return Fail() << "malformed Location decoration on ID " << id
<< ": requires one literal operand"; << ": requires one literal operand";
return nullptr;
} }
decorations.emplace_back( decorations->emplace_back(
create<ast::LocationDecoration>(Source{}, deco[1])); create<ast::LocationDecoration>(Source{}, deco[1]));
} }
if (deco[0] == SpvDecorationDescriptorSet) { if (deco[0] == SpvDecorationDescriptorSet) {
if (deco.size() == 1) { if (deco.size() == 1) {
Fail() << "malformed DescriptorSet decoration on ID " << id return Fail() << "malformed DescriptorSet decoration on ID " << id
<< ": has no operand"; << ": has no operand";
return nullptr;
} }
decorations.emplace_back(create<ast::GroupDecoration>(Source{}, deco[1])); decorations->emplace_back(
create<ast::GroupDecoration>(Source{}, deco[1]));
} }
if (deco[0] == SpvDecorationBinding) { if (deco[0] == SpvDecorationBinding) {
if (deco.size() == 1) { if (deco.size() == 1) {
Fail() << "malformed Binding decoration on ID " << id return Fail() << "malformed Binding decoration on ID " << id
<< ": has no operand"; << ": has no operand";
return nullptr;
} }
decorations.emplace_back( decorations->emplace_back(
create<ast::BindingDecoration>(Source{}, deco[1])); create<ast::BindingDecoration>(Source{}, deco[1]));
} }
} }
return success();
std::string name = namer_.Name(id);
return create<ast::Variable>(Source{}, builder_.Symbols().Register(name), sc,
type->Build(builder_), is_const, constructor,
decorations);
} }
TypedExpression ParserImpl::MakeConstantExpression(uint32_t id) { TypedExpression ParserImpl::MakeConstantExpression(uint32_t id) {

View File

@ -200,6 +200,21 @@ class ParserImpl : Reader {
DecorationList GetDecorationsForMember(uint32_t id, DecorationList GetDecorationsForMember(uint32_t id,
uint32_t member_index) const; uint32_t member_index) const;
/// Converts SPIR-V decorations for the variable with the given ID.
/// Registers the IDs of variables that require special handling by code
/// generation. If the WGSL type differs from the store type for SPIR-V,
/// then the `type` parameter is updated. Returns false on failure (with
/// a diagnostic), or when the variable should not be emitted, e.g. for a
/// PointSize builtin.
/// @param id the ID of the SPIR-V variable
/// @param type the WGSL store type for the variable, which should be
/// prepopulatd
/// @param ast_decos the decoration list to populate
/// @returns false when the variable should not be emitted as a variable
bool ConvertDecorationsForVariable(uint32_t id,
const Type** type,
ast::DecorationList* ast_decos);
/// Converts a SPIR-V struct member decoration. If the decoration is /// Converts a SPIR-V struct member decoration. If the decoration is
/// recognized but deliberately dropped, then returns nullptr without a /// recognized but deliberately dropped, then returns nullptr without a
/// diagnostic. On failure, emits a diagnostic and returns nullptr. /// diagnostic. On failure, emits a diagnostic and returns nullptr.