tint: Handle @diagnostic on block statements
Use expect_compound_statement() in all the places that use compound_statement in the WGSL grammar. Handle attributes on statements inside Resolver::StatementScope, so that the logic can be reused for the various places where block statements are used. This will also make it easier to reuse this logic when we allow these attributes on other types of statement in the future. Add an `EmitBlockHeader()` helper to the WGSL writer to reuse the logic for emitting attributes on block statements for all the places that use them. Bug: tint:1809 Change-Id: Iac3bb01f5031e6134c1798ddafdad080412c8bef Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/118000 Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: Ben Clayton <bclayton@google.com> Commit-Queue: James Price <jrprice@google.com>
This commit is contained in:
parent
e60a579c19
commit
d9f659670d
|
@ -23,12 +23,17 @@ namespace tint::ast {
|
||||||
BlockStatement::BlockStatement(ProgramID pid,
|
BlockStatement::BlockStatement(ProgramID pid,
|
||||||
NodeID nid,
|
NodeID nid,
|
||||||
const Source& src,
|
const Source& src,
|
||||||
utils::VectorRef<const Statement*> stmts)
|
utils::VectorRef<const Statement*> stmts,
|
||||||
: Base(pid, nid, src), statements(std::move(stmts)) {
|
utils::VectorRef<const Attribute*> attrs)
|
||||||
|
: Base(pid, nid, src), statements(std::move(stmts)), attributes(attrs) {
|
||||||
for (auto* stmt : statements) {
|
for (auto* stmt : statements) {
|
||||||
TINT_ASSERT(AST, stmt);
|
TINT_ASSERT(AST, stmt);
|
||||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, stmt, program_id);
|
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, stmt, program_id);
|
||||||
}
|
}
|
||||||
|
for (auto* attr : attributes) {
|
||||||
|
TINT_ASSERT(AST, attr);
|
||||||
|
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, attr, program_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockStatement::BlockStatement(BlockStatement&&) = default;
|
BlockStatement::BlockStatement(BlockStatement&&) = default;
|
||||||
|
@ -39,7 +44,8 @@ const BlockStatement* BlockStatement::Clone(CloneContext* ctx) const {
|
||||||
// Clone arguments outside of create() call to have deterministic ordering
|
// Clone arguments outside of create() call to have deterministic ordering
|
||||||
auto src = ctx->Clone(source);
|
auto src = ctx->Clone(source);
|
||||||
auto stmts = ctx->Clone(statements);
|
auto stmts = ctx->Clone(statements);
|
||||||
return ctx->dst->create<BlockStatement>(src, std::move(stmts));
|
auto attrs = ctx->Clone(attributes);
|
||||||
|
return ctx->dst->create<BlockStatement>(src, std::move(stmts), std::move(attrs));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace tint::ast
|
} // namespace tint::ast
|
||||||
|
|
|
@ -19,6 +19,11 @@
|
||||||
|
|
||||||
#include "src/tint/ast/statement.h"
|
#include "src/tint/ast/statement.h"
|
||||||
|
|
||||||
|
// Forward declarations
|
||||||
|
namespace tint::ast {
|
||||||
|
class Attribute;
|
||||||
|
} // namespace tint::ast
|
||||||
|
|
||||||
namespace tint::ast {
|
namespace tint::ast {
|
||||||
|
|
||||||
/// A block statement
|
/// A block statement
|
||||||
|
@ -29,10 +34,12 @@ class BlockStatement final : public Castable<BlockStatement, Statement> {
|
||||||
/// @param nid the unique node identifier
|
/// @param nid the unique node identifier
|
||||||
/// @param source the block statement source
|
/// @param source the block statement source
|
||||||
/// @param statements the statements
|
/// @param statements the statements
|
||||||
|
/// @param attributes the block statement attributes
|
||||||
BlockStatement(ProgramID pid,
|
BlockStatement(ProgramID pid,
|
||||||
NodeID nid,
|
NodeID nid,
|
||||||
const Source& source,
|
const Source& source,
|
||||||
utils::VectorRef<const Statement*> statements);
|
utils::VectorRef<const Statement*> statements,
|
||||||
|
utils::VectorRef<const Attribute*> attributes);
|
||||||
/// Move constructor
|
/// Move constructor
|
||||||
BlockStatement(BlockStatement&&);
|
BlockStatement(BlockStatement&&);
|
||||||
~BlockStatement() override;
|
~BlockStatement() override;
|
||||||
|
@ -51,6 +58,9 @@ class BlockStatement final : public Castable<BlockStatement, Statement> {
|
||||||
|
|
||||||
/// the statement list
|
/// the statement list
|
||||||
const utils::Vector<const Statement*, 8> statements;
|
const utils::Vector<const Statement*, 8> statements;
|
||||||
|
|
||||||
|
/// the attribute list
|
||||||
|
const utils::Vector<const Attribute*, 4> attributes;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace tint::ast
|
} // namespace tint::ast
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "gmock/gmock.h"
|
||||||
#include "gtest/gtest-spi.h"
|
#include "gtest/gtest-spi.h"
|
||||||
#include "src/tint/ast/discard_statement.h"
|
#include "src/tint/ast/discard_statement.h"
|
||||||
#include "src/tint/ast/if_statement.h"
|
#include "src/tint/ast/if_statement.h"
|
||||||
|
@ -26,21 +27,35 @@ TEST_F(BlockStatementTest, Creation) {
|
||||||
auto* d = create<DiscardStatement>();
|
auto* d = create<DiscardStatement>();
|
||||||
auto* ptr = d;
|
auto* ptr = d;
|
||||||
|
|
||||||
auto* b = create<BlockStatement>(utils::Vector{d});
|
auto* b = create<BlockStatement>(utils::Vector{d}, utils::Empty);
|
||||||
|
|
||||||
ASSERT_EQ(b->statements.Length(), 1u);
|
ASSERT_EQ(b->statements.Length(), 1u);
|
||||||
EXPECT_EQ(b->statements[0], ptr);
|
EXPECT_EQ(b->statements[0], ptr);
|
||||||
|
EXPECT_EQ(b->attributes.Length(), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(BlockStatementTest, Creation_WithSource) {
|
TEST_F(BlockStatementTest, Creation_WithSource) {
|
||||||
auto* b = create<BlockStatement>(Source{Source::Location{20, 2}}, utils::Empty);
|
auto* b = create<BlockStatement>(Source{Source::Location{20, 2}}, utils::Empty, utils::Empty);
|
||||||
auto src = b->source;
|
auto src = b->source;
|
||||||
EXPECT_EQ(src.range.begin.line, 20u);
|
EXPECT_EQ(src.range.begin.line, 20u);
|
||||||
EXPECT_EQ(src.range.begin.column, 2u);
|
EXPECT_EQ(src.range.begin.column, 2u);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(BlockStatementTest, Creation_WithAttributes) {
|
||||||
|
auto* d = create<DiscardStatement>();
|
||||||
|
auto* ptr = d;
|
||||||
|
|
||||||
|
auto* attr1 = DiagnosticAttribute(ast::DiagnosticSeverity::kOff, Expr("foo"));
|
||||||
|
auto* attr2 = DiagnosticAttribute(ast::DiagnosticSeverity::kOff, Expr("bar"));
|
||||||
|
auto* b = create<BlockStatement>(utils::Vector{d}, utils::Vector{attr1, attr2});
|
||||||
|
|
||||||
|
ASSERT_EQ(b->statements.Length(), 1u);
|
||||||
|
EXPECT_EQ(b->statements[0], ptr);
|
||||||
|
EXPECT_THAT(b->attributes, testing::ElementsAre(attr1, attr2));
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(BlockStatementTest, IsBlock) {
|
TEST_F(BlockStatementTest, IsBlock) {
|
||||||
auto* b = create<BlockStatement>(utils::Empty);
|
auto* b = create<BlockStatement>(utils::Empty, utils::Empty);
|
||||||
EXPECT_TRUE(b->Is<BlockStatement>());
|
EXPECT_TRUE(b->Is<BlockStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,7 +63,8 @@ TEST_F(BlockStatementTest, Assert_Null_Statement) {
|
||||||
EXPECT_FATAL_FAILURE(
|
EXPECT_FATAL_FAILURE(
|
||||||
{
|
{
|
||||||
ProgramBuilder b;
|
ProgramBuilder b;
|
||||||
b.create<BlockStatement>(utils::Vector<const ast::Statement*, 1>{nullptr});
|
b.create<BlockStatement>(utils::Vector<const ast::Statement*, 1>{nullptr},
|
||||||
|
utils::Empty);
|
||||||
},
|
},
|
||||||
"internal compiler error");
|
"internal compiler error");
|
||||||
}
|
}
|
||||||
|
@ -58,7 +74,7 @@ TEST_F(BlockStatementTest, Assert_DifferentProgramID_Statement) {
|
||||||
{
|
{
|
||||||
ProgramBuilder b1;
|
ProgramBuilder b1;
|
||||||
ProgramBuilder b2;
|
ProgramBuilder b2;
|
||||||
b1.create<BlockStatement>(utils::Vector{b2.create<DiscardStatement>()});
|
b1.create<BlockStatement>(utils::Vector{b2.create<DiscardStatement>()}, utils::Empty);
|
||||||
},
|
},
|
||||||
"internal compiler error");
|
"internal compiler error");
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ TEST_F(CaseStatementTest, Creation_i32) {
|
||||||
utils::Vector b{selector};
|
utils::Vector b{selector};
|
||||||
|
|
||||||
auto* discard = create<DiscardStatement>();
|
auto* discard = create<DiscardStatement>();
|
||||||
auto* body = create<BlockStatement>(utils::Vector{discard});
|
auto* body = create<BlockStatement>(utils::Vector{discard}, utils::Empty);
|
||||||
|
|
||||||
auto* c = create<CaseStatement>(b, body);
|
auto* c = create<CaseStatement>(b, body);
|
||||||
ASSERT_EQ(c->selectors.Length(), 1u);
|
ASSERT_EQ(c->selectors.Length(), 1u);
|
||||||
|
@ -45,7 +45,7 @@ TEST_F(CaseStatementTest, Creation_u32) {
|
||||||
utils::Vector b{selector};
|
utils::Vector b{selector};
|
||||||
|
|
||||||
auto* discard = create<DiscardStatement>();
|
auto* discard = create<DiscardStatement>();
|
||||||
auto* body = create<BlockStatement>(utils::Vector{discard});
|
auto* body = create<BlockStatement>(utils::Vector{discard}, utils::Empty);
|
||||||
|
|
||||||
auto* c = create<CaseStatement>(b, body);
|
auto* c = create<CaseStatement>(b, body);
|
||||||
ASSERT_EQ(c->selectors.Length(), 1u);
|
ASSERT_EQ(c->selectors.Length(), 1u);
|
||||||
|
@ -56,22 +56,24 @@ TEST_F(CaseStatementTest, Creation_u32) {
|
||||||
|
|
||||||
TEST_F(CaseStatementTest, ContainsDefault_WithDefault) {
|
TEST_F(CaseStatementTest, ContainsDefault_WithDefault) {
|
||||||
utils::Vector b{CaseSelector(2_u), DefaultCaseSelector()};
|
utils::Vector b{CaseSelector(2_u), DefaultCaseSelector()};
|
||||||
auto* c = create<CaseStatement>(b, create<BlockStatement>(utils::Empty));
|
auto* c = create<CaseStatement>(b, create<BlockStatement>(utils::Empty, utils::Empty));
|
||||||
EXPECT_TRUE(c->ContainsDefault());
|
EXPECT_TRUE(c->ContainsDefault());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CaseStatementTest, ContainsDefault_WithOutDefault) {
|
TEST_F(CaseStatementTest, ContainsDefault_WithOutDefault) {
|
||||||
utils::Vector b{CaseSelector(2_u), CaseSelector(3_u)};
|
utils::Vector b{CaseSelector(2_u), CaseSelector(3_u)};
|
||||||
auto* c = create<CaseStatement>(b, create<BlockStatement>(utils::Empty));
|
auto* c = create<CaseStatement>(b, create<BlockStatement>(utils::Empty, utils::Empty));
|
||||||
EXPECT_FALSE(c->ContainsDefault());
|
EXPECT_FALSE(c->ContainsDefault());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CaseStatementTest, Creation_WithSource) {
|
TEST_F(CaseStatementTest, Creation_WithSource) {
|
||||||
utils::Vector b{CaseSelector(2_i)};
|
utils::Vector b{CaseSelector(2_i)};
|
||||||
|
|
||||||
auto* body = create<BlockStatement>(utils::Vector{
|
auto* body = create<BlockStatement>(
|
||||||
create<DiscardStatement>(),
|
utils::Vector{
|
||||||
});
|
create<DiscardStatement>(),
|
||||||
|
},
|
||||||
|
utils::Empty);
|
||||||
auto* c = create<CaseStatement>(Source{Source::Location{20, 2}}, b, body);
|
auto* c = create<CaseStatement>(Source{Source::Location{20, 2}}, b, body);
|
||||||
auto src = c->source;
|
auto src = c->source;
|
||||||
EXPECT_EQ(src.range.begin.line, 20u);
|
EXPECT_EQ(src.range.begin.line, 20u);
|
||||||
|
@ -80,7 +82,7 @@ TEST_F(CaseStatementTest, Creation_WithSource) {
|
||||||
|
|
||||||
TEST_F(CaseStatementTest, IsCase) {
|
TEST_F(CaseStatementTest, IsCase) {
|
||||||
auto* c = create<CaseStatement>(utils::Vector{DefaultCaseSelector()},
|
auto* c = create<CaseStatement>(utils::Vector{DefaultCaseSelector()},
|
||||||
create<BlockStatement>(utils::Empty));
|
create<BlockStatement>(utils::Empty, utils::Empty));
|
||||||
EXPECT_TRUE(c->Is<CaseStatement>());
|
EXPECT_TRUE(c->Is<CaseStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,7 +100,7 @@ TEST_F(CaseStatementTest, Assert_Null_Selector) {
|
||||||
{
|
{
|
||||||
ProgramBuilder b;
|
ProgramBuilder b;
|
||||||
b.create<CaseStatement>(utils::Vector<const ast::CaseSelector*, 1>{nullptr},
|
b.create<CaseStatement>(utils::Vector<const ast::CaseSelector*, 1>{nullptr},
|
||||||
b.create<BlockStatement>(utils::Empty));
|
b.create<BlockStatement>(utils::Empty, utils::Empty));
|
||||||
},
|
},
|
||||||
"internal compiler error");
|
"internal compiler error");
|
||||||
}
|
}
|
||||||
|
@ -109,7 +111,7 @@ TEST_F(CaseStatementTest, Assert_DifferentProgramID_Call) {
|
||||||
ProgramBuilder b1;
|
ProgramBuilder b1;
|
||||||
ProgramBuilder b2;
|
ProgramBuilder b2;
|
||||||
b1.create<CaseStatement>(utils::Vector{b1.DefaultCaseSelector()},
|
b1.create<CaseStatement>(utils::Vector{b1.DefaultCaseSelector()},
|
||||||
b2.create<BlockStatement>(utils::Empty));
|
b2.create<BlockStatement>(utils::Empty, utils::Empty));
|
||||||
},
|
},
|
||||||
"internal compiler error");
|
"internal compiler error");
|
||||||
}
|
}
|
||||||
|
@ -120,7 +122,7 @@ TEST_F(CaseStatementTest, Assert_DifferentProgramID_Selector) {
|
||||||
ProgramBuilder b1;
|
ProgramBuilder b1;
|
||||||
ProgramBuilder b2;
|
ProgramBuilder b2;
|
||||||
b1.create<CaseStatement>(utils::Vector{b2.CaseSelector(b2.Expr(2_i))},
|
b1.create<CaseStatement>(utils::Vector{b2.CaseSelector(b2.Expr(2_i))},
|
||||||
b1.create<BlockStatement>(utils::Empty));
|
b1.create<BlockStatement>(utils::Empty, utils::Empty));
|
||||||
},
|
},
|
||||||
"internal compiler error");
|
"internal compiler error");
|
||||||
}
|
}
|
||||||
|
|
|
@ -2456,7 +2456,8 @@ class ProgramBuilder {
|
||||||
/// @param type the function return type
|
/// @param type the function return type
|
||||||
/// @param body the function body
|
/// @param body the function body
|
||||||
/// @param attributes the optional function attributes
|
/// @param attributes the optional function attributes
|
||||||
/// @param return_type_attributes the optional function return type
|
/// @param return_type_attributes the optional function return type attributes
|
||||||
|
/// @param body_attributes the optional function body attributes
|
||||||
/// attributes
|
/// attributes
|
||||||
/// @returns the function pointer
|
/// @returns the function pointer
|
||||||
template <typename NAME>
|
template <typename NAME>
|
||||||
|
@ -2467,11 +2468,12 @@ class ProgramBuilder {
|
||||||
const ast::Type* type,
|
const ast::Type* type,
|
||||||
utils::VectorRef<const ast::Statement*> body,
|
utils::VectorRef<const ast::Statement*> body,
|
||||||
utils::VectorRef<const ast::Attribute*> attributes = utils::Empty,
|
utils::VectorRef<const ast::Attribute*> attributes = utils::Empty,
|
||||||
utils::VectorRef<const ast::Attribute*> return_type_attributes = utils::Empty) {
|
utils::VectorRef<const ast::Attribute*> return_type_attributes = utils::Empty,
|
||||||
auto* func =
|
utils::VectorRef<const ast::Attribute*> body_attributes = utils::Empty) {
|
||||||
create<ast::Function>(source, Sym(std::forward<NAME>(name)), std::move(params), type,
|
auto* func = create<ast::Function>(
|
||||||
create<ast::BlockStatement>(std::move(body)),
|
source, Sym(std::forward<NAME>(name)), std::move(params), type,
|
||||||
std::move(attributes), std::move(return_type_attributes));
|
create<ast::BlockStatement>(std::move(body), std::move(body_attributes)),
|
||||||
|
std::move(attributes), std::move(return_type_attributes));
|
||||||
AST().AddFunction(func);
|
AST().AddFunction(func);
|
||||||
return func;
|
return func;
|
||||||
}
|
}
|
||||||
|
@ -2482,7 +2484,8 @@ class ProgramBuilder {
|
||||||
/// @param type the function return type
|
/// @param type the function return type
|
||||||
/// @param body the function body
|
/// @param body the function body
|
||||||
/// @param attributes the optional function attributes
|
/// @param attributes the optional function attributes
|
||||||
/// @param return_type_attributes the optional function return type
|
/// @param return_type_attributes the optional function return type attributes
|
||||||
|
/// @param body_attributes the optional function body attributes
|
||||||
/// attributes
|
/// attributes
|
||||||
/// @returns the function pointer
|
/// @returns the function pointer
|
||||||
template <typename NAME>
|
template <typename NAME>
|
||||||
|
@ -2492,11 +2495,12 @@ class ProgramBuilder {
|
||||||
const ast::Type* type,
|
const ast::Type* type,
|
||||||
utils::VectorRef<const ast::Statement*> body,
|
utils::VectorRef<const ast::Statement*> body,
|
||||||
utils::VectorRef<const ast::Attribute*> attributes = utils::Empty,
|
utils::VectorRef<const ast::Attribute*> attributes = utils::Empty,
|
||||||
utils::VectorRef<const ast::Attribute*> return_type_attributes = utils::Empty) {
|
utils::VectorRef<const ast::Attribute*> return_type_attributes = utils::Empty,
|
||||||
auto* func =
|
utils::VectorRef<const ast::Attribute*> body_attributes = utils::Empty) {
|
||||||
create<ast::Function>(Sym(std::forward<NAME>(name)), std::move(params), type,
|
auto* func = create<ast::Function>(
|
||||||
create<ast::BlockStatement>(std::move(body)),
|
Sym(std::forward<NAME>(name)), std::move(params), type,
|
||||||
std::move(attributes), std::move(return_type_attributes));
|
create<ast::BlockStatement>(std::move(body), std::move(body_attributes)),
|
||||||
|
std::move(attributes), std::move(return_type_attributes));
|
||||||
AST().AddFunction(func);
|
AST().AddFunction(func);
|
||||||
return func;
|
return func;
|
||||||
}
|
}
|
||||||
|
@ -2676,23 +2680,50 @@ class ProgramBuilder {
|
||||||
/// @param source the source information for the block
|
/// @param source the source information for the block
|
||||||
/// @param statements statements of block
|
/// @param statements statements of block
|
||||||
/// @returns the block statement pointer
|
/// @returns the block statement pointer
|
||||||
template <typename... Statements>
|
template <typename... STATEMENTS, typename = DisableIfVectorLike<STATEMENTS...>>
|
||||||
const ast::BlockStatement* Block(const Source& source, Statements&&... statements) {
|
const ast::BlockStatement* Block(const Source& source, STATEMENTS&&... statements) {
|
||||||
return create<ast::BlockStatement>(
|
return create<ast::BlockStatement>(
|
||||||
source, utils::Vector<const ast::Statement*, sizeof...(statements)>{
|
source,
|
||||||
std::forward<Statements>(statements)...,
|
utils::Vector<const ast::Statement*, sizeof...(statements)>{
|
||||||
});
|
std::forward<STATEMENTS>(statements)...,
|
||||||
|
},
|
||||||
|
utils::Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a ast::BlockStatement with input statements
|
/// Creates a ast::BlockStatement with input statements
|
||||||
/// @param statements statements of block
|
/// @param statements statements of block
|
||||||
/// @returns the block statement pointer
|
/// @returns the block statement pointer
|
||||||
template <typename... STATEMENTS, typename = DisableIfSource<STATEMENTS...>>
|
template <typename... STATEMENTS,
|
||||||
|
typename = DisableIfSource<STATEMENTS...>,
|
||||||
|
typename = DisableIfVectorLike<STATEMENTS...>>
|
||||||
const ast::BlockStatement* Block(STATEMENTS&&... statements) {
|
const ast::BlockStatement* Block(STATEMENTS&&... statements) {
|
||||||
return create<ast::BlockStatement>(
|
return create<ast::BlockStatement>(
|
||||||
utils::Vector<const ast::Statement*, sizeof...(statements)>{
|
utils::Vector<const ast::Statement*, sizeof...(statements)>{
|
||||||
std::forward<STATEMENTS>(statements)...,
|
std::forward<STATEMENTS>(statements)...,
|
||||||
});
|
},
|
||||||
|
utils::Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a ast::BlockStatement with input statements and attributes
|
||||||
|
/// @param source the source information for the block
|
||||||
|
/// @param statements statements of block
|
||||||
|
/// @param attributes the attributes
|
||||||
|
/// @returns the block statement pointer
|
||||||
|
const ast::BlockStatement* Block(
|
||||||
|
const Source& source,
|
||||||
|
utils::VectorRef<const ast::Statement*> statements,
|
||||||
|
utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
|
||||||
|
return create<ast::BlockStatement>(source, std::move(statements), std::move(attributes));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a ast::BlockStatement with input statements and attributes
|
||||||
|
/// @param statements statements of block
|
||||||
|
/// @param attributes the attributes
|
||||||
|
/// @returns the block statement pointer
|
||||||
|
const ast::BlockStatement* Block(
|
||||||
|
utils::VectorRef<const ast::Statement*> statements,
|
||||||
|
utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
|
||||||
|
return create<ast::BlockStatement>(std::move(statements), std::move(attributes));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A wrapper type for the Else statement used to create If statements.
|
/// A wrapper type for the Else statement used to create If statements.
|
||||||
|
|
|
@ -882,7 +882,7 @@ void FunctionEmitter::PushGuard(const std::string& guard_name, uint32_t end_id)
|
||||||
auto* builder = AddStatementBuilder<IfStatementBuilder>(cond);
|
auto* builder = AddStatementBuilder<IfStatementBuilder>(cond);
|
||||||
|
|
||||||
PushNewStatementBlock(top.GetConstruct(), end_id, [=](const StatementList& stmts) {
|
PushNewStatementBlock(top.GetConstruct(), end_id, [=](const StatementList& stmts) {
|
||||||
builder->body = create<ast::BlockStatement>(Source{}, stmts);
|
builder->body = create<ast::BlockStatement>(Source{}, stmts, utils::Empty);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -894,7 +894,7 @@ void FunctionEmitter::PushTrueGuard(uint32_t end_id) {
|
||||||
auto* builder = AddStatementBuilder<IfStatementBuilder>(cond);
|
auto* builder = AddStatementBuilder<IfStatementBuilder>(cond);
|
||||||
|
|
||||||
PushNewStatementBlock(top.GetConstruct(), end_id, [=](const StatementList& stmts) {
|
PushNewStatementBlock(top.GetConstruct(), end_id, [=](const StatementList& stmts) {
|
||||||
builder->body = create<ast::BlockStatement>(Source{}, stmts);
|
builder->body = create<ast::BlockStatement>(Source{}, stmts, utils::Empty);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -985,7 +985,7 @@ const ast::BlockStatement* FunctionEmitter::MakeFunctionBody() {
|
||||||
|
|
||||||
statements_stack_[0].Finalize(&builder_);
|
statements_stack_[0].Finalize(&builder_);
|
||||||
auto& statements = statements_stack_[0].GetStatements();
|
auto& statements = statements_stack_[0].GetStatements();
|
||||||
auto* body = create<ast::BlockStatement>(Source{}, statements);
|
auto* body = create<ast::BlockStatement>(Source{}, statements, utils::Empty);
|
||||||
|
|
||||||
// Maintain the invariant by repopulating the one and only element.
|
// Maintain the invariant by repopulating the one and only element.
|
||||||
statements_stack_.Clear();
|
statements_stack_.Clear();
|
||||||
|
@ -1407,7 +1407,7 @@ bool FunctionEmitter::EmitEntryPointAsWrapper() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* body = create<ast::BlockStatement>(source, stmts);
|
auto* body = create<ast::BlockStatement>(source, stmts, utils::Empty);
|
||||||
AttributeList fn_attrs;
|
AttributeList fn_attrs;
|
||||||
fn_attrs.Push(create<ast::StageAttribute>(source, ep_info_->stage));
|
fn_attrs.Push(create<ast::StageAttribute>(source, ep_info_->stage));
|
||||||
|
|
||||||
|
@ -2938,7 +2938,7 @@ bool FunctionEmitter::EmitIfStart(const BlockInfo& block_info) {
|
||||||
if (!stmts.IsEmpty()) {
|
if (!stmts.IsEmpty()) {
|
||||||
// The "else" consists of the statement list from the top of
|
// The "else" consists of the statement list from the top of
|
||||||
// statements stack, without an "else if" condition.
|
// statements stack, without an "else if" condition.
|
||||||
builder->else_stmt = create<ast::BlockStatement>(Source{}, stmts);
|
builder->else_stmt = create<ast::BlockStatement>(Source{}, stmts, utils::Empty);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (false_is_break) {
|
if (false_is_break) {
|
||||||
|
@ -2985,7 +2985,7 @@ bool FunctionEmitter::EmitIfStart(const BlockInfo& block_info) {
|
||||||
|
|
||||||
// Push the then clause onto the stack.
|
// Push the then clause onto the stack.
|
||||||
PushNewStatementBlock(construct, then_end, [=](const StatementList& stmts) {
|
PushNewStatementBlock(construct, then_end, [=](const StatementList& stmts) {
|
||||||
builder->body = create<ast::BlockStatement>(Source{}, stmts);
|
builder->body = create<ast::BlockStatement>(Source{}, stmts, utils::Empty);
|
||||||
});
|
});
|
||||||
if (true_is_break) {
|
if (true_is_break) {
|
||||||
AddStatement(create<ast::BreakStatement>(Source{}));
|
AddStatement(create<ast::BreakStatement>(Source{}));
|
||||||
|
@ -3098,7 +3098,7 @@ bool FunctionEmitter::EmitSwitchStart(const BlockInfo& block_info) {
|
||||||
auto case_idx = swch->cases.Length();
|
auto case_idx = swch->cases.Length();
|
||||||
swch->cases.Push(nullptr);
|
swch->cases.Push(nullptr);
|
||||||
PushNewStatementBlock(construct, end_id, [=](const StatementList& stmts) {
|
PushNewStatementBlock(construct, end_id, [=](const StatementList& stmts) {
|
||||||
auto* body = create<ast::BlockStatement>(Source{}, stmts);
|
auto* body = create<ast::BlockStatement>(Source{}, stmts, utils::Empty);
|
||||||
swch->cases[case_idx] = create<ast::CaseStatement>(Source{}, selectors, body);
|
swch->cases[case_idx] = create<ast::CaseStatement>(Source{}, selectors, body);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -3113,7 +3113,7 @@ bool FunctionEmitter::EmitSwitchStart(const BlockInfo& block_info) {
|
||||||
bool FunctionEmitter::EmitLoopStart(const Construct* construct) {
|
bool FunctionEmitter::EmitLoopStart(const Construct* construct) {
|
||||||
auto* builder = AddStatementBuilder<LoopStatementBuilder>();
|
auto* builder = AddStatementBuilder<LoopStatementBuilder>();
|
||||||
PushNewStatementBlock(construct, construct->end_id, [=](const StatementList& stmts) {
|
PushNewStatementBlock(construct, construct->end_id, [=](const StatementList& stmts) {
|
||||||
builder->body = create<ast::BlockStatement>(Source{}, stmts);
|
builder->body = create<ast::BlockStatement>(Source{}, stmts, utils::Empty);
|
||||||
});
|
});
|
||||||
return success();
|
return success();
|
||||||
}
|
}
|
||||||
|
@ -3128,7 +3128,7 @@ bool FunctionEmitter::EmitContinuingStart(const Construct* construct) {
|
||||||
"expected loop on top of stack";
|
"expected loop on top of stack";
|
||||||
}
|
}
|
||||||
PushNewStatementBlock(construct, construct->end_id, [=](const StatementList& stmts) {
|
PushNewStatementBlock(construct, construct->end_id, [=](const StatementList& stmts) {
|
||||||
loop->continuing = create<ast::BlockStatement>(Source{}, stmts);
|
loop->continuing = create<ast::BlockStatement>(Source{}, stmts, utils::Empty);
|
||||||
});
|
});
|
||||||
|
|
||||||
return success();
|
return success();
|
||||||
|
@ -3354,11 +3354,11 @@ const ast::Statement* FunctionEmitter::MakeSimpleIf(const ast::Expression* condi
|
||||||
if (then_stmt != nullptr) {
|
if (then_stmt != nullptr) {
|
||||||
if_stmts.Push(then_stmt);
|
if_stmts.Push(then_stmt);
|
||||||
}
|
}
|
||||||
auto* if_block = create<ast::BlockStatement>(Source{}, if_stmts);
|
auto* if_block = create<ast::BlockStatement>(Source{}, if_stmts, utils::Empty);
|
||||||
|
|
||||||
const ast::Statement* else_block = nullptr;
|
const ast::Statement* else_block = nullptr;
|
||||||
if (else_stmt) {
|
if (else_stmt) {
|
||||||
else_block = create<ast::BlockStatement>(StatementList{else_stmt});
|
else_block = create<ast::BlockStatement>(StatementList{else_stmt}, utils::Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* if_stmt = create<ast::IfStatement>(Source{}, condition, if_block, else_block);
|
auto* if_stmt = create<ast::IfStatement>(Source{}, condition, if_block, else_block);
|
||||||
|
|
|
@ -1500,7 +1500,7 @@ Maybe<const ast::Function*> ParserImpl::function_decl(AttributeList& attrs) {
|
||||||
// function body. The AST isn't used as we've already errored, but this
|
// function body. The AST isn't used as we've already errored, but this
|
||||||
// catches any errors inside the body, and can help keep the parser in
|
// catches any errors inside the body, and can help keep the parser in
|
||||||
// sync.
|
// sync.
|
||||||
expect_compound_statement();
|
expect_compound_statement("function body");
|
||||||
}
|
}
|
||||||
return Failure::kErrored;
|
return Failure::kErrored;
|
||||||
}
|
}
|
||||||
|
@ -1510,7 +1510,7 @@ Maybe<const ast::Function*> ParserImpl::function_decl(AttributeList& attrs) {
|
||||||
|
|
||||||
bool errored = false;
|
bool errored = false;
|
||||||
|
|
||||||
auto body = expect_compound_statement();
|
auto body = expect_compound_statement("function body");
|
||||||
if (body.errored) {
|
if (body.errored) {
|
||||||
errored = true;
|
errored = true;
|
||||||
}
|
}
|
||||||
|
@ -1666,14 +1666,26 @@ Expect<ast::BuiltinValue> ParserImpl::expect_builtin() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// compound_statement
|
// compound_statement
|
||||||
// : BRACE_LEFT statement* BRACE_RIGHT
|
// : attribute* BRACE_LEFT statement* BRACE_RIGHT
|
||||||
Expect<ast::BlockStatement*> ParserImpl::expect_compound_statement() {
|
Expect<ast::BlockStatement*> ParserImpl::expect_compound_statement(std::string_view use) {
|
||||||
return expect_brace_block("", [&]() -> Expect<ast::BlockStatement*> {
|
auto attrs = attribute_list();
|
||||||
|
if (attrs.errored) {
|
||||||
|
return Failure::kErrored;
|
||||||
|
}
|
||||||
|
return expect_compound_statement(attrs.value, use);
|
||||||
|
}
|
||||||
|
|
||||||
|
// compound_statement
|
||||||
|
// : attribute* BRACE_LEFT statement* BRACE_RIGHT
|
||||||
|
Expect<ast::BlockStatement*> ParserImpl::expect_compound_statement(AttributeList& attrs,
|
||||||
|
std::string_view use) {
|
||||||
|
return expect_brace_block(use, [&]() -> Expect<ast::BlockStatement*> {
|
||||||
auto stmts = expect_statements();
|
auto stmts = expect_statements();
|
||||||
if (stmts.errored) {
|
if (stmts.errored) {
|
||||||
return Failure::kErrored;
|
return Failure::kErrored;
|
||||||
}
|
}
|
||||||
return create<ast::BlockStatement>(Source{}, stmts.value);
|
TINT_DEFER(attrs.Clear());
|
||||||
|
return create<ast::BlockStatement>(Source{}, stmts.value, std::move(attrs));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1731,6 +1743,12 @@ Maybe<const ast::Statement*> ParserImpl::statement() {
|
||||||
// Skip empty statements
|
// Skip empty statements
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto attrs = attribute_list();
|
||||||
|
if (attrs.errored) {
|
||||||
|
return Failure::kErrored;
|
||||||
|
}
|
||||||
|
TINT_DEFER(expect_attributes_consumed(attrs.value));
|
||||||
|
|
||||||
// Non-block statements that error can resynchronize on semicolon.
|
// Non-block statements that error can resynchronize on semicolon.
|
||||||
auto stmt = sync(Token::Type::kSemicolon, [&] { return non_block_statement(); });
|
auto stmt = sync(Token::Type::kSemicolon, [&] { return non_block_statement(); });
|
||||||
if (stmt.errored) {
|
if (stmt.errored) {
|
||||||
|
@ -1781,7 +1799,7 @@ Maybe<const ast::Statement*> ParserImpl::statement() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (peek_is(Token::Type::kBraceLeft)) {
|
if (peek_is(Token::Type::kBraceLeft)) {
|
||||||
auto body = expect_compound_statement();
|
auto body = expect_compound_statement(attrs.value, "block statement");
|
||||||
if (body.errored) {
|
if (body.errored) {
|
||||||
return Failure::kErrored;
|
return Failure::kErrored;
|
||||||
}
|
}
|
||||||
|
@ -2023,7 +2041,7 @@ Maybe<const ast::IfStatement*> ParserImpl::if_statement() {
|
||||||
return add_error(peek(), "unable to parse condition expression");
|
return add_error(peek(), "unable to parse condition expression");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto body = expect_compound_statement();
|
auto body = expect_compound_statement("if statement");
|
||||||
if (body.errored) {
|
if (body.errored) {
|
||||||
return Failure::kErrored;
|
return Failure::kErrored;
|
||||||
}
|
}
|
||||||
|
@ -2059,7 +2077,7 @@ Maybe<const ast::IfStatement*> ParserImpl::if_statement() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// If it wasn't an "else if", it must just be an "else".
|
// If it wasn't an "else if", it must just be an "else".
|
||||||
auto else_body = expect_compound_statement();
|
auto else_body = expect_compound_statement("else statement");
|
||||||
if (else_body.errored) {
|
if (else_body.errored) {
|
||||||
return Failure::kErrored;
|
return Failure::kErrored;
|
||||||
}
|
}
|
||||||
|
@ -2119,8 +2137,8 @@ Maybe<const ast::SwitchStatement*> ParserImpl::switch_statement() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// switch_body
|
// switch_body
|
||||||
// : CASE case_selectors COLON? BRACKET_LEFT case_body BRACKET_RIGHT
|
// : CASE case_selectors COLON? compound_statement
|
||||||
// | DEFAULT COLON? BRACKET_LEFT case_body BRACKET_RIGHT
|
// | DEFAULT COLON? compound_statement
|
||||||
Maybe<const ast::CaseStatement*> ParserImpl::switch_body() {
|
Maybe<const ast::CaseStatement*> ParserImpl::switch_body() {
|
||||||
if (!peek_is(Token::Type::kCase) && !peek_is(Token::Type::kDefault)) {
|
if (!peek_is(Token::Type::kCase) && !peek_is(Token::Type::kDefault)) {
|
||||||
return Failure::kNoMatch;
|
return Failure::kNoMatch;
|
||||||
|
@ -2145,14 +2163,10 @@ Maybe<const ast::CaseStatement*> ParserImpl::switch_body() {
|
||||||
match(Token::Type::kColon);
|
match(Token::Type::kColon);
|
||||||
|
|
||||||
const char* use = "case statement";
|
const char* use = "case statement";
|
||||||
auto body = expect_brace_block(use, [&] { return case_body(); });
|
auto body = expect_compound_statement(use);
|
||||||
|
|
||||||
if (body.errored) {
|
if (body.errored) {
|
||||||
return Failure::kErrored;
|
return Failure::kErrored;
|
||||||
}
|
}
|
||||||
if (!body.matched) {
|
|
||||||
return add_error(body.source, "expected case body");
|
|
||||||
}
|
|
||||||
|
|
||||||
return create<ast::CaseStatement>(t.source(), selector_list, body.value);
|
return create<ast::CaseStatement>(t.source(), selector_list, body.value);
|
||||||
}
|
}
|
||||||
|
@ -2231,7 +2245,7 @@ Maybe<const ast::BlockStatement*> ParserImpl::case_body() {
|
||||||
stmts.Push(stmt.value);
|
stmts.Push(stmt.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return create<ast::BlockStatement>(Source{}, stmts);
|
return create<ast::BlockStatement>(Source{}, stmts, utils::Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
// loop_statement
|
// loop_statement
|
||||||
|
@ -2253,7 +2267,7 @@ Maybe<const ast::LoopStatement*> ParserImpl::loop_statement() {
|
||||||
return Failure::kErrored;
|
return Failure::kErrored;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* body = create<ast::BlockStatement>(source, stmts.value);
|
auto* body = create<ast::BlockStatement>(source, stmts.value, utils::Empty);
|
||||||
return create<ast::LoopStatement>(source, body, continuing.value);
|
return create<ast::LoopStatement>(source, body, continuing.value);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -2345,7 +2359,7 @@ Expect<std::unique_ptr<ForHeader>> ParserImpl::expect_for_header() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// for_statement
|
// for_statement
|
||||||
// : FOR PAREN_LEFT for_header PAREN_RIGHT BRACE_LEFT statements BRACE_RIGHT
|
// : FOR PAREN_LEFT for_header PAREN_RIGHT compound_statement
|
||||||
Maybe<const ast::ForLoopStatement*> ParserImpl::for_statement() {
|
Maybe<const ast::ForLoopStatement*> ParserImpl::for_statement() {
|
||||||
Source source;
|
Source source;
|
||||||
if (!match(Token::Type::kFor, &source)) {
|
if (!match(Token::Type::kFor, &source)) {
|
||||||
|
@ -2357,14 +2371,13 @@ Maybe<const ast::ForLoopStatement*> ParserImpl::for_statement() {
|
||||||
return Failure::kErrored;
|
return Failure::kErrored;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto stmts = expect_brace_block("for loop", [&] { return expect_statements(); });
|
auto body = expect_compound_statement("for loop");
|
||||||
if (stmts.errored) {
|
if (body.errored) {
|
||||||
return Failure::kErrored;
|
return Failure::kErrored;
|
||||||
}
|
}
|
||||||
|
|
||||||
return create<ast::ForLoopStatement>(source, header->initializer, header->condition,
|
return create<ast::ForLoopStatement>(source, header->initializer, header->condition,
|
||||||
header->continuing,
|
header->continuing, body.value);
|
||||||
create<ast::BlockStatement>(stmts.value));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// while_statement
|
// while_statement
|
||||||
|
@ -2383,7 +2396,7 @@ Maybe<const ast::WhileStatement*> ParserImpl::while_statement() {
|
||||||
return add_error(peek(), "unable to parse while condition expression");
|
return add_error(peek(), "unable to parse while condition expression");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto body = expect_compound_statement();
|
auto body = expect_compound_statement("while loop");
|
||||||
if (body.errored) {
|
if (body.errored) {
|
||||||
return Failure::kErrored;
|
return Failure::kErrored;
|
||||||
}
|
}
|
||||||
|
@ -2491,7 +2504,7 @@ Maybe<const ast::BlockStatement*> ParserImpl::continuing_compound_statement() {
|
||||||
stmts.Push(stmt.value);
|
stmts.Push(stmt.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return create<ast::BlockStatement>(Source{}, stmts);
|
return create<ast::BlockStatement>(Source{}, stmts, utils::Empty);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2499,7 +2512,7 @@ Maybe<const ast::BlockStatement*> ParserImpl::continuing_compound_statement() {
|
||||||
// : CONTINUING continuing_compound_statement
|
// : CONTINUING continuing_compound_statement
|
||||||
Maybe<const ast::BlockStatement*> ParserImpl::continuing_statement() {
|
Maybe<const ast::BlockStatement*> ParserImpl::continuing_statement() {
|
||||||
if (!match(Token::Type::kContinuing)) {
|
if (!match(Token::Type::kContinuing)) {
|
||||||
return create<ast::BlockStatement>(Source{}, utils::Empty);
|
return create<ast::BlockStatement>(Source{}, utils::Empty, utils::Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
return continuing_compound_statement();
|
return continuing_compound_statement();
|
||||||
|
|
|
@ -542,8 +542,15 @@ class ParserImpl {
|
||||||
/// @returns the parsed builtin.
|
/// @returns the parsed builtin.
|
||||||
Expect<ast::BuiltinValue> expect_builtin();
|
Expect<ast::BuiltinValue> expect_builtin();
|
||||||
/// Parses a `compound_statement` grammar element, erroring on parse failure.
|
/// Parses a `compound_statement` grammar element, erroring on parse failure.
|
||||||
|
/// @param use a description of what was being parsed if an error was raised
|
||||||
/// @returns the parsed statements
|
/// @returns the parsed statements
|
||||||
Expect<ast::BlockStatement*> expect_compound_statement();
|
Expect<ast::BlockStatement*> expect_compound_statement(std::string_view use);
|
||||||
|
/// Parses a `compound_statement` grammar element, with the attribute list provided as `attrs`.
|
||||||
|
/// @param attrs the list of attributes for the statement
|
||||||
|
/// @param use a description of what was being parsed if an error was raised
|
||||||
|
/// @returns the parsed statements
|
||||||
|
Expect<ast::BlockStatement*> expect_compound_statement(AttributeList& attrs,
|
||||||
|
std::string_view use);
|
||||||
/// Parses a `paren_expression` grammar element, erroring on parse failure.
|
/// Parses a `paren_expression` grammar element, erroring on parse failure.
|
||||||
/// @returns the parsed element or nullptr
|
/// @returns the parsed element or nullptr
|
||||||
Expect<const ast::Expression*> expect_paren_expression();
|
Expect<const ast::Expression*> expect_paren_expression();
|
||||||
|
|
|
@ -23,7 +23,7 @@ TEST_F(ParserImplTest, CompoundStmt) {
|
||||||
discard;
|
discard;
|
||||||
return 1 + b / 2;
|
return 1 + b / 2;
|
||||||
})");
|
})");
|
||||||
auto e = p->expect_compound_statement();
|
auto e = p->expect_compound_statement("");
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_FALSE(e.errored);
|
ASSERT_FALSE(e.errored);
|
||||||
ASSERT_EQ(e->statements.Length(), 2u);
|
ASSERT_EQ(e->statements.Length(), 2u);
|
||||||
|
@ -33,7 +33,7 @@ TEST_F(ParserImplTest, CompoundStmt) {
|
||||||
|
|
||||||
TEST_F(ParserImplTest, CompoundStmt_Empty) {
|
TEST_F(ParserImplTest, CompoundStmt_Empty) {
|
||||||
auto p = parser("{}");
|
auto p = parser("{}");
|
||||||
auto e = p->expect_compound_statement();
|
auto e = p->expect_compound_statement("");
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_FALSE(e.errored);
|
ASSERT_FALSE(e.errored);
|
||||||
EXPECT_EQ(e->statements.Length(), 0u);
|
EXPECT_EQ(e->statements.Length(), 0u);
|
||||||
|
@ -41,7 +41,7 @@ TEST_F(ParserImplTest, CompoundStmt_Empty) {
|
||||||
|
|
||||||
TEST_F(ParserImplTest, CompoundStmt_InvalidStmt) {
|
TEST_F(ParserImplTest, CompoundStmt_InvalidStmt) {
|
||||||
auto p = parser("{fn main() {}}");
|
auto p = parser("{fn main() {}}");
|
||||||
auto e = p->expect_compound_statement();
|
auto e = p->expect_compound_statement("");
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_TRUE(e.errored);
|
ASSERT_TRUE(e.errored);
|
||||||
EXPECT_EQ(p->error(), "1:2: expected '}'");
|
EXPECT_EQ(p->error(), "1:2: expected '}'");
|
||||||
|
@ -49,7 +49,7 @@ TEST_F(ParserImplTest, CompoundStmt_InvalidStmt) {
|
||||||
|
|
||||||
TEST_F(ParserImplTest, CompoundStmt_MissingRightParen) {
|
TEST_F(ParserImplTest, CompoundStmt_MissingRightParen) {
|
||||||
auto p = parser("{return;");
|
auto p = parser("{return;");
|
||||||
auto e = p->expect_compound_statement();
|
auto e = p->expect_compound_statement("");
|
||||||
ASSERT_TRUE(p->has_error());
|
ASSERT_TRUE(p->has_error());
|
||||||
ASSERT_TRUE(e.errored);
|
ASSERT_TRUE(e.errored);
|
||||||
EXPECT_EQ(p->error(), "1:9: expected '}'");
|
EXPECT_EQ(p->error(), "1:9: expected '}'");
|
||||||
|
|
|
@ -489,7 +489,7 @@ fn f( {}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplErrorTest, FunctionDeclMissingArrow) {
|
TEST_F(ParserImplErrorTest, FunctionDeclMissingArrow) {
|
||||||
EXPECT("fn f() f32 {}", R"(test.wgsl:1:8 error: expected '{'
|
EXPECT("fn f() f32 {}", R"(test.wgsl:1:8 error: expected '{' for function body
|
||||||
fn f() f32 {}
|
fn f() f32 {}
|
||||||
^^^
|
^^^
|
||||||
)");
|
)");
|
||||||
|
@ -526,14 +526,14 @@ fn f(x : i32, ,) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplErrorTest, FunctionDeclMissingLBrace) {
|
TEST_F(ParserImplErrorTest, FunctionDeclMissingLBrace) {
|
||||||
EXPECT("fn f() }", R"(test.wgsl:1:8 error: expected '{'
|
EXPECT("fn f() }", R"(test.wgsl:1:8 error: expected '{' for function body
|
||||||
fn f() }
|
fn f() }
|
||||||
^
|
^
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplErrorTest, FunctionDeclMissingRBrace) {
|
TEST_F(ParserImplErrorTest, FunctionDeclMissingRBrace) {
|
||||||
EXPECT("fn f() {", R"(test.wgsl:1:9 error: expected '}'
|
EXPECT("fn f() {", R"(test.wgsl:1:9 error: expected '}' for function body
|
||||||
fn f() {
|
fn f() {
|
||||||
^
|
^
|
||||||
)");
|
)");
|
||||||
|
@ -541,9 +541,9 @@ fn f() {
|
||||||
|
|
||||||
TEST_F(ParserImplErrorTest, FunctionScopeUnusedDecl) {
|
TEST_F(ParserImplErrorTest, FunctionScopeUnusedDecl) {
|
||||||
EXPECT("fn f(a:i32)->i32{return a;@size(1)}",
|
EXPECT("fn f(a:i32)->i32{return a;@size(1)}",
|
||||||
R"(test.wgsl:1:27 error: expected '}'
|
R"(test.wgsl:1:28 error: unexpected attributes
|
||||||
fn f(a:i32)->i32{return a;@size(1)}
|
fn f(a:i32)->i32{return a;@size(1)}
|
||||||
^
|
^^^^
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -305,7 +305,7 @@ TEST_F(ParserImplTest, FunctionDecl_MissingLeftBrace) {
|
||||||
EXPECT_FALSE(f.matched);
|
EXPECT_FALSE(f.matched);
|
||||||
EXPECT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(f.value, nullptr);
|
EXPECT_EQ(f.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:11: expected '{'");
|
EXPECT_EQ(p->error(), "1:11: expected '{' for function body");
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -85,7 +85,7 @@ TEST_F(ParserImplTest, IfStmt_InvalidCondition) {
|
||||||
EXPECT_TRUE(e.errored);
|
EXPECT_TRUE(e.errored);
|
||||||
EXPECT_EQ(e.value, nullptr);
|
EXPECT_EQ(e.value, nullptr);
|
||||||
EXPECT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:6: expected '{'");
|
EXPECT_EQ(p->error(), "1:6: expected '{' for if statement");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, IfStmt_MissingCondition) {
|
TEST_F(ParserImplTest, IfStmt_MissingCondition) {
|
||||||
|
@ -105,7 +105,7 @@ TEST_F(ParserImplTest, IfStmt_InvalidBody) {
|
||||||
EXPECT_TRUE(e.errored);
|
EXPECT_TRUE(e.errored);
|
||||||
EXPECT_EQ(e.value, nullptr);
|
EXPECT_EQ(e.value, nullptr);
|
||||||
EXPECT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:8: expected '}'");
|
EXPECT_EQ(p->error(), "1:8: expected '}' for if statement");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, IfStmt_MissingBody) {
|
TEST_F(ParserImplTest, IfStmt_MissingBody) {
|
||||||
|
@ -115,7 +115,7 @@ TEST_F(ParserImplTest, IfStmt_MissingBody) {
|
||||||
EXPECT_TRUE(e.errored);
|
EXPECT_TRUE(e.errored);
|
||||||
EXPECT_EQ(e.value, nullptr);
|
EXPECT_EQ(e.value, nullptr);
|
||||||
EXPECT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:5: expected '{'");
|
EXPECT_EQ(p->error(), "1:5: expected '{' for if statement");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, IfStmt_InvalidElseif) {
|
TEST_F(ParserImplTest, IfStmt_InvalidElseif) {
|
||||||
|
@ -125,7 +125,7 @@ TEST_F(ParserImplTest, IfStmt_InvalidElseif) {
|
||||||
EXPECT_TRUE(e.errored);
|
EXPECT_TRUE(e.errored);
|
||||||
EXPECT_EQ(e.value, nullptr);
|
EXPECT_EQ(e.value, nullptr);
|
||||||
EXPECT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:21: expected '}'");
|
EXPECT_EQ(p->error(), "1:21: expected '}' for if statement");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, IfStmt_InvalidElse) {
|
TEST_F(ParserImplTest, IfStmt_InvalidElse) {
|
||||||
|
@ -135,7 +135,7 @@ TEST_F(ParserImplTest, IfStmt_InvalidElse) {
|
||||||
EXPECT_TRUE(e.errored);
|
EXPECT_TRUE(e.errored);
|
||||||
EXPECT_EQ(e.value, nullptr);
|
EXPECT_EQ(e.value, nullptr);
|
||||||
EXPECT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), "1:16: expected '}'");
|
EXPECT_EQ(p->error(), "1:16: expected '}' for else statement");
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -95,7 +95,7 @@ TEST_F(ParserImplTest, Statement_If_Invalid) {
|
||||||
EXPECT_TRUE(e.errored);
|
EXPECT_TRUE(e.errored);
|
||||||
EXPECT_FALSE(e.matched);
|
EXPECT_FALSE(e.matched);
|
||||||
EXPECT_EQ(e.value, nullptr);
|
EXPECT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:10: expected '}'");
|
EXPECT_EQ(p->error(), "1:10: expected '}' for if statement");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Statement_Variable) {
|
TEST_F(ParserImplTest, Statement_Variable) {
|
||||||
|
@ -269,7 +269,7 @@ TEST_F(ParserImplTest, Statement_Body_Invalid) {
|
||||||
EXPECT_TRUE(e.errored);
|
EXPECT_TRUE(e.errored);
|
||||||
EXPECT_FALSE(e.matched);
|
EXPECT_FALSE(e.matched);
|
||||||
EXPECT_EQ(e.value, nullptr);
|
EXPECT_EQ(e.value, nullptr);
|
||||||
EXPECT_EQ(p->error(), "1:3: expected '}'");
|
EXPECT_EQ(p->error(), "1:3: expected '}' for block statement");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Statement_ConstAssert_WithParen) {
|
TEST_F(ParserImplTest, Statement_ConstAssert_WithParen) {
|
||||||
|
@ -358,5 +358,15 @@ TEST_F(ParserImplTest, DEPRECATED_Statement_StaticAssert_WithoutParen) {
|
||||||
EXPECT_EQ(sa->condition->source.range.end.column, 20u);
|
EXPECT_EQ(sa->condition->source.range.end.column, 20u);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ParserImplTest, Statement_UnexpectedAttributes) {
|
||||||
|
auto p = parser("@diagnostic(off, derivative_uniformity) return;");
|
||||||
|
auto e = p->statement();
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_TRUE(e.matched);
|
||||||
|
EXPECT_NE(e.value, nullptr);
|
||||||
|
EXPECT_EQ(p->error(), "1:2: unexpected attributes");
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace tint::reader::wgsl
|
} // namespace tint::reader::wgsl
|
||||||
|
|
|
@ -118,7 +118,7 @@ TEST_F(WhileStmtErrorTest, MissingRightParen) {
|
||||||
// Test a while loop with missing left brace is invalid.
|
// Test a while loop with missing left brace is invalid.
|
||||||
TEST_F(WhileStmtErrorTest, MissingLeftBrace) {
|
TEST_F(WhileStmtErrorTest, MissingLeftBrace) {
|
||||||
std::string while_str = "while (true) }";
|
std::string while_str = "while (true) }";
|
||||||
std::string error_str = "1:14: expected '{'";
|
std::string error_str = "1:14: expected '{' for while loop";
|
||||||
|
|
||||||
TestWhileWithError(while_str, error_str);
|
TestWhileWithError(while_str, error_str);
|
||||||
}
|
}
|
||||||
|
@ -126,7 +126,7 @@ TEST_F(WhileStmtErrorTest, MissingLeftBrace) {
|
||||||
// Test a for loop with missing right brace is invalid.
|
// Test a for loop with missing right brace is invalid.
|
||||||
TEST_F(WhileStmtErrorTest, MissingRightBrace) {
|
TEST_F(WhileStmtErrorTest, MissingRightBrace) {
|
||||||
std::string while_str = "while (true) {";
|
std::string while_str = "while (true) {";
|
||||||
std::string error_str = "1:15: expected '}'";
|
std::string error_str = "1:15: expected '}' for while loop";
|
||||||
|
|
||||||
TestWhileWithError(while_str, error_str);
|
TestWhileWithError(while_str, error_str);
|
||||||
}
|
}
|
||||||
|
@ -159,7 +159,7 @@ TEST_F(WhileStmtErrorTest, InvalidBody) {
|
||||||
// Test a for loop with a body not matching statements
|
// Test a for loop with a body not matching statements
|
||||||
TEST_F(WhileStmtErrorTest, InvalidBodyMatch) {
|
TEST_F(WhileStmtErrorTest, InvalidBodyMatch) {
|
||||||
std::string while_str = "while (true) { fn main() {} }";
|
std::string while_str = "while (true) { fn main() {} }";
|
||||||
std::string error_str = "1:16: expected '}'";
|
std::string error_str = "1:16: expected '}' for while loop";
|
||||||
|
|
||||||
TestWhileWithError(while_str, error_str);
|
TestWhileWithError(while_str, error_str);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1030,6 +1030,104 @@ TEST_F(OverrideAttributeTest, DuplicateAttribute) {
|
||||||
12:34 note: first attribute declared here)");
|
12:34 note: first attribute declared here)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace BlockStatementTests {
|
||||||
|
class BlockStatementTest : public TestWithParams {
|
||||||
|
protected:
|
||||||
|
void Check() {
|
||||||
|
if (GetParam().should_pass) {
|
||||||
|
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||||
|
} else {
|
||||||
|
EXPECT_FALSE(r()->Resolve());
|
||||||
|
EXPECT_EQ(r()->error(), "error: attribute is not valid for block statements");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
TEST_P(BlockStatementTest, CompoundStatement) {
|
||||||
|
Func("foo", utils::Empty, ty.void_(),
|
||||||
|
utils::Vector{
|
||||||
|
Block(utils::Vector{Return()}, createAttributes({}, *this, GetParam().kind)),
|
||||||
|
});
|
||||||
|
Check();
|
||||||
|
}
|
||||||
|
TEST_P(BlockStatementTest, FunctionBody) {
|
||||||
|
Func("foo", utils::Empty, ty.void_(),
|
||||||
|
utils::Vector{
|
||||||
|
Block(utils::Vector{Return()}),
|
||||||
|
},
|
||||||
|
utils::Empty, utils::Empty, createAttributes({}, *this, GetParam().kind));
|
||||||
|
Check();
|
||||||
|
}
|
||||||
|
TEST_P(BlockStatementTest, IfStatementBody) {
|
||||||
|
Func("foo", utils::Empty, ty.void_(),
|
||||||
|
utils::Vector{
|
||||||
|
If(Expr(true),
|
||||||
|
Block(utils::Vector{Return()}, createAttributes({}, *this, GetParam().kind))),
|
||||||
|
});
|
||||||
|
Check();
|
||||||
|
}
|
||||||
|
TEST_P(BlockStatementTest, ElseStatementBody) {
|
||||||
|
Func("foo", utils::Empty, ty.void_(),
|
||||||
|
utils::Vector{
|
||||||
|
If(Expr(true), Block(utils::Vector{Return()}),
|
||||||
|
Else(Block(utils::Vector{Return()}, createAttributes({}, *this, GetParam().kind)))),
|
||||||
|
});
|
||||||
|
Check();
|
||||||
|
}
|
||||||
|
TEST_P(BlockStatementTest, ForStatementBody) {
|
||||||
|
Func("foo", utils::Empty, ty.void_(),
|
||||||
|
utils::Vector{
|
||||||
|
For(nullptr, Expr(true), nullptr,
|
||||||
|
Block(utils::Vector{Break()}, createAttributes({}, *this, GetParam().kind))),
|
||||||
|
});
|
||||||
|
Check();
|
||||||
|
}
|
||||||
|
TEST_P(BlockStatementTest, WhileStatementBody) {
|
||||||
|
Func("foo", utils::Empty, ty.void_(),
|
||||||
|
utils::Vector{
|
||||||
|
While(Expr(true),
|
||||||
|
Block(utils::Vector{Break()}, createAttributes({}, *this, GetParam().kind))),
|
||||||
|
});
|
||||||
|
Check();
|
||||||
|
}
|
||||||
|
TEST_P(BlockStatementTest, CaseStatementBody) {
|
||||||
|
Func("foo", utils::Empty, ty.void_(),
|
||||||
|
utils::Vector{
|
||||||
|
Switch(1_a,
|
||||||
|
Case(CaseSelector(1_a), Block(utils::Vector{Break()},
|
||||||
|
createAttributes({}, *this, GetParam().kind))),
|
||||||
|
DefaultCase(Block({}))),
|
||||||
|
});
|
||||||
|
Check();
|
||||||
|
}
|
||||||
|
TEST_P(BlockStatementTest, DefaultStatementBody) {
|
||||||
|
Func("foo", utils::Empty, ty.void_(),
|
||||||
|
utils::Vector{
|
||||||
|
Switch(1_a, Case(CaseSelector(1_a), Block()),
|
||||||
|
DefaultCase(Block(utils::Vector{Break()},
|
||||||
|
createAttributes({}, *this, GetParam().kind)))),
|
||||||
|
});
|
||||||
|
Check();
|
||||||
|
}
|
||||||
|
INSTANTIATE_TEST_SUITE_P(ResolverAttributeValidationTest,
|
||||||
|
BlockStatementTest,
|
||||||
|
testing::Values(TestParams{AttributeKind::kAlign, false},
|
||||||
|
TestParams{AttributeKind::kBinding, false},
|
||||||
|
TestParams{AttributeKind::kBuiltin, false},
|
||||||
|
TestParams{AttributeKind::kDiagnostic, true},
|
||||||
|
TestParams{AttributeKind::kGroup, false},
|
||||||
|
TestParams{AttributeKind::kId, false},
|
||||||
|
TestParams{AttributeKind::kInterpolate, false},
|
||||||
|
TestParams{AttributeKind::kInvariant, false},
|
||||||
|
TestParams{AttributeKind::kLocation, false},
|
||||||
|
TestParams{AttributeKind::kOffset, false},
|
||||||
|
TestParams{AttributeKind::kSize, false},
|
||||||
|
TestParams{AttributeKind::kStage, false},
|
||||||
|
TestParams{AttributeKind::kStride, false},
|
||||||
|
TestParams{AttributeKind::kWorkgroup, false},
|
||||||
|
TestParams{AttributeKind::kBindingAndGroup, false}));
|
||||||
|
|
||||||
|
} // namespace BlockStatementTests
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace AttributeTests
|
} // namespace AttributeTests
|
||||||
|
|
||||||
|
|
|
@ -181,6 +181,66 @@ TEST_F(ResolverDiagnosticControlTest, FunctionAttributeScope) {
|
||||||
89:10 note: code is unreachable)");
|
89:10 note: code is unreachable)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ResolverDiagnosticControlTest, BlockAttributeScope) {
|
||||||
|
// fn foo() @diagnostic(off, chromium_unreachable_code) {
|
||||||
|
// {
|
||||||
|
// return;
|
||||||
|
// return; // Should not produce a diagnostic
|
||||||
|
// }
|
||||||
|
// @diagnostic(warning, chromium_unreachable_code) {
|
||||||
|
// if (true) @diagnostic(info, chromium_unreachable_code) {
|
||||||
|
// return;
|
||||||
|
// return; // Should produce an info
|
||||||
|
// } else {
|
||||||
|
// while (true) @diagnostic(off, chromium_unreachable_code) {
|
||||||
|
// return;
|
||||||
|
// return; // Should not produce a diagnostic
|
||||||
|
// }
|
||||||
|
// return;
|
||||||
|
// return; // Should produce an warning
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
auto attr = [&](auto severity) {
|
||||||
|
return utils::Vector{DiagnosticAttribute(severity, Expr("chromium_unreachable_code"))};
|
||||||
|
};
|
||||||
|
Func("foo", {}, ty.void_(),
|
||||||
|
utils::Vector{
|
||||||
|
Return(),
|
||||||
|
Return(Source{{12, 21}}),
|
||||||
|
Block(utils::Vector{
|
||||||
|
Block(
|
||||||
|
utils::Vector{
|
||||||
|
If(Expr(true),
|
||||||
|
Block(
|
||||||
|
utils::Vector{
|
||||||
|
Return(),
|
||||||
|
Return(Source{{34, 43}}),
|
||||||
|
},
|
||||||
|
attr(ast::DiagnosticSeverity::kInfo)),
|
||||||
|
Else(Block(utils::Vector{
|
||||||
|
While(
|
||||||
|
Expr(true), Block(
|
||||||
|
utils::Vector{
|
||||||
|
Return(),
|
||||||
|
Return(Source{{56, 65}}),
|
||||||
|
},
|
||||||
|
attr(ast::DiagnosticSeverity::kOff))),
|
||||||
|
Return(),
|
||||||
|
Return(Source{{78, 87}}),
|
||||||
|
}))),
|
||||||
|
},
|
||||||
|
attr(ast::DiagnosticSeverity::kWarning)),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
attr(ast::DiagnosticSeverity::kOff));
|
||||||
|
|
||||||
|
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||||
|
EXPECT_EQ(r()->error(), R"(34:43 note: code is unreachable
|
||||||
|
78:87 warning: code is unreachable)");
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(ResolverDiagnosticControlTest, UnrecognizedRuleName_Directive) {
|
TEST_F(ResolverDiagnosticControlTest, UnrecognizedRuleName_Directive) {
|
||||||
DiagnosticDirective(ast::DiagnosticSeverity::kError,
|
DiagnosticDirective(ast::DiagnosticSeverity::kError,
|
||||||
Expr(Source{{12, 34}}, "chromium_unreachable_cod"));
|
Expr(Source{{12, 34}}, "chromium_unreachable_cod"));
|
||||||
|
|
|
@ -3845,6 +3845,43 @@ SEM* Resolver::StatementScope(const ast::Statement* ast, SEM* sem, F&& callback)
|
||||||
|
|
||||||
auto* as_compound = As<sem::CompoundStatement, CastFlags::kDontErrorOnImpossibleCast>(sem);
|
auto* as_compound = As<sem::CompoundStatement, CastFlags::kDontErrorOnImpossibleCast>(sem);
|
||||||
|
|
||||||
|
// Helper to handle attributes that are supported on certain types of statement.
|
||||||
|
auto handle_attributes = [&](auto* stmt, sem::Statement* sem_stmt, const char* use) {
|
||||||
|
for (auto* attr : stmt->attributes) {
|
||||||
|
Mark(attr);
|
||||||
|
if (auto* dc = attr->template As<ast::DiagnosticAttribute>()) {
|
||||||
|
Mark(dc->control);
|
||||||
|
if (!DiagnosticControl(dc->control)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
std::ostringstream ss;
|
||||||
|
ss << "attribute is not valid for " << use;
|
||||||
|
AddError(ss.str(), attr->source);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!validator_.NoDuplicateAttributes(stmt->attributes)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ApplyDiagnosticSeverities(sem_stmt);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handle attributes, if necessary.
|
||||||
|
// Some statements can take diagnostic filtering attributes, so push a new diagnostic filter
|
||||||
|
// scope to capture them.
|
||||||
|
validator_.DiagnosticFilters().Push();
|
||||||
|
TINT_DEFER(validator_.DiagnosticFilters().Pop());
|
||||||
|
if (!Switch(
|
||||||
|
ast, //
|
||||||
|
[&](const ast::BlockStatement* block) {
|
||||||
|
return handle_attributes(block, sem, "block statements");
|
||||||
|
},
|
||||||
|
[&](Default) { return true; })) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
TINT_SCOPED_ASSIGNMENT(current_statement_, sem);
|
TINT_SCOPED_ASSIGNMENT(current_statement_, sem);
|
||||||
TINT_SCOPED_ASSIGNMENT(current_compound_statement_,
|
TINT_SCOPED_ASSIGNMENT(current_compound_statement_,
|
||||||
as_compound ? as_compound : current_compound_statement_);
|
as_compound ? as_compound : current_compound_statement_);
|
||||||
|
|
|
@ -7942,6 +7942,32 @@ TEST_P(UniformityAnalysisDiagnosticFilterTest, AttributeOnFunction) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_P(UniformityAnalysisDiagnosticFilterTest, AttributeOnBlock) {
|
||||||
|
auto& param = GetParam();
|
||||||
|
std::ostringstream ss;
|
||||||
|
ss << R"(
|
||||||
|
@group(0) @binding(0) var<storage, read_write> non_uniform : i32;
|
||||||
|
@group(0) @binding(1) var t : texture_2d<f32>;
|
||||||
|
@group(0) @binding(2) var s : sampler;
|
||||||
|
fn foo() {
|
||||||
|
if (non_uniform == 42))"
|
||||||
|
<< "@diagnostic(" << param << ", derivative_uniformity)"
|
||||||
|
<< R"({
|
||||||
|
let color = textureSample(t, s, vec2(0, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
RunTest(ss.str(), param != ast::DiagnosticSeverity::kError);
|
||||||
|
if (param == ast::DiagnosticSeverity::kOff) {
|
||||||
|
EXPECT_TRUE(error_.empty());
|
||||||
|
} else {
|
||||||
|
std::ostringstream err;
|
||||||
|
err << ToStr(param) << ": 'textureSample' must only be called";
|
||||||
|
EXPECT_THAT(error_, ::testing::HasSubstr(err.str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
INSTANTIATE_TEST_SUITE_P(UniformityAnalysisTest,
|
INSTANTIATE_TEST_SUITE_P(UniformityAnalysisTest,
|
||||||
UniformityAnalysisDiagnosticFilterTest,
|
UniformityAnalysisDiagnosticFilterTest,
|
||||||
::testing::Values(ast::DiagnosticSeverity::kError,
|
::testing::Values(ast::DiagnosticSeverity::kError,
|
||||||
|
|
|
@ -30,26 +30,44 @@ class DiagnosticSeverityTest : public TestHelper {
|
||||||
void Run(ast::DiagnosticSeverity global_severity) {
|
void Run(ast::DiagnosticSeverity global_severity) {
|
||||||
// @diagnostic(off, chromium_unreachable_code)
|
// @diagnostic(off, chromium_unreachable_code)
|
||||||
// fn foo() {
|
// fn foo() {
|
||||||
// return;
|
// @diagnostic(info, chromium_unreachable_code) {
|
||||||
|
// if (true) @diagnostic(warning, chromium_unreachable_code) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// fn bar() {
|
// fn bar() {
|
||||||
// return;
|
// {
|
||||||
|
// if (true) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
// }
|
// }
|
||||||
auto rule = ast::DiagnosticRule::kChromiumUnreachableCode;
|
auto rule = ast::DiagnosticRule::kChromiumUnreachableCode;
|
||||||
auto func_severity = ast::DiagnosticSeverity::kOff;
|
auto func_severity = ast::DiagnosticSeverity::kOff;
|
||||||
|
auto block_severity = ast::DiagnosticSeverity::kInfo;
|
||||||
|
auto if_severity = ast::DiagnosticSeverity::kInfo;
|
||||||
|
auto attr = [&](auto severity) {
|
||||||
|
return utils::Vector{DiagnosticAttribute(severity, Expr("chromium_unreachable_code"))};
|
||||||
|
};
|
||||||
|
|
||||||
auto* return_1 = Return();
|
auto* return_1 = Return();
|
||||||
auto* return_2 = Return();
|
auto* if_1 = If(Expr(true), Block(utils::Vector{return_1}, attr(if_severity)));
|
||||||
|
auto* block_1 = Block(utils::Vector{if_1}, attr(block_severity));
|
||||||
auto* func_attr = DiagnosticAttribute(func_severity, Expr("chromium_unreachable_code"));
|
auto* func_attr = DiagnosticAttribute(func_severity, Expr("chromium_unreachable_code"));
|
||||||
auto* foo = Func("foo", {}, ty.void_(), utils::Vector{return_1}, utils::Vector{func_attr});
|
auto* foo = Func("foo", {}, ty.void_(), utils::Vector{block_1}, utils::Vector{func_attr});
|
||||||
|
|
||||||
|
auto* return_2 = Return();
|
||||||
auto* bar = Func("bar", {}, ty.void_(), utils::Vector{return_2});
|
auto* bar = Func("bar", {}, ty.void_(), utils::Vector{return_2});
|
||||||
|
|
||||||
auto p = Build();
|
auto p = Build();
|
||||||
EXPECT_TRUE(p.IsValid()) << p.Diagnostics().str();
|
EXPECT_TRUE(p.IsValid()) << p.Diagnostics().str();
|
||||||
|
|
||||||
EXPECT_EQ(p.Sem().DiagnosticSeverity(foo, rule), func_severity);
|
EXPECT_EQ(p.Sem().DiagnosticSeverity(foo, rule), func_severity);
|
||||||
EXPECT_EQ(p.Sem().DiagnosticSeverity(return_1, rule), func_severity);
|
EXPECT_EQ(p.Sem().DiagnosticSeverity(block_1, rule), block_severity);
|
||||||
|
EXPECT_EQ(p.Sem().DiagnosticSeverity(if_1, rule), block_severity);
|
||||||
|
EXPECT_EQ(p.Sem().DiagnosticSeverity(return_1, rule), if_severity);
|
||||||
EXPECT_EQ(p.Sem().DiagnosticSeverity(bar, rule), global_severity);
|
EXPECT_EQ(p.Sem().DiagnosticSeverity(bar, rule), global_severity);
|
||||||
EXPECT_EQ(p.Sem().DiagnosticSeverity(return_2, rule), global_severity);
|
EXPECT_EQ(p.Sem().DiagnosticSeverity(return_2, rule), global_severity);
|
||||||
}
|
}
|
||||||
|
|
|
@ -353,7 +353,10 @@ bool GeneratorImpl::EmitFunction(const ast::Function* func) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (func->body) {
|
if (func->body) {
|
||||||
out << " {";
|
out << " ";
|
||||||
|
if (!EmitBlockHeader(out, func->body)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -979,7 +982,12 @@ bool GeneratorImpl::EmitUnaryOp(std::ostream& out, const ast::UnaryOpExpression*
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GeneratorImpl::EmitBlock(const ast::BlockStatement* stmt) {
|
bool GeneratorImpl::EmitBlock(const ast::BlockStatement* stmt) {
|
||||||
line() << "{";
|
{
|
||||||
|
auto out = line();
|
||||||
|
if (!EmitBlockHeader(out, stmt)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!EmitStatementsWithIndent(stmt->statements)) {
|
if (!EmitStatementsWithIndent(stmt->statements)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -988,6 +996,17 @@ bool GeneratorImpl::EmitBlock(const ast::BlockStatement* stmt) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GeneratorImpl::EmitBlockHeader(std::ostream& out, const ast::BlockStatement* stmt) {
|
||||||
|
if (!stmt->attributes.IsEmpty()) {
|
||||||
|
if (!EmitAttributes(out, stmt->attributes)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
out << " ";
|
||||||
|
}
|
||||||
|
out << "{";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool GeneratorImpl::EmitStatement(const ast::Statement* stmt) {
|
bool GeneratorImpl::EmitStatement(const ast::Statement* stmt) {
|
||||||
return Switch(
|
return Switch(
|
||||||
stmt, //
|
stmt, //
|
||||||
|
@ -1072,7 +1091,11 @@ bool GeneratorImpl::EmitBreakIf(const ast::BreakIfStatement* b) {
|
||||||
|
|
||||||
bool GeneratorImpl::EmitCase(const ast::CaseStatement* stmt) {
|
bool GeneratorImpl::EmitCase(const ast::CaseStatement* stmt) {
|
||||||
if (stmt->selectors.Length() == 1 && stmt->ContainsDefault()) {
|
if (stmt->selectors.Length() == 1 && stmt->ContainsDefault()) {
|
||||||
line() << "default: {";
|
auto out = line();
|
||||||
|
out << "default: ";
|
||||||
|
if (!EmitBlockHeader(out, stmt->body)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
auto out = line();
|
auto out = line();
|
||||||
out << "case ";
|
out << "case ";
|
||||||
|
@ -1091,7 +1114,10 @@ bool GeneratorImpl::EmitCase(const ast::CaseStatement* stmt) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out << ": {";
|
out << ": ";
|
||||||
|
if (!EmitBlockHeader(out, stmt->body)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!EmitStatementsWithIndent(stmt->body->statements)) {
|
if (!EmitStatementsWithIndent(stmt->body->statements)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -1135,7 +1161,10 @@ bool GeneratorImpl::EmitIf(const ast::IfStatement* stmt) {
|
||||||
if (!EmitExpression(out, stmt->condition)) {
|
if (!EmitExpression(out, stmt->condition)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
out << ") {";
|
out << ") ";
|
||||||
|
if (!EmitBlockHeader(out, stmt->body)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!EmitStatementsWithIndent(stmt->body->statements)) {
|
if (!EmitStatementsWithIndent(stmt->body->statements)) {
|
||||||
|
@ -1151,15 +1180,25 @@ bool GeneratorImpl::EmitIf(const ast::IfStatement* stmt) {
|
||||||
if (!EmitExpression(out, elseif->condition)) {
|
if (!EmitExpression(out, elseif->condition)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
out << ") {";
|
out << ") ";
|
||||||
|
if (!EmitBlockHeader(out, elseif->body)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!EmitStatementsWithIndent(elseif->body->statements)) {
|
if (!EmitStatementsWithIndent(elseif->body->statements)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
e = elseif->else_statement;
|
e = elseif->else_statement;
|
||||||
} else {
|
} else {
|
||||||
line() << "} else {";
|
auto* body = e->As<ast::BlockStatement>();
|
||||||
if (!EmitStatementsWithIndent(e->As<ast::BlockStatement>()->statements)) {
|
{
|
||||||
|
auto out = line();
|
||||||
|
out << "} else ";
|
||||||
|
if (!EmitBlockHeader(out, body)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!EmitStatementsWithIndent(body->statements)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1270,7 +1309,10 @@ bool GeneratorImpl::EmitForLoop(const ast::ForLoopStatement* stmt) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out << " {";
|
out << " ";
|
||||||
|
if (!EmitBlockHeader(out, stmt->body)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!EmitStatementsWithIndent(stmt->body->statements)) {
|
if (!EmitStatementsWithIndent(stmt->body->statements)) {
|
||||||
|
@ -1294,7 +1336,10 @@ bool GeneratorImpl::EmitWhile(const ast::WhileStatement* stmt) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out << " {";
|
out << " ";
|
||||||
|
if (!EmitBlockHeader(out, stmt->body)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!EmitStatementsWithIndent(stmt->body->statements)) {
|
if (!EmitStatementsWithIndent(stmt->body->statements)) {
|
||||||
|
|
|
@ -93,6 +93,11 @@ class GeneratorImpl : public TextGenerator {
|
||||||
/// @param stmt the statement to emit
|
/// @param stmt the statement to emit
|
||||||
/// @returns true if the statement was emitted successfully
|
/// @returns true if the statement was emitted successfully
|
||||||
bool EmitBlock(const ast::BlockStatement* stmt);
|
bool EmitBlock(const ast::BlockStatement* stmt);
|
||||||
|
/// Handles emitting the start of a block statement (including attributes)
|
||||||
|
/// @param out the output stream to write the header to
|
||||||
|
/// @param stmt the block statement to emit the header for
|
||||||
|
/// @returns true if the statement was emitted successfully
|
||||||
|
bool EmitBlockHeader(std::ostream& out, const ast::BlockStatement* stmt);
|
||||||
/// Handles a break statement
|
/// Handles a break statement
|
||||||
/// @param stmt the statement to emit
|
/// @param stmt the statement to emit
|
||||||
/// @returns true if the statement was emitted successfully
|
/// @returns true if the statement was emitted successfully
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
@group(0) @binding(1) var t : texture_2d<f32>;
|
||||||
|
@group(0) @binding(2) var s : sampler;
|
||||||
|
|
||||||
|
@fragment
|
||||||
|
fn main(@location(0) x : f32) {
|
||||||
|
switch (i32(x)) {
|
||||||
|
case 0 @diagnostic(warning, derivative_uniformity) {
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
}
|
||||||
|
default {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
diagnostic_filtering/case_body_attribute.wgsl:8:11 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/case_body_attribute.wgsl:6:3 note: control flow depends on possibly non-uniform value
|
||||||
|
switch (i32(x)) {
|
||||||
|
^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/case_body_attribute.wgsl:6:15 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
switch (i32(x)) {
|
||||||
|
^
|
||||||
|
|
||||||
|
Texture2D<float4> t : register(t1, space0);
|
||||||
|
SamplerState s : register(s2, space0);
|
||||||
|
|
||||||
|
struct tint_symbol_1 {
|
||||||
|
float x : TEXCOORD0;
|
||||||
|
};
|
||||||
|
|
||||||
|
void main_inner(float x) {
|
||||||
|
switch(int(x)) {
|
||||||
|
case 0: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main(tint_symbol_1 tint_symbol) {
|
||||||
|
main_inner(tint_symbol.x);
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
diagnostic_filtering/case_body_attribute.wgsl:8:11 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/case_body_attribute.wgsl:6:3 note: control flow depends on possibly non-uniform value
|
||||||
|
switch (i32(x)) {
|
||||||
|
^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/case_body_attribute.wgsl:6:15 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
switch (i32(x)) {
|
||||||
|
^
|
||||||
|
|
||||||
|
Texture2D<float4> t : register(t1, space0);
|
||||||
|
SamplerState s : register(s2, space0);
|
||||||
|
|
||||||
|
struct tint_symbol_1 {
|
||||||
|
float x : TEXCOORD0;
|
||||||
|
};
|
||||||
|
|
||||||
|
void main_inner(float x) {
|
||||||
|
switch(int(x)) {
|
||||||
|
case 0: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main(tint_symbol_1 tint_symbol) {
|
||||||
|
main_inner(tint_symbol.x);
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
diagnostic_filtering/case_body_attribute.wgsl:8:11 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/case_body_attribute.wgsl:6:3 note: control flow depends on possibly non-uniform value
|
||||||
|
switch (i32(x)) {
|
||||||
|
^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/case_body_attribute.wgsl:6:15 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
switch (i32(x)) {
|
||||||
|
^
|
||||||
|
|
||||||
|
#version 310 es
|
||||||
|
precision mediump float;
|
||||||
|
|
||||||
|
layout(location = 0) in float x_1;
|
||||||
|
void tint_symbol(float x) {
|
||||||
|
switch(int(x)) {
|
||||||
|
case 0: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
tint_symbol(x_1);
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
diagnostic_filtering/case_body_attribute.wgsl:8:11 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/case_body_attribute.wgsl:6:3 note: control flow depends on possibly non-uniform value
|
||||||
|
switch (i32(x)) {
|
||||||
|
^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/case_body_attribute.wgsl:6:15 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
switch (i32(x)) {
|
||||||
|
^
|
||||||
|
|
||||||
|
#include <metal_stdlib>
|
||||||
|
|
||||||
|
using namespace metal;
|
||||||
|
struct tint_symbol_2 {
|
||||||
|
float x [[user(locn0)]];
|
||||||
|
};
|
||||||
|
|
||||||
|
void tint_symbol_inner(float x) {
|
||||||
|
switch(int(x)) {
|
||||||
|
case 0: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fragment void tint_symbol(tint_symbol_2 tint_symbol_1 [[stage_in]]) {
|
||||||
|
tint_symbol_inner(tint_symbol_1.x);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
diagnostic_filtering/case_body_attribute.wgsl:8:11 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/case_body_attribute.wgsl:6:3 note: control flow depends on possibly non-uniform value
|
||||||
|
switch (i32(x)) {
|
||||||
|
^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/case_body_attribute.wgsl:6:15 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
switch (i32(x)) {
|
||||||
|
^
|
||||||
|
|
||||||
|
; SPIR-V
|
||||||
|
; Version: 1.3
|
||||||
|
; Generator: Google Tint Compiler; 0
|
||||||
|
; Bound: 25
|
||||||
|
; Schema: 0
|
||||||
|
OpCapability Shader
|
||||||
|
OpMemoryModel Logical GLSL450
|
||||||
|
OpEntryPoint Fragment %main "main" %x_1
|
||||||
|
OpExecutionMode %main OriginUpperLeft
|
||||||
|
OpName %x_1 "x_1"
|
||||||
|
OpName %t "t"
|
||||||
|
OpName %s "s"
|
||||||
|
OpName %main_inner "main_inner"
|
||||||
|
OpName %x "x"
|
||||||
|
OpName %main "main"
|
||||||
|
OpDecorate %x_1 Location 0
|
||||||
|
OpDecorate %t DescriptorSet 0
|
||||||
|
OpDecorate %t Binding 1
|
||||||
|
OpDecorate %s DescriptorSet 0
|
||||||
|
OpDecorate %s Binding 2
|
||||||
|
%float = OpTypeFloat 32
|
||||||
|
%_ptr_Input_float = OpTypePointer Input %float
|
||||||
|
%x_1 = OpVariable %_ptr_Input_float Input
|
||||||
|
%6 = OpTypeImage %float 2D 0 0 0 1 Unknown
|
||||||
|
%_ptr_UniformConstant_6 = OpTypePointer UniformConstant %6
|
||||||
|
%t = OpVariable %_ptr_UniformConstant_6 UniformConstant
|
||||||
|
%9 = OpTypeSampler
|
||||||
|
%_ptr_UniformConstant_9 = OpTypePointer UniformConstant %9
|
||||||
|
%s = OpVariable %_ptr_UniformConstant_9 UniformConstant
|
||||||
|
%void = OpTypeVoid
|
||||||
|
%10 = OpTypeFunction %void %float
|
||||||
|
%int = OpTypeInt 32 1
|
||||||
|
%20 = OpTypeFunction %void
|
||||||
|
%main_inner = OpFunction %void None %10
|
||||||
|
%x = OpFunctionParameter %float
|
||||||
|
%14 = OpLabel
|
||||||
|
%16 = OpConvertFToS %int %x
|
||||||
|
OpSelectionMerge %15 None
|
||||||
|
OpSwitch %16 %18 0 %19
|
||||||
|
%19 = OpLabel
|
||||||
|
OpBranch %15
|
||||||
|
%18 = OpLabel
|
||||||
|
OpBranch %15
|
||||||
|
%15 = OpLabel
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
%main = OpFunction %void None %20
|
||||||
|
%22 = OpLabel
|
||||||
|
%24 = OpLoad %float %x_1
|
||||||
|
%23 = OpFunctionCall %void %main_inner %24
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
|
@ -0,0 +1,26 @@
|
||||||
|
diagnostic_filtering/case_body_attribute.wgsl:8:11 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/case_body_attribute.wgsl:6:3 note: control flow depends on possibly non-uniform value
|
||||||
|
switch (i32(x)) {
|
||||||
|
^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/case_body_attribute.wgsl:6:15 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
switch (i32(x)) {
|
||||||
|
^
|
||||||
|
|
||||||
|
@group(0) @binding(1) var t : texture_2d<f32>;
|
||||||
|
|
||||||
|
@group(0) @binding(2) var s : sampler;
|
||||||
|
|
||||||
|
@fragment
|
||||||
|
fn main(@location(0) x : f32) {
|
||||||
|
switch(i32(x)) {
|
||||||
|
case 0: @diagnostic(warning, derivative_uniformity) {
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
@group(0) @binding(1) var t : texture_2d<f32>;
|
||||||
|
@group(0) @binding(2) var s : sampler;
|
||||||
|
|
||||||
|
@fragment
|
||||||
|
fn main(@location(0) x : f32) {
|
||||||
|
@diagnostic(warning, derivative_uniformity) {
|
||||||
|
if (x > 0) {
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
diagnostic_filtering/compound_statement_attribute.wgsl:8:11 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/compound_statement_attribute.wgsl:7:5 note: control flow depends on possibly non-uniform value
|
||||||
|
if (x > 0) {
|
||||||
|
^^
|
||||||
|
|
||||||
|
diagnostic_filtering/compound_statement_attribute.wgsl:7:9 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
if (x > 0) {
|
||||||
|
^
|
||||||
|
|
||||||
|
Texture2D<float4> t : register(t1, space0);
|
||||||
|
SamplerState s : register(s2, space0);
|
||||||
|
|
||||||
|
struct tint_symbol_1 {
|
||||||
|
float x : TEXCOORD0;
|
||||||
|
};
|
||||||
|
|
||||||
|
void main_inner(float x) {
|
||||||
|
{
|
||||||
|
if ((x > 0.0f)) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main(tint_symbol_1 tint_symbol) {
|
||||||
|
main_inner(tint_symbol.x);
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
diagnostic_filtering/compound_statement_attribute.wgsl:8:11 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/compound_statement_attribute.wgsl:7:5 note: control flow depends on possibly non-uniform value
|
||||||
|
if (x > 0) {
|
||||||
|
^^
|
||||||
|
|
||||||
|
diagnostic_filtering/compound_statement_attribute.wgsl:7:9 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
if (x > 0) {
|
||||||
|
^
|
||||||
|
|
||||||
|
Texture2D<float4> t : register(t1, space0);
|
||||||
|
SamplerState s : register(s2, space0);
|
||||||
|
|
||||||
|
struct tint_symbol_1 {
|
||||||
|
float x : TEXCOORD0;
|
||||||
|
};
|
||||||
|
|
||||||
|
void main_inner(float x) {
|
||||||
|
{
|
||||||
|
if ((x > 0.0f)) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main(tint_symbol_1 tint_symbol) {
|
||||||
|
main_inner(tint_symbol.x);
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
diagnostic_filtering/compound_statement_attribute.wgsl:8:11 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/compound_statement_attribute.wgsl:7:5 note: control flow depends on possibly non-uniform value
|
||||||
|
if (x > 0) {
|
||||||
|
^^
|
||||||
|
|
||||||
|
diagnostic_filtering/compound_statement_attribute.wgsl:7:9 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
if (x > 0) {
|
||||||
|
^
|
||||||
|
|
||||||
|
#version 310 es
|
||||||
|
precision mediump float;
|
||||||
|
|
||||||
|
layout(location = 0) in float x_1;
|
||||||
|
void tint_symbol(float x) {
|
||||||
|
{
|
||||||
|
if ((x > 0.0f)) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
tint_symbol(x_1);
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
diagnostic_filtering/compound_statement_attribute.wgsl:8:11 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/compound_statement_attribute.wgsl:7:5 note: control flow depends on possibly non-uniform value
|
||||||
|
if (x > 0) {
|
||||||
|
^^
|
||||||
|
|
||||||
|
diagnostic_filtering/compound_statement_attribute.wgsl:7:9 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
if (x > 0) {
|
||||||
|
^
|
||||||
|
|
||||||
|
#include <metal_stdlib>
|
||||||
|
|
||||||
|
using namespace metal;
|
||||||
|
struct tint_symbol_2 {
|
||||||
|
float x [[user(locn0)]];
|
||||||
|
};
|
||||||
|
|
||||||
|
void tint_symbol_inner(float x) {
|
||||||
|
{
|
||||||
|
if ((x > 0.0f)) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fragment void tint_symbol(tint_symbol_2 tint_symbol_1 [[stage_in]]) {
|
||||||
|
tint_symbol_inner(tint_symbol_1.x);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
diagnostic_filtering/compound_statement_attribute.wgsl:8:11 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/compound_statement_attribute.wgsl:7:5 note: control flow depends on possibly non-uniform value
|
||||||
|
if (x > 0) {
|
||||||
|
^^
|
||||||
|
|
||||||
|
diagnostic_filtering/compound_statement_attribute.wgsl:7:9 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
if (x > 0) {
|
||||||
|
^
|
||||||
|
|
||||||
|
; SPIR-V
|
||||||
|
; Version: 1.3
|
||||||
|
; Generator: Google Tint Compiler; 0
|
||||||
|
; Bound: 25
|
||||||
|
; Schema: 0
|
||||||
|
OpCapability Shader
|
||||||
|
OpMemoryModel Logical GLSL450
|
||||||
|
OpEntryPoint Fragment %main "main" %x_1
|
||||||
|
OpExecutionMode %main OriginUpperLeft
|
||||||
|
OpName %x_1 "x_1"
|
||||||
|
OpName %t "t"
|
||||||
|
OpName %s "s"
|
||||||
|
OpName %main_inner "main_inner"
|
||||||
|
OpName %x "x"
|
||||||
|
OpName %main "main"
|
||||||
|
OpDecorate %x_1 Location 0
|
||||||
|
OpDecorate %t DescriptorSet 0
|
||||||
|
OpDecorate %t Binding 1
|
||||||
|
OpDecorate %s DescriptorSet 0
|
||||||
|
OpDecorate %s Binding 2
|
||||||
|
%float = OpTypeFloat 32
|
||||||
|
%_ptr_Input_float = OpTypePointer Input %float
|
||||||
|
%x_1 = OpVariable %_ptr_Input_float Input
|
||||||
|
%6 = OpTypeImage %float 2D 0 0 0 1 Unknown
|
||||||
|
%_ptr_UniformConstant_6 = OpTypePointer UniformConstant %6
|
||||||
|
%t = OpVariable %_ptr_UniformConstant_6 UniformConstant
|
||||||
|
%9 = OpTypeSampler
|
||||||
|
%_ptr_UniformConstant_9 = OpTypePointer UniformConstant %9
|
||||||
|
%s = OpVariable %_ptr_UniformConstant_9 UniformConstant
|
||||||
|
%void = OpTypeVoid
|
||||||
|
%10 = OpTypeFunction %void %float
|
||||||
|
%15 = OpConstantNull %float
|
||||||
|
%bool = OpTypeBool
|
||||||
|
%20 = OpTypeFunction %void
|
||||||
|
%main_inner = OpFunction %void None %10
|
||||||
|
%x = OpFunctionParameter %float
|
||||||
|
%14 = OpLabel
|
||||||
|
%16 = OpFOrdGreaterThan %bool %x %15
|
||||||
|
OpSelectionMerge %18 None
|
||||||
|
OpBranchConditional %16 %19 %18
|
||||||
|
%19 = OpLabel
|
||||||
|
OpBranch %18
|
||||||
|
%18 = OpLabel
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
%main = OpFunction %void None %20
|
||||||
|
%22 = OpLabel
|
||||||
|
%24 = OpLoad %float %x_1
|
||||||
|
%23 = OpFunctionCall %void %main_inner %24
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
|
@ -0,0 +1,24 @@
|
||||||
|
diagnostic_filtering/compound_statement_attribute.wgsl:8:11 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/compound_statement_attribute.wgsl:7:5 note: control flow depends on possibly non-uniform value
|
||||||
|
if (x > 0) {
|
||||||
|
^^
|
||||||
|
|
||||||
|
diagnostic_filtering/compound_statement_attribute.wgsl:7:9 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
if (x > 0) {
|
||||||
|
^
|
||||||
|
|
||||||
|
@group(0) @binding(1) var t : texture_2d<f32>;
|
||||||
|
|
||||||
|
@group(0) @binding(2) var s : sampler;
|
||||||
|
|
||||||
|
@fragment
|
||||||
|
fn main(@location(0) x : f32) {
|
||||||
|
@diagnostic(warning, derivative_uniformity) {
|
||||||
|
if ((x > 0)) {
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
@group(0) @binding(1) var t : texture_2d<f32>;
|
||||||
|
@group(0) @binding(2) var s : sampler;
|
||||||
|
|
||||||
|
@fragment
|
||||||
|
fn main(@location(0) x : f32) {
|
||||||
|
switch (i32(x)) {
|
||||||
|
default @diagnostic(warning, derivative_uniformity) {
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
diagnostic_filtering/default_case_body_attribute.wgsl:8:11 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/default_case_body_attribute.wgsl:6:3 note: control flow depends on possibly non-uniform value
|
||||||
|
switch (i32(x)) {
|
||||||
|
^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/default_case_body_attribute.wgsl:6:15 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
switch (i32(x)) {
|
||||||
|
^
|
||||||
|
|
||||||
|
Texture2D<float4> t : register(t1, space0);
|
||||||
|
SamplerState s : register(s2, space0);
|
||||||
|
|
||||||
|
struct tint_symbol_1 {
|
||||||
|
float x : TEXCOORD0;
|
||||||
|
};
|
||||||
|
|
||||||
|
void main_inner(float x) {
|
||||||
|
do {
|
||||||
|
} while (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main(tint_symbol_1 tint_symbol) {
|
||||||
|
main_inner(tint_symbol.x);
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
diagnostic_filtering/default_case_body_attribute.wgsl:8:11 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/default_case_body_attribute.wgsl:6:3 note: control flow depends on possibly non-uniform value
|
||||||
|
switch (i32(x)) {
|
||||||
|
^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/default_case_body_attribute.wgsl:6:15 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
switch (i32(x)) {
|
||||||
|
^
|
||||||
|
|
||||||
|
Texture2D<float4> t : register(t1, space0);
|
||||||
|
SamplerState s : register(s2, space0);
|
||||||
|
|
||||||
|
struct tint_symbol_1 {
|
||||||
|
float x : TEXCOORD0;
|
||||||
|
};
|
||||||
|
|
||||||
|
void main_inner(float x) {
|
||||||
|
do {
|
||||||
|
} while (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main(tint_symbol_1 tint_symbol) {
|
||||||
|
main_inner(tint_symbol.x);
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
diagnostic_filtering/default_case_body_attribute.wgsl:8:11 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/default_case_body_attribute.wgsl:6:3 note: control flow depends on possibly non-uniform value
|
||||||
|
switch (i32(x)) {
|
||||||
|
^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/default_case_body_attribute.wgsl:6:15 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
switch (i32(x)) {
|
||||||
|
^
|
||||||
|
|
||||||
|
#version 310 es
|
||||||
|
precision mediump float;
|
||||||
|
|
||||||
|
layout(location = 0) in float x_1;
|
||||||
|
void tint_symbol(float x) {
|
||||||
|
switch(int(x)) {
|
||||||
|
default: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
tint_symbol(x_1);
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
diagnostic_filtering/default_case_body_attribute.wgsl:8:11 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/default_case_body_attribute.wgsl:6:3 note: control flow depends on possibly non-uniform value
|
||||||
|
switch (i32(x)) {
|
||||||
|
^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/default_case_body_attribute.wgsl:6:15 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
switch (i32(x)) {
|
||||||
|
^
|
||||||
|
|
||||||
|
#include <metal_stdlib>
|
||||||
|
|
||||||
|
using namespace metal;
|
||||||
|
struct tint_symbol_2 {
|
||||||
|
float x [[user(locn0)]];
|
||||||
|
};
|
||||||
|
|
||||||
|
void tint_symbol_inner(float x) {
|
||||||
|
switch(int(x)) {
|
||||||
|
default: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fragment void tint_symbol(tint_symbol_2 tint_symbol_1 [[stage_in]]) {
|
||||||
|
tint_symbol_inner(tint_symbol_1.x);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
diagnostic_filtering/default_case_body_attribute.wgsl:8:11 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/default_case_body_attribute.wgsl:6:3 note: control flow depends on possibly non-uniform value
|
||||||
|
switch (i32(x)) {
|
||||||
|
^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/default_case_body_attribute.wgsl:6:15 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
switch (i32(x)) {
|
||||||
|
^
|
||||||
|
|
||||||
|
; SPIR-V
|
||||||
|
; Version: 1.3
|
||||||
|
; Generator: Google Tint Compiler; 0
|
||||||
|
; Bound: 24
|
||||||
|
; Schema: 0
|
||||||
|
OpCapability Shader
|
||||||
|
OpMemoryModel Logical GLSL450
|
||||||
|
OpEntryPoint Fragment %main "main" %x_1
|
||||||
|
OpExecutionMode %main OriginUpperLeft
|
||||||
|
OpName %x_1 "x_1"
|
||||||
|
OpName %t "t"
|
||||||
|
OpName %s "s"
|
||||||
|
OpName %main_inner "main_inner"
|
||||||
|
OpName %x "x"
|
||||||
|
OpName %main "main"
|
||||||
|
OpDecorate %x_1 Location 0
|
||||||
|
OpDecorate %t DescriptorSet 0
|
||||||
|
OpDecorate %t Binding 1
|
||||||
|
OpDecorate %s DescriptorSet 0
|
||||||
|
OpDecorate %s Binding 2
|
||||||
|
%float = OpTypeFloat 32
|
||||||
|
%_ptr_Input_float = OpTypePointer Input %float
|
||||||
|
%x_1 = OpVariable %_ptr_Input_float Input
|
||||||
|
%6 = OpTypeImage %float 2D 0 0 0 1 Unknown
|
||||||
|
%_ptr_UniformConstant_6 = OpTypePointer UniformConstant %6
|
||||||
|
%t = OpVariable %_ptr_UniformConstant_6 UniformConstant
|
||||||
|
%9 = OpTypeSampler
|
||||||
|
%_ptr_UniformConstant_9 = OpTypePointer UniformConstant %9
|
||||||
|
%s = OpVariable %_ptr_UniformConstant_9 UniformConstant
|
||||||
|
%void = OpTypeVoid
|
||||||
|
%10 = OpTypeFunction %void %float
|
||||||
|
%int = OpTypeInt 32 1
|
||||||
|
%19 = OpTypeFunction %void
|
||||||
|
%main_inner = OpFunction %void None %10
|
||||||
|
%x = OpFunctionParameter %float
|
||||||
|
%14 = OpLabel
|
||||||
|
%16 = OpConvertFToS %int %x
|
||||||
|
OpSelectionMerge %15 None
|
||||||
|
OpSwitch %16 %18
|
||||||
|
%18 = OpLabel
|
||||||
|
OpBranch %15
|
||||||
|
%15 = OpLabel
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
%main = OpFunction %void None %19
|
||||||
|
%21 = OpLabel
|
||||||
|
%23 = OpLoad %float %x_1
|
||||||
|
%22 = OpFunctionCall %void %main_inner %23
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
|
@ -0,0 +1,24 @@
|
||||||
|
diagnostic_filtering/default_case_body_attribute.wgsl:8:11 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/default_case_body_attribute.wgsl:6:3 note: control flow depends on possibly non-uniform value
|
||||||
|
switch (i32(x)) {
|
||||||
|
^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/default_case_body_attribute.wgsl:6:15 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
switch (i32(x)) {
|
||||||
|
^
|
||||||
|
|
||||||
|
@group(0) @binding(1) var t : texture_2d<f32>;
|
||||||
|
|
||||||
|
@group(0) @binding(2) var s : sampler;
|
||||||
|
|
||||||
|
@fragment
|
||||||
|
fn main(@location(0) x : f32) {
|
||||||
|
switch(i32(x)) {
|
||||||
|
default: @diagnostic(warning, derivative_uniformity) {
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
@group(0) @binding(1) var t : texture_2d<f32>;
|
||||||
|
@group(0) @binding(2) var s : sampler;
|
||||||
|
|
||||||
|
@fragment
|
||||||
|
fn main(@location(0) x : f32) {
|
||||||
|
if (x > 0) {
|
||||||
|
} else @diagnostic(warning, derivative_uniformity) {
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
diagnostic_filtering/else_body_attribute.wgsl:8:9 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/else_body_attribute.wgsl:6:3 note: control flow depends on possibly non-uniform value
|
||||||
|
if (x > 0) {
|
||||||
|
^^
|
||||||
|
|
||||||
|
diagnostic_filtering/else_body_attribute.wgsl:6:7 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
if (x > 0) {
|
||||||
|
^
|
||||||
|
|
||||||
|
Texture2D<float4> t : register(t1, space0);
|
||||||
|
SamplerState s : register(s2, space0);
|
||||||
|
|
||||||
|
struct tint_symbol_1 {
|
||||||
|
float x : TEXCOORD0;
|
||||||
|
};
|
||||||
|
|
||||||
|
void main_inner(float x) {
|
||||||
|
if ((x > 0.0f)) {
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main(tint_symbol_1 tint_symbol) {
|
||||||
|
main_inner(tint_symbol.x);
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
diagnostic_filtering/else_body_attribute.wgsl:8:9 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/else_body_attribute.wgsl:6:3 note: control flow depends on possibly non-uniform value
|
||||||
|
if (x > 0) {
|
||||||
|
^^
|
||||||
|
|
||||||
|
diagnostic_filtering/else_body_attribute.wgsl:6:7 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
if (x > 0) {
|
||||||
|
^
|
||||||
|
|
||||||
|
Texture2D<float4> t : register(t1, space0);
|
||||||
|
SamplerState s : register(s2, space0);
|
||||||
|
|
||||||
|
struct tint_symbol_1 {
|
||||||
|
float x : TEXCOORD0;
|
||||||
|
};
|
||||||
|
|
||||||
|
void main_inner(float x) {
|
||||||
|
if ((x > 0.0f)) {
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main(tint_symbol_1 tint_symbol) {
|
||||||
|
main_inner(tint_symbol.x);
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
diagnostic_filtering/else_body_attribute.wgsl:8:9 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/else_body_attribute.wgsl:6:3 note: control flow depends on possibly non-uniform value
|
||||||
|
if (x > 0) {
|
||||||
|
^^
|
||||||
|
|
||||||
|
diagnostic_filtering/else_body_attribute.wgsl:6:7 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
if (x > 0) {
|
||||||
|
^
|
||||||
|
|
||||||
|
#version 310 es
|
||||||
|
precision mediump float;
|
||||||
|
|
||||||
|
layout(location = 0) in float x_1;
|
||||||
|
void tint_symbol(float x) {
|
||||||
|
if ((x > 0.0f)) {
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
tint_symbol(x_1);
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
diagnostic_filtering/else_body_attribute.wgsl:8:9 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/else_body_attribute.wgsl:6:3 note: control flow depends on possibly non-uniform value
|
||||||
|
if (x > 0) {
|
||||||
|
^^
|
||||||
|
|
||||||
|
diagnostic_filtering/else_body_attribute.wgsl:6:7 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
if (x > 0) {
|
||||||
|
^
|
||||||
|
|
||||||
|
#include <metal_stdlib>
|
||||||
|
|
||||||
|
using namespace metal;
|
||||||
|
struct tint_symbol_2 {
|
||||||
|
float x [[user(locn0)]];
|
||||||
|
};
|
||||||
|
|
||||||
|
void tint_symbol_inner(float x) {
|
||||||
|
if ((x > 0.0f)) {
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fragment void tint_symbol(tint_symbol_2 tint_symbol_1 [[stage_in]]) {
|
||||||
|
tint_symbol_inner(tint_symbol_1.x);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
diagnostic_filtering/else_body_attribute.wgsl:8:9 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/else_body_attribute.wgsl:6:3 note: control flow depends on possibly non-uniform value
|
||||||
|
if (x > 0) {
|
||||||
|
^^
|
||||||
|
|
||||||
|
diagnostic_filtering/else_body_attribute.wgsl:6:7 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
if (x > 0) {
|
||||||
|
^
|
||||||
|
|
||||||
|
; SPIR-V
|
||||||
|
; Version: 1.3
|
||||||
|
; Generator: Google Tint Compiler; 0
|
||||||
|
; Bound: 26
|
||||||
|
; Schema: 0
|
||||||
|
OpCapability Shader
|
||||||
|
OpMemoryModel Logical GLSL450
|
||||||
|
OpEntryPoint Fragment %main "main" %x_1
|
||||||
|
OpExecutionMode %main OriginUpperLeft
|
||||||
|
OpName %x_1 "x_1"
|
||||||
|
OpName %t "t"
|
||||||
|
OpName %s "s"
|
||||||
|
OpName %main_inner "main_inner"
|
||||||
|
OpName %x "x"
|
||||||
|
OpName %main "main"
|
||||||
|
OpDecorate %x_1 Location 0
|
||||||
|
OpDecorate %t DescriptorSet 0
|
||||||
|
OpDecorate %t Binding 1
|
||||||
|
OpDecorate %s DescriptorSet 0
|
||||||
|
OpDecorate %s Binding 2
|
||||||
|
%float = OpTypeFloat 32
|
||||||
|
%_ptr_Input_float = OpTypePointer Input %float
|
||||||
|
%x_1 = OpVariable %_ptr_Input_float Input
|
||||||
|
%6 = OpTypeImage %float 2D 0 0 0 1 Unknown
|
||||||
|
%_ptr_UniformConstant_6 = OpTypePointer UniformConstant %6
|
||||||
|
%t = OpVariable %_ptr_UniformConstant_6 UniformConstant
|
||||||
|
%9 = OpTypeSampler
|
||||||
|
%_ptr_UniformConstant_9 = OpTypePointer UniformConstant %9
|
||||||
|
%s = OpVariable %_ptr_UniformConstant_9 UniformConstant
|
||||||
|
%void = OpTypeVoid
|
||||||
|
%10 = OpTypeFunction %void %float
|
||||||
|
%15 = OpConstantNull %float
|
||||||
|
%bool = OpTypeBool
|
||||||
|
%21 = OpTypeFunction %void
|
||||||
|
%main_inner = OpFunction %void None %10
|
||||||
|
%x = OpFunctionParameter %float
|
||||||
|
%14 = OpLabel
|
||||||
|
%16 = OpFOrdGreaterThan %bool %x %15
|
||||||
|
OpSelectionMerge %18 None
|
||||||
|
OpBranchConditional %16 %19 %20
|
||||||
|
%19 = OpLabel
|
||||||
|
OpBranch %18
|
||||||
|
%20 = OpLabel
|
||||||
|
OpBranch %18
|
||||||
|
%18 = OpLabel
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
%main = OpFunction %void None %21
|
||||||
|
%23 = OpLabel
|
||||||
|
%25 = OpLoad %float %x_1
|
||||||
|
%24 = OpFunctionCall %void %main_inner %25
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
|
@ -0,0 +1,23 @@
|
||||||
|
diagnostic_filtering/else_body_attribute.wgsl:8:9 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/else_body_attribute.wgsl:6:3 note: control flow depends on possibly non-uniform value
|
||||||
|
if (x > 0) {
|
||||||
|
^^
|
||||||
|
|
||||||
|
diagnostic_filtering/else_body_attribute.wgsl:6:7 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
if (x > 0) {
|
||||||
|
^
|
||||||
|
|
||||||
|
@group(0) @binding(1) var t : texture_2d<f32>;
|
||||||
|
|
||||||
|
@group(0) @binding(2) var s : sampler;
|
||||||
|
|
||||||
|
@fragment
|
||||||
|
fn main(@location(0) x : f32) {
|
||||||
|
if ((x > 0)) {
|
||||||
|
} else @diagnostic(warning, derivative_uniformity) {
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
@group(0) @binding(1) var t : texture_2d<f32>;
|
||||||
|
@group(0) @binding(2) var s : sampler;
|
||||||
|
|
||||||
|
@fragment
|
||||||
|
fn main(@location(0) x : f32) {
|
||||||
|
if (x > 0) {
|
||||||
|
} else if (x < 0) @diagnostic(warning, derivative_uniformity) {
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
diagnostic_filtering/else_if_body_attribute.wgsl:8:9 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/else_if_body_attribute.wgsl:6:3 note: control flow depends on possibly non-uniform value
|
||||||
|
if (x > 0) {
|
||||||
|
^^
|
||||||
|
|
||||||
|
diagnostic_filtering/else_if_body_attribute.wgsl:6:7 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
if (x > 0) {
|
||||||
|
^
|
||||||
|
|
||||||
|
Texture2D<float4> t : register(t1, space0);
|
||||||
|
SamplerState s : register(s2, space0);
|
||||||
|
|
||||||
|
struct tint_symbol_1 {
|
||||||
|
float x : TEXCOORD0;
|
||||||
|
};
|
||||||
|
|
||||||
|
void main_inner(float x) {
|
||||||
|
if ((x > 0.0f)) {
|
||||||
|
} else {
|
||||||
|
if ((x < 0.0f)) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main(tint_symbol_1 tint_symbol) {
|
||||||
|
main_inner(tint_symbol.x);
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
diagnostic_filtering/else_if_body_attribute.wgsl:8:9 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/else_if_body_attribute.wgsl:6:3 note: control flow depends on possibly non-uniform value
|
||||||
|
if (x > 0) {
|
||||||
|
^^
|
||||||
|
|
||||||
|
diagnostic_filtering/else_if_body_attribute.wgsl:6:7 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
if (x > 0) {
|
||||||
|
^
|
||||||
|
|
||||||
|
Texture2D<float4> t : register(t1, space0);
|
||||||
|
SamplerState s : register(s2, space0);
|
||||||
|
|
||||||
|
struct tint_symbol_1 {
|
||||||
|
float x : TEXCOORD0;
|
||||||
|
};
|
||||||
|
|
||||||
|
void main_inner(float x) {
|
||||||
|
if ((x > 0.0f)) {
|
||||||
|
} else {
|
||||||
|
if ((x < 0.0f)) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main(tint_symbol_1 tint_symbol) {
|
||||||
|
main_inner(tint_symbol.x);
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
diagnostic_filtering/else_if_body_attribute.wgsl:8:9 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/else_if_body_attribute.wgsl:6:3 note: control flow depends on possibly non-uniform value
|
||||||
|
if (x > 0) {
|
||||||
|
^^
|
||||||
|
|
||||||
|
diagnostic_filtering/else_if_body_attribute.wgsl:6:7 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
if (x > 0) {
|
||||||
|
^
|
||||||
|
|
||||||
|
#version 310 es
|
||||||
|
precision mediump float;
|
||||||
|
|
||||||
|
layout(location = 0) in float x_1;
|
||||||
|
void tint_symbol(float x) {
|
||||||
|
if ((x > 0.0f)) {
|
||||||
|
} else {
|
||||||
|
if ((x < 0.0f)) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
tint_symbol(x_1);
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
diagnostic_filtering/else_if_body_attribute.wgsl:8:9 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/else_if_body_attribute.wgsl:6:3 note: control flow depends on possibly non-uniform value
|
||||||
|
if (x > 0) {
|
||||||
|
^^
|
||||||
|
|
||||||
|
diagnostic_filtering/else_if_body_attribute.wgsl:6:7 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
if (x > 0) {
|
||||||
|
^
|
||||||
|
|
||||||
|
#include <metal_stdlib>
|
||||||
|
|
||||||
|
using namespace metal;
|
||||||
|
struct tint_symbol_2 {
|
||||||
|
float x [[user(locn0)]];
|
||||||
|
};
|
||||||
|
|
||||||
|
void tint_symbol_inner(float x) {
|
||||||
|
if ((x > 0.0f)) {
|
||||||
|
} else {
|
||||||
|
if ((x < 0.0f)) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fragment void tint_symbol(tint_symbol_2 tint_symbol_1 [[stage_in]]) {
|
||||||
|
tint_symbol_inner(tint_symbol_1.x);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
diagnostic_filtering/else_if_body_attribute.wgsl:8:9 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/else_if_body_attribute.wgsl:6:3 note: control flow depends on possibly non-uniform value
|
||||||
|
if (x > 0) {
|
||||||
|
^^
|
||||||
|
|
||||||
|
diagnostic_filtering/else_if_body_attribute.wgsl:6:7 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
if (x > 0) {
|
||||||
|
^
|
||||||
|
|
||||||
|
; SPIR-V
|
||||||
|
; Version: 1.3
|
||||||
|
; Generator: Google Tint Compiler; 0
|
||||||
|
; Bound: 29
|
||||||
|
; Schema: 0
|
||||||
|
OpCapability Shader
|
||||||
|
OpMemoryModel Logical GLSL450
|
||||||
|
OpEntryPoint Fragment %main "main" %x_1
|
||||||
|
OpExecutionMode %main OriginUpperLeft
|
||||||
|
OpName %x_1 "x_1"
|
||||||
|
OpName %t "t"
|
||||||
|
OpName %s "s"
|
||||||
|
OpName %main_inner "main_inner"
|
||||||
|
OpName %x "x"
|
||||||
|
OpName %main "main"
|
||||||
|
OpDecorate %x_1 Location 0
|
||||||
|
OpDecorate %t DescriptorSet 0
|
||||||
|
OpDecorate %t Binding 1
|
||||||
|
OpDecorate %s DescriptorSet 0
|
||||||
|
OpDecorate %s Binding 2
|
||||||
|
%float = OpTypeFloat 32
|
||||||
|
%_ptr_Input_float = OpTypePointer Input %float
|
||||||
|
%x_1 = OpVariable %_ptr_Input_float Input
|
||||||
|
%6 = OpTypeImage %float 2D 0 0 0 1 Unknown
|
||||||
|
%_ptr_UniformConstant_6 = OpTypePointer UniformConstant %6
|
||||||
|
%t = OpVariable %_ptr_UniformConstant_6 UniformConstant
|
||||||
|
%9 = OpTypeSampler
|
||||||
|
%_ptr_UniformConstant_9 = OpTypePointer UniformConstant %9
|
||||||
|
%s = OpVariable %_ptr_UniformConstant_9 UniformConstant
|
||||||
|
%void = OpTypeVoid
|
||||||
|
%10 = OpTypeFunction %void %float
|
||||||
|
%15 = OpConstantNull %float
|
||||||
|
%bool = OpTypeBool
|
||||||
|
%24 = OpTypeFunction %void
|
||||||
|
%main_inner = OpFunction %void None %10
|
||||||
|
%x = OpFunctionParameter %float
|
||||||
|
%14 = OpLabel
|
||||||
|
%16 = OpFOrdGreaterThan %bool %x %15
|
||||||
|
OpSelectionMerge %18 None
|
||||||
|
OpBranchConditional %16 %19 %20
|
||||||
|
%19 = OpLabel
|
||||||
|
OpBranch %18
|
||||||
|
%20 = OpLabel
|
||||||
|
%21 = OpFOrdLessThan %bool %x %15
|
||||||
|
OpSelectionMerge %22 None
|
||||||
|
OpBranchConditional %21 %23 %22
|
||||||
|
%23 = OpLabel
|
||||||
|
OpBranch %22
|
||||||
|
%22 = OpLabel
|
||||||
|
OpBranch %18
|
||||||
|
%18 = OpLabel
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
%main = OpFunction %void None %24
|
||||||
|
%26 = OpLabel
|
||||||
|
%28 = OpLoad %float %x_1
|
||||||
|
%27 = OpFunctionCall %void %main_inner %28
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
|
@ -0,0 +1,23 @@
|
||||||
|
diagnostic_filtering/else_if_body_attribute.wgsl:8:9 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/else_if_body_attribute.wgsl:6:3 note: control flow depends on possibly non-uniform value
|
||||||
|
if (x > 0) {
|
||||||
|
^^
|
||||||
|
|
||||||
|
diagnostic_filtering/else_if_body_attribute.wgsl:6:7 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
if (x > 0) {
|
||||||
|
^
|
||||||
|
|
||||||
|
@group(0) @binding(1) var t : texture_2d<f32>;
|
||||||
|
|
||||||
|
@group(0) @binding(2) var s : sampler;
|
||||||
|
|
||||||
|
@fragment
|
||||||
|
fn main(@location(0) x : f32) {
|
||||||
|
if ((x > 0)) {
|
||||||
|
} else if ((x < 0)) @diagnostic(warning, derivative_uniformity) {
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
@group(0) @binding(1) var t : texture_2d<f32>;
|
||||||
|
@group(0) @binding(2) var s : sampler;
|
||||||
|
|
||||||
|
@fragment
|
||||||
|
fn main(@location(0) x : f32) {
|
||||||
|
var v = vec4<f32>(0);
|
||||||
|
for (; x > v.x; ) @diagnostic(warning, derivative_uniformity) {
|
||||||
|
v = textureSample(t, s, vec2(0, 0));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
diagnostic_filtering/for_loop_body_attribute.wgsl:8:9 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
v = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/for_loop_body_attribute.wgsl:7:3 note: control flow depends on possibly non-uniform value
|
||||||
|
for (; x > v.x; ) @diagnostic(warning, derivative_uniformity) {
|
||||||
|
^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/for_loop_body_attribute.wgsl:8:9 note: return value of 'textureSample' may be non-uniform
|
||||||
|
v = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Texture2D<float4> t : register(t1, space0);
|
||||||
|
SamplerState s : register(s2, space0);
|
||||||
|
|
||||||
|
struct tint_symbol_1 {
|
||||||
|
float x : TEXCOORD0;
|
||||||
|
};
|
||||||
|
|
||||||
|
void main_inner(float x) {
|
||||||
|
float4 v = (0.0f).xxxx;
|
||||||
|
{
|
||||||
|
for(; (x > v.x); ) {
|
||||||
|
v = t.Sample(s, (0.0f).xx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main(tint_symbol_1 tint_symbol) {
|
||||||
|
main_inner(tint_symbol.x);
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
SKIP: FXC rejects non-uniform texture sample operation in output
|
||||||
|
|
||||||
|
diagnostic_filtering/for_loop_body_attribute.wgsl:8:9 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
v = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/for_loop_body_attribute.wgsl:7:3 note: control flow depends on possibly non-uniform value
|
||||||
|
for (; x > v.x; ) @diagnostic(warning, derivative_uniformity) {
|
||||||
|
^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/for_loop_body_attribute.wgsl:8:9 note: return value of 'textureSample' may be non-uniform
|
||||||
|
v = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Texture2D<float4> t : register(t1, space0);
|
||||||
|
SamplerState s : register(s2, space0);
|
||||||
|
|
||||||
|
struct tint_symbol_1 {
|
||||||
|
float x : TEXCOORD0;
|
||||||
|
};
|
||||||
|
|
||||||
|
void main_inner(float x) {
|
||||||
|
float4 v = (0.0f).xxxx;
|
||||||
|
{
|
||||||
|
for(; (x > v.x); ) {
|
||||||
|
v = t.Sample(s, (0.0f).xx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main(tint_symbol_1 tint_symbol) {
|
||||||
|
main_inner(tint_symbol.x);
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
diagnostic_filtering/for_loop_body_attribute.wgsl:8:9 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
v = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/for_loop_body_attribute.wgsl:7:3 note: control flow depends on possibly non-uniform value
|
||||||
|
for (; x > v.x; ) @diagnostic(warning, derivative_uniformity) {
|
||||||
|
^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/for_loop_body_attribute.wgsl:8:9 note: return value of 'textureSample' may be non-uniform
|
||||||
|
v = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
#version 310 es
|
||||||
|
precision mediump float;
|
||||||
|
|
||||||
|
layout(location = 0) in float x_1;
|
||||||
|
uniform highp sampler2D t_s;
|
||||||
|
|
||||||
|
void tint_symbol(float x) {
|
||||||
|
vec4 v = vec4(0.0f);
|
||||||
|
{
|
||||||
|
for(; (x > v.x); ) {
|
||||||
|
v = texture(t_s, vec2(0.0f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
tint_symbol(x_1);
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
diagnostic_filtering/for_loop_body_attribute.wgsl:8:9 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
v = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/for_loop_body_attribute.wgsl:7:3 note: control flow depends on possibly non-uniform value
|
||||||
|
for (; x > v.x; ) @diagnostic(warning, derivative_uniformity) {
|
||||||
|
^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/for_loop_body_attribute.wgsl:8:9 note: return value of 'textureSample' may be non-uniform
|
||||||
|
v = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
#include <metal_stdlib>
|
||||||
|
|
||||||
|
using namespace metal;
|
||||||
|
struct tint_symbol_2 {
|
||||||
|
float x [[user(locn0)]];
|
||||||
|
};
|
||||||
|
|
||||||
|
void tint_symbol_inner(float x, texture2d<float, access::sample> tint_symbol_3, sampler tint_symbol_4) {
|
||||||
|
float4 v = float4(0.0f);
|
||||||
|
for(; (x > v[0]); ) {
|
||||||
|
v = tint_symbol_3.sample(tint_symbol_4, float2(0.0f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fragment void tint_symbol(texture2d<float, access::sample> tint_symbol_5 [[texture(0)]], sampler tint_symbol_6 [[sampler(0)]], tint_symbol_2 tint_symbol_1 [[stage_in]]) {
|
||||||
|
tint_symbol_inner(tint_symbol_1.x, tint_symbol_5, tint_symbol_6);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,91 @@
|
||||||
|
diagnostic_filtering/for_loop_body_attribute.wgsl:8:9 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
v = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/for_loop_body_attribute.wgsl:7:3 note: control flow depends on possibly non-uniform value
|
||||||
|
for (; x > v.x; ) @diagnostic(warning, derivative_uniformity) {
|
||||||
|
^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/for_loop_body_attribute.wgsl:8:9 note: return value of 'textureSample' may be non-uniform
|
||||||
|
v = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
; SPIR-V
|
||||||
|
; Version: 1.3
|
||||||
|
; Generator: Google Tint Compiler; 0
|
||||||
|
; Bound: 45
|
||||||
|
; Schema: 0
|
||||||
|
OpCapability Shader
|
||||||
|
OpMemoryModel Logical GLSL450
|
||||||
|
OpEntryPoint Fragment %main "main" %x_1
|
||||||
|
OpExecutionMode %main OriginUpperLeft
|
||||||
|
OpName %x_1 "x_1"
|
||||||
|
OpName %t "t"
|
||||||
|
OpName %s "s"
|
||||||
|
OpName %main_inner "main_inner"
|
||||||
|
OpName %x "x"
|
||||||
|
OpName %v "v"
|
||||||
|
OpName %main "main"
|
||||||
|
OpDecorate %x_1 Location 0
|
||||||
|
OpDecorate %t DescriptorSet 0
|
||||||
|
OpDecorate %t Binding 1
|
||||||
|
OpDecorate %s DescriptorSet 0
|
||||||
|
OpDecorate %s Binding 2
|
||||||
|
%float = OpTypeFloat 32
|
||||||
|
%_ptr_Input_float = OpTypePointer Input %float
|
||||||
|
%x_1 = OpVariable %_ptr_Input_float Input
|
||||||
|
%6 = OpTypeImage %float 2D 0 0 0 1 Unknown
|
||||||
|
%_ptr_UniformConstant_6 = OpTypePointer UniformConstant %6
|
||||||
|
%t = OpVariable %_ptr_UniformConstant_6 UniformConstant
|
||||||
|
%9 = OpTypeSampler
|
||||||
|
%_ptr_UniformConstant_9 = OpTypePointer UniformConstant %9
|
||||||
|
%s = OpVariable %_ptr_UniformConstant_9 UniformConstant
|
||||||
|
%void = OpTypeVoid
|
||||||
|
%10 = OpTypeFunction %void %float
|
||||||
|
%v4float = OpTypeVector %float 4
|
||||||
|
%16 = OpConstantNull %v4float
|
||||||
|
%_ptr_Function_v4float = OpTypePointer Function %v4float
|
||||||
|
%uint = OpTypeInt 32 0
|
||||||
|
%uint_0 = OpConstant %uint 0
|
||||||
|
%_ptr_Function_float = OpTypePointer Function %float
|
||||||
|
%bool = OpTypeBool
|
||||||
|
%36 = OpTypeSampledImage %6
|
||||||
|
%v2float = OpTypeVector %float 2
|
||||||
|
%39 = OpConstantNull %v2float
|
||||||
|
%40 = OpTypeFunction %void
|
||||||
|
%main_inner = OpFunction %void None %10
|
||||||
|
%x = OpFunctionParameter %float
|
||||||
|
%14 = OpLabel
|
||||||
|
%v = OpVariable %_ptr_Function_v4float Function %16
|
||||||
|
OpStore %v %16
|
||||||
|
OpBranch %19
|
||||||
|
%19 = OpLabel
|
||||||
|
OpLoopMerge %20 %21 None
|
||||||
|
OpBranch %22
|
||||||
|
%22 = OpLabel
|
||||||
|
%27 = OpAccessChain %_ptr_Function_float %v %uint_0
|
||||||
|
%28 = OpLoad %float %27
|
||||||
|
%29 = OpFOrdGreaterThan %bool %x %28
|
||||||
|
%23 = OpLogicalNot %bool %29
|
||||||
|
OpSelectionMerge %31 None
|
||||||
|
OpBranchConditional %23 %32 %31
|
||||||
|
%32 = OpLabel
|
||||||
|
OpBranch %20
|
||||||
|
%31 = OpLabel
|
||||||
|
%34 = OpLoad %9 %s
|
||||||
|
%35 = OpLoad %6 %t
|
||||||
|
%37 = OpSampledImage %36 %35 %34
|
||||||
|
%33 = OpImageSampleImplicitLod %v4float %37 %39
|
||||||
|
OpStore %v %33
|
||||||
|
OpBranch %21
|
||||||
|
%21 = OpLabel
|
||||||
|
OpBranch %19
|
||||||
|
%20 = OpLabel
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
%main = OpFunction %void None %40
|
||||||
|
%42 = OpLabel
|
||||||
|
%44 = OpLoad %float %x_1
|
||||||
|
%43 = OpFunctionCall %void %main_inner %44
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
|
@ -0,0 +1,23 @@
|
||||||
|
diagnostic_filtering/for_loop_body_attribute.wgsl:8:9 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
v = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/for_loop_body_attribute.wgsl:7:3 note: control flow depends on possibly non-uniform value
|
||||||
|
for (; x > v.x; ) @diagnostic(warning, derivative_uniformity) {
|
||||||
|
^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/for_loop_body_attribute.wgsl:8:9 note: return value of 'textureSample' may be non-uniform
|
||||||
|
v = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
@group(0) @binding(1) var t : texture_2d<f32>;
|
||||||
|
|
||||||
|
@group(0) @binding(2) var s : sampler;
|
||||||
|
|
||||||
|
@fragment
|
||||||
|
fn main(@location(0) x : f32) {
|
||||||
|
var v = vec4<f32>(0);
|
||||||
|
for(; (x > v.x); ) @diagnostic(warning, derivative_uniformity) {
|
||||||
|
v = textureSample(t, s, vec2(0, 0));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
@group(0) @binding(1) var t : texture_2d<f32>;
|
||||||
|
@group(0) @binding(2) var s : sampler;
|
||||||
|
|
||||||
|
@fragment
|
||||||
|
fn main(@location(0) x : f32) @diagnostic(warning, derivative_uniformity) {
|
||||||
|
if (x > 0) {
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
diagnostic_filtering/function_body_attribute.wgsl:7:9 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/function_body_attribute.wgsl:6:3 note: control flow depends on possibly non-uniform value
|
||||||
|
if (x > 0) {
|
||||||
|
^^
|
||||||
|
|
||||||
|
diagnostic_filtering/function_body_attribute.wgsl:6:7 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
if (x > 0) {
|
||||||
|
^
|
||||||
|
|
||||||
|
Texture2D<float4> t : register(t1, space0);
|
||||||
|
SamplerState s : register(s2, space0);
|
||||||
|
|
||||||
|
struct tint_symbol_1 {
|
||||||
|
float x : TEXCOORD0;
|
||||||
|
};
|
||||||
|
|
||||||
|
void main_inner(float x) {
|
||||||
|
if ((x > 0.0f)) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main(tint_symbol_1 tint_symbol) {
|
||||||
|
main_inner(tint_symbol.x);
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
diagnostic_filtering/function_body_attribute.wgsl:7:9 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/function_body_attribute.wgsl:6:3 note: control flow depends on possibly non-uniform value
|
||||||
|
if (x > 0) {
|
||||||
|
^^
|
||||||
|
|
||||||
|
diagnostic_filtering/function_body_attribute.wgsl:6:7 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
if (x > 0) {
|
||||||
|
^
|
||||||
|
|
||||||
|
Texture2D<float4> t : register(t1, space0);
|
||||||
|
SamplerState s : register(s2, space0);
|
||||||
|
|
||||||
|
struct tint_symbol_1 {
|
||||||
|
float x : TEXCOORD0;
|
||||||
|
};
|
||||||
|
|
||||||
|
void main_inner(float x) {
|
||||||
|
if ((x > 0.0f)) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main(tint_symbol_1 tint_symbol) {
|
||||||
|
main_inner(tint_symbol.x);
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
diagnostic_filtering/function_body_attribute.wgsl:7:9 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/function_body_attribute.wgsl:6:3 note: control flow depends on possibly non-uniform value
|
||||||
|
if (x > 0) {
|
||||||
|
^^
|
||||||
|
|
||||||
|
diagnostic_filtering/function_body_attribute.wgsl:6:7 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
if (x > 0) {
|
||||||
|
^
|
||||||
|
|
||||||
|
#version 310 es
|
||||||
|
precision mediump float;
|
||||||
|
|
||||||
|
layout(location = 0) in float x_1;
|
||||||
|
void tint_symbol(float x) {
|
||||||
|
if ((x > 0.0f)) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
tint_symbol(x_1);
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
diagnostic_filtering/function_body_attribute.wgsl:7:9 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/function_body_attribute.wgsl:6:3 note: control flow depends on possibly non-uniform value
|
||||||
|
if (x > 0) {
|
||||||
|
^^
|
||||||
|
|
||||||
|
diagnostic_filtering/function_body_attribute.wgsl:6:7 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
if (x > 0) {
|
||||||
|
^
|
||||||
|
|
||||||
|
#include <metal_stdlib>
|
||||||
|
|
||||||
|
using namespace metal;
|
||||||
|
struct tint_symbol_2 {
|
||||||
|
float x [[user(locn0)]];
|
||||||
|
};
|
||||||
|
|
||||||
|
void tint_symbol_inner(float x) {
|
||||||
|
if ((x > 0.0f)) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fragment void tint_symbol(tint_symbol_2 tint_symbol_1 [[stage_in]]) {
|
||||||
|
tint_symbol_inner(tint_symbol_1.x);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
diagnostic_filtering/function_body_attribute.wgsl:7:9 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/function_body_attribute.wgsl:6:3 note: control flow depends on possibly non-uniform value
|
||||||
|
if (x > 0) {
|
||||||
|
^^
|
||||||
|
|
||||||
|
diagnostic_filtering/function_body_attribute.wgsl:6:7 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
if (x > 0) {
|
||||||
|
^
|
||||||
|
|
||||||
|
; SPIR-V
|
||||||
|
; Version: 1.3
|
||||||
|
; Generator: Google Tint Compiler; 0
|
||||||
|
; Bound: 25
|
||||||
|
; Schema: 0
|
||||||
|
OpCapability Shader
|
||||||
|
OpMemoryModel Logical GLSL450
|
||||||
|
OpEntryPoint Fragment %main "main" %x_1
|
||||||
|
OpExecutionMode %main OriginUpperLeft
|
||||||
|
OpName %x_1 "x_1"
|
||||||
|
OpName %t "t"
|
||||||
|
OpName %s "s"
|
||||||
|
OpName %main_inner "main_inner"
|
||||||
|
OpName %x "x"
|
||||||
|
OpName %main "main"
|
||||||
|
OpDecorate %x_1 Location 0
|
||||||
|
OpDecorate %t DescriptorSet 0
|
||||||
|
OpDecorate %t Binding 1
|
||||||
|
OpDecorate %s DescriptorSet 0
|
||||||
|
OpDecorate %s Binding 2
|
||||||
|
%float = OpTypeFloat 32
|
||||||
|
%_ptr_Input_float = OpTypePointer Input %float
|
||||||
|
%x_1 = OpVariable %_ptr_Input_float Input
|
||||||
|
%6 = OpTypeImage %float 2D 0 0 0 1 Unknown
|
||||||
|
%_ptr_UniformConstant_6 = OpTypePointer UniformConstant %6
|
||||||
|
%t = OpVariable %_ptr_UniformConstant_6 UniformConstant
|
||||||
|
%9 = OpTypeSampler
|
||||||
|
%_ptr_UniformConstant_9 = OpTypePointer UniformConstant %9
|
||||||
|
%s = OpVariable %_ptr_UniformConstant_9 UniformConstant
|
||||||
|
%void = OpTypeVoid
|
||||||
|
%10 = OpTypeFunction %void %float
|
||||||
|
%15 = OpConstantNull %float
|
||||||
|
%bool = OpTypeBool
|
||||||
|
%20 = OpTypeFunction %void
|
||||||
|
%main_inner = OpFunction %void None %10
|
||||||
|
%x = OpFunctionParameter %float
|
||||||
|
%14 = OpLabel
|
||||||
|
%16 = OpFOrdGreaterThan %bool %x %15
|
||||||
|
OpSelectionMerge %18 None
|
||||||
|
OpBranchConditional %16 %19 %18
|
||||||
|
%19 = OpLabel
|
||||||
|
OpBranch %18
|
||||||
|
%18 = OpLabel
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
%main = OpFunction %void None %20
|
||||||
|
%22 = OpLabel
|
||||||
|
%24 = OpLoad %float %x_1
|
||||||
|
%23 = OpFunctionCall %void %main_inner %24
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
|
@ -0,0 +1,22 @@
|
||||||
|
diagnostic_filtering/function_body_attribute.wgsl:7:9 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/function_body_attribute.wgsl:6:3 note: control flow depends on possibly non-uniform value
|
||||||
|
if (x > 0) {
|
||||||
|
^^
|
||||||
|
|
||||||
|
diagnostic_filtering/function_body_attribute.wgsl:6:7 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
if (x > 0) {
|
||||||
|
^
|
||||||
|
|
||||||
|
@group(0) @binding(1) var t : texture_2d<f32>;
|
||||||
|
|
||||||
|
@group(0) @binding(2) var s : sampler;
|
||||||
|
|
||||||
|
@fragment
|
||||||
|
fn main(@location(0) x : f32) @diagnostic(warning, derivative_uniformity) {
|
||||||
|
if ((x > 0)) {
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
@group(0) @binding(1) var t : texture_2d<f32>;
|
||||||
|
@group(0) @binding(2) var s : sampler;
|
||||||
|
|
||||||
|
@fragment
|
||||||
|
fn main(@location(0) x : f32) {
|
||||||
|
if (x > 0) @diagnostic(warning, derivative_uniformity) {
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
diagnostic_filtering/if_body_attribute.wgsl:7:9 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/if_body_attribute.wgsl:6:3 note: control flow depends on possibly non-uniform value
|
||||||
|
if (x > 0) @diagnostic(warning, derivative_uniformity) {
|
||||||
|
^^
|
||||||
|
|
||||||
|
diagnostic_filtering/if_body_attribute.wgsl:6:7 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
if (x > 0) @diagnostic(warning, derivative_uniformity) {
|
||||||
|
^
|
||||||
|
|
||||||
|
Texture2D<float4> t : register(t1, space0);
|
||||||
|
SamplerState s : register(s2, space0);
|
||||||
|
|
||||||
|
struct tint_symbol_1 {
|
||||||
|
float x : TEXCOORD0;
|
||||||
|
};
|
||||||
|
|
||||||
|
void main_inner(float x) {
|
||||||
|
if ((x > 0.0f)) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main(tint_symbol_1 tint_symbol) {
|
||||||
|
main_inner(tint_symbol.x);
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
diagnostic_filtering/if_body_attribute.wgsl:7:9 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/if_body_attribute.wgsl:6:3 note: control flow depends on possibly non-uniform value
|
||||||
|
if (x > 0) @diagnostic(warning, derivative_uniformity) {
|
||||||
|
^^
|
||||||
|
|
||||||
|
diagnostic_filtering/if_body_attribute.wgsl:6:7 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
if (x > 0) @diagnostic(warning, derivative_uniformity) {
|
||||||
|
^
|
||||||
|
|
||||||
|
Texture2D<float4> t : register(t1, space0);
|
||||||
|
SamplerState s : register(s2, space0);
|
||||||
|
|
||||||
|
struct tint_symbol_1 {
|
||||||
|
float x : TEXCOORD0;
|
||||||
|
};
|
||||||
|
|
||||||
|
void main_inner(float x) {
|
||||||
|
if ((x > 0.0f)) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main(tint_symbol_1 tint_symbol) {
|
||||||
|
main_inner(tint_symbol.x);
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
diagnostic_filtering/if_body_attribute.wgsl:7:9 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/if_body_attribute.wgsl:6:3 note: control flow depends on possibly non-uniform value
|
||||||
|
if (x > 0) @diagnostic(warning, derivative_uniformity) {
|
||||||
|
^^
|
||||||
|
|
||||||
|
diagnostic_filtering/if_body_attribute.wgsl:6:7 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
if (x > 0) @diagnostic(warning, derivative_uniformity) {
|
||||||
|
^
|
||||||
|
|
||||||
|
#version 310 es
|
||||||
|
precision mediump float;
|
||||||
|
|
||||||
|
layout(location = 0) in float x_1;
|
||||||
|
void tint_symbol(float x) {
|
||||||
|
if ((x > 0.0f)) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
tint_symbol(x_1);
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
diagnostic_filtering/if_body_attribute.wgsl:7:9 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/if_body_attribute.wgsl:6:3 note: control flow depends on possibly non-uniform value
|
||||||
|
if (x > 0) @diagnostic(warning, derivative_uniformity) {
|
||||||
|
^^
|
||||||
|
|
||||||
|
diagnostic_filtering/if_body_attribute.wgsl:6:7 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
if (x > 0) @diagnostic(warning, derivative_uniformity) {
|
||||||
|
^
|
||||||
|
|
||||||
|
#include <metal_stdlib>
|
||||||
|
|
||||||
|
using namespace metal;
|
||||||
|
struct tint_symbol_2 {
|
||||||
|
float x [[user(locn0)]];
|
||||||
|
};
|
||||||
|
|
||||||
|
void tint_symbol_inner(float x) {
|
||||||
|
if ((x > 0.0f)) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fragment void tint_symbol(tint_symbol_2 tint_symbol_1 [[stage_in]]) {
|
||||||
|
tint_symbol_inner(tint_symbol_1.x);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
diagnostic_filtering/if_body_attribute.wgsl:7:9 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/if_body_attribute.wgsl:6:3 note: control flow depends on possibly non-uniform value
|
||||||
|
if (x > 0) @diagnostic(warning, derivative_uniformity) {
|
||||||
|
^^
|
||||||
|
|
||||||
|
diagnostic_filtering/if_body_attribute.wgsl:6:7 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
if (x > 0) @diagnostic(warning, derivative_uniformity) {
|
||||||
|
^
|
||||||
|
|
||||||
|
; SPIR-V
|
||||||
|
; Version: 1.3
|
||||||
|
; Generator: Google Tint Compiler; 0
|
||||||
|
; Bound: 25
|
||||||
|
; Schema: 0
|
||||||
|
OpCapability Shader
|
||||||
|
OpMemoryModel Logical GLSL450
|
||||||
|
OpEntryPoint Fragment %main "main" %x_1
|
||||||
|
OpExecutionMode %main OriginUpperLeft
|
||||||
|
OpName %x_1 "x_1"
|
||||||
|
OpName %t "t"
|
||||||
|
OpName %s "s"
|
||||||
|
OpName %main_inner "main_inner"
|
||||||
|
OpName %x "x"
|
||||||
|
OpName %main "main"
|
||||||
|
OpDecorate %x_1 Location 0
|
||||||
|
OpDecorate %t DescriptorSet 0
|
||||||
|
OpDecorate %t Binding 1
|
||||||
|
OpDecorate %s DescriptorSet 0
|
||||||
|
OpDecorate %s Binding 2
|
||||||
|
%float = OpTypeFloat 32
|
||||||
|
%_ptr_Input_float = OpTypePointer Input %float
|
||||||
|
%x_1 = OpVariable %_ptr_Input_float Input
|
||||||
|
%6 = OpTypeImage %float 2D 0 0 0 1 Unknown
|
||||||
|
%_ptr_UniformConstant_6 = OpTypePointer UniformConstant %6
|
||||||
|
%t = OpVariable %_ptr_UniformConstant_6 UniformConstant
|
||||||
|
%9 = OpTypeSampler
|
||||||
|
%_ptr_UniformConstant_9 = OpTypePointer UniformConstant %9
|
||||||
|
%s = OpVariable %_ptr_UniformConstant_9 UniformConstant
|
||||||
|
%void = OpTypeVoid
|
||||||
|
%10 = OpTypeFunction %void %float
|
||||||
|
%15 = OpConstantNull %float
|
||||||
|
%bool = OpTypeBool
|
||||||
|
%20 = OpTypeFunction %void
|
||||||
|
%main_inner = OpFunction %void None %10
|
||||||
|
%x = OpFunctionParameter %float
|
||||||
|
%14 = OpLabel
|
||||||
|
%16 = OpFOrdGreaterThan %bool %x %15
|
||||||
|
OpSelectionMerge %18 None
|
||||||
|
OpBranchConditional %16 %19 %18
|
||||||
|
%19 = OpLabel
|
||||||
|
OpBranch %18
|
||||||
|
%18 = OpLabel
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
%main = OpFunction %void None %20
|
||||||
|
%22 = OpLabel
|
||||||
|
%24 = OpLoad %float %x_1
|
||||||
|
%23 = OpFunctionCall %void %main_inner %24
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
|
@ -0,0 +1,22 @@
|
||||||
|
diagnostic_filtering/if_body_attribute.wgsl:7:9 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/if_body_attribute.wgsl:6:3 note: control flow depends on possibly non-uniform value
|
||||||
|
if (x > 0) @diagnostic(warning, derivative_uniformity) {
|
||||||
|
^^
|
||||||
|
|
||||||
|
diagnostic_filtering/if_body_attribute.wgsl:6:7 note: user-defined input 'x' of 'main' may be non-uniform
|
||||||
|
if (x > 0) @diagnostic(warning, derivative_uniformity) {
|
||||||
|
^
|
||||||
|
|
||||||
|
@group(0) @binding(1) var t : texture_2d<f32>;
|
||||||
|
|
||||||
|
@group(0) @binding(2) var s : sampler;
|
||||||
|
|
||||||
|
@fragment
|
||||||
|
fn main(@location(0) x : f32) {
|
||||||
|
if ((x > 0)) @diagnostic(warning, derivative_uniformity) {
|
||||||
|
_ = textureSample(t, s, vec2(0, 0));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
@group(0) @binding(1) var t : texture_2d<f32>;
|
||||||
|
@group(0) @binding(2) var s : sampler;
|
||||||
|
|
||||||
|
@fragment
|
||||||
|
fn main(@location(0) x : f32) {
|
||||||
|
var v = vec4<f32>(0);
|
||||||
|
while (x > v.x) @diagnostic(warning, derivative_uniformity) {
|
||||||
|
v = textureSample(t, s, vec2(0, 0));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
diagnostic_filtering/while_loop_body_attribute.wgsl:8:9 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
v = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/while_loop_body_attribute.wgsl:7:3 note: control flow depends on possibly non-uniform value
|
||||||
|
while (x > v.x) @diagnostic(warning, derivative_uniformity) {
|
||||||
|
^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/while_loop_body_attribute.wgsl:8:9 note: return value of 'textureSample' may be non-uniform
|
||||||
|
v = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Texture2D<float4> t : register(t1, space0);
|
||||||
|
SamplerState s : register(s2, space0);
|
||||||
|
|
||||||
|
struct tint_symbol_1 {
|
||||||
|
float x : TEXCOORD0;
|
||||||
|
};
|
||||||
|
|
||||||
|
void main_inner(float x) {
|
||||||
|
float4 v = (0.0f).xxxx;
|
||||||
|
while((x > v.x)) {
|
||||||
|
v = t.Sample(s, (0.0f).xx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main(tint_symbol_1 tint_symbol) {
|
||||||
|
main_inner(tint_symbol.x);
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
SKIP: FXC rejects non-uniform texture sample operation in output
|
||||||
|
|
||||||
|
diagnostic_filtering/while_loop_body_attribute.wgsl:8:9 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
v = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/while_loop_body_attribute.wgsl:7:3 note: control flow depends on possibly non-uniform value
|
||||||
|
while (x > v.x) @diagnostic(warning, derivative_uniformity) {
|
||||||
|
^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/while_loop_body_attribute.wgsl:8:9 note: return value of 'textureSample' may be non-uniform
|
||||||
|
v = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Texture2D<float4> t : register(t1, space0);
|
||||||
|
SamplerState s : register(s2, space0);
|
||||||
|
|
||||||
|
struct tint_symbol_1 {
|
||||||
|
float x : TEXCOORD0;
|
||||||
|
};
|
||||||
|
|
||||||
|
void main_inner(float x) {
|
||||||
|
float4 v = (0.0f).xxxx;
|
||||||
|
while((x > v.x)) {
|
||||||
|
v = t.Sample(s, (0.0f).xx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main(tint_symbol_1 tint_symbol) {
|
||||||
|
main_inner(tint_symbol.x);
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
diagnostic_filtering/while_loop_body_attribute.wgsl:8:9 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
v = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/while_loop_body_attribute.wgsl:7:3 note: control flow depends on possibly non-uniform value
|
||||||
|
while (x > v.x) @diagnostic(warning, derivative_uniformity) {
|
||||||
|
^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/while_loop_body_attribute.wgsl:8:9 note: return value of 'textureSample' may be non-uniform
|
||||||
|
v = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
#version 310 es
|
||||||
|
precision mediump float;
|
||||||
|
|
||||||
|
layout(location = 0) in float x_1;
|
||||||
|
uniform highp sampler2D t_s;
|
||||||
|
|
||||||
|
void tint_symbol(float x) {
|
||||||
|
vec4 v = vec4(0.0f);
|
||||||
|
while((x > v.x)) {
|
||||||
|
v = texture(t_s, vec2(0.0f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
tint_symbol(x_1);
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
diagnostic_filtering/while_loop_body_attribute.wgsl:8:9 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
v = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/while_loop_body_attribute.wgsl:7:3 note: control flow depends on possibly non-uniform value
|
||||||
|
while (x > v.x) @diagnostic(warning, derivative_uniformity) {
|
||||||
|
^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/while_loop_body_attribute.wgsl:8:9 note: return value of 'textureSample' may be non-uniform
|
||||||
|
v = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
#include <metal_stdlib>
|
||||||
|
|
||||||
|
using namespace metal;
|
||||||
|
struct tint_symbol_2 {
|
||||||
|
float x [[user(locn0)]];
|
||||||
|
};
|
||||||
|
|
||||||
|
void tint_symbol_inner(float x, texture2d<float, access::sample> tint_symbol_3, sampler tint_symbol_4) {
|
||||||
|
float4 v = float4(0.0f);
|
||||||
|
while((x > v[0])) {
|
||||||
|
v = tint_symbol_3.sample(tint_symbol_4, float2(0.0f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fragment void tint_symbol(texture2d<float, access::sample> tint_symbol_5 [[texture(0)]], sampler tint_symbol_6 [[sampler(0)]], tint_symbol_2 tint_symbol_1 [[stage_in]]) {
|
||||||
|
tint_symbol_inner(tint_symbol_1.x, tint_symbol_5, tint_symbol_6);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,91 @@
|
||||||
|
diagnostic_filtering/while_loop_body_attribute.wgsl:8:9 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
v = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/while_loop_body_attribute.wgsl:7:3 note: control flow depends on possibly non-uniform value
|
||||||
|
while (x > v.x) @diagnostic(warning, derivative_uniformity) {
|
||||||
|
^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/while_loop_body_attribute.wgsl:8:9 note: return value of 'textureSample' may be non-uniform
|
||||||
|
v = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
; SPIR-V
|
||||||
|
; Version: 1.3
|
||||||
|
; Generator: Google Tint Compiler; 0
|
||||||
|
; Bound: 45
|
||||||
|
; Schema: 0
|
||||||
|
OpCapability Shader
|
||||||
|
OpMemoryModel Logical GLSL450
|
||||||
|
OpEntryPoint Fragment %main "main" %x_1
|
||||||
|
OpExecutionMode %main OriginUpperLeft
|
||||||
|
OpName %x_1 "x_1"
|
||||||
|
OpName %t "t"
|
||||||
|
OpName %s "s"
|
||||||
|
OpName %main_inner "main_inner"
|
||||||
|
OpName %x "x"
|
||||||
|
OpName %v "v"
|
||||||
|
OpName %main "main"
|
||||||
|
OpDecorate %x_1 Location 0
|
||||||
|
OpDecorate %t DescriptorSet 0
|
||||||
|
OpDecorate %t Binding 1
|
||||||
|
OpDecorate %s DescriptorSet 0
|
||||||
|
OpDecorate %s Binding 2
|
||||||
|
%float = OpTypeFloat 32
|
||||||
|
%_ptr_Input_float = OpTypePointer Input %float
|
||||||
|
%x_1 = OpVariable %_ptr_Input_float Input
|
||||||
|
%6 = OpTypeImage %float 2D 0 0 0 1 Unknown
|
||||||
|
%_ptr_UniformConstant_6 = OpTypePointer UniformConstant %6
|
||||||
|
%t = OpVariable %_ptr_UniformConstant_6 UniformConstant
|
||||||
|
%9 = OpTypeSampler
|
||||||
|
%_ptr_UniformConstant_9 = OpTypePointer UniformConstant %9
|
||||||
|
%s = OpVariable %_ptr_UniformConstant_9 UniformConstant
|
||||||
|
%void = OpTypeVoid
|
||||||
|
%10 = OpTypeFunction %void %float
|
||||||
|
%v4float = OpTypeVector %float 4
|
||||||
|
%16 = OpConstantNull %v4float
|
||||||
|
%_ptr_Function_v4float = OpTypePointer Function %v4float
|
||||||
|
%uint = OpTypeInt 32 0
|
||||||
|
%uint_0 = OpConstant %uint 0
|
||||||
|
%_ptr_Function_float = OpTypePointer Function %float
|
||||||
|
%bool = OpTypeBool
|
||||||
|
%36 = OpTypeSampledImage %6
|
||||||
|
%v2float = OpTypeVector %float 2
|
||||||
|
%39 = OpConstantNull %v2float
|
||||||
|
%40 = OpTypeFunction %void
|
||||||
|
%main_inner = OpFunction %void None %10
|
||||||
|
%x = OpFunctionParameter %float
|
||||||
|
%14 = OpLabel
|
||||||
|
%v = OpVariable %_ptr_Function_v4float Function %16
|
||||||
|
OpStore %v %16
|
||||||
|
OpBranch %19
|
||||||
|
%19 = OpLabel
|
||||||
|
OpLoopMerge %20 %21 None
|
||||||
|
OpBranch %22
|
||||||
|
%22 = OpLabel
|
||||||
|
%27 = OpAccessChain %_ptr_Function_float %v %uint_0
|
||||||
|
%28 = OpLoad %float %27
|
||||||
|
%29 = OpFOrdGreaterThan %bool %x %28
|
||||||
|
%23 = OpLogicalNot %bool %29
|
||||||
|
OpSelectionMerge %31 None
|
||||||
|
OpBranchConditional %23 %32 %31
|
||||||
|
%32 = OpLabel
|
||||||
|
OpBranch %20
|
||||||
|
%31 = OpLabel
|
||||||
|
%34 = OpLoad %9 %s
|
||||||
|
%35 = OpLoad %6 %t
|
||||||
|
%37 = OpSampledImage %36 %35 %34
|
||||||
|
%33 = OpImageSampleImplicitLod %v4float %37 %39
|
||||||
|
OpStore %v %33
|
||||||
|
OpBranch %21
|
||||||
|
%21 = OpLabel
|
||||||
|
OpBranch %19
|
||||||
|
%20 = OpLabel
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
%main = OpFunction %void None %40
|
||||||
|
%42 = OpLabel
|
||||||
|
%44 = OpLoad %float %x_1
|
||||||
|
%43 = OpFunctionCall %void %main_inner %44
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
|
@ -0,0 +1,23 @@
|
||||||
|
diagnostic_filtering/while_loop_body_attribute.wgsl:8:9 warning: 'textureSample' must only be called from uniform control flow
|
||||||
|
v = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/while_loop_body_attribute.wgsl:7:3 note: control flow depends on possibly non-uniform value
|
||||||
|
while (x > v.x) @diagnostic(warning, derivative_uniformity) {
|
||||||
|
^^^^^
|
||||||
|
|
||||||
|
diagnostic_filtering/while_loop_body_attribute.wgsl:8:9 note: return value of 'textureSample' may be non-uniform
|
||||||
|
v = textureSample(t, s, vec2(0, 0));
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
@group(0) @binding(1) var t : texture_2d<f32>;
|
||||||
|
|
||||||
|
@group(0) @binding(2) var s : sampler;
|
||||||
|
|
||||||
|
@fragment
|
||||||
|
fn main(@location(0) x : f32) {
|
||||||
|
var v = vec4<f32>(0);
|
||||||
|
while((x > v.x)) @diagnostic(warning, derivative_uniformity) {
|
||||||
|
v = textureSample(t, s, vec2(0, 0));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue