[llvm] [SPIRV] Implement lowering for HLSL Texture2D sampling intrinsics (PR #179312)

Nathan Gauër via llvm-commits llvm-commits at lists.llvm.org
Fri Feb 6 08:27:54 PST 2026


================
@@ -4292,78 +4329,189 @@ bool SPIRVInstructionSelector::selectReadImageIntrinsic(
                                   Pos);
 }
 
-bool SPIRVInstructionSelector::selectSampleIntrinsic(Register &ResVReg,
-                                                     const SPIRVType *ResType,
-                                                     MachineInstr &I) const {
-  Register ImageReg = I.getOperand(2).getReg();
-  Register SamplerReg = I.getOperand(3).getReg();
-  Register CoordinateReg = I.getOperand(4).getReg();
-  std::optional<Register> OffsetReg;
-  std::optional<Register> ClampReg;
-
-  if (I.getNumOperands() > 5)
-    OffsetReg = I.getOperand(5).getReg();
-  if (I.getNumOperands() > 6)
-    ClampReg = I.getOperand(6).getReg();
-
-  DebugLoc Loc = I.getDebugLoc();
-
+bool SPIRVInstructionSelector::generateSampleImage(
+    Register ResVReg, const SPIRVType *ResType, Register ImageReg,
+    Register SamplerReg, Register CoordinateReg, const ImageOperands &ImOps,
+    DebugLoc Loc, MachineInstr &Pos) const {
   auto *ImageDef = cast<GIntrinsic>(getVRegDef(*MRI, ImageReg));
   Register NewImageReg = MRI->createVirtualRegister(MRI->getRegClass(ImageReg));
   if (!loadHandleBeforePosition(NewImageReg, GR.getSPIRVTypeForVReg(ImageReg),
-                                *ImageDef, I)) {
+                                *ImageDef, Pos)) {
     return false;
   }
 
   auto *SamplerDef = cast<GIntrinsic>(getVRegDef(*MRI, SamplerReg));
   Register NewSamplerReg =
       MRI->createVirtualRegister(MRI->getRegClass(SamplerReg));
-  if (!loadHandleBeforePosition(
-          NewSamplerReg, GR.getSPIRVTypeForVReg(SamplerReg), *SamplerDef, I)) {
+  if (!loadHandleBeforePosition(NewSamplerReg,
+                                GR.getSPIRVTypeForVReg(SamplerReg), *SamplerDef,
+                                Pos)) {
     return false;
   }
 
-  MachineIRBuilder MIRBuilder(I);
+  MachineIRBuilder MIRBuilder(Pos);
   SPIRVType *SampledImageType = GR.getOrCreateOpTypeSampledImage(
       GR.getSPIRVTypeForVReg(ImageReg), MIRBuilder);
-
   Register SampledImageReg =
       MRI->createVirtualRegister(GR.getRegClass(SampledImageType));
-  BuildMI(*I.getParent(), I, Loc, TII.get(SPIRV::OpSampledImage))
+
+  BuildMI(*Pos.getParent(), Pos, Loc, TII.get(SPIRV::OpSampledImage))
       .addDef(SampledImageReg)
       .addUse(GR.getSPIRVTypeID(SampledImageType))
       .addUse(NewImageReg)
       .addUse(NewSamplerReg)
       .constrainAllUses(TII, TRI, RBI);
 
-  auto MIB =
-      BuildMI(*I.getParent(), I, Loc, TII.get(SPIRV::OpImageSampleImplicitLod))
-          .addDef(ResVReg)
-          .addUse(GR.getSPIRVTypeID(ResType))
-          .addUse(SampledImageReg)
-          .addUse(CoordinateReg);
+  bool IsExplicitLod = ImOps.GradX.has_value() || ImOps.GradY.has_value() ||
+                       ImOps.Lod.has_value();
+  unsigned Opcode = IsExplicitLod ? SPIRV::OpImageSampleExplicitLod
+                                  : SPIRV::OpImageSampleImplicitLod;
+  if (ImOps.Compare)
+    Opcode = IsExplicitLod ? SPIRV::OpImageSampleDrefExplicitLod
+                           : SPIRV::OpImageSampleDrefImplicitLod;
 
-  uint32_t ImageOperands = 0;
-  if (OffsetReg && !isScalarOrVectorIntConstantZero(*OffsetReg)) {
-    ImageOperands |= 0x8; // ConstOffset
-  }
+  auto MIB = BuildMI(*Pos.getParent(), Pos, Loc, TII.get(Opcode))
+                 .addDef(ResVReg)
+                 .addUse(GR.getSPIRVTypeID(ResType))
+                 .addUse(SampledImageReg)
+                 .addUse(CoordinateReg);
+
+  if (ImOps.Compare)
+    MIB.addUse(*ImOps.Compare);
 
-  if (ClampReg) {
-    ImageOperands |= 0x80; // MinLod
+  uint32_t ImageOperands = 0;
+  if (ImOps.Bias)
+    ImageOperands |= SPIRV::ImageOperand::Bias;
+  if (ImOps.Lod)
+    ImageOperands |= SPIRV::ImageOperand::Lod;
+  if (ImOps.GradX && ImOps.GradY)
+    ImageOperands |= SPIRV::ImageOperand::Grad;
+  if (ImOps.Offset && !isScalarOrVectorIntConstantZero(*ImOps.Offset)) {
+    if (isConstReg(MRI, *ImOps.Offset))
+      ImageOperands |= SPIRV::ImageOperand::ConstOffset;
+    else {
+      std::string DiagMsg;
+      raw_string_ostream OS(DiagMsg);
+      OS << "Non-constant offsets are not supported in sample instructions: ";
+      Loc.print(OS);
+      OS << " ";
+      Pos.print(OS);
+      OS.flush();
+      report_fatal_error(DiagMsg.c_str(), false);
----------------
Keenuts wrote:

Should you use `Pos.emitGenericError(<msg>)` instead?

https://github.com/llvm/llvm-project/pull/179312


More information about the llvm-commits mailing list