[spirv-reader][ir] Handle SpecConstants without a SpecId. If an `OpSpecConstant*` does not have a `SpecId` decoration then we can treat it as a constant. There is no-way from the SPIR-V side to override the value, so we do not treat it as an override. Bug: 398007970 Change-Id: If6f911634fe921f026a8f944c07e99350127ce94 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/230255 Commit-Queue: dan sinclair <dsinclair@chromium.org> Reviewed-by: James Price <jrprice@google.com>
diff --git a/src/tint/lang/spirv/reader/parser/parser.cc b/src/tint/lang/spirv/reader/parser/parser.cc index 0cdf89d..4c3fcc5 100644 --- a/src/tint/lang/spirv/reader/parser/parser.cc +++ b/src/tint/lang/spirv/reader/parser/parser.cc
@@ -126,44 +126,53 @@ return std::move(ir_); } + std::optional<uint16_t> GetSpecId(const spvtools::opt::Instruction& inst) { + 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)) { + return {static_cast<uint16_t>(deco_inst->GetSingleWordInOperand(2))}; + } + } + return std::nullopt; + } + // 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; + core::ir::Value* value = nullptr; + std::optional<uint16_t> spec_id = std::nullopt; 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)); + case spv::Op::OpSpecConstantFalse: { + value = b_.Value(inst.opcode() == spv::Op::OpSpecConstantTrue); + spec_id = GetSpecId(inst); break; + } default: - break; + continue; } - if (!override_) { + + // No spec_id means treat this as a constant. + if (!spec_id.has_value()) { + AddValue(inst.result_id(), value); continue; } + auto* override_ = b_.Override(Type(inst.type_id())); + override_->SetInitializer(value); + override_->SetOverrideId(OverrideId{spec_id.value()}); + 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; - } - } } }
diff --git a/src/tint/lang/spirv/reader/parser/var_test.cc b/src/tint/lang/spirv/reader/parser/var_test.cc index 88c141a..e37e7e8 100644 --- a/src/tint/lang/spirv/reader/parser/var_test.cc +++ b/src/tint/lang/spirv/reader/parser/var_test.cc
@@ -642,6 +642,35 @@ )"); } +TEST_F(SpirvParserTest, Var_OpSpecConstantTrue_NoSpecId) { + EXPECT_IR(R"( + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %main "main" + OpExecutionMode %main LocalSize 1 1 1 + OpName %c "myconst" + %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"( +%main = @compute @workgroup_size(1u, 1u, 1u) func():void { + $B1: { + %2:bool = and true, true + ret + } +} +)"); +} + TEST_F(SpirvParserTest, Var_OpSpecConstantFalse) { EXPECT_IR(R"( OpCapability Shader @@ -676,5 +705,34 @@ )"); } +TEST_F(SpirvParserTest, Var_OpSpecConstantFalse_NoSpecId) { + EXPECT_IR(R"( + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint GLCompute %main "main" + OpExecutionMode %main LocalSize 1 1 1 + OpName %c "myconst" + %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"( +%main = @compute @workgroup_size(1u, 1u, 1u) func():void { + $B1: { + %2:bool = and false, false + ret + } +} +)"); +} + } // namespace } // namespace tint::spirv::reader