[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