diff --git a/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp b/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp index 98d3720df9361..091368a309a82 100644 --- a/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp @@ -282,6 +282,8 @@ getExecutionModel(const SPIRVSubtarget &STI, const Function &F) { return SPIRV::ExecutionModel::GLCompute; if (value == "vertex") return SPIRV::ExecutionModel::Vertex; + if (value == "pixel") + return SPIRV::ExecutionModel::Fragment; report_fatal_error( "This HLSL entry point is not supported by this backend."); @@ -306,6 +308,8 @@ getExecutionModel(const SPIRVSubtarget &STI, const Function &F) { return SPIRV::ExecutionModel::GLCompute; if (value == "vertex") return SPIRV::ExecutionModel::Vertex; + if (value == "pixel") + return SPIRV::ExecutionModel::Fragment; report_fatal_error("This HLSL entry point is not supported by this backend."); } @@ -471,10 +475,21 @@ bool SPIRVCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, // environment if we need to. const SPIRVSubtarget *ST = static_cast(&MIRBuilder.getMF().getSubtarget()); + SPIRV::ExecutionModel::ExecutionModel ExecutionModel = + getExecutionModel(*ST, F); auto MIB = MIRBuilder.buildInstr(SPIRV::OpEntryPoint) - .addImm(static_cast(getExecutionModel(*ST, F))) + .addImm(static_cast(ExecutionModel)) .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(SPIRV::ExecutionMode::OriginUpperLeft)); + } } else if (F.getLinkage() != GlobalValue::InternalLinkage && F.getLinkage() != GlobalValue::PrivateLinkage) { SPIRV::LinkageType::LinkageType LnkTy = diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp index b71a9dd68dd44..2ddd028c79412 100644 --- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp @@ -595,6 +595,8 @@ 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)) { diff --git a/llvm/test/CodeGen/SPIRV/ExecutionMode_Fragment.ll b/llvm/test/CodeGen/SPIRV/ExecutionMode_Fragment.ll new file mode 100644 index 0000000000000..0a62db446cc11 --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/ExecutionMode_Fragment.ll @@ -0,0 +1,12 @@ +; 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: OpExecutionMode %[[#entry]] OriginUpperLeft + +define void @main() #1 { +entry: + ret void +} + +attributes #1 = { "hlsl.shader"="pixel" }