Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions llvm/include/llvm/IR/IntrinsicsDirectX.td
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ def int_dx_resource_updatecounter
: DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_any_ty, llvm_i8_ty],
[IntrInaccessibleMemOrArgMemOnly]>;

def int_dx_resource_getdimensions
: DefaultAttrsIntrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [llvm_any_ty, llvm_i32_ty],
[IntrReadMem]>;

// Cast between target extension handle types and dxil-style opaque handles
def int_dx_resource_casthandle : Intrinsic<[llvm_any_ty], [llvm_any_ty]>;

Expand Down
8 changes: 8 additions & 0 deletions llvm/lib/Target/DirectX/DXIL.td
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ def ResBindTy : DXILOpParamType;
def ResPropsTy : DXILOpParamType;
def SplitDoubleTy : DXILOpParamType;
def BinaryWithCarryTy : DXILOpParamType;
def DimensionsTy : DXILOpParamType;

class DXILOpClass;

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

def GetDimensions : DXILOp<72, getDimensions> {
let Doc = "gets the dimensions of a buffer or texture";
let arguments = [HandleTy, Int32Ty];
let result = DimensionsTy;
let stages = [Stages<DXIL1_0, [all_stages]>];
}

def Barrier : DXILOp<80, barrier> {
let Doc = "inserts a memory barrier in the shader";
let intrinsics = [
Expand Down
8 changes: 8 additions & 0 deletions llvm/lib/Target/DirectX/DXILOpBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,12 @@ static StructType *getBinaryWithCarryType(LLVMContext &Context) {
return StructType::create({Int32Ty, Int1Ty}, "dx.types.i32c");
}

static StructType *getDimensionsType(LLVMContext &Ctx) {
Type *Int32Ty = Type::getInt32Ty(Ctx);
return getOrCreateStructType("dx.types.Dimensions",
{Int32Ty, Int32Ty, Int32Ty, Int32Ty}, Ctx);
}

static Type *getTypeFromOpParamType(OpParamType Kind, LLVMContext &Ctx,
Type *OverloadTy) {
switch (Kind) {
Expand Down Expand Up @@ -318,6 +324,8 @@ static Type *getTypeFromOpParamType(OpParamType Kind, LLVMContext &Ctx,
return getSplitDoubleType(Ctx);
case OpParamType::BinaryWithCarryTy:
return getBinaryWithCarryType(Ctx);
case OpParamType::DimensionsTy:
return getDimensionsType(Ctx);
}
llvm_unreachable("Invalid parameter kind");
return nullptr;
Expand Down
27 changes: 27 additions & 0 deletions llvm/lib/Target/DirectX/DXILOpLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,30 @@ class OpLowerer {
});
}

[[nodiscard]] bool lowerGetDimensions(Function &F) {
IRBuilder<> &IRB = OpBuilder.getIRB();
Type *Int32Ty = IRB.getInt32Ty();

return replaceFunction(F, [&](CallInst *CI) -> Error {
IRB.SetInsertPoint(CI);
Value *Handle =
createTmpHandleCast(CI->getArgOperand(0), OpBuilder.getHandleType());
Value *Op1 = CI->getArgOperand(1);
if (isa<llvm::PoisonValue>(Op1))
Op1 = UndefValue::get(Int32Ty);

Expected<CallInst *> OpCall = OpBuilder.tryCreateOp(
OpCode::GetDimensions, {Handle, Op1}, CI->getName(), Int32Ty);
if (Error E = OpCall.takeError())
return E;
if (Error E = replaceNamedStructUses(CI, *OpCall))
return E;

CI->eraseFromParent();
return Error::success();
});
}

[[nodiscard]] bool lowerGetPointer(Function &F) {
// These should have already been handled in DXILResourceAccess, so we can
// just clean up the dead prototype.
Expand Down Expand Up @@ -934,6 +958,9 @@ class OpLowerer {
case Intrinsic::dx_resource_updatecounter:
HasErrors |= lowerUpdateCounter(F);
break;
case Intrinsic::dx_resource_getdimensions:
HasErrors |= lowerGetDimensions(F);
break;
case Intrinsic::ctpop:
HasErrors |= lowerCtpopToCountBits(F);
break;
Expand Down
34 changes: 34 additions & 0 deletions llvm/test/CodeGen/DirectX/bufferGetDimensions.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
; RUN: opt -S -dxil-op-lower %s | FileCheck %s

target triple = "dxil-pc-shadermodel6.6-compute"

define i32 @test_getdimensions_no_mips() {
; CHECK: [[HANDLE1:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217,
; CHECK-NEXT: [[ANNOT_HANDLE1:%.*]] = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[HANDLE1]]
%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)

; CHECK-NEXT: [[RETVAL1:%.*]] = call %dx.types.Dimensions @dx.op.getDimensions(i32 72, %dx.types.Handle [[ANNOT_HANDLE1]], i32 undef)
%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)

; CHECK-NEXT: %[[DIM1:.*]] = extractvalue %dx.types.Dimensions [[RETVAL1]], 0
%2 = extractvalue { i32, i32, i32, i32 } %1, 0

; CHECK-NEXT: ret i32 %[[DIM1]]
ret i32 %2
}


define i32 @test_getdimensions_with_0_mips() {
; CHECK: [[HANDLE2:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217,
; CHECK-NEXT: [[ANNOT_HANDLE2:%.*]] = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[HANDLE2]]
%handle1 = call target("dx.RawBuffer", float, 0, 0) @llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 1, i32 0, ptr null)

; CHECK-NEXT: [[RETVAL2:%.*]] = call %dx.types.Dimensions @dx.op.getDimensions(i32 72, %dx.types.Handle [[ANNOT_HANDLE2]], i32 0)
%1 = call { i32, i32, i32, i32 } @llvm.dx.resource.getdimensions.tdx.RawBuffer_i32_1_0t(target("dx.RawBuffer", float, 0, 0) %handle1, i32 0)

; CHECK-NEXT: %[[DIM2:.*]] = extractvalue %dx.types.Dimensions [[RETVAL2]], 0
%2 = extractvalue { i32, i32, i32, i32 } %1, 0

; CHECK-NEXT: ret i32 %[[DIM2]]
ret i32 %2
}
Loading