Add support for override keyword and @id attribute
This replaces the @override keyword that was previously used for pipeline-overridable constants. Support for pipeline-overridable constants in Dawn is hidden behind the "disallow-unsafe-APIs" toggle, so we can make this change directly instead of deprecating and continuing to support the old syntax. Fixed: tint:1403 Change-Id: I9b2957a1e33b12772bfe449c0f3a31d929f8aa8b Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/80480 Reviewed-by: Ben Clayton <bclayton@google.com> Kokoro: Kokoro <noreply+kokoro@google.com> Commit-Queue: James Price <jrprice@google.com>
This commit is contained in:
parent
5f60eb72c0
commit
d0ec88ce61
|
@ -11,6 +11,7 @@
|
|||
### New Features
|
||||
|
||||
* Module-scope declarations can now be declared in any order. [tint:1266](crbug.com/tint/1266)
|
||||
* The `override` keyword and `@id()` attribute for pipeline-overridable constants are now supported, replacing the `@override` attribute. [tint:1403](crbug.com/tint/1403)
|
||||
|
||||
## Changes for M99
|
||||
|
||||
|
|
|
@ -240,6 +240,8 @@ libtint_source_set("libtint_core_all_src") {
|
|||
"ast/group_attribute.h",
|
||||
"ast/i32.cc",
|
||||
"ast/i32.h",
|
||||
"ast/id_attribute.cc",
|
||||
"ast/id_attribute.h",
|
||||
"ast/identifier_expression.cc",
|
||||
"ast/identifier_expression.h",
|
||||
"ast/if_statement.cc",
|
||||
|
@ -270,8 +272,6 @@ libtint_source_set("libtint_core_all_src") {
|
|||
"ast/multisampled_texture.h",
|
||||
"ast/node.cc",
|
||||
"ast/node.h",
|
||||
"ast/override_attribute.cc",
|
||||
"ast/override_attribute.h",
|
||||
"ast/phony_expression.cc",
|
||||
"ast/phony_expression.h",
|
||||
"ast/pipeline_stage.cc",
|
||||
|
|
|
@ -123,6 +123,8 @@ set(TINT_LIB_SRCS
|
|||
ast/group_attribute.h
|
||||
ast/i32.cc
|
||||
ast/i32.h
|
||||
ast/id_attribute.cc
|
||||
ast/id_attribute.h
|
||||
ast/identifier_expression.cc
|
||||
ast/identifier_expression.h
|
||||
ast/if_statement.cc
|
||||
|
@ -151,8 +153,6 @@ set(TINT_LIB_SRCS
|
|||
ast/multisampled_texture.h
|
||||
ast/node.cc
|
||||
ast/node.h
|
||||
ast/override_attribute.cc
|
||||
ast/override_attribute.h
|
||||
ast/phony_expression.cc
|
||||
ast/phony_expression.h
|
||||
ast/pipeline_stage.cc
|
||||
|
@ -659,6 +659,7 @@ if(TINT_BUILD_TESTS)
|
|||
ast/function_test.cc
|
||||
ast/group_attribute_test.cc
|
||||
ast/i32_test.cc
|
||||
ast/id_attribute_test.cc
|
||||
ast/identifier_expression_test.cc
|
||||
ast/if_statement_test.cc
|
||||
ast/index_accessor_expression_test.cc
|
||||
|
@ -672,7 +673,6 @@ if(TINT_BUILD_TESTS)
|
|||
ast/module_clone_test.cc
|
||||
ast/module_test.cc
|
||||
ast/multisampled_texture_test.cc
|
||||
ast/override_attribute_test.cc
|
||||
ast/phony_expression_test.cc
|
||||
ast/pointer_test.cc
|
||||
ast/return_statement_test.cc
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "src/ast/override_attribute.h"
|
||||
#include "src/ast/test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
// Copyright 2022 The Tint Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "src/ast/id_attribute.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "src/program_builder.h"
|
||||
|
||||
TINT_INSTANTIATE_TYPEINFO(tint::ast::IdAttribute);
|
||||
|
||||
namespace tint {
|
||||
namespace ast {
|
||||
|
||||
IdAttribute::IdAttribute(ProgramID pid, const Source& src, uint32_t val)
|
||||
: Base(pid, src), value(val) {}
|
||||
|
||||
IdAttribute::~IdAttribute() = default;
|
||||
|
||||
std::string IdAttribute::Name() const {
|
||||
return "id";
|
||||
}
|
||||
|
||||
const IdAttribute* IdAttribute::Clone(CloneContext* ctx) const {
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
return ctx->dst->create<IdAttribute>(src, value);
|
||||
}
|
||||
|
||||
} // namespace ast
|
||||
} // namespace tint
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright 2020 The Tint Authors.
|
||||
// Copyright 2022 The Tint Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
@ -12,8 +12,8 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef SRC_AST_OVERRIDE_ATTRIBUTE_H_
|
||||
#define SRC_AST_OVERRIDE_ATTRIBUTE_H_
|
||||
#ifndef SRC_AST_ID_ATTRIBUTE_H_
|
||||
#define SRC_AST_ID_ATTRIBUTE_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
|
@ -22,19 +22,15 @@
|
|||
namespace tint {
|
||||
namespace ast {
|
||||
|
||||
/// An override attribute
|
||||
class OverrideAttribute : public Castable<OverrideAttribute, Attribute> {
|
||||
/// An id attribute for pipeline-overridable constants
|
||||
class IdAttribute : public Castable<IdAttribute, Attribute> {
|
||||
public:
|
||||
/// Create an override attribute with no specified id.
|
||||
/// Create an id attribute.
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
OverrideAttribute(ProgramID pid, const Source& src);
|
||||
/// Create an override attribute with a specific id value.
|
||||
/// @param pid the identifier of the program that owns this node
|
||||
/// @param src the source of this node
|
||||
/// @param val the override value
|
||||
OverrideAttribute(ProgramID pid, const Source& src, uint32_t val);
|
||||
~OverrideAttribute() override;
|
||||
/// @param val the numeric id value
|
||||
IdAttribute(ProgramID pid, const Source& src, uint32_t val);
|
||||
~IdAttribute() override;
|
||||
|
||||
/// @returns the WGSL name for the attribute
|
||||
std::string Name() const override;
|
||||
|
@ -43,16 +39,13 @@ class OverrideAttribute : public Castable<OverrideAttribute, Attribute> {
|
|||
/// `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const OverrideAttribute* Clone(CloneContext* ctx) const override;
|
||||
const IdAttribute* Clone(CloneContext* ctx) const override;
|
||||
|
||||
/// True if an override id was specified
|
||||
const bool has_value;
|
||||
|
||||
/// The override id value
|
||||
/// The id value
|
||||
const uint32_t value;
|
||||
};
|
||||
|
||||
} // namespace ast
|
||||
} // namespace tint
|
||||
|
||||
#endif // SRC_AST_OVERRIDE_ATTRIBUTE_H_
|
||||
#endif // SRC_AST_ID_ATTRIBUTE_H_
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "src/ast/override_attribute.h"
|
||||
#include "src/ast/id_attribute.h"
|
||||
|
||||
#include "src/ast/test_helper.h"
|
||||
|
||||
|
@ -20,19 +20,13 @@ namespace tint {
|
|||
namespace ast {
|
||||
namespace {
|
||||
|
||||
using OverrideAttributeTest = TestHelper;
|
||||
using IdAttributeTest = TestHelper;
|
||||
|
||||
TEST_F(OverrideAttributeTest, Creation_WithValue) {
|
||||
auto* d = create<OverrideAttribute>(12);
|
||||
EXPECT_TRUE(d->has_value);
|
||||
TEST_F(IdAttributeTest, Creation) {
|
||||
auto* d = create<IdAttribute>(12);
|
||||
EXPECT_EQ(12u, d->value);
|
||||
}
|
||||
|
||||
TEST_F(OverrideAttributeTest, Creation_WithoutValue) {
|
||||
auto* d = create<OverrideAttribute>();
|
||||
EXPECT_FALSE(d->has_value);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace ast
|
||||
} // namespace tint
|
|
@ -12,7 +12,6 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "src/ast/override_attribute.h"
|
||||
#include "src/ast/test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
// Copyright 2020 The Tint Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "src/ast/override_attribute.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "src/program_builder.h"
|
||||
|
||||
TINT_INSTANTIATE_TYPEINFO(tint::ast::OverrideAttribute);
|
||||
|
||||
namespace tint {
|
||||
namespace ast {
|
||||
|
||||
OverrideAttribute::OverrideAttribute(ProgramID pid, const Source& src)
|
||||
: Base(pid, src), has_value(false), value(0) {}
|
||||
|
||||
OverrideAttribute::OverrideAttribute(ProgramID pid,
|
||||
const Source& src,
|
||||
uint32_t val)
|
||||
: Base(pid, src), has_value(true), value(val) {}
|
||||
|
||||
OverrideAttribute::~OverrideAttribute() = default;
|
||||
|
||||
std::string OverrideAttribute::Name() const {
|
||||
return "override";
|
||||
}
|
||||
|
||||
const OverrideAttribute* OverrideAttribute::Clone(CloneContext* ctx) const {
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
if (has_value) {
|
||||
return ctx->dst->create<OverrideAttribute>(src, value);
|
||||
} else {
|
||||
return ctx->dst->create<OverrideAttribute>(src);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ast
|
||||
} // namespace tint
|
|
@ -14,7 +14,6 @@
|
|||
|
||||
#include "src/ast/variable.h"
|
||||
|
||||
#include "src/ast/override_attribute.h"
|
||||
#include "src/program_builder.h"
|
||||
#include "src/sem/variable.h"
|
||||
|
||||
|
@ -30,17 +29,20 @@ Variable::Variable(ProgramID pid,
|
|||
Access da,
|
||||
const ast::Type* ty,
|
||||
bool constant,
|
||||
bool overridable,
|
||||
const Expression* ctor,
|
||||
AttributeList attrs)
|
||||
: Base(pid, src),
|
||||
symbol(sym),
|
||||
type(ty),
|
||||
is_const(constant),
|
||||
is_overridable(overridable),
|
||||
constructor(ctor),
|
||||
attributes(std::move(attrs)),
|
||||
declared_storage_class(dsc),
|
||||
declared_access(da) {
|
||||
TINT_ASSERT(AST, symbol.IsValid());
|
||||
TINT_ASSERT(AST, is_overridable ? is_const : true);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, symbol, program_id);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, constructor, program_id);
|
||||
}
|
||||
|
@ -69,7 +71,8 @@ const Variable* Variable::Clone(CloneContext* ctx) const {
|
|||
auto* ctor = ctx->Clone(constructor);
|
||||
auto attrs = ctx->Clone(attributes);
|
||||
return ctx->dst->create<Variable>(src, sym, declared_storage_class,
|
||||
declared_access, ty, is_const, ctor, attrs);
|
||||
declared_access, ty, is_const,
|
||||
is_overridable, ctor, attrs);
|
||||
}
|
||||
|
||||
} // namespace ast
|
||||
|
|
|
@ -46,8 +46,9 @@ struct VariableBindingPoint {
|
|||
|
||||
/// A Variable statement.
|
||||
///
|
||||
/// An instance of this class represents one of three constructs in WGSL: "var"
|
||||
/// declaration, "let" declaration, or formal parameter to a function.
|
||||
/// An instance of this class represents one of four constructs in WGSL: "var"
|
||||
/// declaration, "let" declaration, "override" declaration, or formal parameter
|
||||
/// to a function.
|
||||
///
|
||||
/// 1. A "var" declaration is a name for typed storage. Examples:
|
||||
///
|
||||
|
@ -65,7 +66,14 @@ struct VariableBindingPoint {
|
|||
///
|
||||
/// let twice_depth : i32 = width + width; // Must have initializer
|
||||
///
|
||||
/// 3. A formal parameter to a function is a name for a typed value to
|
||||
/// 3. An "override" declaration is a name for a pipeline-overridable constant.
|
||||
/// Examples:
|
||||
///
|
||||
/// override radius : i32 = 2; // Can be overridden by name.
|
||||
/// @id(5) override width : i32 = 2; // Can be overridden by ID.
|
||||
/// override scale : f32; // No default - must be overridden.
|
||||
///
|
||||
/// 4. A formal parameter to a function is a name for a typed value to
|
||||
/// be passed into a function. Example:
|
||||
///
|
||||
/// fn twice(a: i32) -> i32 { // "a:i32" is the formal parameter
|
||||
|
@ -84,14 +92,22 @@ struct VariableBindingPoint {
|
|||
///
|
||||
/// This class uses the term "type" to refer to:
|
||||
/// the value type of a "let",
|
||||
/// the value type of an "override",
|
||||
/// the value type of the formal parameter,
|
||||
/// or the store type of the "var".
|
||||
//
|
||||
/// Setting is_const:
|
||||
/// - "var" gets false
|
||||
/// - "let" gets true
|
||||
/// - "override" gets true
|
||||
/// - formal parameter gets true
|
||||
///
|
||||
/// Setting is_overrideable:
|
||||
/// - "var" gets false
|
||||
/// - "let" gets false
|
||||
/// - "override" gets true
|
||||
/// - formal parameter gets false
|
||||
///
|
||||
/// Setting storage class:
|
||||
/// - "var" is StorageClass::kNone when using the
|
||||
/// defaulting syntax for a "var" declared inside a function.
|
||||
|
@ -107,6 +123,7 @@ class Variable : public Castable<Variable, Node> {
|
|||
/// @param declared_access the declared access control
|
||||
/// @param type the declared variable type
|
||||
/// @param is_const true if the variable is const
|
||||
/// @param is_overridable true if the variable is pipeline-overridable
|
||||
/// @param constructor the constructor expression
|
||||
/// @param attributes the variable attributes
|
||||
Variable(ProgramID program_id,
|
||||
|
@ -116,6 +133,7 @@ class Variable : public Castable<Variable, Node> {
|
|||
Access declared_access,
|
||||
const ast::Type* type,
|
||||
bool is_const,
|
||||
bool is_overridable,
|
||||
const Expression* constructor,
|
||||
AttributeList attributes);
|
||||
/// Move constructor
|
||||
|
@ -143,6 +161,9 @@ class Variable : public Castable<Variable, Node> {
|
|||
/// True if this is a constant, false otherwise
|
||||
const bool is_const;
|
||||
|
||||
/// True if this is a pipeline-overridable constant, false otherwise
|
||||
const bool is_overridable;
|
||||
|
||||
/// The constructor expression or nullptr if none set
|
||||
const Expression* const constructor;
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
// limitations under the License.
|
||||
|
||||
#include "gtest/gtest-spi.h"
|
||||
#include "src/ast/override_attribute.h"
|
||||
#include "src/ast/id_attribute.h"
|
||||
#include "src/ast/test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
|
@ -96,13 +96,13 @@ TEST_F(VariableTest, WithAttributes) {
|
|||
AttributeList{
|
||||
create<LocationAttribute>(1),
|
||||
create<BuiltinAttribute>(Builtin::kPosition),
|
||||
create<OverrideAttribute>(1200),
|
||||
create<IdAttribute>(1200),
|
||||
});
|
||||
|
||||
auto& attributes = var->attributes;
|
||||
EXPECT_TRUE(ast::HasAttribute<ast::LocationAttribute>(attributes));
|
||||
EXPECT_TRUE(ast::HasAttribute<ast::BuiltinAttribute>(attributes));
|
||||
EXPECT_TRUE(ast::HasAttribute<ast::OverrideAttribute>(attributes));
|
||||
EXPECT_TRUE(ast::HasAttribute<ast::IdAttribute>(attributes));
|
||||
|
||||
auto* location = ast::GetAttribute<ast::LocationAttribute>(attributes);
|
||||
ASSERT_NE(nullptr, location);
|
||||
|
|
|
@ -20,10 +20,10 @@
|
|||
#include "src/ast/bool_literal_expression.h"
|
||||
#include "src/ast/call_expression.h"
|
||||
#include "src/ast/float_literal_expression.h"
|
||||
#include "src/ast/id_attribute.h"
|
||||
#include "src/ast/interpolate_attribute.h"
|
||||
#include "src/ast/location_attribute.h"
|
||||
#include "src/ast/module.h"
|
||||
#include "src/ast/override_attribute.h"
|
||||
#include "src/ast/sint_literal_expression.h"
|
||||
#include "src/ast/uint_literal_expression.h"
|
||||
#include "src/sem/array.h"
|
||||
|
@ -213,10 +213,9 @@ std::vector<EntryPoint> Inspector::GetEntryPoints() {
|
|||
|
||||
overridable_constant.is_initialized =
|
||||
global->Declaration()->constructor;
|
||||
auto* override_attr = ast::GetAttribute<ast::OverrideAttribute>(
|
||||
global->Declaration()->attributes);
|
||||
overridable_constant.is_numeric_id_specified =
|
||||
override_attr ? override_attr->has_value : false;
|
||||
ast::HasAttribute<ast::IdAttribute>(
|
||||
global->Declaration()->attributes);
|
||||
|
||||
entry_point.overridable_constants.push_back(overridable_constant);
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
#include "gtest/gtest.h"
|
||||
#include "src/ast/call_statement.h"
|
||||
#include "src/ast/disable_validation_attribute.h"
|
||||
#include "src/ast/override_attribute.h"
|
||||
#include "src/ast/stage_attribute.h"
|
||||
#include "src/ast/struct_block_attribute.h"
|
||||
#include "src/ast/workgroup_attribute.h"
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
#include "src/ast/call_statement.h"
|
||||
#include "src/ast/disable_validation_attribute.h"
|
||||
#include "src/ast/override_attribute.h"
|
||||
#include "src/ast/id_attribute.h"
|
||||
#include "src/ast/stage_attribute.h"
|
||||
#include "src/ast/struct_block_attribute.h"
|
||||
#include "src/ast/workgroup_attribute.h"
|
||||
|
@ -109,10 +109,7 @@ class InspectorBuilder : public ProgramBuilder {
|
|||
uint32_t id,
|
||||
const ast::Type* type,
|
||||
const ast::Expression* constructor) {
|
||||
return GlobalConst(name, type, constructor,
|
||||
ast::AttributeList{
|
||||
Override(id),
|
||||
});
|
||||
return Override(name, type, constructor, {Id(id)});
|
||||
}
|
||||
|
||||
/// Add a pipeline constant to the global variables, without a specific ID.
|
||||
|
@ -125,10 +122,7 @@ class InspectorBuilder : public ProgramBuilder {
|
|||
std::string name,
|
||||
const ast::Type* type,
|
||||
const ast::Expression* constructor) {
|
||||
return GlobalConst(name, type, constructor,
|
||||
ast::AttributeList{
|
||||
Override(),
|
||||
});
|
||||
return Override(name, type, constructor);
|
||||
}
|
||||
|
||||
/// Generates a function that references module-scoped, plain-typed constant
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "src/ast/float_literal_expression.h"
|
||||
#include "src/ast/for_loop_statement.h"
|
||||
#include "src/ast/i32.h"
|
||||
#include "src/ast/id_attribute.h"
|
||||
#include "src/ast/if_statement.h"
|
||||
#include "src/ast/index_accessor_expression.h"
|
||||
#include "src/ast/interpolate_attribute.h"
|
||||
|
@ -52,7 +53,6 @@
|
|||
#include "src/ast/member_accessor_expression.h"
|
||||
#include "src/ast/module.h"
|
||||
#include "src/ast/multisampled_texture.h"
|
||||
#include "src/ast/override_attribute.h"
|
||||
#include "src/ast/phony_expression.h"
|
||||
#include "src/ast/pointer.h"
|
||||
#include "src/ast/return_statement.h"
|
||||
|
@ -1333,7 +1333,8 @@ class ProgramBuilder {
|
|||
OPTIONAL&&... optional) {
|
||||
VarOptionals opts(std::forward<OPTIONAL>(optional)...);
|
||||
return create<ast::Variable>(Sym(std::forward<NAME>(name)), opts.storage,
|
||||
opts.access, type, false, opts.constructor,
|
||||
opts.access, type, false /* is_const */,
|
||||
false /* is_overridable */, opts.constructor,
|
||||
std::move(opts.attributes));
|
||||
}
|
||||
|
||||
|
@ -1355,9 +1356,10 @@ class ProgramBuilder {
|
|||
const ast::Type* type,
|
||||
OPTIONAL&&... optional) {
|
||||
VarOptionals opts(std::forward<OPTIONAL>(optional)...);
|
||||
return create<ast::Variable>(source, Sym(std::forward<NAME>(name)),
|
||||
opts.storage, opts.access, type, false,
|
||||
opts.constructor, std::move(opts.attributes));
|
||||
return create<ast::Variable>(
|
||||
source, Sym(std::forward<NAME>(name)), opts.storage, opts.access, type,
|
||||
false /* is_const */, false /* is_overridable */, opts.constructor,
|
||||
std::move(opts.attributes));
|
||||
}
|
||||
|
||||
/// @param name the variable name
|
||||
|
@ -1372,7 +1374,8 @@ class ProgramBuilder {
|
|||
ast::AttributeList attributes = {}) {
|
||||
return create<ast::Variable>(
|
||||
Sym(std::forward<NAME>(name)), ast::StorageClass::kNone,
|
||||
ast::Access::kUndefined, type, true, constructor, attributes);
|
||||
ast::Access::kUndefined, type, true /* is_const */,
|
||||
false /* is_overridable */, constructor, attributes);
|
||||
}
|
||||
|
||||
/// @param source the variable source
|
||||
|
@ -1389,7 +1392,8 @@ class ProgramBuilder {
|
|||
ast::AttributeList attributes = {}) {
|
||||
return create<ast::Variable>(
|
||||
source, Sym(std::forward<NAME>(name)), ast::StorageClass::kNone,
|
||||
ast::Access::kUndefined, type, true, constructor, attributes);
|
||||
ast::Access::kUndefined, type, true /* is_const */,
|
||||
false /* is_overridable */, constructor, attributes);
|
||||
}
|
||||
|
||||
/// @param name the parameter name
|
||||
|
@ -1402,7 +1406,8 @@ class ProgramBuilder {
|
|||
ast::AttributeList attributes = {}) {
|
||||
return create<ast::Variable>(
|
||||
Sym(std::forward<NAME>(name)), ast::StorageClass::kNone,
|
||||
ast::Access::kUndefined, type, true, nullptr, attributes);
|
||||
ast::Access::kUndefined, type, true /* is_const */,
|
||||
false /* is_overridable */, nullptr, attributes);
|
||||
}
|
||||
|
||||
/// @param source the parameter source
|
||||
|
@ -1417,7 +1422,8 @@ class ProgramBuilder {
|
|||
ast::AttributeList attributes = {}) {
|
||||
return create<ast::Variable>(
|
||||
source, Sym(std::forward<NAME>(name)), ast::StorageClass::kNone,
|
||||
ast::Access::kUndefined, type, true, nullptr, attributes);
|
||||
ast::Access::kUndefined, type, true /* is_const */,
|
||||
false /* is_overridable */, nullptr, attributes);
|
||||
}
|
||||
|
||||
/// @param name the variable name
|
||||
|
@ -1506,6 +1512,47 @@ class ProgramBuilder {
|
|||
return var;
|
||||
}
|
||||
|
||||
/// @param name the variable name
|
||||
/// @param type the variable type
|
||||
/// @param constructor optional constructor expression
|
||||
/// @param attributes optional variable attributes
|
||||
/// @returns an overridable const `ast::Variable` which is automatically
|
||||
/// registered as a global variable with the ast::Module.
|
||||
template <typename NAME>
|
||||
const ast::Variable* Override(NAME&& name,
|
||||
const ast::Type* type,
|
||||
const ast::Expression* constructor,
|
||||
ast::AttributeList attributes = {}) {
|
||||
auto* var = create<ast::Variable>(
|
||||
source_, Sym(std::forward<NAME>(name)), ast::StorageClass::kNone,
|
||||
ast::Access::kUndefined, type, true /* is_const */,
|
||||
true /* is_overridable */, constructor, std::move(attributes));
|
||||
AST().AddGlobalVariable(var);
|
||||
return var;
|
||||
}
|
||||
|
||||
/// @param source the variable source
|
||||
/// @param name the variable name
|
||||
/// @param type the variable type
|
||||
/// @param constructor constructor expression
|
||||
/// @param attributes optional variable attributes
|
||||
/// @returns a const `ast::Variable` constructed by calling Var() with the
|
||||
/// arguments of `args`, which is automatically registered as a global
|
||||
/// variable with the ast::Module.
|
||||
template <typename NAME>
|
||||
const ast::Variable* Override(const Source& source,
|
||||
NAME&& name,
|
||||
const ast::Type* type,
|
||||
const ast::Expression* constructor,
|
||||
ast::AttributeList attributes = {}) {
|
||||
auto* var = create<ast::Variable>(
|
||||
source, Sym(std::forward<NAME>(name)), ast::StorageClass::kNone,
|
||||
ast::Access::kUndefined, type, true /* is_const */,
|
||||
true /* is_overridable */, constructor, std::move(attributes));
|
||||
AST().AddGlobalVariable(var);
|
||||
return var;
|
||||
}
|
||||
|
||||
/// @param source the source information
|
||||
/// @param expr the expression to take the address of
|
||||
/// @return an ast::UnaryOpExpression that takes the address of `expr`
|
||||
|
@ -2382,31 +2429,18 @@ class ProgramBuilder {
|
|||
return create<ast::LocationAttribute>(source_, location);
|
||||
}
|
||||
|
||||
/// Creates an ast::OverrideAttribute with a specific constant ID
|
||||
/// Creates an ast::IdAttribute
|
||||
/// @param source the source information
|
||||
/// @param id the id value
|
||||
/// @returns the override attribute pointer
|
||||
const ast::OverrideAttribute* Override(const Source& source, uint32_t id) {
|
||||
return create<ast::OverrideAttribute>(source, id);
|
||||
const ast::IdAttribute* Id(const Source& source, uint32_t id) {
|
||||
return create<ast::IdAttribute>(source, id);
|
||||
}
|
||||
|
||||
/// Creates an ast::OverrideAttribute with a specific constant ID
|
||||
/// Creates an ast::IdAttribute with a constant ID
|
||||
/// @param id the optional id value
|
||||
/// @returns the override attribute pointer
|
||||
const ast::OverrideAttribute* Override(uint32_t id) {
|
||||
return Override(source_, id);
|
||||
}
|
||||
|
||||
/// Creates an ast::OverrideAttribute without a constant ID
|
||||
/// @param source the source information
|
||||
/// @returns the override attribute pointer
|
||||
const ast::OverrideAttribute* Override(const Source& source) {
|
||||
return create<ast::OverrideAttribute>(source);
|
||||
}
|
||||
|
||||
/// Creates an ast::OverrideAttribute without a constant ID
|
||||
/// @returns the override attribute pointer
|
||||
const ast::OverrideAttribute* Override() { return Override(source_); }
|
||||
const ast::IdAttribute* Id(uint32_t id) { return Id(source_, id); }
|
||||
|
||||
/// Creates an ast::StageAttribute
|
||||
/// @param source the source information
|
||||
|
|
|
@ -1440,8 +1440,8 @@ bool FunctionEmitter::ParseFunctionDeclaration(FunctionDeclaration* decl) {
|
|||
auto* type = parser_impl_.ConvertType(param->type_id());
|
||||
if (type != nullptr) {
|
||||
auto* ast_param = parser_impl_.MakeVariable(
|
||||
param->result_id(), ast::StorageClass::kNone, type, true, nullptr,
|
||||
ast::AttributeList{});
|
||||
param->result_id(), ast::StorageClass::kNone, type, true, false,
|
||||
nullptr, ast::AttributeList{});
|
||||
// Parameters are treated as const declarations.
|
||||
ast_params.emplace_back(ast_param);
|
||||
// The value is accessible by name.
|
||||
|
@ -2542,7 +2542,7 @@ bool FunctionEmitter::EmitFunctionVariables() {
|
|||
}
|
||||
auto* var = parser_impl_.MakeVariable(
|
||||
inst.result_id(), ast::StorageClass::kNone, var_store_type, false,
|
||||
constructor, ast::AttributeList{});
|
||||
false, constructor, ast::AttributeList{});
|
||||
auto* var_decl_stmt = create<ast::VariableDeclStatement>(Source{}, var);
|
||||
AddStatement(var_decl_stmt);
|
||||
auto* var_type = ty_.Reference(var_store_type, ast::StorageClass::kNone);
|
||||
|
@ -3444,9 +3444,9 @@ bool FunctionEmitter::EmitStatementsInBasicBlock(const BlockInfo& block_info,
|
|||
auto* storage_type =
|
||||
RemapStorageClass(parser_impl_.ConvertType(def_inst->type_id()), id);
|
||||
AddStatement(create<ast::VariableDeclStatement>(
|
||||
Source{},
|
||||
parser_impl_.MakeVariable(id, ast::StorageClass::kNone, storage_type,
|
||||
false, nullptr, ast::AttributeList{})));
|
||||
Source{}, parser_impl_.MakeVariable(id, ast::StorageClass::kNone,
|
||||
storage_type, false, false, nullptr,
|
||||
ast::AttributeList{})));
|
||||
auto* type = ty_.Reference(storage_type, ast::StorageClass::kNone);
|
||||
identifier_types_.emplace(id, type);
|
||||
}
|
||||
|
@ -3518,8 +3518,8 @@ bool FunctionEmitter::EmitConstDefinition(
|
|||
|
||||
expr = AddressOfIfNeeded(expr, &inst);
|
||||
auto* ast_const = parser_impl_.MakeVariable(
|
||||
inst.result_id(), ast::StorageClass::kNone, expr.type, true, expr.expr,
|
||||
ast::AttributeList{});
|
||||
inst.result_id(), ast::StorageClass::kNone, expr.type, true, false,
|
||||
expr.expr, ast::AttributeList{});
|
||||
if (!ast_const) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -22,8 +22,8 @@
|
|||
#include "source/opt/build_module.h"
|
||||
#include "src/ast/bitcast_expression.h"
|
||||
#include "src/ast/disable_validation_attribute.h"
|
||||
#include "src/ast/id_attribute.h"
|
||||
#include "src/ast/interpolate_attribute.h"
|
||||
#include "src/ast/override_attribute.h"
|
||||
#include "src/ast/type_name.h"
|
||||
#include "src/ast/unary_op_expression.h"
|
||||
#include "src/reader/spirv/function.h"
|
||||
|
@ -1395,14 +1395,14 @@ bool ParserImpl::EmitScalarSpecConstants() {
|
|||
"between 0 and 65535: ID %"
|
||||
<< inst.result_id() << " has SpecId " << id;
|
||||
}
|
||||
auto* cid = create<ast::OverrideAttribute>(Source{}, id);
|
||||
auto* cid = create<ast::IdAttribute>(Source{}, id);
|
||||
spec_id_decos.push_back(cid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
auto* ast_var =
|
||||
MakeVariable(inst.result_id(), ast::StorageClass::kNone, ast_type,
|
||||
true, ast_expr, std::move(spec_id_decos));
|
||||
true, true, ast_expr, std::move(spec_id_decos));
|
||||
if (ast_var) {
|
||||
builder_.AST().AddGlobalVariable(ast_var);
|
||||
scalar_spec_constants_.insert(inst.result_id());
|
||||
|
@ -1526,7 +1526,7 @@ bool ParserImpl::EmitModuleScopeVariables() {
|
|||
}
|
||||
auto* ast_var =
|
||||
MakeVariable(var.result_id(), ast_storage_class, ast_store_type, false,
|
||||
ast_constructor, ast::AttributeList{});
|
||||
false, ast_constructor, ast::AttributeList{});
|
||||
// TODO(dneto): initializers (a.k.a. constructor expression)
|
||||
if (ast_var) {
|
||||
builder_.AST().AddGlobalVariable(ast_var);
|
||||
|
@ -1561,7 +1561,7 @@ bool ParserImpl::EmitModuleScopeVariables() {
|
|||
auto* ast_var = MakeVariable(
|
||||
builtin_position_.per_vertex_var_id,
|
||||
enum_converter_.ToStorageClass(builtin_position_.storage_class),
|
||||
ConvertType(builtin_position_.position_member_type_id), false,
|
||||
ConvertType(builtin_position_.position_member_type_id), false, false,
|
||||
ast_constructor, {});
|
||||
|
||||
builder_.AST().AddGlobalVariable(ast_var);
|
||||
|
@ -1598,6 +1598,7 @@ ast::Variable* ParserImpl::MakeVariable(uint32_t id,
|
|||
ast::StorageClass sc,
|
||||
const Type* storage_type,
|
||||
bool is_const,
|
||||
bool is_overridable,
|
||||
const ast::Expression* constructor,
|
||||
ast::AttributeList decorations) {
|
||||
if (storage_type == nullptr) {
|
||||
|
@ -1630,12 +1631,12 @@ ast::Variable* ParserImpl::MakeVariable(uint32_t id,
|
|||
std::string name = namer_.Name(id);
|
||||
|
||||
// Note: we're constructing the variable here with the *storage* type,
|
||||
// regardless of whether this is a `let` or `var` declaration.
|
||||
// regardless of whether this is a `let`, `override`, or `var` declaration.
|
||||
// `var` declarations will have a resolved type of ref<storage>, but at the
|
||||
// AST level both `var` and `let` are declared with the same type.
|
||||
// AST level all three are declared with the same type.
|
||||
return create<ast::Variable>(Source{}, builder_.Symbols().Register(name), sc,
|
||||
access, storage_type->Build(builder_), is_const,
|
||||
constructor, decorations);
|
||||
is_overridable, constructor, decorations);
|
||||
}
|
||||
|
||||
bool ParserImpl::ConvertDecorationsForVariable(uint32_t id,
|
||||
|
|
|
@ -421,6 +421,7 @@ class ParserImpl : Reader {
|
|||
/// @param sc the storage class, which cannot be ast::StorageClass::kNone
|
||||
/// @param storage_type the storage type of the variable
|
||||
/// @param is_const if true, the variable is const
|
||||
/// @param is_overridable if true, the variable is pipeline-overridable
|
||||
/// @param constructor the variable constructor
|
||||
/// @param decorations the variable decorations
|
||||
/// @returns a new Variable node, or null in the ignorable variable case and
|
||||
|
@ -429,6 +430,7 @@ class ParserImpl : Reader {
|
|||
ast::StorageClass sc,
|
||||
const Type* storage_type,
|
||||
bool is_const,
|
||||
bool is_overridable,
|
||||
const ast::Expression* constructor,
|
||||
ast::AttributeList decorations);
|
||||
|
||||
|
|
|
@ -1655,7 +1655,7 @@ TEST_F(SpvModuleScopeVarParserTest, ScalarSpecConstant_DeclareConst_True) {
|
|||
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
|
||||
EXPECT_TRUE(p->error().empty());
|
||||
const auto module_str = test::ToString(p->program());
|
||||
EXPECT_THAT(module_str, HasSubstr("@override(12) let myconst : bool = true;"))
|
||||
EXPECT_THAT(module_str, HasSubstr("@id(12) override myconst : bool = true;"))
|
||||
<< module_str;
|
||||
}
|
||||
|
||||
|
@ -1671,8 +1671,7 @@ TEST_F(SpvModuleScopeVarParserTest, ScalarSpecConstant_DeclareConst_False) {
|
|||
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
|
||||
EXPECT_TRUE(p->error().empty());
|
||||
const auto module_str = test::ToString(p->program());
|
||||
EXPECT_THAT(module_str,
|
||||
HasSubstr("@override(12) let myconst : bool = false;"))
|
||||
EXPECT_THAT(module_str, HasSubstr("@id(12) override myconst : bool = false;"))
|
||||
<< module_str;
|
||||
}
|
||||
|
||||
|
@ -1688,7 +1687,7 @@ TEST_F(SpvModuleScopeVarParserTest, ScalarSpecConstant_DeclareConst_U32) {
|
|||
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
|
||||
EXPECT_TRUE(p->error().empty());
|
||||
const auto module_str = test::ToString(p->program());
|
||||
EXPECT_THAT(module_str, HasSubstr("@override(12) let myconst : u32 = 42u;"))
|
||||
EXPECT_THAT(module_str, HasSubstr("@id(12) override myconst : u32 = 42u;"))
|
||||
<< module_str;
|
||||
}
|
||||
|
||||
|
@ -1704,7 +1703,7 @@ TEST_F(SpvModuleScopeVarParserTest, ScalarSpecConstant_DeclareConst_I32) {
|
|||
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
|
||||
EXPECT_TRUE(p->error().empty());
|
||||
const auto module_str = test::ToString(p->program());
|
||||
EXPECT_THAT(module_str, HasSubstr("@override(12) let myconst : i32 = 42;"))
|
||||
EXPECT_THAT(module_str, HasSubstr("@id(12) override myconst : i32 = 42;"))
|
||||
<< module_str;
|
||||
}
|
||||
|
||||
|
@ -1720,7 +1719,7 @@ TEST_F(SpvModuleScopeVarParserTest, ScalarSpecConstant_DeclareConst_F32) {
|
|||
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
|
||||
EXPECT_TRUE(p->error().empty());
|
||||
const auto module_str = test::ToString(p->program());
|
||||
EXPECT_THAT(module_str, HasSubstr("@override(12) let myconst : f32 = 2.5;"))
|
||||
EXPECT_THAT(module_str, HasSubstr("@id(12) override myconst : f32 = 2.5;"))
|
||||
<< module_str;
|
||||
}
|
||||
|
||||
|
@ -1737,7 +1736,8 @@ TEST_F(SpvModuleScopeVarParserTest,
|
|||
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
|
||||
EXPECT_TRUE(p->error().empty());
|
||||
const auto module_str = test::ToString(p->program());
|
||||
EXPECT_THAT(module_str, HasSubstr("let myconst : f32 = 2.5;")) << module_str;
|
||||
EXPECT_THAT(module_str, HasSubstr("override myconst : f32 = 2.5;"))
|
||||
<< module_str;
|
||||
}
|
||||
|
||||
TEST_F(SpvModuleScopeVarParserTest, ScalarSpecConstant_UsedInFunction) {
|
||||
|
|
|
@ -996,6 +996,8 @@ Token Lexer::check_keyword(const Source& source, std::string_view str) {
|
|||
return {Token::Type::kMat4x3, source, "mat4x3"};
|
||||
if (str == "mat4x4")
|
||||
return {Token::Type::kMat4x4, source, "mat4x4"};
|
||||
if (str == "override")
|
||||
return {Token::Type::kOverride, source, "override"};
|
||||
if (str == "private")
|
||||
return {Token::Type::kPrivate, source, "private"};
|
||||
if (str == "ptr")
|
||||
|
|
|
@ -750,6 +750,7 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
TokenData{"mat4x2", Token::Type::kMat4x2},
|
||||
TokenData{"mat4x3", Token::Type::kMat4x3},
|
||||
TokenData{"mat4x4", Token::Type::kMat4x4},
|
||||
TokenData{"override", Token::Type::kOverride},
|
||||
TokenData{"private", Token::Type::kPrivate},
|
||||
TokenData{"ptr", Token::Type::kPtr},
|
||||
TokenData{"return", Token::Type::kReturn},
|
||||
|
|
|
@ -23,10 +23,10 @@
|
|||
#include "src/ast/discard_statement.h"
|
||||
#include "src/ast/external_texture.h"
|
||||
#include "src/ast/fallthrough_statement.h"
|
||||
#include "src/ast/id_attribute.h"
|
||||
#include "src/ast/if_statement.h"
|
||||
#include "src/ast/invariant_attribute.h"
|
||||
#include "src/ast/loop_statement.h"
|
||||
#include "src/ast/override_attribute.h"
|
||||
#include "src/ast/return_statement.h"
|
||||
#include "src/ast/stage_attribute.h"
|
||||
#include "src/ast/struct_block_attribute.h"
|
||||
|
@ -114,10 +114,10 @@ const char kBindingAttribute[] = "binding";
|
|||
const char kBlockAttribute[] = "block";
|
||||
const char kBuiltinAttribute[] = "builtin";
|
||||
const char kGroupAttribute[] = "group";
|
||||
const char kIdAttribute[] = "id";
|
||||
const char kInterpolateAttribute[] = "interpolate";
|
||||
const char kInvariantAttribute[] = "invariant";
|
||||
const char kLocationAttribute[] = "location";
|
||||
const char kOverrideAttribute[] = "override";
|
||||
const char kSizeAttribute[] = "size";
|
||||
const char kAlignAttribute[] = "align";
|
||||
const char kStageAttribute[] = "stage";
|
||||
|
@ -127,8 +127,8 @@ const char kWorkgroupSizeAttribute[] = "workgroup_size";
|
|||
bool is_attribute(Token t) {
|
||||
return t == kAlignAttribute || t == kBindingAttribute ||
|
||||
t == kBlockAttribute || t == kBuiltinAttribute ||
|
||||
t == kGroupAttribute || t == kInterpolateAttribute ||
|
||||
t == kLocationAttribute || t == kOverrideAttribute ||
|
||||
t == kGroupAttribute || t == kIdAttribute ||
|
||||
t == kInterpolateAttribute || t == kLocationAttribute ||
|
||||
t == kSizeAttribute || t == kStageAttribute || t == kStrideAttribute ||
|
||||
t == kWorkgroupSizeAttribute;
|
||||
}
|
||||
|
@ -485,22 +485,29 @@ Maybe<const ast::Variable*> ParserImpl::global_variable_decl(
|
|||
decl->access, // access control
|
||||
decl->type, // type
|
||||
false, // is_const
|
||||
false, // is_overridable
|
||||
constructor, // constructor
|
||||
std::move(attrs)); // attributes
|
||||
}
|
||||
|
||||
// global_constant_decl
|
||||
// : attribute_list* LET variable_ident_decl global_const_initializer?
|
||||
// global_constant_decl :
|
||||
// | LET (ident | variable_ident_decl) global_const_initializer
|
||||
// | attribute* override (ident | variable_ident_decl) (equal expression)?
|
||||
// global_const_initializer
|
||||
// : EQUAL const_expr
|
||||
Maybe<const ast::Variable*> ParserImpl::global_constant_decl(
|
||||
ast::AttributeList& attrs) {
|
||||
if (!match(Token::Type::kLet)) {
|
||||
bool is_overridable = false;
|
||||
const char* use = nullptr;
|
||||
if (match(Token::Type::kLet)) {
|
||||
use = "let declaration";
|
||||
} else if (match(Token::Type::kOverride)) {
|
||||
use = "override declaration";
|
||||
is_overridable = true;
|
||||
} else {
|
||||
return Failure::kNoMatch;
|
||||
}
|
||||
|
||||
const char* use = "let declaration";
|
||||
|
||||
auto decl = expect_variable_ident_decl(use, /* allow_inferred = */ true);
|
||||
if (decl.errored)
|
||||
return Failure::kErrored;
|
||||
|
@ -521,6 +528,7 @@ Maybe<const ast::Variable*> ParserImpl::global_constant_decl(
|
|||
ast::Access::kUndefined, // access control
|
||||
decl->type, // type
|
||||
true, // is_const
|
||||
is_overridable, // is_overridable
|
||||
initializer, // constructor
|
||||
std::move(attrs)); // attributes
|
||||
}
|
||||
|
@ -1402,6 +1410,7 @@ Expect<ast::Variable*> ParserImpl::expect_param() {
|
|||
ast::Access::kUndefined, // access control
|
||||
decl->type, // type
|
||||
true, // is_const
|
||||
false, // is_overridable
|
||||
nullptr, // constructor
|
||||
std::move(attrs.value)); // attributes
|
||||
// Formal parameters are treated like a const declaration where the
|
||||
|
@ -1660,6 +1669,7 @@ Maybe<const ast::VariableDeclStatement*> ParserImpl::variable_stmt() {
|
|||
ast::Access::kUndefined, // access control
|
||||
decl->type, // type
|
||||
true, // is_const
|
||||
false, // is_overridable
|
||||
constructor.value, // constructor
|
||||
ast::AttributeList{}); // attributes
|
||||
|
||||
|
@ -1690,6 +1700,7 @@ Maybe<const ast::VariableDeclStatement*> ParserImpl::variable_stmt() {
|
|||
decl->access, // access control
|
||||
decl->type, // type
|
||||
false, // is_const
|
||||
false, // is_overridable
|
||||
constructor, // constructor
|
||||
ast::AttributeList{}); // attributes
|
||||
|
||||
|
@ -3081,22 +3092,15 @@ Maybe<const ast::Attribute*> ParserImpl::attribute() {
|
|||
});
|
||||
}
|
||||
|
||||
if (t == kOverrideAttribute) {
|
||||
const char* use = "override attribute";
|
||||
if (t == kIdAttribute) {
|
||||
const char* use = "id attribute";
|
||||
return expect_paren_block(use, [&]() -> Result {
|
||||
auto val = expect_positive_sint(use);
|
||||
if (val.errored)
|
||||
return Failure::kErrored;
|
||||
|
||||
if (peek_is(Token::Type::kParenLeft)) {
|
||||
// @override(x)
|
||||
return expect_paren_block(use, [&]() -> Result {
|
||||
auto val = expect_positive_sint(use);
|
||||
if (val.errored)
|
||||
return Failure::kErrored;
|
||||
|
||||
return create<ast::OverrideAttribute>(t.source(), val.value);
|
||||
});
|
||||
} else {
|
||||
// [[override]]
|
||||
return create<ast::OverrideAttribute>(t.source());
|
||||
}
|
||||
return create<ast::IdAttribute>(t.source(), val.value);
|
||||
});
|
||||
}
|
||||
|
||||
return Failure::kNoMatch;
|
||||
|
|
|
@ -54,24 +54,24 @@ fn f() { return 1 & >; }
|
|||
}
|
||||
|
||||
TEST_F(ParserImplErrorTest, AliasDeclInvalidAttribute) {
|
||||
EXPECT("@override type e=u32;",
|
||||
EXPECT("@invariant type e=u32;",
|
||||
R"(test.wgsl:1:2 error: unexpected attributes
|
||||
@override type e=u32;
|
||||
^^^^^^^^
|
||||
@invariant type e=u32;
|
||||
^^^^^^^^^
|
||||
)");
|
||||
}
|
||||
|
||||
// TODO(crbug.com/tint/1382): Remove
|
||||
TEST_F(ParserImplErrorTest, DEPRECATED_AliasDeclInvalidAttribute) {
|
||||
EXPECT(
|
||||
"[[override]]type e=u32;",
|
||||
"[[invariant]]type e=u32;",
|
||||
R"(test.wgsl:1:1 warning: use of deprecated language feature: [[attribute]] style attributes have been replaced with @attribute style
|
||||
[[override]]type e=u32;
|
||||
[[invariant]]type e=u32;
|
||||
^^
|
||||
|
||||
test.wgsl:1:3 error: unexpected attributes
|
||||
[[override]]type e=u32;
|
||||
^^^^^^^^
|
||||
[[invariant]]type e=u32;
|
||||
^^^^^^^^^
|
||||
)");
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "src/ast/override_attribute.h"
|
||||
#include "src/ast/id_attribute.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
|
@ -32,6 +32,7 @@ TEST_F(ParserImplTest, GlobalConstantDecl) {
|
|||
ASSERT_NE(e.value, nullptr);
|
||||
|
||||
EXPECT_TRUE(e->is_const);
|
||||
EXPECT_FALSE(e->is_overridable);
|
||||
EXPECT_EQ(e->symbol, p->builder().Symbols().Get("a"));
|
||||
ASSERT_NE(e->type, nullptr);
|
||||
EXPECT_TRUE(e->type->Is<ast::F32>());
|
||||
|
@ -43,8 +44,6 @@ TEST_F(ParserImplTest, GlobalConstantDecl) {
|
|||
|
||||
ASSERT_NE(e->constructor, nullptr);
|
||||
EXPECT_TRUE(e->constructor->Is<ast::LiteralExpression>());
|
||||
|
||||
EXPECT_FALSE(ast::HasAttribute<ast::OverrideAttribute>(e.value->attributes));
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, GlobalConstantDecl_Inferred) {
|
||||
|
@ -59,6 +58,7 @@ TEST_F(ParserImplTest, GlobalConstantDecl_Inferred) {
|
|||
ASSERT_NE(e.value, nullptr);
|
||||
|
||||
EXPECT_TRUE(e->is_const);
|
||||
EXPECT_FALSE(e->is_overridable);
|
||||
EXPECT_EQ(e->symbol, p->builder().Symbols().Get("a"));
|
||||
EXPECT_EQ(e->type, nullptr);
|
||||
|
||||
|
@ -69,8 +69,6 @@ TEST_F(ParserImplTest, GlobalConstantDecl_Inferred) {
|
|||
|
||||
ASSERT_NE(e->constructor, nullptr);
|
||||
EXPECT_TRUE(e->constructor->Is<ast::LiteralExpression>());
|
||||
|
||||
EXPECT_FALSE(ast::HasAttribute<ast::OverrideAttribute>(e.value->attributes));
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, GlobalConstantDecl_InvalidExpression) {
|
||||
|
@ -100,7 +98,7 @@ TEST_F(ParserImplTest, GlobalConstantDecl_MissingExpression) {
|
|||
}
|
||||
|
||||
TEST_F(ParserImplTest, GlobalConstantDec_Override_WithId) {
|
||||
auto p = parser("@override(7) let a : f32 = 1.");
|
||||
auto p = parser("@id(7) override a : f32 = 1.");
|
||||
auto attrs = p->attribute_list();
|
||||
EXPECT_FALSE(attrs.errored);
|
||||
EXPECT_TRUE(attrs.matched);
|
||||
|
@ -112,30 +110,30 @@ TEST_F(ParserImplTest, GlobalConstantDec_Override_WithId) {
|
|||
ASSERT_NE(e.value, nullptr);
|
||||
|
||||
EXPECT_TRUE(e->is_const);
|
||||
EXPECT_TRUE(e->is_overridable);
|
||||
EXPECT_EQ(e->symbol, p->builder().Symbols().Get("a"));
|
||||
ASSERT_NE(e->type, nullptr);
|
||||
EXPECT_TRUE(e->type->Is<ast::F32>());
|
||||
|
||||
EXPECT_EQ(e->source.range.begin.line, 1u);
|
||||
EXPECT_EQ(e->source.range.begin.column, 18u);
|
||||
EXPECT_EQ(e->source.range.begin.column, 17u);
|
||||
EXPECT_EQ(e->source.range.end.line, 1u);
|
||||
EXPECT_EQ(e->source.range.end.column, 19u);
|
||||
EXPECT_EQ(e->source.range.end.column, 18u);
|
||||
|
||||
ASSERT_NE(e->constructor, nullptr);
|
||||
EXPECT_TRUE(e->constructor->Is<ast::LiteralExpression>());
|
||||
|
||||
auto* override_attr =
|
||||
ast::GetAttribute<ast::OverrideAttribute>(e.value->attributes);
|
||||
ast::GetAttribute<ast::IdAttribute>(e.value->attributes);
|
||||
ASSERT_NE(override_attr, nullptr);
|
||||
EXPECT_TRUE(override_attr->has_value);
|
||||
EXPECT_EQ(override_attr->value, 7u);
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, GlobalConstantDec_Override_WithoutId) {
|
||||
auto p = parser("[[override]] let a : f32 = 1.");
|
||||
auto p = parser("override a : f32 = 1.");
|
||||
auto attrs = p->attribute_list();
|
||||
EXPECT_FALSE(attrs.errored);
|
||||
EXPECT_TRUE(attrs.matched);
|
||||
EXPECT_FALSE(attrs.matched);
|
||||
|
||||
auto e = p->global_constant_decl(attrs.value);
|
||||
EXPECT_FALSE(p->has_error()) << p->error();
|
||||
|
@ -144,26 +142,25 @@ TEST_F(ParserImplTest, GlobalConstantDec_Override_WithoutId) {
|
|||
ASSERT_NE(e.value, nullptr);
|
||||
|
||||
EXPECT_TRUE(e->is_const);
|
||||
EXPECT_TRUE(e->is_overridable);
|
||||
EXPECT_EQ(e->symbol, p->builder().Symbols().Get("a"));
|
||||
ASSERT_NE(e->type, nullptr);
|
||||
EXPECT_TRUE(e->type->Is<ast::F32>());
|
||||
|
||||
EXPECT_EQ(e->source.range.begin.line, 1u);
|
||||
EXPECT_EQ(e->source.range.begin.column, 18u);
|
||||
EXPECT_EQ(e->source.range.begin.column, 10u);
|
||||
EXPECT_EQ(e->source.range.end.line, 1u);
|
||||
EXPECT_EQ(e->source.range.end.column, 19u);
|
||||
EXPECT_EQ(e->source.range.end.column, 11u);
|
||||
|
||||
ASSERT_NE(e->constructor, nullptr);
|
||||
EXPECT_TRUE(e->constructor->Is<ast::LiteralExpression>());
|
||||
|
||||
auto* override_attr =
|
||||
ast::GetAttribute<ast::OverrideAttribute>(e.value->attributes);
|
||||
ASSERT_NE(override_attr, nullptr);
|
||||
EXPECT_FALSE(override_attr->has_value);
|
||||
auto* id_attr = ast::GetAttribute<ast::IdAttribute>(e.value->attributes);
|
||||
ASSERT_EQ(id_attr, nullptr);
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, GlobalConstantDec_Override_MissingId) {
|
||||
auto p = parser("@override() let a : f32 = 1.");
|
||||
auto p = parser("@id() override a : f32 = 1.");
|
||||
auto attrs = p->attribute_list();
|
||||
EXPECT_TRUE(attrs.errored);
|
||||
EXPECT_FALSE(attrs.matched);
|
||||
|
@ -175,11 +172,11 @@ TEST_F(ParserImplTest, GlobalConstantDec_Override_MissingId) {
|
|||
|
||||
EXPECT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(),
|
||||
"1:11: expected signed integer literal for override attribute");
|
||||
"1:5: expected signed integer literal for id attribute");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, GlobalConstantDec_Override_InvalidId) {
|
||||
auto p = parser("@override(-7) let a : f32 = 1.");
|
||||
auto p = parser("@id(-7) override a : f32 = 1.");
|
||||
auto attrs = p->attribute_list();
|
||||
EXPECT_TRUE(attrs.errored);
|
||||
EXPECT_FALSE(attrs.matched);
|
||||
|
@ -190,7 +187,7 @@ TEST_F(ParserImplTest, GlobalConstantDec_Override_InvalidId) {
|
|||
ASSERT_NE(e.value, nullptr);
|
||||
|
||||
EXPECT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "1:11: override attribute must be positive");
|
||||
EXPECT_EQ(p->error(), "1:5: id attribute must be positive");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "src/ast/override_attribute.h"
|
||||
#include "src/ast/invariant_attribute.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
|
@ -21,14 +21,14 @@ namespace wgsl {
|
|||
namespace {
|
||||
|
||||
TEST_F(ParserImplTest, AttributeDecl_Parses) {
|
||||
auto p = parser("@override");
|
||||
auto p = parser("@invariant");
|
||||
auto attrs = p->attribute_list();
|
||||
EXPECT_FALSE(p->has_error());
|
||||
EXPECT_FALSE(attrs.errored);
|
||||
EXPECT_TRUE(attrs.matched);
|
||||
ASSERT_EQ(attrs.value.size(), 1u);
|
||||
auto* override_attr = attrs.value[0]->As<ast::Attribute>();
|
||||
EXPECT_TRUE(override_attr->Is<ast::OverrideAttribute>());
|
||||
auto* invariant = attrs.value[0]->As<ast::Attribute>();
|
||||
EXPECT_TRUE(invariant->Is<ast::InvariantAttribute>());
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, AttributeDecl_MissingParenLeft) {
|
||||
|
@ -73,19 +73,19 @@ TEST_F(ParserImplTest, AttributeDecl_Invalidattribute) {
|
|||
|
||||
// TODO(crbug.com/tint/1382): Remove
|
||||
TEST_F(ParserImplTest, DEPRECATED_attributeDecl_Parses) {
|
||||
auto p = parser("[[override]]");
|
||||
auto p = parser("[[invariant]]");
|
||||
auto attrs = p->attribute_list();
|
||||
EXPECT_FALSE(p->has_error());
|
||||
EXPECT_FALSE(attrs.errored);
|
||||
EXPECT_TRUE(attrs.matched);
|
||||
ASSERT_EQ(attrs.value.size(), 1u);
|
||||
auto* override_attr = attrs.value[0]->As<ast::Attribute>();
|
||||
EXPECT_TRUE(override_attr->Is<ast::OverrideAttribute>());
|
||||
auto* invariant_attr = attrs.value[0]->As<ast::Attribute>();
|
||||
EXPECT_TRUE(invariant_attr->Is<ast::InvariantAttribute>());
|
||||
}
|
||||
|
||||
// TODO(crbug.com/tint/1382): Remove
|
||||
TEST_F(ParserImplTest, DEPRECATED_attributeDecl_MissingAttrRight) {
|
||||
auto p = parser("[[override");
|
||||
auto p = parser("[[invariant");
|
||||
auto attrs = p->attribute_list();
|
||||
EXPECT_TRUE(p->has_error());
|
||||
EXPECT_TRUE(attrs.errored);
|
||||
|
@ -94,7 +94,7 @@ TEST_F(ParserImplTest, DEPRECATED_attributeDecl_MissingAttrRight) {
|
|||
EXPECT_EQ(
|
||||
p->error(),
|
||||
R"(1:1: use of deprecated language feature: [[attribute]] style attributes have been replaced with @attribute style
|
||||
1:11: expected ']]' for attribute list)");
|
||||
1:12: expected ']]' for attribute list)");
|
||||
}
|
||||
|
||||
// TODO(crbug.com/tint/1382): Remove
|
||||
|
|
|
@ -177,6 +177,8 @@ std::string_view Token::TypeToName(Type type) {
|
|||
return "mat4x3";
|
||||
case Token::Type::kMat4x4:
|
||||
return "mat4x4";
|
||||
case Token::Type::kOverride:
|
||||
return "override";
|
||||
case Token::Type::kPrivate:
|
||||
return "private";
|
||||
case Token::Type::kPtr:
|
||||
|
|
|
@ -187,6 +187,8 @@ class Token {
|
|||
kMat4x3,
|
||||
/// A 'mat4x4'
|
||||
kMat4x4,
|
||||
/// A 'override'
|
||||
kOverride,
|
||||
/// A 'private'
|
||||
kPrivate,
|
||||
/// A 'ptr'
|
||||
|
|
|
@ -55,10 +55,10 @@ enum class AttributeKind {
|
|||
kBinding,
|
||||
kBuiltin,
|
||||
kGroup,
|
||||
kId,
|
||||
kInterpolate,
|
||||
kInvariant,
|
||||
kLocation,
|
||||
kOverride,
|
||||
kOffset,
|
||||
kSize,
|
||||
kStage,
|
||||
|
@ -98,6 +98,8 @@ static ast::AttributeList createAttributes(const Source& source,
|
|||
return {builder.Builtin(source, ast::Builtin::kPosition)};
|
||||
case AttributeKind::kGroup:
|
||||
return {builder.create<ast::GroupAttribute>(source, 1u)};
|
||||
case AttributeKind::kId:
|
||||
return {builder.create<ast::IdAttribute>(source, 0u)};
|
||||
case AttributeKind::kInterpolate:
|
||||
return {builder.Interpolate(source, ast::InterpolationType::kLinear,
|
||||
ast::InterpolationSampling::kCenter)};
|
||||
|
@ -105,8 +107,6 @@ static ast::AttributeList createAttributes(const Source& source,
|
|||
return {builder.Invariant(source)};
|
||||
case AttributeKind::kLocation:
|
||||
return {builder.Location(source, 1)};
|
||||
case AttributeKind::kOverride:
|
||||
return {builder.create<ast::OverrideAttribute>(source, 0u)};
|
||||
case AttributeKind::kOffset:
|
||||
return {builder.create<ast::StructMemberOffsetAttribute>(source, 4u)};
|
||||
case AttributeKind::kSize:
|
||||
|
@ -152,10 +152,10 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
TestParams{AttributeKind::kBinding, false},
|
||||
TestParams{AttributeKind::kBuiltin, false},
|
||||
TestParams{AttributeKind::kGroup, false},
|
||||
TestParams{AttributeKind::kId, false},
|
||||
TestParams{AttributeKind::kInterpolate, false},
|
||||
TestParams{AttributeKind::kInvariant, false},
|
||||
TestParams{AttributeKind::kLocation, false},
|
||||
TestParams{AttributeKind::kOverride, false},
|
||||
TestParams{AttributeKind::kOffset, false},
|
||||
TestParams{AttributeKind::kSize, false},
|
||||
TestParams{AttributeKind::kStage, false},
|
||||
|
@ -187,10 +187,10 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
TestParams{AttributeKind::kBinding, false},
|
||||
TestParams{AttributeKind::kBuiltin, false},
|
||||
TestParams{AttributeKind::kGroup, false},
|
||||
TestParams{AttributeKind::kId, false},
|
||||
TestParams{AttributeKind::kInterpolate, false},
|
||||
TestParams{AttributeKind::kInvariant, false},
|
||||
TestParams{AttributeKind::kLocation, false},
|
||||
TestParams{AttributeKind::kOverride, false},
|
||||
TestParams{AttributeKind::kOffset, false},
|
||||
TestParams{AttributeKind::kSize, false},
|
||||
TestParams{AttributeKind::kStage, false},
|
||||
|
@ -236,10 +236,10 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
TestParams{AttributeKind::kBinding, false},
|
||||
TestParams{AttributeKind::kBuiltin, false},
|
||||
TestParams{AttributeKind::kGroup, false},
|
||||
TestParams{AttributeKind::kId, false},
|
||||
TestParams{AttributeKind::kInterpolate, false},
|
||||
TestParams{AttributeKind::kInvariant, false},
|
||||
TestParams{AttributeKind::kLocation, false},
|
||||
TestParams{AttributeKind::kOverride, false},
|
||||
TestParams{AttributeKind::kOffset, false},
|
||||
TestParams{AttributeKind::kSize, false},
|
||||
TestParams{AttributeKind::kStage, false},
|
||||
|
@ -275,10 +275,10 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
TestParams{AttributeKind::kBinding, false},
|
||||
TestParams{AttributeKind::kBuiltin, true},
|
||||
TestParams{AttributeKind::kGroup, false},
|
||||
TestParams{AttributeKind::kId, false},
|
||||
// kInterpolate tested separately (requires [[location]])
|
||||
TestParams{AttributeKind::kInvariant, true},
|
||||
TestParams{AttributeKind::kLocation, true},
|
||||
TestParams{AttributeKind::kOverride, false},
|
||||
TestParams{AttributeKind::kOffset, false},
|
||||
TestParams{AttributeKind::kSize, false},
|
||||
TestParams{AttributeKind::kStage, false},
|
||||
|
@ -325,10 +325,10 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
TestParams{AttributeKind::kBinding, false},
|
||||
TestParams{AttributeKind::kBuiltin, false},
|
||||
TestParams{AttributeKind::kGroup, false},
|
||||
TestParams{AttributeKind::kId, false},
|
||||
TestParams{AttributeKind::kInterpolate, true},
|
||||
TestParams{AttributeKind::kInvariant, false},
|
||||
TestParams{AttributeKind::kLocation, true},
|
||||
TestParams{AttributeKind::kOverride, false},
|
||||
TestParams{AttributeKind::kOffset, false},
|
||||
TestParams{AttributeKind::kSize, false},
|
||||
TestParams{AttributeKind::kStage, false},
|
||||
|
@ -373,10 +373,10 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
TestParams{AttributeKind::kBinding, false},
|
||||
TestParams{AttributeKind::kBuiltin, false},
|
||||
TestParams{AttributeKind::kGroup, false},
|
||||
TestParams{AttributeKind::kId, false},
|
||||
TestParams{AttributeKind::kInterpolate, false},
|
||||
TestParams{AttributeKind::kInvariant, false},
|
||||
TestParams{AttributeKind::kLocation, false},
|
||||
TestParams{AttributeKind::kOverride, false},
|
||||
TestParams{AttributeKind::kOffset, false},
|
||||
TestParams{AttributeKind::kSize, false},
|
||||
TestParams{AttributeKind::kStage, false},
|
||||
|
@ -423,10 +423,10 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
TestParams{AttributeKind::kBinding, false},
|
||||
TestParams{AttributeKind::kBuiltin, false},
|
||||
TestParams{AttributeKind::kGroup, false},
|
||||
TestParams{AttributeKind::kId, false},
|
||||
TestParams{AttributeKind::kInterpolate, true},
|
||||
TestParams{AttributeKind::kInvariant, false},
|
||||
TestParams{AttributeKind::kLocation, false},
|
||||
TestParams{AttributeKind::kOverride, false},
|
||||
TestParams{AttributeKind::kOffset, false},
|
||||
TestParams{AttributeKind::kSize, false},
|
||||
TestParams{AttributeKind::kStage, false},
|
||||
|
@ -469,10 +469,10 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
TestParams{AttributeKind::kBinding, false},
|
||||
TestParams{AttributeKind::kBuiltin, true},
|
||||
TestParams{AttributeKind::kGroup, false},
|
||||
TestParams{AttributeKind::kId, false},
|
||||
// kInterpolate tested separately (requires [[location]])
|
||||
TestParams{AttributeKind::kInvariant, true},
|
||||
TestParams{AttributeKind::kLocation, false},
|
||||
TestParams{AttributeKind::kOverride, false},
|
||||
TestParams{AttributeKind::kOffset, false},
|
||||
TestParams{AttributeKind::kSize, false},
|
||||
TestParams{AttributeKind::kStage, false},
|
||||
|
@ -560,10 +560,10 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
TestParams{AttributeKind::kBinding, false},
|
||||
TestParams{AttributeKind::kBuiltin, false},
|
||||
TestParams{AttributeKind::kGroup, false},
|
||||
TestParams{AttributeKind::kId, false},
|
||||
TestParams{AttributeKind::kInterpolate, false},
|
||||
TestParams{AttributeKind::kInvariant, false},
|
||||
TestParams{AttributeKind::kLocation, false},
|
||||
TestParams{AttributeKind::kOverride, false},
|
||||
TestParams{AttributeKind::kOffset, false},
|
||||
TestParams{AttributeKind::kSize, false},
|
||||
TestParams{AttributeKind::kStage, false},
|
||||
|
@ -617,10 +617,10 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
TestParams{AttributeKind::kBinding, false},
|
||||
TestParams{AttributeKind::kBuiltin, true},
|
||||
TestParams{AttributeKind::kGroup, false},
|
||||
TestParams{AttributeKind::kId, false},
|
||||
// kInterpolate tested separately (requires [[location]])
|
||||
// kInvariant tested separately (requires position builtin)
|
||||
TestParams{AttributeKind::kLocation, true},
|
||||
TestParams{AttributeKind::kOverride, false},
|
||||
TestParams{AttributeKind::kOffset, true},
|
||||
TestParams{AttributeKind::kSize, true},
|
||||
TestParams{AttributeKind::kStage, false},
|
||||
|
@ -701,10 +701,10 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
TestParams{AttributeKind::kBinding, false},
|
||||
TestParams{AttributeKind::kBuiltin, false},
|
||||
TestParams{AttributeKind::kGroup, false},
|
||||
TestParams{AttributeKind::kId, false},
|
||||
TestParams{AttributeKind::kInterpolate, false},
|
||||
TestParams{AttributeKind::kInvariant, false},
|
||||
TestParams{AttributeKind::kLocation, false},
|
||||
TestParams{AttributeKind::kOverride, false},
|
||||
TestParams{AttributeKind::kOffset, false},
|
||||
TestParams{AttributeKind::kSize, false},
|
||||
TestParams{AttributeKind::kStage, false},
|
||||
|
@ -745,10 +745,10 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
TestParams{AttributeKind::kBinding, false},
|
||||
TestParams{AttributeKind::kBuiltin, false},
|
||||
TestParams{AttributeKind::kGroup, false},
|
||||
TestParams{AttributeKind::kId, false},
|
||||
TestParams{AttributeKind::kInterpolate, false},
|
||||
TestParams{AttributeKind::kInvariant, false},
|
||||
TestParams{AttributeKind::kLocation, false},
|
||||
TestParams{AttributeKind::kOverride, false},
|
||||
TestParams{AttributeKind::kOffset, false},
|
||||
TestParams{AttributeKind::kSize, false},
|
||||
TestParams{AttributeKind::kStage, false},
|
||||
|
@ -810,10 +810,10 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
TestParams{AttributeKind::kBinding, false},
|
||||
TestParams{AttributeKind::kBuiltin, false},
|
||||
TestParams{AttributeKind::kGroup, false},
|
||||
TestParams{AttributeKind::kId, true},
|
||||
TestParams{AttributeKind::kInterpolate, false},
|
||||
TestParams{AttributeKind::kInvariant, false},
|
||||
TestParams{AttributeKind::kLocation, false},
|
||||
TestParams{AttributeKind::kOverride, true},
|
||||
TestParams{AttributeKind::kOffset, false},
|
||||
TestParams{AttributeKind::kSize, false},
|
||||
TestParams{AttributeKind::kStage, false},
|
||||
|
@ -825,15 +825,15 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
TEST_F(ConstantAttributeTest, DuplicateAttribute) {
|
||||
GlobalConst("a", ty.f32(), Expr(1.23f),
|
||||
ast::AttributeList{
|
||||
create<ast::OverrideAttribute>(Source{{12, 34}}),
|
||||
create<ast::OverrideAttribute>(Source{{56, 78}}, 1),
|
||||
create<ast::IdAttribute>(Source{{12, 34}}, 0),
|
||||
create<ast::IdAttribute>(Source{{56, 78}}, 1),
|
||||
});
|
||||
|
||||
WrapInFunction();
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(r()->error(),
|
||||
R"(56:78 error: duplicate override attribute
|
||||
R"(56:78 error: duplicate id attribute
|
||||
12:34 note: first attribute declared here)");
|
||||
}
|
||||
|
||||
|
|
|
@ -404,9 +404,9 @@ class DependencyScanner {
|
|||
}
|
||||
if (attr->IsAnyOf<
|
||||
ast::BindingAttribute, ast::BuiltinAttribute, ast::GroupAttribute,
|
||||
ast::InternalAttribute, ast::InterpolateAttribute,
|
||||
ast::IdAttribute, ast::InternalAttribute, ast::InterpolateAttribute,
|
||||
ast::InvariantAttribute, ast::LocationAttribute,
|
||||
ast::OverrideAttribute, ast::StageAttribute, ast::StrideAttribute,
|
||||
ast::StageAttribute, ast::StrideAttribute,
|
||||
ast::StructBlockAttribute, ast::StructMemberAlignAttribute,
|
||||
ast::StructMemberOffsetAttribute,
|
||||
ast::StructMemberSizeAttribute>()) {
|
||||
|
|
|
@ -49,7 +49,7 @@ TEST_F(ResolverPipelineOverridableConstantTest, NonOverridable) {
|
|||
}
|
||||
|
||||
TEST_F(ResolverPipelineOverridableConstantTest, WithId) {
|
||||
auto* a = GlobalConst("a", ty.f32(), Expr(1.f), {Override(7u)});
|
||||
auto* a = Override("a", ty.f32(), Expr(1.f), {Id(7u)});
|
||||
|
||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
|
||||
|
@ -57,7 +57,7 @@ TEST_F(ResolverPipelineOverridableConstantTest, WithId) {
|
|||
}
|
||||
|
||||
TEST_F(ResolverPipelineOverridableConstantTest, WithoutId) {
|
||||
auto* a = GlobalConst("a", ty.f32(), Expr(1.f), {Override()});
|
||||
auto* a = Override("a", ty.f32(), Expr(1.f));
|
||||
|
||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
|
||||
|
@ -66,12 +66,12 @@ TEST_F(ResolverPipelineOverridableConstantTest, WithoutId) {
|
|||
|
||||
TEST_F(ResolverPipelineOverridableConstantTest, WithAndWithoutIds) {
|
||||
std::vector<ast::Variable*> variables;
|
||||
auto* a = GlobalConst("a", ty.f32(), Expr(1.f), {Override()});
|
||||
auto* b = GlobalConst("b", ty.f32(), Expr(1.f), {Override()});
|
||||
auto* c = GlobalConst("c", ty.f32(), Expr(1.f), {Override(2u)});
|
||||
auto* d = GlobalConst("d", ty.f32(), Expr(1.f), {Override(4u)});
|
||||
auto* e = GlobalConst("e", ty.f32(), Expr(1.f), {Override()});
|
||||
auto* f = GlobalConst("f", ty.f32(), Expr(1.f), {Override(1u)});
|
||||
auto* a = Override("a", ty.f32(), Expr(1.f));
|
||||
auto* b = Override("b", ty.f32(), Expr(1.f));
|
||||
auto* c = Override("c", ty.f32(), Expr(1.f), {Id(2u)});
|
||||
auto* d = Override("d", ty.f32(), Expr(1.f), {Id(4u)});
|
||||
auto* e = Override("e", ty.f32(), Expr(1.f));
|
||||
auto* f = Override("f", ty.f32(), Expr(1.f), {Id(1u)});
|
||||
|
||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
|
||||
|
@ -85,8 +85,8 @@ TEST_F(ResolverPipelineOverridableConstantTest, WithAndWithoutIds) {
|
|||
}
|
||||
|
||||
TEST_F(ResolverPipelineOverridableConstantTest, DuplicateIds) {
|
||||
GlobalConst("a", ty.f32(), Expr(1.f), {Override(Source{{12, 34}}, 7u)});
|
||||
GlobalConst("b", ty.f32(), Expr(1.f), {Override(Source{{56, 78}}, 7u)});
|
||||
Override("a", ty.f32(), Expr(1.f), {Id(Source{{12, 34}}, 7u)});
|
||||
Override("b", ty.f32(), Expr(1.f), {Id(Source{{56, 78}}, 7u)});
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
|
||||
|
@ -95,7 +95,7 @@ TEST_F(ResolverPipelineOverridableConstantTest, DuplicateIds) {
|
|||
}
|
||||
|
||||
TEST_F(ResolverPipelineOverridableConstantTest, IdTooLarge) {
|
||||
GlobalConst("a", ty.f32(), Expr(1.f), {Override(Source{{12, 34}}, 65536u)});
|
||||
Override("a", ty.f32(), Expr(1.f), {Id(Source{{12, 34}}, 65536u)});
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
|
||||
|
|
|
@ -32,12 +32,12 @@
|
|||
#include "src/ast/discard_statement.h"
|
||||
#include "src/ast/fallthrough_statement.h"
|
||||
#include "src/ast/for_loop_statement.h"
|
||||
#include "src/ast/id_attribute.h"
|
||||
#include "src/ast/if_statement.h"
|
||||
#include "src/ast/internal_attribute.h"
|
||||
#include "src/ast/interpolate_attribute.h"
|
||||
#include "src/ast/loop_statement.h"
|
||||
#include "src/ast/matrix.h"
|
||||
#include "src/ast/override_attribute.h"
|
||||
#include "src/ast/pointer.h"
|
||||
#include "src/ast/return_statement.h"
|
||||
#include "src/ast/sampled_texture.h"
|
||||
|
@ -333,8 +333,8 @@ sem::Variable* Resolver::Variable(const ast::Variable* var,
|
|||
|
||||
storage_ty = rhs->Type()->UnwrapRef(); // Implicit load of RHS
|
||||
}
|
||||
} else if (var->is_const && kind != VariableKind::kParameter &&
|
||||
!ast::HasAttribute<ast::OverrideAttribute>(var->attributes)) {
|
||||
} else if (var->is_const && !var->is_overridable &&
|
||||
kind != VariableKind::kParameter) {
|
||||
AddError("let declaration must have an initializer", var->source);
|
||||
return nullptr;
|
||||
} else if (!var->type) {
|
||||
|
@ -426,19 +426,16 @@ sem::Variable* Resolver::Variable(const ast::Variable* var,
|
|||
binding_point = {bp.group->value, bp.binding->value};
|
||||
}
|
||||
|
||||
auto* override =
|
||||
ast::GetAttribute<ast::OverrideAttribute>(var->attributes);
|
||||
bool has_const_val = rhs && var->is_const && !override;
|
||||
|
||||
bool has_const_val = rhs && var->is_const && !var->is_overridable;
|
||||
auto* global = builder_->create<sem::GlobalVariable>(
|
||||
var, var_ty, storage_class, access,
|
||||
has_const_val ? rhs->ConstantValue() : sem::Constant{},
|
||||
binding_point);
|
||||
|
||||
if (override) {
|
||||
if (var->is_overridable) {
|
||||
global->SetIsOverridable();
|
||||
if (override->has_value) {
|
||||
global->SetConstantId(static_cast<uint16_t>(override->value));
|
||||
if (auto* id = ast::GetAttribute<ast::IdAttribute>(var->attributes)) {
|
||||
global->SetConstantId(static_cast<uint16_t>(id->value));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -492,18 +489,13 @@ void Resolver::AllocateOverridableConstantIds() {
|
|||
// unused constant, the allocation may change on the next Resolver pass.
|
||||
for (auto* decl : builder_->AST().GlobalDeclarations()) {
|
||||
auto* var = decl->As<ast::Variable>();
|
||||
if (!var) {
|
||||
continue;
|
||||
}
|
||||
auto* override_attr =
|
||||
ast::GetAttribute<ast::OverrideAttribute>(var->attributes);
|
||||
if (!override_attr) {
|
||||
if (!var || !var->is_overridable) {
|
||||
continue;
|
||||
}
|
||||
|
||||
uint16_t constant_id;
|
||||
if (override_attr->has_value) {
|
||||
constant_id = static_cast<uint16_t>(override_attr->value);
|
||||
if (auto* id_attr = ast::GetAttribute<ast::IdAttribute>(var->attributes)) {
|
||||
constant_id = static_cast<uint16_t>(id_attr->value);
|
||||
} else {
|
||||
// No ID was specified, so allocate the next available ID.
|
||||
constant_id = next_constant_id;
|
||||
|
@ -551,11 +543,9 @@ sem::GlobalVariable* Resolver::GlobalVariable(const ast::Variable* var) {
|
|||
for (auto* attr : var->attributes) {
|
||||
Mark(attr);
|
||||
|
||||
if (auto* override_attr = attr->As<ast::OverrideAttribute>()) {
|
||||
if (auto* id_attr = attr->As<ast::IdAttribute>()) {
|
||||
// Track the constant IDs that are specified in the shader.
|
||||
if (override_attr->has_value) {
|
||||
constant_ids_.emplace(override_attr->value, sem);
|
||||
}
|
||||
constant_ids_.emplace(id_attr->value, sem);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -791,8 +781,8 @@ bool Resolver::WorkgroupSize(const ast::Function* func) {
|
|||
AddError(kErrBadType, expr->source);
|
||||
return false;
|
||||
}
|
||||
// Capture the constant if an [[override]] attribute is present.
|
||||
if (ast::HasAttribute<ast::OverrideAttribute>(decl->attributes)) {
|
||||
// Capture the constant if it is pipeline-overridable.
|
||||
if (decl->is_overridable) {
|
||||
ws[i].overridable_const = decl;
|
||||
}
|
||||
|
||||
|
@ -2275,15 +2265,13 @@ sem::Array* Resolver::Array(const ast::Array* arr) {
|
|||
|
||||
if (auto* ident = count_expr->As<ast::IdentifierExpression>()) {
|
||||
// Make sure the identifier is a non-overridable module-scope constant.
|
||||
auto* var = ResolvedSymbol<sem::Variable>(ident);
|
||||
if (!var || !var->Is<sem::GlobalVariable>() ||
|
||||
!var->Declaration()->is_const) {
|
||||
auto* var = ResolvedSymbol<sem::GlobalVariable>(ident);
|
||||
if (!var || !var->Declaration()->is_const) {
|
||||
AddError("array size identifier must be a module-scope constant",
|
||||
size_source);
|
||||
return nullptr;
|
||||
}
|
||||
if (ast::HasAttribute<ast::OverrideAttribute>(
|
||||
var->Declaration()->attributes)) {
|
||||
if (var->IsOverridable()) {
|
||||
AddError("array size expression must not be pipeline-overridable",
|
||||
size_source);
|
||||
return nullptr;
|
||||
|
|
|
@ -25,9 +25,9 @@
|
|||
#include "src/ast/call_statement.h"
|
||||
#include "src/ast/continue_statement.h"
|
||||
#include "src/ast/float_literal_expression.h"
|
||||
#include "src/ast/id_attribute.h"
|
||||
#include "src/ast/if_statement.h"
|
||||
#include "src/ast/loop_statement.h"
|
||||
#include "src/ast/override_attribute.h"
|
||||
#include "src/ast/return_statement.h"
|
||||
#include "src/ast/stage_attribute.h"
|
||||
#include "src/ast/struct_block_attribute.h"
|
||||
|
@ -1011,14 +1011,14 @@ TEST_F(ResolverTest, Function_WorkgroupSize_Consts_NestedInitializer) {
|
|||
}
|
||||
|
||||
TEST_F(ResolverTest, Function_WorkgroupSize_OverridableConsts) {
|
||||
// @override(0) let width = 16;
|
||||
// @override(1) let height = 8;
|
||||
// @override(2) let depth = 2;
|
||||
// @id(0) override width = 16;
|
||||
// @id(1) override height = 8;
|
||||
// @id(2) override depth = 2;
|
||||
// @stage(compute) @workgroup_size(width, height, depth)
|
||||
// fn main() {}
|
||||
auto* width = GlobalConst("width", ty.i32(), Expr(16), {Override(0)});
|
||||
auto* height = GlobalConst("height", ty.i32(), Expr(8), {Override(1)});
|
||||
auto* depth = GlobalConst("depth", ty.i32(), Expr(2), {Override(2)});
|
||||
auto* width = Override("width", ty.i32(), Expr(16), {Id(0)});
|
||||
auto* height = Override("height", ty.i32(), Expr(8), {Id(1)});
|
||||
auto* depth = Override("depth", ty.i32(), Expr(2), {Id(2)});
|
||||
auto* func = Func("main", ast::VariableList{}, ty.void_(), {},
|
||||
{Stage(ast::PipelineStage::kCompute),
|
||||
WorkgroupSize("width", "height", "depth")});
|
||||
|
@ -1037,14 +1037,14 @@ TEST_F(ResolverTest, Function_WorkgroupSize_OverridableConsts) {
|
|||
}
|
||||
|
||||
TEST_F(ResolverTest, Function_WorkgroupSize_OverridableConsts_NoInit) {
|
||||
// @override(0) let width : i32;
|
||||
// @override(1) let height : i32;
|
||||
// @override(2) let depth : i32;
|
||||
// @id(0) override width : i32;
|
||||
// @id(1) override height : i32;
|
||||
// @id(2) override depth : i32;
|
||||
// @stage(compute) @workgroup_size(width, height, depth)
|
||||
// fn main() {}
|
||||
auto* width = GlobalConst("width", ty.i32(), nullptr, {Override(0)});
|
||||
auto* height = GlobalConst("height", ty.i32(), nullptr, {Override(1)});
|
||||
auto* depth = GlobalConst("depth", ty.i32(), nullptr, {Override(2)});
|
||||
auto* width = Override("width", ty.i32(), nullptr, {Id(0)});
|
||||
auto* height = Override("height", ty.i32(), nullptr, {Id(1)});
|
||||
auto* depth = Override("depth", ty.i32(), nullptr, {Id(2)});
|
||||
auto* func = Func("main", ast::VariableList{}, ty.void_(), {},
|
||||
{Stage(ast::PipelineStage::kCompute),
|
||||
WorkgroupSize("width", "height", "depth")});
|
||||
|
@ -1063,11 +1063,11 @@ TEST_F(ResolverTest, Function_WorkgroupSize_OverridableConsts_NoInit) {
|
|||
}
|
||||
|
||||
TEST_F(ResolverTest, Function_WorkgroupSize_Mixed) {
|
||||
// @override(1) let height = 2;
|
||||
// @id(1) override height = 2;
|
||||
// let depth = 3;
|
||||
// @stage(compute) @workgroup_size(8, height, depth)
|
||||
// fn main() {}
|
||||
auto* height = GlobalConst("height", ty.i32(), Expr(2), {Override(0)});
|
||||
auto* height = Override("height", ty.i32(), Expr(2), {Id(0)});
|
||||
GlobalConst("depth", ty.i32(), Expr(3));
|
||||
auto* func = Func("main", ast::VariableList{}, ty.void_(), {},
|
||||
{Stage(ast::PipelineStage::kCompute),
|
||||
|
|
|
@ -30,12 +30,12 @@
|
|||
#include "src/ast/discard_statement.h"
|
||||
#include "src/ast/fallthrough_statement.h"
|
||||
#include "src/ast/for_loop_statement.h"
|
||||
#include "src/ast/id_attribute.h"
|
||||
#include "src/ast/if_statement.h"
|
||||
#include "src/ast/internal_attribute.h"
|
||||
#include "src/ast/interpolate_attribute.h"
|
||||
#include "src/ast/loop_statement.h"
|
||||
#include "src/ast/matrix.h"
|
||||
#include "src/ast/override_attribute.h"
|
||||
#include "src/ast/pointer.h"
|
||||
#include "src/ast/return_statement.h"
|
||||
#include "src/ast/sampled_texture.h"
|
||||
|
@ -411,25 +411,23 @@ bool Resolver::ValidateGlobalVariable(const sem::Variable* var) {
|
|||
|
||||
for (auto* attr : decl->attributes) {
|
||||
if (decl->is_const) {
|
||||
if (auto* override_attr = attr->As<ast::OverrideAttribute>()) {
|
||||
if (override_attr->has_value) {
|
||||
uint32_t id = override_attr->value;
|
||||
auto it = constant_ids_.find(id);
|
||||
if (it != constant_ids_.end() && it->second != var) {
|
||||
AddError("pipeline constant IDs must be unique", attr->source);
|
||||
AddNote("a pipeline constant with an ID of " + std::to_string(id) +
|
||||
" was previously declared "
|
||||
"here:",
|
||||
ast::GetAttribute<ast::OverrideAttribute>(
|
||||
it->second->Declaration()->attributes)
|
||||
->source);
|
||||
return false;
|
||||
}
|
||||
if (id > 65535) {
|
||||
AddError("pipeline constant IDs must be between 0 and 65535",
|
||||
attr->source);
|
||||
return false;
|
||||
}
|
||||
if (auto* id_attr = attr->As<ast::IdAttribute>()) {
|
||||
uint32_t id = id_attr->value;
|
||||
auto it = constant_ids_.find(id);
|
||||
if (it != constant_ids_.end() && it->second != var) {
|
||||
AddError("pipeline constant IDs must be unique", attr->source);
|
||||
AddNote("a pipeline constant with an ID of " + std::to_string(id) +
|
||||
" was previously declared "
|
||||
"here:",
|
||||
ast::GetAttribute<ast::IdAttribute>(
|
||||
it->second->Declaration()->attributes)
|
||||
->source);
|
||||
return false;
|
||||
}
|
||||
if (id > 65535) {
|
||||
AddError("pipeline constant IDs must be between 0 and 65535",
|
||||
attr->source);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
AddError("attribute is not valid for constants", attr->source);
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "src/ast/override_attribute.h"
|
||||
#include "src/ast/id_attribute.h"
|
||||
#include "src/ast/return_statement.h"
|
||||
#include "src/ast/stage_attribute.h"
|
||||
#include "src/ast/struct_block_attribute.h"
|
||||
|
@ -79,9 +79,8 @@ TEST_F(ResolverTypeValidationTest, VariableDeclNoConstructor_Pass) {
|
|||
}
|
||||
|
||||
TEST_F(ResolverTypeValidationTest, GlobalConstantNoConstructor_Pass) {
|
||||
// @override(0) let a :i32;
|
||||
GlobalConst(Source{{12, 34}}, "a", ty.i32(), nullptr,
|
||||
ast::AttributeList{create<ast::OverrideAttribute>(0)});
|
||||
// @id(0) override a :i32;
|
||||
Override(Source{{12, 34}}, "a", ty.i32(), nullptr, ast::AttributeList{Id(0)});
|
||||
|
||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
}
|
||||
|
@ -98,7 +97,7 @@ TEST_F(ResolverTypeValidationTest, GlobalConstantWithStorageClass_Fail) {
|
|||
AST().AddGlobalVariable(create<ast::Variable>(
|
||||
Source{{12, 34}}, Symbols().Register("global_var"),
|
||||
ast::StorageClass::kPrivate, ast::Access::kUndefined, ty.f32(), true,
|
||||
Expr(1.23f), ast::AttributeList{}));
|
||||
false, Expr(1.23f), ast::AttributeList{}));
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(r()->error(),
|
||||
|
@ -346,9 +345,9 @@ TEST_F(ResolverTypeValidationTest, ArraySize_TooBig_ExplicitStride) {
|
|||
}
|
||||
|
||||
TEST_F(ResolverTypeValidationTest, ArraySize_OverridableConstant) {
|
||||
// [[override]] let size = 10;
|
||||
// override size = 10;
|
||||
// var<private> a : array<f32, size>;
|
||||
GlobalConst("size", nullptr, Expr(10), {Override()});
|
||||
Override("size", nullptr, Expr(10));
|
||||
Global("a", ty.array(ty.f32(), Expr(Source{{12, 34}}, "size")),
|
||||
ast::StorageClass::kPrivate);
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
|
|
|
@ -142,7 +142,7 @@ void BindingRemapper::Run(CloneContext& ctx,
|
|||
const ast::Type* inner_ty = CreateASTTypeFor(ctx, ty);
|
||||
auto* new_var = ctx.dst->create<ast::Variable>(
|
||||
ctx.Clone(var->source), ctx.Clone(var->symbol),
|
||||
var->declared_storage_class, ac, inner_ty, var->is_const,
|
||||
var->declared_storage_class, ac, inner_ty, false, false,
|
||||
ctx.Clone(var->constructor), ctx.Clone(var->attributes));
|
||||
ctx.Replace(var, new_var);
|
||||
}
|
||||
|
|
|
@ -108,7 +108,7 @@ void CalculateArrayLength::Run(CloneContext& ctx,
|
|||
// in order for HLSL to emit this as a ByteAddressBuffer.
|
||||
ctx.dst->create<ast::Variable>(
|
||||
ctx.dst->Sym("buffer"), ast::StorageClass::kStorage,
|
||||
ast::Access::kUndefined, type, true, nullptr,
|
||||
ast::Access::kUndefined, type, true, false, nullptr,
|
||||
ast::AttributeList{disable_validation}),
|
||||
ctx.dst->Param("result",
|
||||
ctx.dst->ty.pointer(ctx.dst->ty.u32(),
|
||||
|
|
|
@ -457,7 +457,7 @@ struct DecomposeMemoryAccess::State {
|
|||
// array.
|
||||
b.create<ast::Variable>(b.Sym("buffer"), storage_class,
|
||||
var_user->Variable()->Access(),
|
||||
buf_ast_ty, true, nullptr,
|
||||
buf_ast_ty, true, false, nullptr,
|
||||
ast::AttributeList{disable_validation}),
|
||||
b.Param("offset", b.ty.u32()),
|
||||
};
|
||||
|
@ -556,7 +556,7 @@ struct DecomposeMemoryAccess::State {
|
|||
|
||||
b.create<ast::Variable>(b.Sym("buffer"), storage_class,
|
||||
var_user->Variable()->Access(),
|
||||
buf_ast_ty, true, nullptr,
|
||||
buf_ast_ty, true, false, nullptr,
|
||||
ast::AttributeList{disable_validation}),
|
||||
b.Param("offset", b.ty.u32()),
|
||||
b.Param("value", el_ast_ty),
|
||||
|
@ -656,7 +656,7 @@ struct DecomposeMemoryAccess::State {
|
|||
// order for HLSL to emit this as a ByteAddressBuffer.
|
||||
b.create<ast::Variable>(b.Sym("buffer"), ast::StorageClass::kStorage,
|
||||
var_user->Variable()->Access(), buf_ast_ty,
|
||||
true, nullptr,
|
||||
true, false, nullptr,
|
||||
ast::AttributeList{disable_validation}),
|
||||
b.Param("offset", b.ty.u32()),
|
||||
};
|
||||
|
|
|
@ -116,7 +116,7 @@ void ExternalTextureTransform::Run(CloneContext& ctx,
|
|||
auto clonedAttributes = ctx.Clone(var->attributes);
|
||||
auto* newVar = ctx.dst->create<ast::Variable>(
|
||||
clonedSrc, clonedSym, var->declared_storage_class,
|
||||
var->declared_access, newType, var->is_const, clonedConstructor,
|
||||
var->declared_access, newType, false, false, clonedConstructor,
|
||||
clonedAttributes);
|
||||
|
||||
ctx.Replace(var, newVar);
|
||||
|
|
|
@ -1201,7 +1201,7 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
"operator",
|
||||
"or",
|
||||
"or_eq",
|
||||
"override",
|
||||
// "override", // Also used in WGSL
|
||||
// "private", // Also used in WGSL
|
||||
"protected",
|
||||
"public",
|
||||
|
|
|
@ -1056,7 +1056,7 @@ var<private> a : mat3x2<f32>;
|
|||
|
||||
// TODO(dsinclair): Implement when constant_id exists
|
||||
TEST_F(RobustnessTest, DISABLED_Vector_Constant_Id_Clamps) {
|
||||
// @override(1300) let idx : i32;
|
||||
// @id(1300) override idx : i32;
|
||||
// var a : vec3<f32>
|
||||
// var b : f32 = a[idx]
|
||||
//
|
||||
|
@ -1065,7 +1065,7 @@ TEST_F(RobustnessTest, DISABLED_Vector_Constant_Id_Clamps) {
|
|||
|
||||
// TODO(dsinclair): Implement when constant_id exists
|
||||
TEST_F(RobustnessTest, DISABLED_Array_Constant_Id_Clamps) {
|
||||
// @override(1300) let idx : i32;
|
||||
// @id(1300) override idx : i32;
|
||||
// var a : array<f32, 4>
|
||||
// var b : f32 = a[idx]
|
||||
//
|
||||
|
@ -1074,7 +1074,7 @@ TEST_F(RobustnessTest, DISABLED_Array_Constant_Id_Clamps) {
|
|||
|
||||
// TODO(dsinclair): Implement when constant_id exists
|
||||
TEST_F(RobustnessTest, DISABLED_Matrix_Column_Constant_Id_Clamps) {
|
||||
// @override(1300) let idx : i32;
|
||||
// @id(1300) override idx : i32;
|
||||
// var a : mat3x2<f32>
|
||||
// var b : f32 = a[idx][1]
|
||||
//
|
||||
|
@ -1083,7 +1083,7 @@ TEST_F(RobustnessTest, DISABLED_Matrix_Column_Constant_Id_Clamps) {
|
|||
|
||||
// TODO(dsinclair): Implement when constant_id exists
|
||||
TEST_F(RobustnessTest, DISABLED_Matrix_Row_Constant_Id_Clamps) {
|
||||
// @override(1300) let idx : i32;
|
||||
// @id(1300) override idx : i32;
|
||||
// var a : mat3x2<f32>
|
||||
// var b : f32 = a[1][idx]
|
||||
//
|
||||
|
|
|
@ -77,19 +77,15 @@ void SingleEntryPoint::Run(CloneContext& ctx,
|
|||
ctx.dst->AST().AddTypeDecl(ctx.Clone(ty));
|
||||
} else if (auto* var = decl->As<ast::Variable>()) {
|
||||
if (referenced_vars.count(var)) {
|
||||
if (var->is_const) {
|
||||
if (auto* attr =
|
||||
ast::GetAttribute<ast::OverrideAttribute>(var->attributes)) {
|
||||
// It is an overridable constant
|
||||
if (!attr->has_value) {
|
||||
// If the attribute doesn't have numeric ID specified explicitly
|
||||
// Make their ids explicitly assigned in the attribute so that
|
||||
// they won't be affected by other stripped away constants
|
||||
auto* global = sem.Get(var)->As<sem::GlobalVariable>();
|
||||
const auto* new_deco =
|
||||
ctx.dst->Override(attr->source, global->ConstantId());
|
||||
ctx.Replace(attr, new_deco);
|
||||
}
|
||||
if (var->is_overridable) {
|
||||
// It is an overridable constant
|
||||
if (!ast::HasAttribute<ast::IdAttribute>(var->attributes)) {
|
||||
// If the constant doesn't already have an @id() attribute, add one
|
||||
// so that its allocated ID so that it won't be affected by other
|
||||
// stripped away constants
|
||||
auto* global = sem.Get(var)->As<sem::GlobalVariable>();
|
||||
const auto* id = ctx.dst->Id(global->ConstantId());
|
||||
ctx.InsertFront(var->attributes, id);
|
||||
}
|
||||
}
|
||||
ctx.dst->AST().AddGlobalVariable(ctx.Clone(var));
|
||||
|
|
|
@ -258,10 +258,10 @@ fn main() {
|
|||
|
||||
TEST_F(SingleEntryPointTest, OverridableConstants) {
|
||||
auto* src = R"(
|
||||
@override(1001) let c1 : u32 = 1u;
|
||||
[[override]] let c2 : u32 = 1u;
|
||||
@override(0) let c3 : u32 = 1u;
|
||||
@override(9999) let c4 : u32 = 1u;
|
||||
@id(1001) override c1 : u32 = 1u;
|
||||
override c2 : u32 = 1u;
|
||||
@id(0) override c3 : u32 = 1u;
|
||||
@id(9999) override c4 : u32 = 1u;
|
||||
|
||||
@stage(compute) @workgroup_size(1)
|
||||
fn comp_main1() {
|
||||
|
@ -292,7 +292,7 @@ fn comp_main5() {
|
|||
{
|
||||
SingleEntryPoint::Config cfg("comp_main1");
|
||||
auto* expect = R"(
|
||||
@override(1001) let c1 : u32 = 1u;
|
||||
@id(1001) override c1 : u32 = 1u;
|
||||
|
||||
@stage(compute) @workgroup_size(1)
|
||||
fn comp_main1() {
|
||||
|
@ -310,7 +310,7 @@ fn comp_main1() {
|
|||
// The decorator is replaced with the one with explicit id
|
||||
// And should not be affected by other constants stripped away
|
||||
auto* expect = R"(
|
||||
@override(1) let c2 : u32 = 1u;
|
||||
@id(1) override c2 : u32 = 1u;
|
||||
|
||||
@stage(compute) @workgroup_size(1)
|
||||
fn comp_main2() {
|
||||
|
@ -326,7 +326,7 @@ fn comp_main2() {
|
|||
{
|
||||
SingleEntryPoint::Config cfg("comp_main3");
|
||||
auto* expect = R"(
|
||||
@override(0) let c3 : u32 = 1u;
|
||||
@id(0) override c3 : u32 = 1u;
|
||||
|
||||
@stage(compute) @workgroup_size(1)
|
||||
fn comp_main3() {
|
||||
|
@ -342,7 +342,7 @@ fn comp_main3() {
|
|||
{
|
||||
SingleEntryPoint::Config cfg("comp_main4");
|
||||
auto* expect = R"(
|
||||
@override(9999) let c4 : u32 = 1u;
|
||||
@id(9999) override c4 : u32 = 1u;
|
||||
|
||||
@stage(compute) @workgroup_size(1)
|
||||
fn comp_main4() {
|
||||
|
|
|
@ -57,7 +57,7 @@ struct Unshadow::State {
|
|||
auto attributes = ctx.Clone(decl->attributes);
|
||||
return ctx.dst->create<ast::Variable>(
|
||||
source, symbol, decl->declared_storage_class, decl->declared_access,
|
||||
type, decl->is_const, constructor, attributes);
|
||||
type, decl->is_const, decl->is_overridable, constructor, attributes);
|
||||
};
|
||||
|
||||
ctx.ReplaceAll([&](const ast::Variable* var) -> const ast::Variable* {
|
||||
|
|
|
@ -506,7 +506,7 @@ var<workgroup> b : S;
|
|||
|
||||
var<workgroup> c : array<S, 32>;
|
||||
|
||||
@override(1) let X : i32;
|
||||
@id(1) override X : i32;
|
||||
|
||||
@stage(compute) @workgroup_size(2, 3, X)
|
||||
fn f(@builtin(local_invocation_index) local_idx : u32) {
|
||||
|
@ -528,7 +528,7 @@ var<workgroup> b : S;
|
|||
|
||||
var<workgroup> c : array<S, 32>;
|
||||
|
||||
@override(1) let X : i32;
|
||||
@id(1) override X : i32;
|
||||
|
||||
@stage(compute) @workgroup_size(2, 3, X)
|
||||
fn f(@builtin(local_invocation_index) local_idx : u32) {
|
||||
|
@ -576,7 +576,7 @@ var<workgroup> b : S;
|
|||
|
||||
var<workgroup> c : array<S, 32>;
|
||||
|
||||
@override(1) let X : u32;
|
||||
@id(1) override X : u32;
|
||||
|
||||
@stage(compute) @workgroup_size(5u, X, 10u)
|
||||
fn f(@builtin(local_invocation_index) local_idx : u32) {
|
||||
|
@ -599,7 +599,7 @@ var<workgroup> b : S;
|
|||
|
||||
var<workgroup> c : array<S, 32>;
|
||||
|
||||
@override(1) let X : u32;
|
||||
@id(1) override X : u32;
|
||||
|
||||
@stage(compute) @workgroup_size(5u, X, 10u)
|
||||
fn f(@builtin(local_invocation_index) local_idx : u32) {
|
||||
|
|
|
@ -23,9 +23,9 @@
|
|||
|
||||
#include "src/ast/call_statement.h"
|
||||
#include "src/ast/fallthrough_statement.h"
|
||||
#include "src/ast/id_attribute.h"
|
||||
#include "src/ast/internal_attribute.h"
|
||||
#include "src/ast/interpolate_attribute.h"
|
||||
#include "src/ast/override_attribute.h"
|
||||
#include "src/ast/variable_decl_statement.h"
|
||||
#include "src/debug.h"
|
||||
#include "src/sem/array.h"
|
||||
|
@ -2607,7 +2607,7 @@ bool GeneratorImpl::EmitVariable(const ast::Variable* var) {
|
|||
|
||||
bool GeneratorImpl::EmitProgramConstVariable(const ast::Variable* var) {
|
||||
for (auto* d : var->attributes) {
|
||||
if (!d->Is<ast::OverrideAttribute>()) {
|
||||
if (!d->Is<ast::IdAttribute>()) {
|
||||
diagnostics_.add_error(diag::System::Writer,
|
||||
"Decorated const values not valid");
|
||||
return false;
|
||||
|
|
|
@ -840,9 +840,9 @@ void main() {
|
|||
|
||||
TEST_F(GlslGeneratorImplTest_Function,
|
||||
Emit_Attribute_EntryPoint_Compute_WithWorkgroup_OverridableConst) {
|
||||
GlobalConst("width", ty.i32(), Construct(ty.i32(), 2), {Override(7u)});
|
||||
GlobalConst("height", ty.i32(), Construct(ty.i32(), 3), {Override(8u)});
|
||||
GlobalConst("depth", ty.i32(), Construct(ty.i32(), 4), {Override(9u)});
|
||||
Override("width", ty.i32(), Construct(ty.i32(), 2), {Id(7u)});
|
||||
Override("height", ty.i32(), Construct(ty.i32(), 3), {Id(8u)});
|
||||
Override("depth", ty.i32(), Construct(ty.i32(), 4), {Id(9u)});
|
||||
Func("main", ast::VariableList{}, ty.void_(), {},
|
||||
{
|
||||
Stage(ast::PipelineStage::kCompute),
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "src/ast/override_attribute.h"
|
||||
#include "src/ast/id_attribute.h"
|
||||
#include "src/writer/glsl/test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
|
@ -33,10 +33,10 @@ TEST_F(GlslGeneratorImplTest_ModuleConstant, Emit_ModuleConstant) {
|
|||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_ModuleConstant, Emit_SpecConstant) {
|
||||
auto* var = GlobalConst("pos", ty.f32(), Expr(3.0f),
|
||||
ast::AttributeList{
|
||||
create<ast::OverrideAttribute>(23),
|
||||
});
|
||||
auto* var = Override("pos", ty.f32(), Expr(3.0f),
|
||||
ast::AttributeList{
|
||||
Id(23),
|
||||
});
|
||||
|
||||
GeneratorImpl& gen = Build();
|
||||
|
||||
|
@ -49,10 +49,10 @@ const float pos = WGSL_SPEC_CONSTANT_23;
|
|||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_ModuleConstant, Emit_SpecConstant_NoConstructor) {
|
||||
auto* var = GlobalConst("pos", ty.f32(), nullptr,
|
||||
ast::AttributeList{
|
||||
create<ast::OverrideAttribute>(23),
|
||||
});
|
||||
auto* var = Override("pos", ty.f32(), nullptr,
|
||||
ast::AttributeList{
|
||||
Id(23),
|
||||
});
|
||||
|
||||
GeneratorImpl& gen = Build();
|
||||
|
||||
|
@ -65,14 +65,11 @@ const float pos = WGSL_SPEC_CONSTANT_23;
|
|||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_ModuleConstant, Emit_SpecConstant_NoId) {
|
||||
auto* a = GlobalConst("a", ty.f32(), Expr(3.0f),
|
||||
ast::AttributeList{
|
||||
create<ast::OverrideAttribute>(0),
|
||||
});
|
||||
auto* b = GlobalConst("b", ty.f32(), Expr(2.0f),
|
||||
ast::AttributeList{
|
||||
create<ast::OverrideAttribute>(),
|
||||
});
|
||||
auto* a = Override("a", ty.f32(), Expr(3.0f),
|
||||
ast::AttributeList{
|
||||
Id(0),
|
||||
});
|
||||
auto* b = Override("b", ty.f32(), Expr(2.0f));
|
||||
|
||||
GeneratorImpl& gen = Build();
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
// limitations under the License.
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "src/ast/override_attribute.h"
|
||||
#include "src/ast/id_attribute.h"
|
||||
#include "src/ast/stage_attribute.h"
|
||||
#include "src/writer/glsl/test_helper.h"
|
||||
|
||||
|
|
|
@ -24,9 +24,9 @@
|
|||
|
||||
#include "src/ast/call_statement.h"
|
||||
#include "src/ast/fallthrough_statement.h"
|
||||
#include "src/ast/id_attribute.h"
|
||||
#include "src/ast/internal_attribute.h"
|
||||
#include "src/ast/interpolate_attribute.h"
|
||||
#include "src/ast/override_attribute.h"
|
||||
#include "src/ast/variable_decl_statement.h"
|
||||
#include "src/debug.h"
|
||||
#include "src/sem/array.h"
|
||||
|
@ -3898,7 +3898,7 @@ bool GeneratorImpl::EmitVariable(const ast::Variable* var) {
|
|||
|
||||
bool GeneratorImpl::EmitProgramConstVariable(const ast::Variable* var) {
|
||||
for (auto* d : var->attributes) {
|
||||
if (!d->Is<ast::OverrideAttribute>()) {
|
||||
if (!d->Is<ast::IdAttribute>()) {
|
||||
diagnostics_.add_error(diag::System::Writer,
|
||||
"Decorated const values not valid");
|
||||
return false;
|
||||
|
|
|
@ -745,9 +745,9 @@ void main() {
|
|||
|
||||
TEST_F(HlslGeneratorImplTest_Function,
|
||||
Emit_Attribute_EntryPoint_Compute_WithWorkgroup_OverridableConst) {
|
||||
GlobalConst("width", ty.i32(), Construct(ty.i32(), 2), {Override(7u)});
|
||||
GlobalConst("height", ty.i32(), Construct(ty.i32(), 3), {Override(8u)});
|
||||
GlobalConst("depth", ty.i32(), Construct(ty.i32(), 4), {Override(9u)});
|
||||
Override("width", ty.i32(), Construct(ty.i32(), 2), {Id(7u)});
|
||||
Override("height", ty.i32(), Construct(ty.i32(), 3), {Id(8u)});
|
||||
Override("depth", ty.i32(), Construct(ty.i32(), 4), {Id(9u)});
|
||||
Func("main", ast::VariableList{}, ty.void_(), {},
|
||||
{
|
||||
Stage(ast::PipelineStage::kCompute),
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "src/ast/override_attribute.h"
|
||||
#include "src/ast/id_attribute.h"
|
||||
#include "src/writer/hlsl/test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
|
@ -33,10 +33,10 @@ TEST_F(HlslGeneratorImplTest_ModuleConstant, Emit_ModuleConstant) {
|
|||
}
|
||||
|
||||
TEST_F(HlslGeneratorImplTest_ModuleConstant, Emit_SpecConstant) {
|
||||
auto* var = GlobalConst("pos", ty.f32(), Expr(3.0f),
|
||||
ast::AttributeList{
|
||||
create<ast::OverrideAttribute>(23),
|
||||
});
|
||||
auto* var = Override("pos", ty.f32(), Expr(3.0f),
|
||||
ast::AttributeList{
|
||||
Id(23),
|
||||
});
|
||||
|
||||
GeneratorImpl& gen = Build();
|
||||
|
||||
|
@ -49,10 +49,10 @@ static const float pos = WGSL_SPEC_CONSTANT_23;
|
|||
}
|
||||
|
||||
TEST_F(HlslGeneratorImplTest_ModuleConstant, Emit_SpecConstant_NoConstructor) {
|
||||
auto* var = GlobalConst("pos", ty.f32(), nullptr,
|
||||
ast::AttributeList{
|
||||
create<ast::OverrideAttribute>(23),
|
||||
});
|
||||
auto* var = Override("pos", ty.f32(), nullptr,
|
||||
ast::AttributeList{
|
||||
Id(23),
|
||||
});
|
||||
|
||||
GeneratorImpl& gen = Build();
|
||||
|
||||
|
@ -65,14 +65,11 @@ static const float pos = WGSL_SPEC_CONSTANT_23;
|
|||
}
|
||||
|
||||
TEST_F(HlslGeneratorImplTest_ModuleConstant, Emit_SpecConstant_NoId) {
|
||||
auto* a = GlobalConst("a", ty.f32(), Expr(3.0f),
|
||||
ast::AttributeList{
|
||||
create<ast::OverrideAttribute>(0),
|
||||
});
|
||||
auto* b = GlobalConst("b", ty.f32(), Expr(2.0f),
|
||||
ast::AttributeList{
|
||||
create<ast::OverrideAttribute>(),
|
||||
});
|
||||
auto* a = Override("a", ty.f32(), Expr(3.0f),
|
||||
ast::AttributeList{
|
||||
Id(0),
|
||||
});
|
||||
auto* b = Override("b", ty.f32(), Expr(2.0f));
|
||||
|
||||
GeneratorImpl& gen = Build();
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
// limitations under the License.
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "src/ast/override_attribute.h"
|
||||
#include "src/ast/id_attribute.h"
|
||||
#include "src/ast/stage_attribute.h"
|
||||
#include "src/writer/hlsl/test_helper.h"
|
||||
|
||||
|
|
|
@ -27,9 +27,9 @@
|
|||
#include "src/ast/disable_validation_attribute.h"
|
||||
#include "src/ast/fallthrough_statement.h"
|
||||
#include "src/ast/float_literal_expression.h"
|
||||
#include "src/ast/id_attribute.h"
|
||||
#include "src/ast/interpolate_attribute.h"
|
||||
#include "src/ast/module.h"
|
||||
#include "src/ast/override_attribute.h"
|
||||
#include "src/ast/sint_literal_expression.h"
|
||||
#include "src/ast/uint_literal_expression.h"
|
||||
#include "src/ast/variable_decl_statement.h"
|
||||
|
@ -2823,7 +2823,7 @@ bool GeneratorImpl::EmitVariable(const sem::Variable* var) {
|
|||
|
||||
bool GeneratorImpl::EmitProgramConstVariable(const ast::Variable* var) {
|
||||
for (auto* d : var->attributes) {
|
||||
if (!d->Is<ast::OverrideAttribute>()) {
|
||||
if (!d->Is<ast::IdAttribute>()) {
|
||||
diagnostics_.add_error(diag::System::Writer,
|
||||
"Decorated const values not valid");
|
||||
return false;
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "src/ast/override_attribute.h"
|
||||
#include "src/ast/id_attribute.h"
|
||||
#include "src/writer/msl/test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
|
@ -33,10 +33,10 @@ TEST_F(MslGeneratorImplTest, Emit_ModuleConstant) {
|
|||
}
|
||||
|
||||
TEST_F(MslGeneratorImplTest, Emit_SpecConstant) {
|
||||
auto* var = GlobalConst("pos", ty.f32(), Expr(3.f),
|
||||
ast::AttributeList{
|
||||
create<ast::OverrideAttribute>(23),
|
||||
});
|
||||
auto* var = Override("pos", ty.f32(), Expr(3.f),
|
||||
ast::AttributeList{
|
||||
Id(23),
|
||||
});
|
||||
|
||||
GeneratorImpl& gen = Build();
|
||||
|
||||
|
@ -45,14 +45,11 @@ TEST_F(MslGeneratorImplTest, Emit_SpecConstant) {
|
|||
}
|
||||
|
||||
TEST_F(MslGeneratorImplTest, Emit_SpecConstant_NoId) {
|
||||
auto* var_a = GlobalConst("a", ty.f32(), nullptr,
|
||||
ast::AttributeList{
|
||||
create<ast::OverrideAttribute>(0),
|
||||
});
|
||||
auto* var_b = GlobalConst("b", ty.f32(), nullptr,
|
||||
ast::AttributeList{
|
||||
create<ast::OverrideAttribute>(),
|
||||
});
|
||||
auto* var_a = Override("a", ty.f32(), nullptr,
|
||||
ast::AttributeList{
|
||||
Id(0),
|
||||
});
|
||||
auto* var_b = Override("b", ty.f32(), nullptr);
|
||||
|
||||
GeneratorImpl& gen = Build();
|
||||
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
#include "spirv/unified1/GLSL.std.450.h"
|
||||
#include "src/ast/call_statement.h"
|
||||
#include "src/ast/fallthrough_statement.h"
|
||||
#include "src/ast/id_attribute.h"
|
||||
#include "src/ast/internal_attribute.h"
|
||||
#include "src/ast/override_attribute.h"
|
||||
#include "src/ast/traverse_expressions.h"
|
||||
#include "src/sem/array.h"
|
||||
#include "src/sem/atomic_type.h"
|
||||
|
@ -770,9 +770,8 @@ bool Builder::GenerateGlobalVariable(const ast::Variable* var) {
|
|||
|
||||
if (var->is_const) {
|
||||
if (!var->constructor) {
|
||||
// Constants must have an initializer unless they have an override
|
||||
// attribute.
|
||||
if (!ast::HasAttribute<ast::OverrideAttribute>(var->attributes)) {
|
||||
// Constants must have an initializer unless they are overridable.
|
||||
if (!var->is_overridable) {
|
||||
error_ = "missing constructor for constant";
|
||||
return false;
|
||||
}
|
||||
|
@ -905,7 +904,7 @@ bool Builder::GenerateGlobalVariable(const ast::Variable* var) {
|
|||
Operand::Int(group->value)});
|
||||
return true;
|
||||
},
|
||||
[&](const ast::OverrideAttribute*) {
|
||||
[&](const ast::IdAttribute*) {
|
||||
return true; // Spec constants are handled elsewhere
|
||||
},
|
||||
[&](const ast::InternalAttribute*) {
|
||||
|
|
|
@ -155,9 +155,9 @@ TEST_F(BuilderTest, Decoration_ExecutionMode_WorkgroupSize_Const) {
|
|||
}
|
||||
|
||||
TEST_F(BuilderTest, Decoration_ExecutionMode_WorkgroupSize_OverridableConst) {
|
||||
GlobalConst("width", ty.i32(), Construct(ty.i32(), 2), {Override(7u)});
|
||||
GlobalConst("height", ty.i32(), Construct(ty.i32(), 3), {Override(8u)});
|
||||
GlobalConst("depth", ty.i32(), Construct(ty.i32(), 4), {Override(9u)});
|
||||
Override("width", ty.i32(), Construct(ty.i32(), 2), {Id(7u)});
|
||||
Override("height", ty.i32(), Construct(ty.i32(), 3), {Id(8u)});
|
||||
Override("depth", ty.i32(), Construct(ty.i32(), 4), {Id(9u)});
|
||||
auto* func = Func("main", {}, ty.void_(), ast::StatementList{},
|
||||
ast::AttributeList{
|
||||
WorkgroupSize("width", "height", "depth"),
|
||||
|
@ -185,7 +185,7 @@ OpDecorate %3 BuiltIn WorkgroupSize
|
|||
}
|
||||
|
||||
TEST_F(BuilderTest, Decoration_ExecutionMode_WorkgroupSize_LiteralAndConst) {
|
||||
GlobalConst("height", ty.i32(), Construct(ty.i32(), 2), {Override(7u)});
|
||||
Override("height", ty.i32(), Construct(ty.i32(), 2), {Id(7u)});
|
||||
GlobalConst("depth", ty.i32(), Construct(ty.i32(), 3));
|
||||
auto* func = Func("main", {}, ty.void_(), ast::StatementList{},
|
||||
ast::AttributeList{
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "src/ast/override_attribute.h"
|
||||
#include "src/ast/id_attribute.h"
|
||||
#include "src/ast/stage_attribute.h"
|
||||
#include "src/ast/struct_block_attribute.h"
|
||||
#include "src/writer/spirv/spv_dump.h"
|
||||
|
@ -150,10 +150,10 @@ OpDecorate %1 DescriptorSet 3
|
|||
}
|
||||
|
||||
TEST_F(BuilderTest, GlobalVar_Override_Bool) {
|
||||
auto* v = GlobalConst("var", ty.bool_(), Expr(true),
|
||||
ast::AttributeList{
|
||||
create<ast::OverrideAttribute>(1200),
|
||||
});
|
||||
auto* v = Override("var", ty.bool_(), Expr(true),
|
||||
ast::AttributeList{
|
||||
Id(1200),
|
||||
});
|
||||
|
||||
spirv::Builder& b = Build();
|
||||
|
||||
|
@ -168,10 +168,10 @@ TEST_F(BuilderTest, GlobalVar_Override_Bool) {
|
|||
}
|
||||
|
||||
TEST_F(BuilderTest, GlobalVar_Override_Bool_ZeroValue) {
|
||||
auto* v = GlobalConst("var", ty.bool_(), Construct<bool>(),
|
||||
ast::AttributeList{
|
||||
create<ast::OverrideAttribute>(1200),
|
||||
});
|
||||
auto* v = Override("var", ty.bool_(), Construct<bool>(),
|
||||
ast::AttributeList{
|
||||
Id(1200),
|
||||
});
|
||||
|
||||
spirv::Builder& b = Build();
|
||||
|
||||
|
@ -186,10 +186,10 @@ TEST_F(BuilderTest, GlobalVar_Override_Bool_ZeroValue) {
|
|||
}
|
||||
|
||||
TEST_F(BuilderTest, GlobalVar_Override_Bool_NoConstructor) {
|
||||
auto* v = GlobalConst("var", ty.bool_(), nullptr,
|
||||
ast::AttributeList{
|
||||
create<ast::OverrideAttribute>(1200),
|
||||
});
|
||||
auto* v = Override("var", ty.bool_(), nullptr,
|
||||
ast::AttributeList{
|
||||
Id(1200),
|
||||
});
|
||||
|
||||
spirv::Builder& b = Build();
|
||||
|
||||
|
@ -204,10 +204,10 @@ TEST_F(BuilderTest, GlobalVar_Override_Bool_NoConstructor) {
|
|||
}
|
||||
|
||||
TEST_F(BuilderTest, GlobalVar_Override_Scalar) {
|
||||
auto* v = GlobalConst("var", ty.f32(), Expr(2.f),
|
||||
ast::AttributeList{
|
||||
create<ast::OverrideAttribute>(0),
|
||||
});
|
||||
auto* v = Override("var", ty.f32(), Expr(2.f),
|
||||
ast::AttributeList{
|
||||
Id(0),
|
||||
});
|
||||
|
||||
spirv::Builder& b = Build();
|
||||
|
||||
|
@ -222,10 +222,10 @@ TEST_F(BuilderTest, GlobalVar_Override_Scalar) {
|
|||
}
|
||||
|
||||
TEST_F(BuilderTest, GlobalVar_Override_Scalar_ZeroValue) {
|
||||
auto* v = GlobalConst("var", ty.f32(), Construct<f32>(),
|
||||
ast::AttributeList{
|
||||
create<ast::OverrideAttribute>(0),
|
||||
});
|
||||
auto* v = Override("var", ty.f32(), Construct<f32>(),
|
||||
ast::AttributeList{
|
||||
Id(0),
|
||||
});
|
||||
|
||||
spirv::Builder& b = Build();
|
||||
|
||||
|
@ -240,10 +240,10 @@ TEST_F(BuilderTest, GlobalVar_Override_Scalar_ZeroValue) {
|
|||
}
|
||||
|
||||
TEST_F(BuilderTest, GlobalVar_Override_Scalar_F32_NoConstructor) {
|
||||
auto* v = GlobalConst("var", ty.f32(), nullptr,
|
||||
ast::AttributeList{
|
||||
create<ast::OverrideAttribute>(0),
|
||||
});
|
||||
auto* v = Override("var", ty.f32(), nullptr,
|
||||
ast::AttributeList{
|
||||
Id(0),
|
||||
});
|
||||
|
||||
spirv::Builder& b = Build();
|
||||
|
||||
|
@ -258,10 +258,10 @@ TEST_F(BuilderTest, GlobalVar_Override_Scalar_F32_NoConstructor) {
|
|||
}
|
||||
|
||||
TEST_F(BuilderTest, GlobalVar_Override_Scalar_I32_NoConstructor) {
|
||||
auto* v = GlobalConst("var", ty.i32(), nullptr,
|
||||
ast::AttributeList{
|
||||
create<ast::OverrideAttribute>(0),
|
||||
});
|
||||
auto* v = Override("var", ty.i32(), nullptr,
|
||||
ast::AttributeList{
|
||||
Id(0),
|
||||
});
|
||||
|
||||
spirv::Builder& b = Build();
|
||||
|
||||
|
@ -276,10 +276,10 @@ TEST_F(BuilderTest, GlobalVar_Override_Scalar_I32_NoConstructor) {
|
|||
}
|
||||
|
||||
TEST_F(BuilderTest, GlobalVar_Override_Scalar_U32_NoConstructor) {
|
||||
auto* v = GlobalConst("var", ty.u32(), nullptr,
|
||||
ast::AttributeList{
|
||||
create<ast::OverrideAttribute>(0),
|
||||
});
|
||||
auto* v = Override("var", ty.u32(), nullptr,
|
||||
ast::AttributeList{
|
||||
Id(0),
|
||||
});
|
||||
|
||||
spirv::Builder& b = Build();
|
||||
|
||||
|
@ -294,14 +294,11 @@ TEST_F(BuilderTest, GlobalVar_Override_Scalar_U32_NoConstructor) {
|
|||
}
|
||||
|
||||
TEST_F(BuilderTest, GlobalVar_Override_NoId) {
|
||||
auto* var_a = GlobalConst("a", ty.bool_(), Expr(true),
|
||||
ast::AttributeList{
|
||||
create<ast::OverrideAttribute>(0),
|
||||
});
|
||||
auto* var_b = GlobalConst("b", ty.bool_(), Expr(false),
|
||||
ast::AttributeList{
|
||||
create<ast::OverrideAttribute>(),
|
||||
});
|
||||
auto* var_a = Override("a", ty.bool_(), Expr(true),
|
||||
ast::AttributeList{
|
||||
Id(0),
|
||||
});
|
||||
auto* var_b = Override("b", ty.bool_(), Expr(false));
|
||||
|
||||
spirv::Builder& b = Build();
|
||||
|
||||
|
|
|
@ -28,13 +28,13 @@
|
|||
#include "src/ast/f32.h"
|
||||
#include "src/ast/float_literal_expression.h"
|
||||
#include "src/ast/i32.h"
|
||||
#include "src/ast/id_attribute.h"
|
||||
#include "src/ast/internal_attribute.h"
|
||||
#include "src/ast/interpolate_attribute.h"
|
||||
#include "src/ast/invariant_attribute.h"
|
||||
#include "src/ast/matrix.h"
|
||||
#include "src/ast/module.h"
|
||||
#include "src/ast/multisampled_texture.h"
|
||||
#include "src/ast/override_attribute.h"
|
||||
#include "src/ast/pointer.h"
|
||||
#include "src/ast/sampled_texture.h"
|
||||
#include "src/ast/sint_literal_expression.h"
|
||||
|
@ -646,7 +646,9 @@ bool GeneratorImpl::EmitVariable(std::ostream& out, const ast::Variable* var) {
|
|||
out << " ";
|
||||
}
|
||||
|
||||
if (var->is_const) {
|
||||
if (var->is_overridable) {
|
||||
out << "override";
|
||||
} else if (var->is_const) {
|
||||
out << "let";
|
||||
} else {
|
||||
out << "var";
|
||||
|
@ -747,11 +749,8 @@ bool GeneratorImpl::EmitAttributes(std::ostream& out,
|
|||
out << "invariant";
|
||||
return true;
|
||||
},
|
||||
[&](const ast::OverrideAttribute* override_deco) {
|
||||
out << "override";
|
||||
if (override_deco->has_value) {
|
||||
out << "(" << override_deco->value << ")";
|
||||
}
|
||||
[&](const ast::IdAttribute* override_deco) {
|
||||
out << "id(" << override_deco->value << ")";
|
||||
return true;
|
||||
},
|
||||
[&](const ast::StructMemberSizeAttribute* size) {
|
||||
|
|
|
@ -132,17 +132,17 @@ TEST_F(WgslGeneratorImplTest, Emit_Global_Texture) {
|
|||
}
|
||||
|
||||
TEST_F(WgslGeneratorImplTest, Emit_OverridableConstants) {
|
||||
GlobalConst("a", ty.f32(), nullptr, {Override()});
|
||||
GlobalConst("b", ty.f32(), nullptr, {Override(7u)});
|
||||
Override("a", ty.f32(), nullptr);
|
||||
Override("b", ty.f32(), nullptr, {Id(7u)});
|
||||
|
||||
GeneratorImpl& gen = Build();
|
||||
|
||||
gen.increment_indent();
|
||||
|
||||
ASSERT_TRUE(gen.Generate()) << gen.error();
|
||||
EXPECT_EQ(gen.result(), R"( @override let a : f32;
|
||||
EXPECT_EQ(gen.result(), R"( override a : f32;
|
||||
|
||||
@override(7) let b : f32;
|
||||
@id(7) override b : f32;
|
||||
)");
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
|
||||
#include <cstring>
|
||||
|
||||
#include "src/ast/override_attribute.h"
|
||||
#include "src/writer/wgsl/test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "src/ast/override_attribute.h"
|
||||
#include "src/ast/struct_block_attribute.h"
|
||||
#include "src/writer/wgsl/test_helper.h"
|
||||
|
||||
|
|
|
@ -171,6 +171,7 @@ tint_unittests_source_set("tint_unittests_ast_src") {
|
|||
"../src/ast/function_test.cc",
|
||||
"../src/ast/group_attribute_test.cc",
|
||||
"../src/ast/i32_test.cc",
|
||||
"../src/ast/id_attribute_test.cc",
|
||||
"../src/ast/identifier_expression_test.cc",
|
||||
"../src/ast/if_statement_test.cc",
|
||||
"../src/ast/index_accessor_expression_test.cc",
|
||||
|
@ -184,7 +185,6 @@ tint_unittests_source_set("tint_unittests_ast_src") {
|
|||
"../src/ast/module_clone_test.cc",
|
||||
"../src/ast/module_test.cc",
|
||||
"../src/ast/multisampled_texture_test.cc",
|
||||
"../src/ast/override_attribute_test.cc",
|
||||
"../src/ast/phony_expression_test.cc",
|
||||
"../src/ast/pointer_test.cc",
|
||||
"../src/ast/return_statement_test.cc",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@override let o : bool;
|
||||
override o : bool;
|
||||
|
||||
@stage(compute) @workgroup_size(1)
|
||||
fn main() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@override let o : bool;
|
||||
override o : bool;
|
||||
|
||||
@stage(compute) @workgroup_size(1)
|
||||
fn main() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@override let o : f32;
|
||||
override o : f32;
|
||||
|
||||
@stage(compute) @workgroup_size(1)
|
||||
fn main() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@override let o : f32;
|
||||
override o : f32;
|
||||
|
||||
@stage(compute) @workgroup_size(1)
|
||||
fn main() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@override let o : i32;
|
||||
override o : i32;
|
||||
|
||||
@stage(compute) @workgroup_size(1)
|
||||
fn main() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@override let o : i32;
|
||||
override o : i32;
|
||||
|
||||
@stage(compute) @workgroup_size(1)
|
||||
fn main() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@override let o : u32;
|
||||
override o : u32;
|
||||
|
||||
@stage(compute) @workgroup_size(1)
|
||||
fn main() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@override let o : u32;
|
||||
override o : u32;
|
||||
|
||||
@stage(compute) @workgroup_size(1)
|
||||
fn main() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@override let o : bool = true;
|
||||
override o : bool = true;
|
||||
|
||||
@stage(compute) @workgroup_size(1)
|
||||
fn main() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@override let o : bool = true;
|
||||
override o : bool = true;
|
||||
|
||||
@stage(compute) @workgroup_size(1)
|
||||
fn main() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@override let o : f32 = 1.0;
|
||||
override o : f32 = 1.0;
|
||||
|
||||
@stage(compute) @workgroup_size(1)
|
||||
fn main() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@override let o : f32 = 1.0;
|
||||
override o : f32 = 1.0;
|
||||
|
||||
@stage(compute) @workgroup_size(1)
|
||||
fn main() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@override let o : i32 = 1;
|
||||
override o : i32 = 1;
|
||||
|
||||
@stage(compute) @workgroup_size(1)
|
||||
fn main() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@override let o : i32 = 1;
|
||||
override o : i32 = 1;
|
||||
|
||||
@stage(compute) @workgroup_size(1)
|
||||
fn main() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@override let o : u32 = 1u;
|
||||
override o : u32 = 1u;
|
||||
|
||||
@stage(compute) @workgroup_size(1)
|
||||
fn main() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@override let o : u32 = 1u;
|
||||
override o : u32 = 1u;
|
||||
|
||||
@stage(compute) @workgroup_size(1)
|
||||
fn main() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@override let o : bool = bool();
|
||||
override o : bool = bool();
|
||||
|
||||
@stage(compute) @workgroup_size(1)
|
||||
fn main() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@override let o : bool = bool();
|
||||
override o : bool = bool();
|
||||
|
||||
@stage(compute) @workgroup_size(1)
|
||||
fn main() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@override let o : f32 = f32();
|
||||
override o : f32 = f32();
|
||||
|
||||
@stage(compute) @workgroup_size(1)
|
||||
fn main() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@override let o : f32 = f32();
|
||||
override o : f32 = f32();
|
||||
|
||||
@stage(compute) @workgroup_size(1)
|
||||
fn main() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@override let o : i32 = i32();
|
||||
override o : i32 = i32();
|
||||
|
||||
@stage(compute) @workgroup_size(1)
|
||||
fn main() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@override let o : i32 = i32();
|
||||
override o : i32 = i32();
|
||||
|
||||
@stage(compute) @workgroup_size(1)
|
||||
fn main() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@override let o : u32 = u32();
|
||||
override o : u32 = u32();
|
||||
|
||||
@stage(compute) @workgroup_size(1)
|
||||
fn main() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@override let o : u32 = u32();
|
||||
override o : u32 = u32();
|
||||
|
||||
@stage(compute) @workgroup_size(1)
|
||||
fn main() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@override(1234) let o : bool;
|
||||
@id(1234) override o : bool;
|
||||
|
||||
@stage(compute) @workgroup_size(1)
|
||||
fn main() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@override(1234) let o : bool;
|
||||
@id(1234) override o : bool;
|
||||
|
||||
@stage(compute) @workgroup_size(1)
|
||||
fn main() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@override(1234) let o : f32;
|
||||
@id(1234) override o : f32;
|
||||
|
||||
@stage(compute) @workgroup_size(1)
|
||||
fn main() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@override(1234) let o : f32;
|
||||
@id(1234) override o : f32;
|
||||
|
||||
@stage(compute) @workgroup_size(1)
|
||||
fn main() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@override(1234) let o : i32;
|
||||
@id(1234) override o : i32;
|
||||
|
||||
@stage(compute) @workgroup_size(1)
|
||||
fn main() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@override(1234) let o : i32;
|
||||
@id(1234) override o : i32;
|
||||
|
||||
@stage(compute) @workgroup_size(1)
|
||||
fn main() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@override(1234) let o : u32;
|
||||
@id(1234) override o : u32;
|
||||
|
||||
@stage(compute) @workgroup_size(1)
|
||||
fn main() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@override(1234) let o : u32;
|
||||
@id(1234) override o : u32;
|
||||
|
||||
@stage(compute) @workgroup_size(1)
|
||||
fn main() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@override(1234) let o : bool = true;
|
||||
@id(1234) override o : bool = true;
|
||||
|
||||
@stage(compute) @workgroup_size(1)
|
||||
fn main() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@override(1234) let o : bool = true;
|
||||
@id(1234) override o : bool = true;
|
||||
|
||||
@stage(compute) @workgroup_size(1)
|
||||
fn main() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@override(1234) let o : f32 = 1.0;
|
||||
@id(1234) override o : f32 = 1.0;
|
||||
|
||||
@stage(compute) @workgroup_size(1)
|
||||
fn main() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@override(1234) let o : f32 = 1.0;
|
||||
@id(1234) override o : f32 = 1.0;
|
||||
|
||||
@stage(compute) @workgroup_size(1)
|
||||
fn main() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@override(1234) let o : i32 = 1;
|
||||
@id(1234) override o : i32 = 1;
|
||||
|
||||
@stage(compute) @workgroup_size(1)
|
||||
fn main() {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue