[spirv-reader][ir] Add `OpSpecConstant{True,False}` support.
Adds supports for boolean spec constants.
Bug: 398007970
Change-Id: Ib900c767f308794b10f1daceed02b5cfc7af1798
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/230014
Commit-Queue: James Price <jrprice@google.com>
Auto-Submit: dan sinclair <dsinclair@chromium.org>
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Reviewed-by: James Price <jrprice@google.com>
diff --git a/src/tint/lang/core/ir/transform/remove_terminator_args.h b/src/tint/lang/core/ir/transform/remove_terminator_args.h
index 96a1690..77e06ec 100644
--- a/src/tint/lang/core/ir/transform/remove_terminator_args.h
+++ b/src/tint/lang/core/ir/transform/remove_terminator_args.h
@@ -42,6 +42,7 @@
const core::ir::Capabilities kRemoveTerminatorArgsCapabilities{
core::ir::Capability::kAllow8BitIntegers,
core::ir::Capability::kAllow64BitIntegers,
+ core::ir::Capability::kAllowOverrides,
core::ir::Capability::kAllowPointersAndHandlesInStructures,
core::ir::Capability::kAllowVectorElementPointer,
core::ir::Capability::kAllowHandleVarsWithoutBindings,
diff --git a/src/tint/lang/core/ir/transform/rename_conflicts.h b/src/tint/lang/core/ir/transform/rename_conflicts.h
index 1b608a0..f4b3337 100644
--- a/src/tint/lang/core/ir/transform/rename_conflicts.h
+++ b/src/tint/lang/core/ir/transform/rename_conflicts.h
@@ -42,6 +42,7 @@
const core::ir::Capabilities kRenameConflictsCapabilities{
core::ir::Capability::kAllow8BitIntegers,
core::ir::Capability::kAllow64BitIntegers,
+ core::ir::Capability::kAllowOverrides,
core::ir::Capability::kAllowPointersAndHandlesInStructures,
core::ir::Capability::kAllowVectorElementPointer,
core::ir::Capability::kAllowHandleVarsWithoutBindings,
diff --git a/src/tint/lang/spirv/reader/lower/builtins.cc b/src/tint/lang/spirv/reader/lower/builtins.cc
index 7c1cd54..5fe41de 100644
--- a/src/tint/lang/spirv/reader/lower/builtins.cc
+++ b/src/tint/lang/spirv/reader/lower/builtins.cc
@@ -1099,7 +1099,10 @@
} // namespace
Result<SuccessType> Builtins(core::ir::Module& ir) {
- auto result = ValidateAndDumpIfNeeded(ir, "spirv.Builtins");
+ auto result = ValidateAndDumpIfNeeded(ir, "spirv.Builtins",
+ core::ir::Capabilities{
+ core::ir::Capability::kAllowOverrides,
+ });
if (result != Success) {
return result.Failure();
}
diff --git a/src/tint/lang/spirv/reader/lower/lower.cc b/src/tint/lang/spirv/reader/lower/lower.cc
index 55c1659..86d7241 100644
--- a/src/tint/lang/spirv/reader/lower/lower.cc
+++ b/src/tint/lang/spirv/reader/lower/lower.cc
@@ -56,7 +56,11 @@
// `||` statements.
RUN_TRANSFORM(core::ir::transform::RemoveTerminatorArgs, mod);
- if (auto res = core::ir::ValidateAndDumpIfNeeded(mod, "spirv.Lower"); res != Success) {
+ auto res = core::ir::ValidateAndDumpIfNeeded(mod, "spirv.Lower",
+ core::ir::Capabilities{
+ core::ir::Capability::kAllowOverrides,
+ });
+ if (res != Success) {
return res.Failure();
}
diff --git a/src/tint/lang/spirv/reader/lower/shader_io.cc b/src/tint/lang/spirv/reader/lower/shader_io.cc
index 4e64e64..38faf72 100644
--- a/src/tint/lang/spirv/reader/lower/shader_io.cc
+++ b/src/tint/lang/spirv/reader/lower/shader_io.cc
@@ -464,7 +464,10 @@
} // namespace
Result<SuccessType> ShaderIO(core::ir::Module& ir) {
- auto result = ValidateAndDumpIfNeeded(ir, "spirv.ShaderIO");
+ auto result = ValidateAndDumpIfNeeded(ir, "spirv.ShaderIO",
+ core::ir::Capabilities{
+ core::ir::Capability::kAllowOverrides,
+ });
if (result != Success) {
return result.Failure();
}
diff --git a/src/tint/lang/spirv/reader/lower/vector_element_pointer.cc b/src/tint/lang/spirv/reader/lower/vector_element_pointer.cc
index f1f14cc..8db8634 100644
--- a/src/tint/lang/spirv/reader/lower/vector_element_pointer.cc
+++ b/src/tint/lang/spirv/reader/lower/vector_element_pointer.cc
@@ -155,6 +155,7 @@
Result<SuccessType> VectorElementPointer(core::ir::Module& ir) {
auto result = ValidateAndDumpIfNeeded(ir, "spirv.VectorElementPointer",
core::ir::Capabilities{
+ core::ir::Capability::kAllowOverrides,
core::ir::Capability::kAllowVectorElementPointer,
});
if (result != Success) {
diff --git a/src/tint/lang/spirv/reader/parser/helper_test.h b/src/tint/lang/spirv/reader/parser/helper_test.h
index 6b7b9f8..a3da582 100644
--- a/src/tint/lang/spirv/reader/parser/helper_test.h
+++ b/src/tint/lang/spirv/reader/parser/helper_test.h
@@ -75,6 +75,7 @@
// Validate the IR module against the capabilities supported by the SPIR-V dialect.
auto validated =
core::ir::Validate(parsed.Get(), core::ir::Capabilities{
+ core::ir::Capability::kAllowOverrides,
core::ir::Capability::kAllowVectorElementPointer,
});
if (validated != Success) {
diff --git a/src/tint/lang/spirv/reader/parser/parser.cc b/src/tint/lang/spirv/reader/parser/parser.cc
index 9327aa8..c665958 100644
--- a/src/tint/lang/spirv/reader/parser/parser.cc
+++ b/src/tint/lang/spirv/reader/parser/parser.cc
@@ -114,6 +114,7 @@
id_stack_.emplace_back();
{
TINT_SCOPED_ASSIGNMENT(current_block_, ir_.root_block);
+ EmitSpecConstants();
EmitModuleScopeVariables();
}
@@ -125,6 +126,47 @@
return std::move(ir_);
}
+ // Generate a module-scope const declaration for each instruction
+ // that is OpSpecConstantTrue, OpSpecConstantFalse, or OpSpecConstant.
+ void EmitSpecConstants() {
+ for (auto& inst : spirv_context_->types_values()) {
+ core::ir::Override* override_ = nullptr;
+ switch (inst.opcode()) {
+ case spv::Op::OpSpecConstantTrue:
+ case spv::Op::OpSpecConstantFalse:
+ override_ = b_.Override(Type(inst.type_id()));
+ override_->SetInitializer(
+ b_.Value(inst.opcode() == spv::Op::OpSpecConstantTrue));
+ break;
+ default:
+ break;
+ }
+ if (!override_) {
+ continue;
+ }
+
+ Emit(override_, inst.result_id());
+
+ Symbol name = GetSymbolFor(inst.result_id());
+ if (name.IsValid()) {
+ ir_.SetName(override_, name);
+ }
+
+ auto decos =
+ spirv_context_->get_decoration_mgr()->GetDecorationsFor(inst.result_id(), true);
+ for (const auto* deco_inst : decos) {
+ TINT_ASSERT(deco_inst->opcode() == spv::Op::OpDecorate);
+
+ if (deco_inst->GetSingleWordInOperand(1) ==
+ static_cast<uint32_t>(spv::Decoration::SpecId)) {
+ const uint16_t id = static_cast<uint16_t>(deco_inst->GetSingleWordInOperand(2));
+ override_->SetOverrideId(OverrideId{id});
+ break;
+ }
+ }
+ }
+ }
+
void RegisterNames() {
// Register names from OpName
for (const auto& inst : spirv_context_->debugs2()) {
diff --git a/src/tint/lang/spirv/reader/parser/var_test.cc b/src/tint/lang/spirv/reader/parser/var_test.cc
index 3de62a5..88c141a 100644
--- a/src/tint/lang/spirv/reader/parser/var_test.cc
+++ b/src/tint/lang/spirv/reader/parser/var_test.cc
@@ -608,5 +608,73 @@
"var undef @location(6) @interpolate(linear, centroid)",
}));
+TEST_F(SpirvParserTest, Var_OpSpecConstantTrue) {
+ EXPECT_IR(R"(
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main"
+ OpExecutionMode %main LocalSize 1 1 1
+ OpName %c "myconst"
+ OpDecorate %c SpecId 12
+ %void = OpTypeVoid
+ %bool = OpTypeBool
+ %f32 = OpTypeFloat 32
+ %vec4f = OpTypeVector %f32 4
+ %c = OpSpecConstantTrue %bool
+ %voidfn = OpTypeFunction %void
+ %main = OpFunction %void None %voidfn
+ %main_entry = OpLabel
+ %b = OpLogicalAnd %bool %c %c
+ OpReturn
+ OpFunctionEnd
+)",
+ R"(
+$B1: { # root
+ %myconst:bool = override true @id(12)
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+ $B2: {
+ %3:bool = and %myconst, %myconst
+ ret
+ }
+}
+)");
+}
+
+TEST_F(SpirvParserTest, Var_OpSpecConstantFalse) {
+ EXPECT_IR(R"(
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main"
+ OpExecutionMode %main LocalSize 1 1 1
+ OpName %c "myconst"
+ OpDecorate %c SpecId 12
+ %void = OpTypeVoid
+ %bool = OpTypeBool
+ %f32 = OpTypeFloat 32
+ %vec4f = OpTypeVector %f32 4
+ %c = OpSpecConstantFalse %bool
+ %voidfn = OpTypeFunction %void
+ %main = OpFunction %void None %voidfn
+ %main_entry = OpLabel
+ %b = OpLogicalAnd %bool %c %c
+ OpReturn
+ OpFunctionEnd
+)",
+ R"(
+$B1: { # root
+ %myconst:bool = override false @id(12)
+}
+
+%main = @compute @workgroup_size(1u, 1u, 1u) func():void {
+ $B2: {
+ %3:bool = and %myconst, %myconst
+ ret
+ }
+}
+)");
+}
+
} // namespace
} // namespace tint::spirv::reader
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc
index bc414fe..868c5ad 100644
--- a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc
+++ b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc
@@ -58,6 +58,7 @@
#include "src/tint/lang/core/ir/module.h"
#include "src/tint/lang/core/ir/multi_in_block.h"
#include "src/tint/lang/core/ir/next_iteration.h"
+#include "src/tint/lang/core/ir/override.h"
#include "src/tint/lang/core/ir/phony.h"
#include "src/tint/lang/core/ir/return.h"
#include "src/tint/lang/core/ir/store.h"
@@ -114,6 +115,7 @@
Program Run(const ProgramOptions& options) {
core::ir::Capabilities caps{core::ir::Capability::kAllowRefTypes,
+ core::ir::Capability::kAllowOverrides,
core::ir::Capability::kAllowPhonyInstructions};
if (auto res = core::ir::Validate(mod, caps); res != Success) {
// IR module failed validation.
@@ -199,8 +201,9 @@
void RootBlock(const core::ir::Block* root) {
for (auto* inst : *root) {
tint::Switch(
- inst, //
- [&](const core::ir::Var* var) { Var(var); }, //
+ inst, //
+ [&](const core::ir::Var* var) { Var(var); }, //
+ [&](const core::ir::Override* override_) { Override(override_); }, //
TINT_ICE_ON_NO_MATCH);
}
}
@@ -614,6 +617,22 @@
}
}
+ void Override(const core::ir::Override* override_) {
+ auto* val = override_->Result(0);
+ Symbol name = NameFor(override_->Result(0));
+ Bind(override_->Result(0), name);
+
+ Vector<const ast::Attribute*, 4> attrs;
+ attrs.Push(b.Id(override_->OverrideId()));
+
+ auto ty = Type(val->Type());
+ const ast::Expression* init = nullptr;
+ if (override_->Initializer()) {
+ init = Expr(override_->Initializer());
+ }
+ b.Override(name, ty, init, attrs);
+ }
+
void Let(const core::ir::Let* let) {
auto* result = let->Result(0);
Symbol name = NameFor(result);
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc
index 33645fc..7d8e678 100644
--- a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc
+++ b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc
@@ -2690,6 +2690,59 @@
}
////////////////////////////////////////////////////////////////////////////////
+// Override Construct
+////////////////////////////////////////////////////////////////////////////////
+TEST_F(IRToProgramTest, Override_DefaultId) {
+ core::ir::Override* o;
+ b.Append(b.ir.root_block, [&] { o = b.Override("o", false); });
+
+ auto* fn = b.Function("f", ty.bool_());
+ b.Append(fn->Block(), [&] { b.Return(fn, o); });
+
+ EXPECT_WGSL(R"(
+@id(0) override o : bool = false;
+
+fn f() -> bool {
+ return o;
+}
+)");
+}
+
+TEST_F(IRToProgramTest, Override_Id) {
+ core::ir::Override* o;
+ b.Append(b.ir.root_block, [&] { o = b.Override("o", true); });
+ o->SetOverrideId(OverrideId{10});
+
+ auto* fn = b.Function("f", ty.bool_());
+ b.Append(fn->Block(), [&] { b.Return(fn, o); });
+
+ EXPECT_WGSL(R"(
+@id(10) override o : bool = true;
+
+fn f() -> bool {
+ return o;
+}
+)");
+}
+
+TEST_F(IRToProgramTest, Override_NoInit) {
+ core::ir::Override* o;
+ b.Append(b.ir.root_block, [&] { o = b.Override("o", ty.i32()); });
+ o->SetOverrideId(OverrideId{10});
+
+ auto* fn = b.Function("f", ty.i32());
+ b.Append(fn->Block(), [&] { b.Return(fn, o); });
+
+ EXPECT_WGSL(R"(
+@id(10) override o : i32;
+
+fn f() -> i32 {
+ return o;
+}
+)");
+}
+
+////////////////////////////////////////////////////////////////////////////////
// chromium_internal_graphite
////////////////////////////////////////////////////////////////////////////////
TEST_F(IRToProgramTest, Enable_ChromiumInternalGraphite_SubgroupBallot) {
diff --git a/src/tint/lang/wgsl/writer/raise/value_to_let.cc b/src/tint/lang/wgsl/writer/raise/value_to_let.cc
index 32ef545..4c08108 100644
--- a/src/tint/lang/wgsl/writer/raise/value_to_let.cc
+++ b/src/tint/lang/wgsl/writer/raise/value_to_let.cc
@@ -193,7 +193,12 @@
} // namespace
Result<SuccessType> ValueToLet(core::ir::Module& ir) {
- auto result = core::ir::ValidateAndDumpIfNeeded(ir, "wgsl.ValueToLet");
+ auto result = core::ir::ValidateAndDumpIfNeeded(ir, "wgsl.ValueToLet",
+ core::ir::Capabilities{
+ core::ir::Capability::kAllowOverrides,
+ }
+
+ );
if (result != Success) {
return result;
}