tint/ast: Clean up StorageClass enum

Remove unused enum entries.
Add a ParseStorageClass() function. Have the WGSL parser use this.

First step to standardizing the way we parse enum-backed token sets.

Change-Id: I31c02816493beeabda740ff43946edce097f5fd1
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/97148
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
Commit-Queue: Dan Sinclair <dsinclair@chromium.org>
This commit is contained in:
Ben Clayton 2022-07-26 22:51:36 +00:00 committed by Dawn LUCI CQ
parent ce8876074f
commit 48085845bd
24 changed files with 150 additions and 132 deletions

View File

@ -16,34 +16,52 @@
namespace tint::ast { namespace tint::ast {
const char* ToString(StorageClass sc) { /// ParseStorageClass parses a StorageClass from a string.
switch (sc) { /// @param str the string to parse
case StorageClass::kInvalid: /// @returns the parsed enum, or StorageClass::kInvalid if the string could not be parsed.
return "invalid"; StorageClass ParseStorageClass(std::string_view str) {
case StorageClass::kNone: if (str == "function") {
return "none"; return StorageClass::kFunction;
case StorageClass::kInput:
return "in";
case StorageClass::kOutput:
return "out";
case StorageClass::kUniform:
return "uniform";
case StorageClass::kWorkgroup:
return "workgroup";
case StorageClass::kHandle:
return "handle";
case StorageClass::kStorage:
return "storage";
case StorageClass::kPrivate:
return "private";
case StorageClass::kFunction:
return "function";
} }
return "<unknown>"; if (str == "private") {
return StorageClass::kPrivate;
}
if (str == "workgroup") {
return StorageClass::kWorkgroup;
}
if (str == "uniform") {
return StorageClass::kUniform;
}
if (str == "storage") {
return StorageClass::kStorage;
}
return StorageClass::kInvalid;
} }
std::ostream& operator<<(std::ostream& out, StorageClass sc) {
out << ToString(sc); std::ostream& operator<<(std::ostream& out, StorageClass value) {
return out; switch (value) {
case StorageClass::kInvalid:
return out << "invalid";
case StorageClass::kNone:
return out << "none";
case StorageClass::kFunction:
return out << "function";
case StorageClass::kPrivate:
return out << "private";
case StorageClass::kWorkgroup:
return out << "workgroup";
case StorageClass::kUniform:
return out << "uniform";
case StorageClass::kStorage:
return out << "storage";
case StorageClass::kHandle:
return out << "handle";
case StorageClass::kIn:
return out << "in";
case StorageClass::kOut:
return out << "out";
}
return out << "<unknown>";
} }
} // namespace tint::ast } // namespace tint::ast

View File

@ -1,4 +1,4 @@
// Copyright 2020 The Tint Authors. // Copyright 2022 The Tint Authors.
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
@ -21,18 +21,28 @@ namespace tint::ast {
/// Storage class of a given pointer. /// Storage class of a given pointer.
enum class StorageClass { enum class StorageClass {
kInvalid = -1, kInvalid,
kNone, kNone,
kInput, kFunction,
kOutput,
kUniform,
kWorkgroup,
kHandle,
kStorage,
kPrivate, kPrivate,
kFunction kWorkgroup,
kUniform,
kStorage,
kHandle,
kIn,
kOut,
}; };
/// @param out the std::ostream to write to
/// @param sc the StorageClass
/// @return the std::ostream so calls can be chained
std::ostream& operator<<(std::ostream& out, StorageClass sc);
/// ParseStorageClass parses a StorageClass from a string.
/// @param str the string to parse
/// @returns the parsed enum, or StorageClass::kInvalid if the string could not be parsed.
StorageClass ParseStorageClass(std::string_view str);
/// @returns true if the StorageClass is host-shareable /// @returns true if the StorageClass is host-shareable
/// @param sc the StorageClass /// @param sc the StorageClass
/// @see https://gpuweb.github.io/gpuweb/wgsl.html#host-shareable /// @see https://gpuweb.github.io/gpuweb/wgsl.html#host-shareable
@ -40,15 +50,6 @@ inline bool IsHostShareable(StorageClass sc) {
return sc == ast::StorageClass::kUniform || sc == ast::StorageClass::kStorage; return sc == ast::StorageClass::kUniform || sc == ast::StorageClass::kStorage;
} }
/// @param sc the StorageClass
/// @return the name of the given storage class
const char* ToString(StorageClass sc);
/// @param out the std::ostream to write to
/// @param sc the StorageClass
/// @return the std::ostream so calls can be chained
std::ostream& operator<<(std::ostream& out, StorageClass sc);
} // namespace tint::ast } // namespace tint::ast
#endif // SRC_TINT_AST_STORAGE_CLASS_H_ #endif // SRC_TINT_AST_STORAGE_CLASS_H_

View File

@ -49,6 +49,7 @@
#include "src/tint/sem/vector.h" #include "src/tint/sem/vector.h"
#include "src/tint/sem/void.h" #include "src/tint/sem/void.h"
#include "src/tint/utils/math.h" #include "src/tint/utils/math.h"
#include "src/tint/utils/string.h"
#include "src/tint/utils/unique_vector.h" #include "src/tint/utils/unique_vector.h"
namespace tint::inspector { namespace tint::inspector {
@ -570,7 +571,7 @@ std::vector<std::string> Inspector::GetUsedExtensionNames() {
std::vector<std::string> out; std::vector<std::string> out;
out.reserve(extensions.size()); out.reserve(extensions.size());
for (auto ext : extensions) { for (auto ext : extensions) {
out.push_back(ast::str(ext)); out.push_back(utils::ToString(ext));
} }
return out; return out;
} }
@ -582,7 +583,7 @@ std::vector<std::pair<std::string, Source>> Inspector::GetEnableDirectives() {
auto global_decls = program_->AST().GlobalDeclarations(); auto global_decls = program_->AST().GlobalDeclarations();
for (auto* node : global_decls) { for (auto* node : global_decls) {
if (auto* ext = node->As<ast::Enable>()) { if (auto* ext = node->As<ast::Enable>()) {
result.push_back({ast::str(ext->extension), ext->source}); result.push_back({utils::ToString(ext->extension), ext->source});
} }
} }

View File

@ -39,9 +39,9 @@ ast::PipelineStage EnumConverter::ToPipelineStage(SpvExecutionModel model) {
ast::StorageClass EnumConverter::ToStorageClass(const SpvStorageClass sc) { ast::StorageClass EnumConverter::ToStorageClass(const SpvStorageClass sc) {
switch (sc) { switch (sc) {
case SpvStorageClassInput: case SpvStorageClassInput:
return ast::StorageClass::kInput; return ast::StorageClass::kIn;
case SpvStorageClassOutput: case SpvStorageClassOutput:
return ast::StorageClass::kOutput; return ast::StorageClass::kOut;
case SpvStorageClassUniform: case SpvStorageClassUniform:
return ast::StorageClass::kUniform; return ast::StorageClass::kUniform;
case SpvStorageClassWorkgroup: case SpvStorageClassWorkgroup:

View File

@ -125,8 +125,8 @@ INSTANTIATE_TEST_SUITE_P(
EnumConverterGood, EnumConverterGood,
SpvStorageClassTest, SpvStorageClassTest,
testing::Values( testing::Values(
StorageClassCase{SpvStorageClassInput, true, ast::StorageClass::kInput}, StorageClassCase{SpvStorageClassInput, true, ast::StorageClass::kIn},
StorageClassCase{SpvStorageClassOutput, true, ast::StorageClass::kOutput}, StorageClassCase{SpvStorageClassOutput, true, ast::StorageClass::kOut},
StorageClassCase{SpvStorageClassUniform, true, ast::StorageClass::kUniform}, StorageClassCase{SpvStorageClassUniform, true, ast::StorageClass::kUniform},
StorageClassCase{SpvStorageClassWorkgroup, true, ast::StorageClass::kWorkgroup}, StorageClassCase{SpvStorageClassWorkgroup, true, ast::StorageClass::kWorkgroup},
StorageClassCase{SpvStorageClassUniformConstant, true, ast::StorageClass::kNone}, StorageClassCase{SpvStorageClassUniformConstant, true, ast::StorageClass::kNone},

View File

@ -1219,8 +1219,8 @@ const Type* ParserImpl::ConvertType(uint32_t type_id,
} }
// Pipeline input and output variables map to private variables. // Pipeline input and output variables map to private variables.
if (ast_storage_class == ast::StorageClass::kInput || if (ast_storage_class == ast::StorageClass::kIn ||
ast_storage_class == ast::StorageClass::kOutput) { ast_storage_class == ast::StorageClass::kOut) {
ast_storage_class = ast::StorageClass::kPrivate; ast_storage_class = ast::StorageClass::kPrivate;
} }
switch (ptr_as) { switch (ptr_as) {
@ -1446,8 +1446,8 @@ bool ParserImpl::EmitModuleScopeVariables() {
} }
switch (enum_converter_.ToStorageClass(spirv_storage_class)) { switch (enum_converter_.ToStorageClass(spirv_storage_class)) {
case ast::StorageClass::kNone: case ast::StorageClass::kNone:
case ast::StorageClass::kInput: case ast::StorageClass::kIn:
case ast::StorageClass::kOutput: case ast::StorageClass::kOut:
case ast::StorageClass::kUniform: case ast::StorageClass::kUniform:
case ast::StorageClass::kHandle: case ast::StorageClass::kHandle:
case ast::StorageClass::kStorage: case ast::StorageClass::kStorage:

View File

@ -21,6 +21,7 @@
#include "src/tint/program_builder.h" #include "src/tint/program_builder.h"
#include "src/tint/utils/hash.h" #include "src/tint/utils/hash.h"
#include "src/tint/utils/map.h" #include "src/tint/utils/map.h"
#include "src/tint/utils/string.h"
#include "src/tint/utils/unique_allocator.h" #include "src/tint/utils/unique_allocator.h"
TINT_INSTANTIATE_TYPEINFO(tint::reader::spirv::Type); TINT_INSTANTIATE_TYPEINFO(tint::reader::spirv::Type);
@ -518,13 +519,13 @@ std::string I32::String() const {
std::string Pointer::String() const { std::string Pointer::String() const {
std::stringstream ss; std::stringstream ss;
ss << "ptr<" << std::string(ast::ToString(storage_class)) << ", " << type->String() + ">"; ss << "ptr<" << utils::ToString(storage_class) << ", " << type->String() + ">";
return ss.str(); return ss.str();
} }
std::string Reference::String() const { std::string Reference::String() const {
std::stringstream ss; std::stringstream ss;
ss << "ref<" + std::string(ast::ToString(storage_class)) << ", " << type->String() << ">"; ss << "ref<" + utils::ToString(storage_class) << ", " << type->String() << ">";
return ss.str(); return ss.str();
} }

View File

@ -56,7 +56,7 @@ TEST(SpvParserTypeTest, DifferentArgumentsGivesDifferentPointer) {
EXPECT_NE(ty.Pointer(ty.I32(), ast::StorageClass::kNone), EXPECT_NE(ty.Pointer(ty.I32(), ast::StorageClass::kNone),
ty.Pointer(ty.U32(), ast::StorageClass::kNone)); ty.Pointer(ty.U32(), ast::StorageClass::kNone));
EXPECT_NE(ty.Pointer(ty.I32(), ast::StorageClass::kNone), EXPECT_NE(ty.Pointer(ty.I32(), ast::StorageClass::kNone),
ty.Pointer(ty.I32(), ast::StorageClass::kInput)); ty.Pointer(ty.I32(), ast::StorageClass::kIn));
EXPECT_NE(ty.Vector(ty.I32(), 3), ty.Vector(ty.U32(), 3)); EXPECT_NE(ty.Vector(ty.I32(), 3), ty.Vector(ty.U32(), 3));
EXPECT_NE(ty.Vector(ty.I32(), 3), ty.Vector(ty.I32(), 2)); EXPECT_NE(ty.Vector(ty.I32(), 3), ty.Vector(ty.I32(), 2));
EXPECT_NE(ty.Matrix(ty.I32(), 3, 2), ty.Matrix(ty.U32(), 3, 2)); EXPECT_NE(ty.Matrix(ty.I32(), 3, 2), ty.Matrix(ty.U32(), 3, 2));

View File

@ -400,7 +400,7 @@ Maybe<bool> ParserImpl::enable_directive() {
synchronized_ = true; synchronized_ = true;
next(); next();
name = {"f16", t.source()}; name = {"f16", t.source()};
} else if (t.Is(Token::Type::kParenLeft)){ } else if (t.Is(Token::Type::kParenLeft)) {
// A common error case is writing `enable(foo);` instead of `enable foo;`. // A common error case is writing `enable(foo);` instead of `enable foo;`.
synchronized_ = false; synchronized_ = false;
return add_error(t.source(), "enable directives don't take parenthesis"); return add_error(t.source(), "enable directives don't take parenthesis");
@ -1315,28 +1315,12 @@ Expect<ast::StorageClass> ParserImpl::expect_storage_class(std::string_view use)
return Failure::kErrored; return Failure::kErrored;
} }
auto name = ident.value; auto storage_class = ast::ParseStorageClass(ident.value);
if (name == "uniform") { if (storage_class == ast::StorageClass::kInvalid) {
return {ast::StorageClass::kUniform, t.source()}; return add_error(t.source(), "invalid storage class", use);
} }
if (name == "workgroup") { return {storage_class, t.source()};
return {ast::StorageClass::kWorkgroup, t.source()};
}
if (name == "storage" || name == "storage_buffer") {
return {ast::StorageClass::kStorage, t.source()};
}
if (name == "private") {
return {ast::StorageClass::kPrivate, t.source()};
}
if (name == "function") {
return {ast::StorageClass::kFunction, t.source()};
}
return add_error(t.source(), "invalid storage class", use);
} }
// struct_decl // struct_decl

View File

@ -46,7 +46,6 @@ INSTANTIATE_TEST_SUITE_P(
testing::Values(StorageClassData{"uniform", ast::StorageClass::kUniform}, testing::Values(StorageClassData{"uniform", ast::StorageClass::kUniform},
StorageClassData{"workgroup", ast::StorageClass::kWorkgroup}, StorageClassData{"workgroup", ast::StorageClass::kWorkgroup},
StorageClassData{"storage", ast::StorageClass::kStorage}, StorageClassData{"storage", ast::StorageClass::kStorage},
StorageClassData{"storage_buffer", ast::StorageClass::kStorage},
StorageClassData{"private", ast::StorageClass::kPrivate}, StorageClassData{"private", ast::StorageClass::kPrivate},
StorageClassData{"function", ast::StorageClass::kFunction})); StorageClassData{"function", ast::StorageClass::kFunction}));

View File

@ -50,7 +50,6 @@ INSTANTIATE_TEST_SUITE_P(
VariableStorageData{"uniform", ast::StorageClass::kUniform, ast::Access::kUndefined}, VariableStorageData{"uniform", ast::StorageClass::kUniform, ast::Access::kUndefined},
VariableStorageData{"workgroup", ast::StorageClass::kWorkgroup, ast::Access::kUndefined}, VariableStorageData{"workgroup", ast::StorageClass::kWorkgroup, ast::Access::kUndefined},
VariableStorageData{"storage", ast::StorageClass::kStorage, ast::Access::kUndefined}, VariableStorageData{"storage", ast::StorageClass::kStorage, ast::Access::kUndefined},
VariableStorageData{"storage_buffer", ast::StorageClass::kStorage, ast::Access::kUndefined},
VariableStorageData{"private", ast::StorageClass::kPrivate, ast::Access::kUndefined}, VariableStorageData{"private", ast::StorageClass::kPrivate, ast::Access::kUndefined},
VariableStorageData{"function", ast::StorageClass::kFunction, ast::Access::kUndefined}, VariableStorageData{"function", ast::StorageClass::kFunction, ast::Access::kUndefined},
VariableStorageData{"storage, read", ast::StorageClass::kStorage, ast::Access::kRead}, VariableStorageData{"storage, read", ast::StorageClass::kStorage, ast::Access::kRead},

View File

@ -807,8 +807,8 @@ TEST_P(ResolverFunctionParameterValidationTest, StorageClass) {
INSTANTIATE_TEST_SUITE_P(ResolverTest, INSTANTIATE_TEST_SUITE_P(ResolverTest,
ResolverFunctionParameterValidationTest, ResolverFunctionParameterValidationTest,
testing::Values(TestParams{ast::StorageClass::kNone, false}, testing::Values(TestParams{ast::StorageClass::kNone, false},
TestParams{ast::StorageClass::kInput, false}, TestParams{ast::StorageClass::kIn, false},
TestParams{ast::StorageClass::kOutput, false}, TestParams{ast::StorageClass::kOut, false},
TestParams{ast::StorageClass::kUniform, false}, TestParams{ast::StorageClass::kUniform, false},
TestParams{ast::StorageClass::kWorkgroup, true}, TestParams{ast::StorageClass::kWorkgroup, true},
TestParams{ast::StorageClass::kHandle, false}, TestParams{ast::StorageClass::kHandle, false},

View File

@ -78,6 +78,7 @@
#include "src/tint/utils/math.h" #include "src/tint/utils/math.h"
#include "src/tint/utils/reverse.h" #include "src/tint/utils/reverse.h"
#include "src/tint/utils/scoped_assignment.h" #include "src/tint/utils/scoped_assignment.h"
#include "src/tint/utils/string.h"
#include "src/tint/utils/transform.h" #include "src/tint/utils/transform.h"
namespace tint::resolver { namespace tint::resolver {
@ -344,7 +345,7 @@ bool Validator::VariableInitializer(const ast::Variable* v,
// https://gpuweb.github.io/gpuweb/wgsl/#var-and-let // https://gpuweb.github.io/gpuweb/wgsl/#var-and-let
// Optionally has an initializer expression, if the variable is in the // Optionally has an initializer expression, if the variable is in the
// private or function storage classes. // private or function storage classes.
AddError("var of storage class '" + std::string(ast::ToString(storage_class)) + AddError("var of storage class '" + utils::ToString(storage_class) +
"' cannot have an initializer. var initializers are only " "' cannot have an initializer. var initializers are only "
"supported for the storage classes " "supported for the storage classes "
"'private' and 'function'", "'private' and 'function'",
@ -396,9 +397,9 @@ bool Validator::StorageClassLayout(const sem::Type* store_ty,
// TODO(tint:1473, tint:1502): Remove this error after f16 is supported in "uniform" and // TODO(tint:1473, tint:1502): Remove this error after f16 is supported in "uniform" and
// "storage" storage class. // "storage" storage class.
if (Is<sem::F16>(sem::Type::DeepestElementOf(store_ty))) { if (Is<sem::F16>(sem::Type::DeepestElementOf(store_ty))) {
AddError("using f16 types in '" + std::string(ast::ToString(sc)) + AddError(
"' storage class is not implemented yet", "using f16 types in '" + utils::ToString(sc) + "' storage class is not implemented yet",
source); source);
return false; return false;
} }
@ -418,7 +419,7 @@ bool Validator::StorageClassLayout(const sem::Type* store_ty,
if (m->Offset() % required_align != 0) { if (m->Offset() % required_align != 0) {
AddError("the offset of a struct member of type '" + AddError("the offset of a struct member of type '" +
m->Type()->UnwrapRef()->FriendlyName(symbols_) + m->Type()->UnwrapRef()->FriendlyName(symbols_) +
"' in storage class '" + ast::ToString(sc) + "' in storage class '" + utils::ToString(sc) +
"' must be a multiple of " + std::to_string(required_align) + "' must be a multiple of " + std::to_string(required_align) +
" bytes, but '" + member_name_of(m) + "' is currently at offset " + " bytes, but '" + member_name_of(m) + "' is currently at offset " +
std::to_string(m->Offset()) + ". Consider setting @align(" + std::to_string(m->Offset()) + ". Consider setting @align(" +
@ -583,8 +584,8 @@ bool Validator::GlobalVariable(
bool is_shader_io_attribute = bool is_shader_io_attribute =
attr->IsAnyOf<ast::BuiltinAttribute, ast::InterpolateAttribute, attr->IsAnyOf<ast::BuiltinAttribute, ast::InterpolateAttribute,
ast::InvariantAttribute, ast::LocationAttribute>(); ast::InvariantAttribute, ast::LocationAttribute>();
bool has_io_storage_class = global->StorageClass() == ast::StorageClass::kInput || bool has_io_storage_class = global->StorageClass() == ast::StorageClass::kIn ||
global->StorageClass() == ast::StorageClass::kOutput; global->StorageClass() == ast::StorageClass::kOut;
if (!attr->IsAnyOf<ast::BindingAttribute, ast::GroupAttribute, if (!attr->IsAnyOf<ast::BindingAttribute, ast::GroupAttribute,
ast::InternalAttribute>() && ast::InternalAttribute>() &&
(!is_shader_io_attribute || !has_io_storage_class)) { (!is_shader_io_attribute || !has_io_storage_class)) {
@ -740,8 +741,8 @@ bool Validator::Var(const sem::Variable* v) const {
} }
if (IsValidationEnabled(var->attributes, ast::DisabledValidation::kIgnoreStorageClass) && if (IsValidationEnabled(var->attributes, ast::DisabledValidation::kIgnoreStorageClass) &&
(var->declared_storage_class == ast::StorageClass::kInput || (var->declared_storage_class == ast::StorageClass::kIn ||
var->declared_storage_class == ast::StorageClass::kOutput)) { var->declared_storage_class == ast::StorageClass::kOut)) {
AddError("invalid use of input/output storage class", var->source); AddError("invalid use of input/output storage class", var->source);
return false; return false;
} }

View File

@ -22,6 +22,7 @@
#include "src/tint/program_builder.h" #include "src/tint/program_builder.h"
#include "src/tint/sem/function.h" #include "src/tint/sem/function.h"
#include "src/tint/sem/variable.h" #include "src/tint/sem/variable.h"
#include "src/tint/utils/string.h"
TINT_INSTANTIATE_TYPEINFO(tint::transform::BindingRemapper); TINT_INSTANTIATE_TYPEINFO(tint::transform::BindingRemapper);
TINT_INSTANTIATE_TYPEINFO(tint::transform::BindingRemapper::Remappings); TINT_INSTANTIATE_TYPEINFO(tint::transform::BindingRemapper::Remappings);
@ -125,7 +126,7 @@ void BindingRemapper::Run(CloneContext& ctx, const DataMap& inputs, DataMap&) co
ctx.dst->Diagnostics().add_error( ctx.dst->Diagnostics().add_error(
diag::System::Transform, diag::System::Transform,
"cannot apply access control to variable with storage class " + "cannot apply access control to variable with storage class " +
std::string(ast::ToString(sem->StorageClass()))); std::string(utils::ToString(sem->StorageClass())));
return; return;
} }
auto* ty = sem->Type()->UnwrapRef(); auto* ty = sem->Type()->UnwrapRef();

View File

@ -181,7 +181,7 @@ struct CanonicalizeEntryPointIO::State {
auto* builtin = ast::GetAttribute<ast::BuiltinAttribute>(attributes); auto* builtin = ast::GetAttribute<ast::BuiltinAttribute>(attributes);
if (cfg.shader_style == ShaderStyle::kGlsl && builtin) { if (cfg.shader_style == ShaderStyle::kGlsl && builtin) {
name = GLSLBuiltinToString(builtin->builtin, func_ast->PipelineStage(), name = GLSLBuiltinToString(builtin->builtin, func_ast->PipelineStage(),
ast::StorageClass::kInput); ast::StorageClass::kIn);
} }
auto symbol = ctx.dst->Symbols().New(name); auto symbol = ctx.dst->Symbols().New(name);
@ -198,7 +198,7 @@ struct CanonicalizeEntryPointIO::State {
value = ctx.dst->IndexAccessor(value, 0_i); value = ctx.dst->IndexAccessor(value, 0_i);
} }
} }
ctx.dst->GlobalVar(symbol, ast_type, ast::StorageClass::kInput, std::move(attributes)); ctx.dst->GlobalVar(symbol, ast_type, ast::StorageClass::kIn, std::move(attributes));
return value; return value;
} else if (cfg.shader_style == ShaderStyle::kMsl && } else if (cfg.shader_style == ShaderStyle::kMsl &&
ast::HasAttribute<ast::BuiltinAttribute>(attributes)) { ast::HasAttribute<ast::BuiltinAttribute>(attributes)) {
@ -246,7 +246,7 @@ struct CanonicalizeEntryPointIO::State {
if (cfg.shader_style == ShaderStyle::kGlsl) { if (cfg.shader_style == ShaderStyle::kGlsl) {
if (auto* b = ast::GetAttribute<ast::BuiltinAttribute>(attributes)) { if (auto* b = ast::GetAttribute<ast::BuiltinAttribute>(attributes)) {
name = GLSLBuiltinToString(b->builtin, func_ast->PipelineStage(), name = GLSLBuiltinToString(b->builtin, func_ast->PipelineStage(),
ast::StorageClass::kOutput); ast::StorageClass::kOut);
value = ToGLSLBuiltin(b->builtin, value, type); value = ToGLSLBuiltin(b->builtin, value, type);
} }
} }
@ -463,7 +463,7 @@ struct CanonicalizeEntryPointIO::State {
type = ctx.dst->ty.array(type, 1_u); type = ctx.dst->ty.array(type, 1_u);
lhs = ctx.dst->IndexAccessor(lhs, 0_i); lhs = ctx.dst->IndexAccessor(lhs, 0_i);
} }
ctx.dst->GlobalVar(name, type, ast::StorageClass::kOutput, std::move(attributes)); ctx.dst->GlobalVar(name, type, ast::StorageClass::kOut, std::move(attributes));
wrapper_body.push_back(ctx.dst->Assign(lhs, outval.value)); wrapper_body.push_back(ctx.dst->Assign(lhs, outval.value));
} }
} }
@ -640,7 +640,7 @@ struct CanonicalizeEntryPointIO::State {
case ast::Builtin::kSampleIndex: case ast::Builtin::kSampleIndex:
return "gl_SampleID"; return "gl_SampleID";
case ast::Builtin::kSampleMask: case ast::Builtin::kSampleMask:
if (storage_class == ast::StorageClass::kInput) { if (storage_class == ast::StorageClass::kIn) {
return "gl_SampleMaskIn"; return "gl_SampleMaskIn";
} else { } else {
return "gl_SampleMask"; return "gl_SampleMask";

View File

@ -15,6 +15,7 @@
#ifndef SRC_TINT_UTILS_STRING_H_ #ifndef SRC_TINT_UTILS_STRING_H_
#define SRC_TINT_UTILS_STRING_H_ #define SRC_TINT_UTILS_STRING_H_
#include <sstream>
#include <string> #include <string>
namespace tint::utils { namespace tint::utils {
@ -34,6 +35,15 @@ inline std::string ReplaceAll(std::string str,
return str; return str;
} }
/// @param value the value to be printed as a string
/// @returns value printed as a string via the std::ostream `<<` operator
template <typename T>
std::string ToString(const T& value) {
std::stringstream s;
s << value;
return s.str();
}
} // namespace tint::utils } // namespace tint::utils
#endif // SRC_TINT_UTILS_STRING_H_ #endif // SRC_TINT_UTILS_STRING_H_

View File

@ -32,5 +32,10 @@ TEST(StringTest, ReplaceAll) {
ASSERT_EQ("aabxybbxybcc", ReplaceAll("aabbcc", "b", "bxyb")); ASSERT_EQ("aabxybbxybcc", ReplaceAll("aabbcc", "b", "bxyb"));
} }
TEST(StringTest, ToString) {
ASSERT_EQ("123", ToString(123));
ASSERT_EQ("hello", ToString("hello"));
}
} // namespace } // namespace
} // namespace tint::utils } // namespace tint::utils

View File

@ -1929,8 +1929,8 @@ bool GeneratorImpl::EmitGlobalVariable(const ast::Variable* global) {
return EmitPrivateVariable(sem); return EmitPrivateVariable(sem);
case ast::StorageClass::kWorkgroup: case ast::StorageClass::kWorkgroup:
return EmitWorkgroupVariable(sem); return EmitWorkgroupVariable(sem);
case ast::StorageClass::kInput: case ast::StorageClass::kIn:
case ast::StorageClass::kOutput: case ast::StorageClass::kOut:
return EmitIOVariable(sem); return EmitIOVariable(sem);
default: default:
TINT_ICE(Writer, diagnostics_) TINT_ICE(Writer, diagnostics_)
@ -2738,11 +2738,11 @@ bool GeneratorImpl::EmitType(std::ostream& out,
*name_printed = false; *name_printed = false;
} }
switch (storage_class) { switch (storage_class) {
case ast::StorageClass::kInput: { case ast::StorageClass::kIn: {
out << "in "; out << "in ";
break; break;
} }
case ast::StorageClass::kOutput: { case ast::StorageClass::kOut: {
out << "out "; out << "out ";
break; break;
} }

View File

@ -62,7 +62,7 @@ TEST_F(GlslGeneratorImplTest, GenerateSampleIndexES) {
Builtin(ast::Builtin::kSampleIndex), Builtin(ast::Builtin::kSampleIndex),
Disable(ast::DisabledValidation::kIgnoreStorageClass), Disable(ast::DisabledValidation::kIgnoreStorageClass),
}, },
ast::StorageClass::kInput); ast::StorageClass::kIn);
Func("my_func", {}, ty.i32(), Func("my_func", {}, ty.i32(),
{ {
Return(Expr("gl_SampleID")), Return(Expr("gl_SampleID")),
@ -87,7 +87,7 @@ TEST_F(GlslGeneratorImplTest, GenerateSampleIndexDesktop) {
Builtin(ast::Builtin::kSampleIndex), Builtin(ast::Builtin::kSampleIndex),
Disable(ast::DisabledValidation::kIgnoreStorageClass), Disable(ast::DisabledValidation::kIgnoreStorageClass),
}, },
ast::StorageClass::kInput); ast::StorageClass::kIn);
Func("my_func", {}, ty.i32(), Func("my_func", {}, ty.i32(),
{ {
Return(Expr("gl_SampleID")), Return(Expr("gl_SampleID")),

View File

@ -477,8 +477,8 @@ bool Builder::GenerateEntryPoint(const ast::Function* func, uint32_t id) {
for (const auto* var : func_sem->TransitivelyReferencedGlobals()) { for (const auto* var : func_sem->TransitivelyReferencedGlobals()) {
// For SPIR-V 1.3 we only output Input/output variables. If we update to // For SPIR-V 1.3 we only output Input/output variables. If we update to
// SPIR-V 1.4 or later this should be all variables. // SPIR-V 1.4 or later this should be all variables.
if (var->StorageClass() != ast::StorageClass::kInput && if (var->StorageClass() != ast::StorageClass::kIn &&
var->StorageClass() != ast::StorageClass::kOutput) { var->StorageClass() != ast::StorageClass::kOut) {
continue; continue;
} }
@ -856,7 +856,7 @@ bool Builder::GenerateGlobalVariable(const ast::Variable* v) {
// VK_KHR_zero_initialize_workgroup_memory extension is enabled, we should // VK_KHR_zero_initialize_workgroup_memory extension is enabled, we should
// also zero-initialize. // also zero-initialize.
if (sem->StorageClass() == ast::StorageClass::kPrivate || if (sem->StorageClass() == ast::StorageClass::kPrivate ||
sem->StorageClass() == ast::StorageClass::kOutput || sem->StorageClass() == ast::StorageClass::kOut ||
(zero_initialize_workgroup_memory_ && (zero_initialize_workgroup_memory_ &&
sem->StorageClass() == ast::StorageClass::kWorkgroup)) { sem->StorageClass() == ast::StorageClass::kWorkgroup)) {
init_id = GenerateConstantNullIfNeeded(type); init_id = GenerateConstantNullIfNeeded(type);
@ -4113,9 +4113,9 @@ SpvStorageClass Builder::ConvertStorageClass(ast::StorageClass klass) const {
switch (klass) { switch (klass) {
case ast::StorageClass::kInvalid: case ast::StorageClass::kInvalid:
return SpvStorageClassMax; return SpvStorageClassMax;
case ast::StorageClass::kInput: case ast::StorageClass::kIn:
return SpvStorageClassInput; return SpvStorageClassInput;
case ast::StorageClass::kOutput: case ast::StorageClass::kOut:
return SpvStorageClassOutput; return SpvStorageClassOutput;
case ast::StorageClass::kUniform: case ast::StorageClass::kUniform:
return SpvStorageClassUniform; return SpvStorageClassUniform;
@ -4138,9 +4138,9 @@ SpvStorageClass Builder::ConvertStorageClass(ast::StorageClass klass) const {
SpvBuiltIn Builder::ConvertBuiltin(ast::Builtin builtin, ast::StorageClass storage) { SpvBuiltIn Builder::ConvertBuiltin(ast::Builtin builtin, ast::StorageClass storage) {
switch (builtin) { switch (builtin) {
case ast::Builtin::kPosition: case ast::Builtin::kPosition:
if (storage == ast::StorageClass::kInput) { if (storage == ast::StorageClass::kIn) {
return SpvBuiltInFragCoord; return SpvBuiltInFragCoord;
} else if (storage == ast::StorageClass::kOutput) { } else if (storage == ast::StorageClass::kOut) {
return SpvBuiltInPosition; return SpvBuiltInPosition;
} else { } else {
TINT_ICE(Writer, builder_.Diagnostics()) << "invalid storage class for builtin"; TINT_ICE(Writer, builder_.Diagnostics()) << "invalid storage class for builtin";

View File

@ -443,29 +443,27 @@ INSTANTIATE_TEST_SUITE_P(
BuiltinDataTest, BuiltinDataTest,
testing::Values( testing::Values(
BuiltinData{ast::Builtin::kNone, ast::StorageClass::kNone, SpvBuiltInMax}, BuiltinData{ast::Builtin::kNone, ast::StorageClass::kNone, SpvBuiltInMax},
BuiltinData{ast::Builtin::kPosition, ast::StorageClass::kInput, SpvBuiltInFragCoord}, BuiltinData{ast::Builtin::kPosition, ast::StorageClass::kIn, SpvBuiltInFragCoord},
BuiltinData{ast::Builtin::kPosition, ast::StorageClass::kOutput, SpvBuiltInPosition}, BuiltinData{ast::Builtin::kPosition, ast::StorageClass::kOut, SpvBuiltInPosition},
BuiltinData{ BuiltinData{
ast::Builtin::kVertexIndex, ast::Builtin::kVertexIndex,
ast::StorageClass::kInput, ast::StorageClass::kIn,
SpvBuiltInVertexIndex, SpvBuiltInVertexIndex,
}, },
BuiltinData{ast::Builtin::kInstanceIndex, ast::StorageClass::kInput, BuiltinData{ast::Builtin::kInstanceIndex, ast::StorageClass::kIn, SpvBuiltInInstanceIndex},
SpvBuiltInInstanceIndex}, BuiltinData{ast::Builtin::kFrontFacing, ast::StorageClass::kIn, SpvBuiltInFrontFacing},
BuiltinData{ast::Builtin::kFrontFacing, ast::StorageClass::kInput, SpvBuiltInFrontFacing}, BuiltinData{ast::Builtin::kFragDepth, ast::StorageClass::kOut, SpvBuiltInFragDepth},
BuiltinData{ast::Builtin::kFragDepth, ast::StorageClass::kOutput, SpvBuiltInFragDepth}, BuiltinData{ast::Builtin::kLocalInvocationId, ast::StorageClass::kIn,
BuiltinData{ast::Builtin::kLocalInvocationId, ast::StorageClass::kInput,
SpvBuiltInLocalInvocationId}, SpvBuiltInLocalInvocationId},
BuiltinData{ast::Builtin::kLocalInvocationIndex, ast::StorageClass::kInput, BuiltinData{ast::Builtin::kLocalInvocationIndex, ast::StorageClass::kIn,
SpvBuiltInLocalInvocationIndex}, SpvBuiltInLocalInvocationIndex},
BuiltinData{ast::Builtin::kGlobalInvocationId, ast::StorageClass::kInput, BuiltinData{ast::Builtin::kGlobalInvocationId, ast::StorageClass::kIn,
SpvBuiltInGlobalInvocationId}, SpvBuiltInGlobalInvocationId},
BuiltinData{ast::Builtin::kWorkgroupId, ast::StorageClass::kInput, SpvBuiltInWorkgroupId}, BuiltinData{ast::Builtin::kWorkgroupId, ast::StorageClass::kIn, SpvBuiltInWorkgroupId},
BuiltinData{ast::Builtin::kNumWorkgroups, ast::StorageClass::kInput, BuiltinData{ast::Builtin::kNumWorkgroups, ast::StorageClass::kIn, SpvBuiltInNumWorkgroups},
SpvBuiltInNumWorkgroups}, BuiltinData{ast::Builtin::kSampleIndex, ast::StorageClass::kIn, SpvBuiltInSampleId},
BuiltinData{ast::Builtin::kSampleIndex, ast::StorageClass::kInput, SpvBuiltInSampleId}, BuiltinData{ast::Builtin::kSampleMask, ast::StorageClass::kIn, SpvBuiltInSampleMask},
BuiltinData{ast::Builtin::kSampleMask, ast::StorageClass::kInput, SpvBuiltInSampleMask}, BuiltinData{ast::Builtin::kSampleMask, ast::StorageClass::kOut, SpvBuiltInSampleMask}));
BuiltinData{ast::Builtin::kSampleMask, ast::StorageClass::kOutput, SpvBuiltInSampleMask}));
TEST_F(BuilderTest, GlobalVar_DeclReadOnly) { TEST_F(BuilderTest, GlobalVar_DeclReadOnly) {
// struct A { // struct A {

View File

@ -299,7 +299,7 @@ TEST_F(BuilderTest_Type, ReturnsGeneratedF16Matrix) {
TEST_F(BuilderTest_Type, GeneratePtr) { TEST_F(BuilderTest_Type, GeneratePtr) {
auto* i32 = create<sem::I32>(); auto* i32 = create<sem::I32>();
auto* ptr = create<sem::Pointer>(i32, ast::StorageClass::kOutput, ast::Access::kReadWrite); auto* ptr = create<sem::Pointer>(i32, ast::StorageClass::kOut, ast::Access::kReadWrite);
spirv::Builder& b = Build(); spirv::Builder& b = Build();
@ -314,7 +314,7 @@ TEST_F(BuilderTest_Type, GeneratePtr) {
TEST_F(BuilderTest_Type, ReturnsGeneratedPtr) { TEST_F(BuilderTest_Type, ReturnsGeneratedPtr) {
auto* i32 = create<sem::I32>(); auto* i32 = create<sem::I32>();
auto* ptr = create<sem::Pointer>(i32, ast::StorageClass::kOutput, ast::Access::kReadWrite); auto* ptr = create<sem::Pointer>(i32, ast::StorageClass::kOut, ast::Access::kReadWrite);
spirv::Builder& b = Build(); spirv::Builder& b = Build();
@ -601,8 +601,8 @@ INSTANTIATE_TEST_SUITE_P(
BuilderTest_Type, BuilderTest_Type,
PtrDataTest, PtrDataTest,
testing::Values(PtrData{ast::StorageClass::kNone, SpvStorageClassMax}, testing::Values(PtrData{ast::StorageClass::kNone, SpvStorageClassMax},
PtrData{ast::StorageClass::kInput, SpvStorageClassInput}, PtrData{ast::StorageClass::kIn, SpvStorageClassInput},
PtrData{ast::StorageClass::kOutput, SpvStorageClassOutput}, PtrData{ast::StorageClass::kOut, SpvStorageClassOutput},
PtrData{ast::StorageClass::kUniform, SpvStorageClassUniform}, PtrData{ast::StorageClass::kUniform, SpvStorageClassUniform},
PtrData{ast::StorageClass::kWorkgroup, SpvStorageClassWorkgroup}, PtrData{ast::StorageClass::kWorkgroup, SpvStorageClassWorkgroup},
PtrData{ast::StorageClass::kHandle, SpvStorageClassUniformConstant}, PtrData{ast::StorageClass::kHandle, SpvStorageClassUniformConstant},

View File

@ -16,7 +16,7 @@ struct PointLight {
}; };
@binding(0) @group(0) var<uniform> uniforms : Uniforms; @binding(0) @group(0) var<uniform> uniforms : Uniforms;
@binding(1) @group(0) var<storage_buffer, read> pointLights : PointLights; @binding(1) @group(0) var<storage, read> pointLights : PointLights;
@binding(2) @group(0) var mySampler: sampler; @binding(2) @group(0) var mySampler: sampler;
@binding(3) @group(0) var myTexture: texture_2d<f32>; @binding(3) @group(0) var myTexture: texture_2d<f32>;

View File

@ -9,7 +9,7 @@
}; };
@group(0) @binding(0) var src : texture_2d<f32>; @group(0) @binding(0) var src : texture_2d<f32>;
@group(0) @binding(1) var dst : texture_2d<f32>; @group(0) @binding(1) var dst : texture_2d<f32>;
@group(0) @binding(2) var<storage_buffer, read_write> output : OutputBuf; @group(0) @binding(2) var<storage, read_write> output : OutputBuf;
@group(0) @binding(3) var<uniform> uniforms : Uniforms; @group(0) @binding(3) var<uniform> uniforms : Uniforms;
//@builtin(global_invocation_id) var<in> GlobalInvocationID : vec3<u32>; //@builtin(global_invocation_id) var<in> GlobalInvocationID : vec3<u32>;
// Fp16 logic // Fp16 logic