Skip to content

Commit 3d57b10

Browse files
committed
[DirectX] Introduce `llvm.dx.resource.getdimensions and lower it to getDimensions DXIL op
Closes #112982
1 parent 2b2bc63 commit 3d57b10

File tree

5 files changed

+81
-0
lines changed

5 files changed

+81
-0
lines changed

llvm/include/llvm/IR/IntrinsicsDirectX.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ def int_dx_resource_updatecounter
7777
: DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_any_ty, llvm_i8_ty],
7878
[IntrInaccessibleMemOrArgMemOnly]>;
7979

80+
def int_dx_resource_getdimensions
81+
: DefaultAttrsIntrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [llvm_any_ty, llvm_i32_ty],
82+
[IntrReadMem]>;
83+
8084
// Cast between target extension handle types and dxil-style opaque handles
8185
def int_dx_resource_casthandle : Intrinsic<[llvm_any_ty], [llvm_any_ty]>;
8286

llvm/lib/Target/DirectX/DXIL.td

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ def ResBindTy : DXILOpParamType;
5757
def ResPropsTy : DXILOpParamType;
5858
def SplitDoubleTy : DXILOpParamType;
5959
def BinaryWithCarryTy : DXILOpParamType;
60+
def DimensionsTy : DXILOpParamType;
6061

6162
class DXILOpClass;
6263

@@ -901,6 +902,13 @@ def CheckAccessFullyMapped : DXILOp<71, checkAccessFullyMapped> {
901902
let attributes = [Attributes<DXIL1_0, [ReadOnly]>];
902903
}
903904

905+
def GetDimensions : DXILOp<72, getDimensions> {
906+
let Doc = "gets the dimensions of a buffer or texture";
907+
let arguments = [HandleTy, Int32Ty];
908+
let result = DimensionsTy;
909+
let stages = [Stages<DXIL1_0, [all_stages]>];
910+
}
911+
904912
def Barrier : DXILOp<80, barrier> {
905913
let Doc = "inserts a memory barrier in the shader";
906914
let intrinsics = [

llvm/lib/Target/DirectX/DXILOpBuilder.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,12 @@ static StructType *getBinaryWithCarryType(LLVMContext &Context) {
261261
return StructType::create({Int32Ty, Int1Ty}, "dx.types.i32c");
262262
}
263263

264+
static StructType *getDimensionsType(LLVMContext &Ctx) {
265+
Type *Int32Ty = Type::getInt32Ty(Ctx);
266+
return getOrCreateStructType("dx.types.Dimensions",
267+
{Int32Ty, Int32Ty, Int32Ty, Int32Ty}, Ctx);
268+
}
269+
264270
static Type *getTypeFromOpParamType(OpParamType Kind, LLVMContext &Ctx,
265271
Type *OverloadTy) {
266272
switch (Kind) {
@@ -318,6 +324,8 @@ static Type *getTypeFromOpParamType(OpParamType Kind, LLVMContext &Ctx,
318324
return getSplitDoubleType(Ctx);
319325
case OpParamType::BinaryWithCarryTy:
320326
return getBinaryWithCarryType(Ctx);
327+
case OpParamType::DimensionsTy:
328+
return getDimensionsType(Ctx);
321329
}
322330
llvm_unreachable("Invalid parameter kind");
323331
return nullptr;

llvm/lib/Target/DirectX/DXILOpLowering.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,30 @@ class OpLowerer {
627627
});
628628
}
629629

630+
[[nodiscard]] bool lowerGetDimensions(Function &F) {
631+
IRBuilder<> &IRB = OpBuilder.getIRB();
632+
Type *Int32Ty = IRB.getInt32Ty();
633+
634+
return replaceFunction(F, [&](CallInst *CI) -> Error {
635+
IRB.SetInsertPoint(CI);
636+
Value *Handle =
637+
createTmpHandleCast(CI->getArgOperand(0), OpBuilder.getHandleType());
638+
Value *Op1 = CI->getArgOperand(1);
639+
if (isa<llvm::PoisonValue>(Op1))
640+
Op1 = UndefValue::get(Int32Ty);
641+
642+
Expected<CallInst *> OpCall = OpBuilder.tryCreateOp(
643+
OpCode::GetDimensions, {Handle, Op1}, CI->getName(), Int32Ty);
644+
if (Error E = OpCall.takeError())
645+
return E;
646+
if (Error E = replaceNamedStructUses(CI, *OpCall))
647+
return E;
648+
649+
CI->eraseFromParent();
650+
return Error::success();
651+
});
652+
}
653+
630654
[[nodiscard]] bool lowerGetPointer(Function &F) {
631655
// These should have already been handled in DXILResourceAccess, so we can
632656
// just clean up the dead prototype.
@@ -934,6 +958,9 @@ class OpLowerer {
934958
case Intrinsic::dx_resource_updatecounter:
935959
HasErrors |= lowerUpdateCounter(F);
936960
break;
961+
case Intrinsic::dx_resource_getdimensions:
962+
HasErrors |= lowerGetDimensions(F);
963+
break;
937964
case Intrinsic::ctpop:
938965
HasErrors |= lowerCtpopToCountBits(F);
939966
break;
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
; RUN: opt -S -dxil-op-lower %s | FileCheck %s
2+
3+
target triple = "dxil-pc-shadermodel6.6-compute"
4+
5+
define i32 @test_getdimensions_no_mips() {
6+
; CHECK: [[HANDLE1:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217,
7+
; CHECK-NEXT: [[ANNOT_HANDLE1:%.*]] = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[HANDLE1]]
8+
%handle1 = call target("dx.TypedBuffer", <4 x float>, 0, 0, 0) @llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, ptr null)
9+
10+
; CHECK-NEXT: [[RETVAL1:%.*]] = call %dx.types.Dimensions @dx.op.getDimensions(i32 72, %dx.types.Handle [[ANNOT_HANDLE1]], i32 undef)
11+
%1 = call { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_i32_1_0t(target("dx.TypedBuffer", <4 x float>, 0, 0, 0) %handle1, i32 poison)
12+
13+
; CHECK-NEXT: %[[DIM1:.*]] = extractvalue %dx.types.Dimensions [[RETVAL1]], 0
14+
%2 = extractvalue { i32, i32, i32, i32 } %1, 0
15+
16+
; CHECK-NEXT: ret i32 %[[DIM1]]
17+
ret i32 %2
18+
}
19+
20+
21+
define i32 @test_getdimensions_with_0_mips() {
22+
; CHECK: [[HANDLE2:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217,
23+
; CHECK-NEXT: [[ANNOT_HANDLE2:%.*]] = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[HANDLE2]]
24+
%handle1 = call target("dx.RawBuffer", float, 0, 0) @llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, ptr null)
25+
26+
; CHECK-NEXT: [[RETVAL2:%.*]] = call %dx.types.Dimensions @dx.op.getDimensions(i32 72, %dx.types.Handle [[ANNOT_HANDLE2]], i32 0)
27+
%1 = call { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_i32_1_0t(target("dx.RawBuffer", float, 0, 0) %handle1, i32 0)
28+
29+
; CHECK-NEXT: %[[DIM2:.*]] = extractvalue %dx.types.Dimensions [[RETVAL2]], 0
30+
%2 = extractvalue { i32, i32, i32, i32 } %1, 0
31+
32+
; CHECK-NEXT: ret i32 %[[DIM2]]
33+
ret i32 %2
34+
}

0 commit comments

Comments
 (0)