[SPIR-V] Fix ExecutionMode generation (#143888)

PR #141787 added code to emit the Fragment execution model. This
required emitting the OriginUpperLeft ExecutionMode. But this was done
by using the same codepath used for OpEntrypoint.

This has 2 issues:
- the interface variables were added to both OpEntryPoint and
OpExecutionMode.
- the existing OpExecutionMode logic was not used.

This commit fixes this, regrouping OpExecutionMode handling in one
place, and fixing bad codegen issue when interface variiables are added.
This commit is contained in:
Nathan Gauër
2025-06-12 18:13:29 +02:00
committed by GitHub
parent 882b58a90a
commit ef1cb8277a
4 changed files with 28 additions and 17 deletions

View File

@@ -510,6 +510,22 @@ void SPIRVAsmPrinter::outputExecutionMode(const Module &M) {
continue;
MCRegister FReg = MAI->getFuncReg(&F);
assert(FReg.isValid());
if (Attribute Attr = F.getFnAttribute("hlsl.shader"); Attr.isValid()) {
// SPIR-V common validation: Fragment requires OriginUpperLeft or
// OriginLowerLeft.
// VUID-StandaloneSpirv-OriginLowerLeft-04653: Fragment must declare
// OriginUpperLeft.
if (Attr.getValueAsString() == "pixel") {
MCInst Inst;
Inst.setOpcode(SPIRV::OpExecutionMode);
Inst.addOperand(MCOperand::createReg(FReg));
unsigned EM =
static_cast<unsigned>(SPIRV::ExecutionMode::OriginUpperLeft);
Inst.addOperand(MCOperand::createImm(EM));
outputMCInst(Inst);
}
}
if (MDNode *Node = F.getMetadata("reqd_work_group_size"))
outputExecutionModeFromMDNode(FReg, Node, SPIRV::ExecutionMode::LocalSize,
3, 1);

View File

@@ -475,21 +475,10 @@ bool SPIRVCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
// environment if we need to.
const SPIRVSubtarget *ST =
static_cast<const SPIRVSubtarget *>(&MIRBuilder.getMF().getSubtarget());
SPIRV::ExecutionModel::ExecutionModel ExecutionModel =
getExecutionModel(*ST, F);
auto MIB = MIRBuilder.buildInstr(SPIRV::OpEntryPoint)
.addImm(static_cast<uint32_t>(ExecutionModel))
.addImm(static_cast<uint32_t>(getExecutionModel(*ST, F)))
.addUse(FuncVReg);
addStringImm(F.getName(), MIB);
if (ExecutionModel == SPIRV::ExecutionModel::Fragment) {
// SPIR-V common validation: Fragment requires OriginUpperLeft or
// OriginLowerLeft VUID-StandaloneSpirv-OriginLowerLeft-04653: Fragment
// must declare OriginUpperLeft.
MIRBuilder.buildInstr(SPIRV::OpExecutionMode)
.addUse(FuncVReg)
.addImm(static_cast<uint32_t>(SPIRV::ExecutionMode::OriginUpperLeft));
}
} else if (F.getLinkage() != GlobalValue::InternalLinkage &&
F.getLinkage() != GlobalValue::PrivateLinkage) {
SPIRV::LinkageType::LinkageType LnkTy =

View File

@@ -595,8 +595,6 @@ void SPIRVModuleAnalysis::processOtherInstrs(const Module &M) {
collectOtherInstr(MI, MAI, SPIRV::MB_DebugNames, IS);
} else if (OpCode == SPIRV::OpEntryPoint) {
collectOtherInstr(MI, MAI, SPIRV::MB_EntryPoints, IS);
} else if (OpCode == SPIRV::OpExecutionMode) {
collectOtherInstr(MI, MAI, SPIRV::MB_EntryPoints, IS);
} else if (TII->isAliasingInstr(MI)) {
collectOtherInstr(MI, MAI, SPIRV::MB_AliasingInsts, IS);
} else if (TII->isDecorationInstr(MI)) {

View File

@@ -1,12 +1,20 @@
; RUN: llc -O0 -mtriple=spirv-unknown-vulkan1.3-pixel %s -o - | FileCheck %s
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan1.3-pixel %s -o - -filetype=obj | spirv-val --target-env vulkan1.3 %}
; CHECK-DAG: OpEntryPoint Fragment %[[#entry:]] "main"
; CHECK-DAG: OpEntryPoint Fragment %[[#entry:]] "main" {{.*}}
; CHECK-DAG: OpExecutionMode %[[#entry]] OriginUpperLeft
define void @main() #1 {
define void @main() #0 {
entry:
%0 = tail call target("spirv.VulkanBuffer", [0 x i32], 12, 1) @llvm.spv.resource.handlefrombinding.tspirv.VulkanBuffer_a0i32_12_1t(i32 0, i32 1, i32 1, i32 0, i1 false)
%1 = tail call noundef align 4 dereferenceable(4) ptr addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.VulkanBuffer_a0i32_12_1t(target("spirv.VulkanBuffer", [0 x i32], 12, 1) %0, i32 0)
store i32 1, ptr addrspace(11) %1, align 4
ret void
}
attributes #1 = { "hlsl.shader"="pixel" }
declare target("spirv.VulkanBuffer", [0 x i32], 12, 1) @llvm.spv.resource.handlefrombinding.tspirv.VulkanBuffer_a0i32_12_1t(i32, i32, i32, i32, i1) #1
attributes #0 = { "hlsl.shader"="pixel" }
attributes #1 = { mustprogress nocallback nofree nosync nounwind willreturn memory(none) }