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,
|
||||
NodeID nid,
|
||||
const Source& src,
|
||||
utils::VectorRef<const Statement*> stmts)
|
||||
: Base(pid, nid, src), statements(std::move(stmts)) {
|
||||
utils::VectorRef<const Statement*> stmts,
|
||||
utils::VectorRef<const Attribute*> attrs)
|
||||
: Base(pid, nid, src), statements(std::move(stmts)), attributes(attrs) {
|
||||
for (auto* stmt : statements) {
|
||||
TINT_ASSERT(AST, stmt);
|
||||
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;
|
||||
|
@ -39,7 +44,8 @@ const BlockStatement* BlockStatement::Clone(CloneContext* ctx) const {
|
|||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
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
|
||||
|
|
|
@ -19,6 +19,11 @@
|
|||
|
||||
#include "src/tint/ast/statement.h"
|
||||
|
||||
// Forward declarations
|
||||
namespace tint::ast {
|
||||
class Attribute;
|
||||
} // namespace tint::ast
|
||||
|
||||
namespace tint::ast {
|
||||
|
||||
/// A block statement
|
||||
|
@ -29,10 +34,12 @@ class BlockStatement final : public Castable<BlockStatement, Statement> {
|
|||
/// @param nid the unique node identifier
|
||||
/// @param source the block statement source
|
||||
/// @param statements the statements
|
||||
/// @param attributes the block statement attributes
|
||||
BlockStatement(ProgramID pid,
|
||||
NodeID nid,
|
||||
const Source& source,
|
||||
utils::VectorRef<const Statement*> statements);
|
||||
utils::VectorRef<const Statement*> statements,
|
||||
utils::VectorRef<const Attribute*> attributes);
|
||||
/// Move constructor
|
||||
BlockStatement(BlockStatement&&);
|
||||
~BlockStatement() override;
|
||||
|
@ -51,6 +58,9 @@ class BlockStatement final : public Castable<BlockStatement, Statement> {
|
|||
|
||||
/// the statement list
|
||||
const utils::Vector<const Statement*, 8> statements;
|
||||
|
||||
/// the attribute list
|
||||
const utils::Vector<const Attribute*, 4> attributes;
|
||||
};
|
||||
|
||||
} // namespace tint::ast
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest-spi.h"
|
||||
#include "src/tint/ast/discard_statement.h"
|
||||
#include "src/tint/ast/if_statement.h"
|
||||
|
@ -26,21 +27,35 @@ TEST_F(BlockStatementTest, Creation) {
|
|||
auto* d = create<DiscardStatement>();
|
||||
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);
|
||||
EXPECT_EQ(b->statements[0], ptr);
|
||||
EXPECT_EQ(b->attributes.Length(), 0u);
|
||||
}
|
||||
|
||||
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;
|
||||
EXPECT_EQ(src.range.begin.line, 20u);
|
||||
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) {
|
||||
auto* b = create<BlockStatement>(utils::Empty);
|
||||
auto* b = create<BlockStatement>(utils::Empty, utils::Empty);
|
||||
EXPECT_TRUE(b->Is<BlockStatement>());
|
||||
}
|
||||
|
||||
|
@ -48,7 +63,8 @@ TEST_F(BlockStatementTest, Assert_Null_Statement) {
|
|||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
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");
|
||||
}
|
||||
|
@ -58,7 +74,7 @@ TEST_F(BlockStatementTest, Assert_DifferentProgramID_Statement) {
|
|||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.create<BlockStatement>(utils::Vector{b2.create<DiscardStatement>()});
|
||||
b1.create<BlockStatement>(utils::Vector{b2.create<DiscardStatement>()}, utils::Empty);
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ TEST_F(CaseStatementTest, Creation_i32) {
|
|||
utils::Vector b{selector};
|
||||
|
||||
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);
|
||||
ASSERT_EQ(c->selectors.Length(), 1u);
|
||||
|
@ -45,7 +45,7 @@ TEST_F(CaseStatementTest, Creation_u32) {
|
|||
utils::Vector b{selector};
|
||||
|
||||
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);
|
||||
ASSERT_EQ(c->selectors.Length(), 1u);
|
||||
|
@ -56,22 +56,24 @@ TEST_F(CaseStatementTest, Creation_u32) {
|
|||
|
||||
TEST_F(CaseStatementTest, ContainsDefault_WithDefault) {
|
||||
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());
|
||||
}
|
||||
|
||||
TEST_F(CaseStatementTest, ContainsDefault_WithOutDefault) {
|
||||
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());
|
||||
}
|
||||
|
||||
TEST_F(CaseStatementTest, Creation_WithSource) {
|
||||
utils::Vector b{CaseSelector(2_i)};
|
||||
|
||||
auto* body = create<BlockStatement>(utils::Vector{
|
||||
create<DiscardStatement>(),
|
||||
});
|
||||
auto* body = create<BlockStatement>(
|
||||
utils::Vector{
|
||||
create<DiscardStatement>(),
|
||||
},
|
||||
utils::Empty);
|
||||
auto* c = create<CaseStatement>(Source{Source::Location{20, 2}}, b, body);
|
||||
auto src = c->source;
|
||||
EXPECT_EQ(src.range.begin.line, 20u);
|
||||
|
@ -80,7 +82,7 @@ TEST_F(CaseStatementTest, Creation_WithSource) {
|
|||
|
||||
TEST_F(CaseStatementTest, IsCase) {
|
||||
auto* c = create<CaseStatement>(utils::Vector{DefaultCaseSelector()},
|
||||
create<BlockStatement>(utils::Empty));
|
||||
create<BlockStatement>(utils::Empty, utils::Empty));
|
||||
EXPECT_TRUE(c->Is<CaseStatement>());
|
||||
}
|
||||
|
||||
|
@ -98,7 +100,7 @@ TEST_F(CaseStatementTest, Assert_Null_Selector) {
|
|||
{
|
||||
ProgramBuilder b;
|
||||
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");
|
||||
}
|
||||
|
@ -109,7 +111,7 @@ TEST_F(CaseStatementTest, Assert_DifferentProgramID_Call) {
|
|||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.create<CaseStatement>(utils::Vector{b1.DefaultCaseSelector()},
|
||||
b2.create<BlockStatement>(utils::Empty));
|
||||
b2.create<BlockStatement>(utils::Empty, utils::Empty));
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
@ -120,7 +122,7 @@ TEST_F(CaseStatementTest, Assert_DifferentProgramID_Selector) {
|
|||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
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");
|
||||
}
|
||||
|
|
|
@ -2456,7 +2456,8 @@ class ProgramBuilder {
|
|||
/// @param type the function return type
|
||||
/// @param body the function body
|
||||
/// @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
|
||||
/// @returns the function pointer
|
||||
template <typename NAME>
|
||||
|
@ -2467,11 +2468,12 @@ class ProgramBuilder {
|
|||
const ast::Type* type,
|
||||
utils::VectorRef<const ast::Statement*> body,
|
||||
utils::VectorRef<const ast::Attribute*> attributes = utils::Empty,
|
||||
utils::VectorRef<const ast::Attribute*> return_type_attributes = utils::Empty) {
|
||||
auto* func =
|
||||
create<ast::Function>(source, Sym(std::forward<NAME>(name)), std::move(params), type,
|
||||
create<ast::BlockStatement>(std::move(body)),
|
||||
std::move(attributes), std::move(return_type_attributes));
|
||||
utils::VectorRef<const ast::Attribute*> return_type_attributes = utils::Empty,
|
||||
utils::VectorRef<const ast::Attribute*> body_attributes = utils::Empty) {
|
||||
auto* func = create<ast::Function>(
|
||||
source, Sym(std::forward<NAME>(name)), std::move(params), type,
|
||||
create<ast::BlockStatement>(std::move(body), std::move(body_attributes)),
|
||||
std::move(attributes), std::move(return_type_attributes));
|
||||
AST().AddFunction(func);
|
||||
return func;
|
||||
}
|
||||
|
@ -2482,7 +2484,8 @@ class ProgramBuilder {
|
|||
/// @param type the function return type
|
||||
/// @param body the function body
|
||||
/// @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
|
||||
/// @returns the function pointer
|
||||
template <typename NAME>
|
||||
|
@ -2492,11 +2495,12 @@ class ProgramBuilder {
|
|||
const ast::Type* type,
|
||||
utils::VectorRef<const ast::Statement*> body,
|
||||
utils::VectorRef<const ast::Attribute*> attributes = utils::Empty,
|
||||
utils::VectorRef<const ast::Attribute*> return_type_attributes = utils::Empty) {
|
||||
auto* func =
|
||||
create<ast::Function>(Sym(std::forward<NAME>(name)), std::move(params), type,
|
||||
create<ast::BlockStatement>(std::move(body)),
|
||||
std::move(attributes), std::move(return_type_attributes));
|
||||
utils::VectorRef<const ast::Attribute*> return_type_attributes = utils::Empty,
|
||||
utils::VectorRef<const ast::Attribute*> body_attributes = utils::Empty) {
|
||||
auto* func = create<ast::Function>(
|
||||
Sym(std::forward<NAME>(name)), std::move(params), type,
|
||||
create<ast::BlockStatement>(std::move(body), std::move(body_attributes)),
|
||||
std::move(attributes), std::move(return_type_attributes));
|
||||
AST().AddFunction(func);
|
||||
return func;
|
||||
}
|
||||
|
@ -2676,23 +2680,50 @@ class ProgramBuilder {
|
|||
/// @param source the source information for the block
|
||||
/// @param statements statements of block
|
||||
/// @returns the block statement pointer
|
||||
template <typename... Statements>
|
||||
const ast::BlockStatement* Block(const Source& source, Statements&&... statements) {
|
||||
template <typename... STATEMENTS, typename = DisableIfVectorLike<STATEMENTS...>>
|
||||
const ast::BlockStatement* Block(const Source& source, STATEMENTS&&... statements) {
|
||||
return create<ast::BlockStatement>(
|
||||
source, utils::Vector<const ast::Statement*, sizeof...(statements)>{
|
||||
std::forward<Statements>(statements)...,
|
||||
});
|
||||
source,
|
||||
utils::Vector<const ast::Statement*, sizeof...(statements)>{
|
||||
std::forward<STATEMENTS>(statements)...,
|
||||
},
|
||||
utils::Empty);
|
||||
}
|
||||
|
||||
/// Creates a ast::BlockStatement with input statements
|
||||
/// @param statements statements of block
|
||||
/// @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) {
|
||||
return create<ast::BlockStatement>(
|
||||
utils::Vector<const ast::Statement*, sizeof...(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.
|
||||
|
|
|
@ -882,7 +882,7 @@ void FunctionEmitter::PushGuard(const std::string& guard_name, uint32_t end_id)
|
|||
auto* builder = AddStatementBuilder<IfStatementBuilder>(cond);
|
||||
|
||||
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);
|
||||
|
||||
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_);
|
||||
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.
|
||||
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;
|
||||
fn_attrs.Push(create<ast::StageAttribute>(source, ep_info_->stage));
|
||||
|
||||
|
@ -2938,7 +2938,7 @@ bool FunctionEmitter::EmitIfStart(const BlockInfo& block_info) {
|
|||
if (!stmts.IsEmpty()) {
|
||||
// The "else" consists of the statement list from the top of
|
||||
// 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) {
|
||||
|
@ -2985,7 +2985,7 @@ bool FunctionEmitter::EmitIfStart(const BlockInfo& block_info) {
|
|||
|
||||
// Push the then clause onto the stack.
|
||||
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) {
|
||||
AddStatement(create<ast::BreakStatement>(Source{}));
|
||||
|
@ -3098,7 +3098,7 @@ bool FunctionEmitter::EmitSwitchStart(const BlockInfo& block_info) {
|
|||
auto case_idx = swch->cases.Length();
|
||||
swch->cases.Push(nullptr);
|
||||
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);
|
||||
});
|
||||
|
||||
|
@ -3113,7 +3113,7 @@ bool FunctionEmitter::EmitSwitchStart(const BlockInfo& block_info) {
|
|||
bool FunctionEmitter::EmitLoopStart(const Construct* construct) {
|
||||
auto* builder = AddStatementBuilder<LoopStatementBuilder>();
|
||||
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();
|
||||
}
|
||||
|
@ -3128,7 +3128,7 @@ bool FunctionEmitter::EmitContinuingStart(const Construct* construct) {
|
|||
"expected loop on top of stack";
|
||||
}
|
||||
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();
|
||||
|
@ -3354,11 +3354,11 @@ const ast::Statement* FunctionEmitter::MakeSimpleIf(const ast::Expression* condi
|
|||
if (then_stmt != nullptr) {
|
||||
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;
|
||||
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);
|
||||
|
|
|
@ -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
|
||||
// catches any errors inside the body, and can help keep the parser in
|
||||
// sync.
|
||||
expect_compound_statement();
|
||||
expect_compound_statement("function body");
|
||||
}
|
||||
return Failure::kErrored;
|
||||
}
|
||||
|
@ -1510,7 +1510,7 @@ Maybe<const ast::Function*> ParserImpl::function_decl(AttributeList& attrs) {
|
|||
|
||||
bool errored = false;
|
||||
|
||||
auto body = expect_compound_statement();
|
||||
auto body = expect_compound_statement("function body");
|
||||
if (body.errored) {
|
||||
errored = true;
|
||||
}
|
||||
|
@ -1666,14 +1666,26 @@ Expect<ast::BuiltinValue> ParserImpl::expect_builtin() {
|
|||
}
|
||||
|
||||
// compound_statement
|
||||
// : BRACE_LEFT statement* BRACE_RIGHT
|
||||
Expect<ast::BlockStatement*> ParserImpl::expect_compound_statement() {
|
||||
return expect_brace_block("", [&]() -> Expect<ast::BlockStatement*> {
|
||||
// : attribute* BRACE_LEFT statement* BRACE_RIGHT
|
||||
Expect<ast::BlockStatement*> ParserImpl::expect_compound_statement(std::string_view use) {
|
||||
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();
|
||||
if (stmts.errored) {
|
||||
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
|
||||
}
|
||||
|
||||
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.
|
||||
auto stmt = sync(Token::Type::kSemicolon, [&] { return non_block_statement(); });
|
||||
if (stmt.errored) {
|
||||
|
@ -1781,7 +1799,7 @@ Maybe<const ast::Statement*> ParserImpl::statement() {
|
|||
}
|
||||
|
||||
if (peek_is(Token::Type::kBraceLeft)) {
|
||||
auto body = expect_compound_statement();
|
||||
auto body = expect_compound_statement(attrs.value, "block statement");
|
||||
if (body.errored) {
|
||||
return Failure::kErrored;
|
||||
}
|
||||
|
@ -2023,7 +2041,7 @@ Maybe<const ast::IfStatement*> ParserImpl::if_statement() {
|
|||
return add_error(peek(), "unable to parse condition expression");
|
||||
}
|
||||
|
||||
auto body = expect_compound_statement();
|
||||
auto body = expect_compound_statement("if statement");
|
||||
if (body.errored) {
|
||||
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".
|
||||
auto else_body = expect_compound_statement();
|
||||
auto else_body = expect_compound_statement("else statement");
|
||||
if (else_body.errored) {
|
||||
return Failure::kErrored;
|
||||
}
|
||||
|
@ -2119,8 +2137,8 @@ Maybe<const ast::SwitchStatement*> ParserImpl::switch_statement() {
|
|||
}
|
||||
|
||||
// switch_body
|
||||
// : CASE case_selectors COLON? BRACKET_LEFT case_body BRACKET_RIGHT
|
||||
// | DEFAULT COLON? BRACKET_LEFT case_body BRACKET_RIGHT
|
||||
// : CASE case_selectors COLON? compound_statement
|
||||
// | DEFAULT COLON? compound_statement
|
||||
Maybe<const ast::CaseStatement*> ParserImpl::switch_body() {
|
||||
if (!peek_is(Token::Type::kCase) && !peek_is(Token::Type::kDefault)) {
|
||||
return Failure::kNoMatch;
|
||||
|
@ -2145,14 +2163,10 @@ Maybe<const ast::CaseStatement*> ParserImpl::switch_body() {
|
|||
match(Token::Type::kColon);
|
||||
|
||||
const char* use = "case statement";
|
||||
auto body = expect_brace_block(use, [&] { return case_body(); });
|
||||
|
||||
auto body = expect_compound_statement(use);
|
||||
if (body.errored) {
|
||||
return Failure::kErrored;
|
||||
}
|
||||
if (!body.matched) {
|
||||
return add_error(body.source, "expected case body");
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
return create<ast::BlockStatement>(Source{}, stmts);
|
||||
return create<ast::BlockStatement>(Source{}, stmts, utils::Empty);
|
||||
}
|
||||
|
||||
// loop_statement
|
||||
|
@ -2253,7 +2267,7 @@ Maybe<const ast::LoopStatement*> ParserImpl::loop_statement() {
|
|||
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);
|
||||
});
|
||||
}
|
||||
|
@ -2345,7 +2359,7 @@ Expect<std::unique_ptr<ForHeader>> ParserImpl::expect_for_header() {
|
|||
}
|
||||
|
||||
// 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() {
|
||||
Source source;
|
||||
if (!match(Token::Type::kFor, &source)) {
|
||||
|
@ -2357,14 +2371,13 @@ Maybe<const ast::ForLoopStatement*> ParserImpl::for_statement() {
|
|||
return Failure::kErrored;
|
||||
}
|
||||
|
||||
auto stmts = expect_brace_block("for loop", [&] { return expect_statements(); });
|
||||
if (stmts.errored) {
|
||||
auto body = expect_compound_statement("for loop");
|
||||
if (body.errored) {
|
||||
return Failure::kErrored;
|
||||
}
|
||||
|
||||
return create<ast::ForLoopStatement>(source, header->initializer, header->condition,
|
||||
header->continuing,
|
||||
create<ast::BlockStatement>(stmts.value));
|
||||
header->continuing, body.value);
|
||||
}
|
||||
|
||||
// while_statement
|
||||
|
@ -2383,7 +2396,7 @@ Maybe<const ast::WhileStatement*> ParserImpl::while_statement() {
|
|||
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) {
|
||||
return Failure::kErrored;
|
||||
}
|
||||
|
@ -2491,7 +2504,7 @@ Maybe<const ast::BlockStatement*> ParserImpl::continuing_compound_statement() {
|
|||
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
|
||||
Maybe<const ast::BlockStatement*> ParserImpl::continuing_statement() {
|
||||
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();
|
||||
|
|
|
@ -542,8 +542,15 @@ class ParserImpl {
|
|||
/// @returns the parsed builtin.
|
||||
Expect<ast::BuiltinValue> expect_builtin();
|
||||
/// 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
|
||||
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.
|
||||
/// @returns the parsed element or nullptr
|
||||
Expect<const ast::Expression*> expect_paren_expression();
|
||||
|
|
|
@ -23,7 +23,7 @@ TEST_F(ParserImplTest, CompoundStmt) {
|
|||
discard;
|
||||
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(e.errored);
|
||||
ASSERT_EQ(e->statements.Length(), 2u);
|
||||
|
@ -33,7 +33,7 @@ TEST_F(ParserImplTest, CompoundStmt) {
|
|||
|
||||
TEST_F(ParserImplTest, CompoundStmt_Empty) {
|
||||
auto p = parser("{}");
|
||||
auto e = p->expect_compound_statement();
|
||||
auto e = p->expect_compound_statement("");
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_FALSE(e.errored);
|
||||
EXPECT_EQ(e->statements.Length(), 0u);
|
||||
|
@ -41,7 +41,7 @@ TEST_F(ParserImplTest, CompoundStmt_Empty) {
|
|||
|
||||
TEST_F(ParserImplTest, CompoundStmt_InvalidStmt) {
|
||||
auto p = parser("{fn main() {}}");
|
||||
auto e = p->expect_compound_statement();
|
||||
auto e = p->expect_compound_statement("");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_TRUE(e.errored);
|
||||
EXPECT_EQ(p->error(), "1:2: expected '}'");
|
||||
|
@ -49,7 +49,7 @@ TEST_F(ParserImplTest, CompoundStmt_InvalidStmt) {
|
|||
|
||||
TEST_F(ParserImplTest, CompoundStmt_MissingRightParen) {
|
||||
auto p = parser("{return;");
|
||||
auto e = p->expect_compound_statement();
|
||||
auto e = p->expect_compound_statement("");
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_TRUE(e.errored);
|
||||
EXPECT_EQ(p->error(), "1:9: expected '}'");
|
||||
|
|
|
@ -489,7 +489,7 @@ fn f( {}
|
|||
}
|
||||
|
||||
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 {}
|
||||
^^^
|
||||
)");
|
||||
|
@ -526,14 +526,14 @@ fn f(x : i32, ,) {}
|
|||
}
|
||||
|
||||
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() }
|
||||
^
|
||||
)");
|
||||
}
|
||||
|
||||
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() {
|
||||
^
|
||||
)");
|
||||
|
@ -541,9 +541,9 @@ fn f() {
|
|||
|
||||
TEST_F(ParserImplErrorTest, FunctionScopeUnusedDecl) {
|
||||
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)}
|
||||
^
|
||||
^^^^
|
||||
)");
|
||||
}
|
||||
|
||||
|
|
|
@ -305,7 +305,7 @@ TEST_F(ParserImplTest, FunctionDecl_MissingLeftBrace) {
|
|||
EXPECT_FALSE(f.matched);
|
||||
EXPECT_TRUE(p->has_error());
|
||||
EXPECT_EQ(f.value, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:11: expected '{'");
|
||||
EXPECT_EQ(p->error(), "1:11: expected '{' for function body");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -85,7 +85,7 @@ TEST_F(ParserImplTest, IfStmt_InvalidCondition) {
|
|||
EXPECT_TRUE(e.errored);
|
||||
EXPECT_EQ(e.value, nullptr);
|
||||
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) {
|
||||
|
@ -105,7 +105,7 @@ TEST_F(ParserImplTest, IfStmt_InvalidBody) {
|
|||
EXPECT_TRUE(e.errored);
|
||||
EXPECT_EQ(e.value, nullptr);
|
||||
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) {
|
||||
|
@ -115,7 +115,7 @@ TEST_F(ParserImplTest, IfStmt_MissingBody) {
|
|||
EXPECT_TRUE(e.errored);
|
||||
EXPECT_EQ(e.value, nullptr);
|
||||
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) {
|
||||
|
@ -125,7 +125,7 @@ TEST_F(ParserImplTest, IfStmt_InvalidElseif) {
|
|||
EXPECT_TRUE(e.errored);
|
||||
EXPECT_EQ(e.value, nullptr);
|
||||
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) {
|
||||
|
@ -135,7 +135,7 @@ TEST_F(ParserImplTest, IfStmt_InvalidElse) {
|
|||
EXPECT_TRUE(e.errored);
|
||||
EXPECT_EQ(e.value, nullptr);
|
||||
EXPECT_TRUE(p->has_error());
|
||||
EXPECT_EQ(p->error(), "1:16: expected '}'");
|
||||
EXPECT_EQ(p->error(), "1:16: expected '}' for else statement");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -95,7 +95,7 @@ TEST_F(ParserImplTest, Statement_If_Invalid) {
|
|||
EXPECT_TRUE(e.errored);
|
||||
EXPECT_FALSE(e.matched);
|
||||
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) {
|
||||
|
@ -269,7 +269,7 @@ TEST_F(ParserImplTest, Statement_Body_Invalid) {
|
|||
EXPECT_TRUE(e.errored);
|
||||
EXPECT_FALSE(e.matched);
|
||||
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) {
|
||||
|
@ -358,5 +358,15 @@ TEST_F(ParserImplTest, DEPRECATED_Statement_StaticAssert_WithoutParen) {
|
|||
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 tint::reader::wgsl
|
||||
|
|
|
@ -118,7 +118,7 @@ TEST_F(WhileStmtErrorTest, MissingRightParen) {
|
|||
// Test a while loop with missing left brace is invalid.
|
||||
TEST_F(WhileStmtErrorTest, MissingLeftBrace) {
|
||||
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);
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ TEST_F(WhileStmtErrorTest, MissingLeftBrace) {
|
|||
// Test a for loop with missing right brace is invalid.
|
||||
TEST_F(WhileStmtErrorTest, MissingRightBrace) {
|
||||
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);
|
||||
}
|
||||
|
@ -159,7 +159,7 @@ TEST_F(WhileStmtErrorTest, InvalidBody) {
|
|||
// Test a for loop with a body not matching statements
|
||||
TEST_F(WhileStmtErrorTest, InvalidBodyMatch) {
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -1030,6 +1030,104 @@ TEST_F(OverrideAttributeTest, DuplicateAttribute) {
|
|||
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 AttributeTests
|
||||
|
||||
|
|
|
@ -181,6 +181,66 @@ TEST_F(ResolverDiagnosticControlTest, FunctionAttributeScope) {
|
|||
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) {
|
||||
DiagnosticDirective(ast::DiagnosticSeverity::kError,
|
||||
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);
|
||||
|
||||
// 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_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,
|
||||
UniformityAnalysisDiagnosticFilterTest,
|
||||
::testing::Values(ast::DiagnosticSeverity::kError,
|
||||
|
|
|
@ -30,26 +30,44 @@ class DiagnosticSeverityTest : public TestHelper {
|
|||
void Run(ast::DiagnosticSeverity global_severity) {
|
||||
// @diagnostic(off, chromium_unreachable_code)
|
||||
// fn foo() {
|
||||
// return;
|
||||
// @diagnostic(info, chromium_unreachable_code) {
|
||||
// if (true) @diagnostic(warning, chromium_unreachable_code) {
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// fn bar() {
|
||||
// return;
|
||||
// {
|
||||
// if (true) {
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
auto rule = ast::DiagnosticRule::kChromiumUnreachableCode;
|
||||
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_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* 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 p = Build();
|
||||
EXPECT_TRUE(p.IsValid()) << p.Diagnostics().str();
|
||||
|
||||
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(return_2, rule), global_severity);
|
||||
}
|
||||
|
|
|
@ -353,7 +353,10 @@ bool GeneratorImpl::EmitFunction(const ast::Function* func) {
|
|||
}
|
||||
|
||||
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) {
|
||||
line() << "{";
|
||||
{
|
||||
auto out = line();
|
||||
if (!EmitBlockHeader(out, stmt)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!EmitStatementsWithIndent(stmt->statements)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -988,6 +996,17 @@ bool GeneratorImpl::EmitBlock(const ast::BlockStatement* stmt) {
|
|||
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) {
|
||||
return Switch(
|
||||
stmt, //
|
||||
|
@ -1072,7 +1091,11 @@ bool GeneratorImpl::EmitBreakIf(const ast::BreakIfStatement* b) {
|
|||
|
||||
bool GeneratorImpl::EmitCase(const ast::CaseStatement* stmt) {
|
||||
if (stmt->selectors.Length() == 1 && stmt->ContainsDefault()) {
|
||||
line() << "default: {";
|
||||
auto out = line();
|
||||
out << "default: ";
|
||||
if (!EmitBlockHeader(out, stmt->body)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
auto out = line();
|
||||
out << "case ";
|
||||
|
@ -1091,7 +1114,10 @@ bool GeneratorImpl::EmitCase(const ast::CaseStatement* stmt) {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
out << ": {";
|
||||
out << ": ";
|
||||
if (!EmitBlockHeader(out, stmt->body)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!EmitStatementsWithIndent(stmt->body->statements)) {
|
||||
return false;
|
||||
|
@ -1135,7 +1161,10 @@ bool GeneratorImpl::EmitIf(const ast::IfStatement* stmt) {
|
|||
if (!EmitExpression(out, stmt->condition)) {
|
||||
return false;
|
||||
}
|
||||
out << ") {";
|
||||
out << ") ";
|
||||
if (!EmitBlockHeader(out, stmt->body)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!EmitStatementsWithIndent(stmt->body->statements)) {
|
||||
|
@ -1151,15 +1180,25 @@ bool GeneratorImpl::EmitIf(const ast::IfStatement* stmt) {
|
|||
if (!EmitExpression(out, elseif->condition)) {
|
||||
return false;
|
||||
}
|
||||
out << ") {";
|
||||
out << ") ";
|
||||
if (!EmitBlockHeader(out, elseif->body)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!EmitStatementsWithIndent(elseif->body->statements)) {
|
||||
return false;
|
||||
}
|
||||
e = elseif->else_statement;
|
||||
} else {
|
||||
line() << "} else {";
|
||||
if (!EmitStatementsWithIndent(e->As<ast::BlockStatement>()->statements)) {
|
||||
auto* body = e->As<ast::BlockStatement>();
|
||||
{
|
||||
auto out = line();
|
||||
out << "} else ";
|
||||
if (!EmitBlockHeader(out, body)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!EmitStatementsWithIndent(body->statements)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
@ -1270,7 +1309,10 @@ bool GeneratorImpl::EmitForLoop(const ast::ForLoopStatement* stmt) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
out << " {";
|
||||
out << " ";
|
||||
if (!EmitBlockHeader(out, stmt->body)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!EmitStatementsWithIndent(stmt->body->statements)) {
|
||||
|
@ -1294,7 +1336,10 @@ bool GeneratorImpl::EmitWhile(const ast::WhileStatement* stmt) {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
out << " {";
|
||||
out << " ";
|
||||
if (!EmitBlockHeader(out, stmt->body)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!EmitStatementsWithIndent(stmt->body->statements)) {
|
||||
|
|
|
@ -93,6 +93,11 @@ class GeneratorImpl : public TextGenerator {
|
|||
/// @param stmt the statement to emit
|
||||
/// @returns true if the statement was emitted successfully
|
||||
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
|
||||
/// @param stmt the statement to emit
|
||||
/// @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