[llvm] [SPIRV] Add reads from image buffer for shaders. (PR #115178)
Nathan Gauër via llvm-commits
llvm-commits at lists.llvm.org
Fri Nov 8 08:37:50 PST 2024
================
@@ -2803,6 +2814,84 @@ void SPIRVInstructionSelector::selectHandleFromBinding(Register &ResVReg,
.addUse(VarReg);
}
+void SPIRVInstructionSelector::selectReadImageIntrinsic(
+ Register &ResVReg, const SPIRVType *ResType, MachineInstr &I) const {
+
+ // If the load of the image is in a different basic block, then
+ // this will generate invalid code. A proper solution is to move
+ // the OpLoad from selectHandleFromBinding here. However, to do
+ // that we will need to change the return type of the intrinsic.
+ // We will do that when we can, but for now trying to move forward with other
+ // issues.
+ Register ImageReg = I.getOperand(2).getReg();
+ assert(MRI->getVRegDef(ImageReg)->getParent() == I.getParent() &&
+ "The image must be loaded in the same basic block as its use.");
+
+ uint64_t ResultSize = GR.getScalarOrVectorComponentCount(ResType);
+ if (ResultSize == 4) {
+ BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpImageRead))
+ .addDef(ResVReg)
+ .addUse(GR.getSPIRVTypeID(ResType))
+ .addUse(ImageReg)
+ .addUse(I.getOperand(3).getReg());
+ return;
+ }
+
+ SPIRVType *ReadType = widenTypeToVec4(ResType, I);
+ Register ReadReg = MRI->createVirtualRegister(GR.getRegClass(ReadType));
+ BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpImageRead))
+ .addDef(ReadReg)
+ .addUse(GR.getSPIRVTypeID(ReadType))
+ .addUse(ImageReg)
+ .addUse(I.getOperand(3).getReg());
+
+ if (ResultSize == 1) {
+ BuildMI(*I.getParent(), I, I.getDebugLoc(),
+ TII.get(SPIRV::OpCompositeExtract))
+ .addDef(ResVReg)
+ .addUse(GR.getSPIRVTypeID(ResType))
+ .addUse(ReadReg)
+ .addImm(0);
+ return;
+ }
+ extractSubvector(ResVReg, ResType, ReadReg, I);
+}
+
+void SPIRVInstructionSelector::extractSubvector(
+ Register &ResVReg, const SPIRVType *ResType, Register &ReadReg,
+ MachineInstr &InsertionPoint) const {
+ SPIRVType *InputType = GR.getResultType(ReadReg);
+ uint64_t InputSize = GR.getScalarOrVectorComponentCount(InputType);
+ uint64_t ResultSize = GR.getScalarOrVectorComponentCount(ResType);
+ assert(InputSize > 1 && "The input must be a vector.");
+ assert(ResultSize > 1 && "The result must be a vector.");
+ assert(ResultSize < InputSize &&
+ "Cannot extract more element than there are in the input.");
+ SmallVector<Register> ComponentRegisters;
+ SPIRVType *ScalarType = GR.getScalarOrVectorComponentType(ResType);
+ const TargetRegisterClass *ScalarRegClass = GR.getRegClass(ScalarType);
+ for (uint64_t I = 0; I < ResultSize; I++) {
+ Register ComponentReg = MRI->createVirtualRegister(ScalarRegClass);
+ BuildMI(*InsertionPoint.getParent(), InsertionPoint,
+ InsertionPoint.getDebugLoc(), TII.get(SPIRV::OpCompositeExtract))
+ .addDef(ComponentReg)
+ .addUse(ScalarType->getOperand(0).getReg())
+ .addUse(ReadReg)
+ .addImm(I);
+ ComponentRegisters.emplace_back(ComponentReg);
+ }
+
+ MachineInstrBuilder MIB = BuildMI(*InsertionPoint.getParent(), InsertionPoint,
+ InsertionPoint.getDebugLoc(),
+ TII.get(SPIRV::OpCompositeConstruct))
+ .addDef(ResVReg)
+ .addUse(GR.getSPIRVTypeID(ResType));
+
+ for (Register ComponentReg : ComponentRegisters) {
+ MIB.addUse(ComponentReg);
+ }
----------------
Keenuts wrote:
nit
```suggestion
for (Register ComponentReg : ComponentRegisters)
MIB.addUse(ComponentReg);
```
https://github.com/llvm/llvm-project/pull/115178
More information about the llvm-commits
mailing list