Skip to content

[SPIR-V] Add Fragment execution model #141787

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 10, 2025
Merged

[SPIR-V] Add Fragment execution model #141787

merged 3 commits into from
Jun 10, 2025

Conversation

Keenuts
Copy link
Contributor

@Keenuts Keenuts commented May 28, 2025

This commits allows the fragment execution model to be set using the hlsl.shader attribute.

Fixes #136962

@llvmbot
Copy link
Member

llvmbot commented May 28, 2025

@llvm/pr-subscribers-backend-spir-v

Author: Nathan Gauër (Keenuts)

Changes

This commits allows the fragment execution model to be set using the hlsl.shader attribute.

Fixes #136962


Full diff: https://github.com/llvm/llvm-project/pull/141787.diff

3 Files Affected:

  • (modified) llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp (+14-1)
  • (modified) llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp (+2)
  • (added) llvm/test/CodeGen/SPIRV/ExecutionMode_Fragment.ll (+12)
diff --git a/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp b/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp
index 5991a9af6364d..3a02f2764ad40 100644
--- a/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp
@@ -279,6 +279,8 @@ getExecutionModel(const SPIRVSubtarget &STI, const Function &F) {
   const auto value = attribute.getValueAsString();
   if (value == "compute")
     return SPIRV::ExecutionModel::GLCompute;
+  if (value == "pixel")
+    return SPIRV::ExecutionModel::Fragment;
 
   report_fatal_error("This HLSL entry point is not supported by this backend.");
 }
@@ -439,10 +441,21 @@ bool SPIRVCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
 
   // Handle entry points and function linkage.
   if (isEntryPoint(F)) {
+    SPIRV::ExecutionModel::ExecutionModel ExecutionModel =
+        getExecutionModel(*ST, F);
     auto MIB = MIRBuilder.buildInstr(SPIRV::OpEntryPoint)
-                   .addImm(static_cast<uint32_t>(getExecutionModel(*ST, F)))
+                   .addImm(static_cast<uint32_t>(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<uint32_t>(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 2fdd54fdfc390..1de0784e16255 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..3374274bb3445
--- /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 %}
+
+; CHECK-DAG: OpEntryPoint Fragment %[[#entry:]] "main"
+; CHECK-DAG: OpExecutionMode %[[#entry]] OriginUpperLeft
+
+define void @main() #1 {
+entry:
+  ret void
+}
+
+attributes #1 = { "hlsl.shader"="pixel" }

@Keenuts Keenuts requested a review from michalpaszkowski May 30, 2025 11:08
Keenuts added 3 commits June 10, 2025 15:37
This commits allows the fragment execution model to be set
using the hlsl.shader attribute.

Fixes llvm#136962
@Keenuts
Copy link
Contributor Author

Keenuts commented Jun 10, 2025

rebased for merging

@Keenuts
Copy link
Contributor Author

Keenuts commented Jun 10, 2025

Tests are passing, merging this

@Keenuts Keenuts merged commit 65d5301 into llvm:main Jun 10, 2025
6 of 8 checks passed
@Keenuts Keenuts deleted the ps-shader branch June 10, 2025 13:44
rorth pushed a commit to rorth/llvm-project that referenced this pull request Jun 11, 2025
This commits allows the fragment execution model to be set using the
hlsl.shader attribute.

Fixes llvm#136962
Keenuts added a commit to Keenuts/llvm-project that referenced this pull request Jun 12, 2025
PR llvm#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.
Keenuts added a commit that referenced this pull request Jun 12, 2025
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.
tomtor pushed a commit to tomtor/llvm-project that referenced this pull request Jun 14, 2025
This commits allows the fragment execution model to be set using the
hlsl.shader attribute.

Fixes llvm#136962
tomtor pushed a commit to tomtor/llvm-project that referenced this pull request Jun 14, 2025
PR llvm#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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[HLSL][SPIRV] Implement fragment shaders
3 participants