diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index a1afa82955f6a..b8bbc544595e2 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -5138,6 +5138,36 @@ def HLSLResourceGetDimensionsX : LangBuiltin<"HLSL_LANG"> { let Prototype = "void(__hlsl_resource_t, uint32_t&)"; } +def HLSLResourceGetDimensionsXY : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_resource_getdimensions_xy"]; + let Attributes = [NoThrow]; + let Prototype = "void(__hlsl_resource_t, uint32_t&, uint32_t&)"; +} + +def HLSLResourceGetDimensionsLevelsXY : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_resource_getdimensions_levels_xy"]; + let Attributes = [NoThrow]; + let Prototype = "void(__hlsl_resource_t, uint32_t, uint32_t&, uint32_t&, uint32_t&)"; +} + +def HLSLResourceGetDimensionsXFloat : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_resource_getdimensions_x_float"]; + let Attributes = [NoThrow]; + let Prototype = "void(__hlsl_resource_t, float&)"; +} + +def HLSLResourceGetDimensionsXYFloat : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_resource_getdimensions_xy_float"]; + let Attributes = [NoThrow]; + let Prototype = "void(__hlsl_resource_t, float&, float&)"; +} + +def HLSLResourceGetDimensionsLevelsXYFloat : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_resource_getdimensions_levels_xy_float"]; + let Attributes = [NoThrow]; + let Prototype = "void(__hlsl_resource_t, uint32_t, float&, float&, float&)"; +} + def HLSLResourceGetStride : LangBuiltin<"HLSL_LANG"> { let Spellings = ["__builtin_hlsl_resource_getstride"]; let Attributes = [NoThrow]; diff --git a/clang/lib/CodeGen/CGHLSLBuiltins.cpp b/clang/lib/CodeGen/CGHLSLBuiltins.cpp index 71ddbdebf7245..f510195dbd6cb 100644 --- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp +++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp @@ -475,6 +475,37 @@ static Value *emitHlslClamp(CodeGenFunction &CGF, const CallExpr *E, return Clamp; } +static Value *emitGetDimensions(CodeGenFunction &CGF, const CallExpr *E, + unsigned IntrinsicID, unsigned NumRetComps, + bool HasLod) { + Value *Handle = CGF.EmitScalarExpr(E->getArg(0)); + + SmallVector Args{Handle}; + if (HasLod) + Args.push_back(CGF.EmitScalarExpr(E->getArg(1))); + + Value *DimValue = + CGF.Builder.CreateIntrinsic(IntrinsicID, {Handle->getType()}, Args); + + Value *LastStore = nullptr; + unsigned ArgIndex = HasLod ? 2 : 1; + for (unsigned i = 0; i < NumRetComps; ++i) { + const Expr *Arg = E->getArg(ArgIndex++); + LValue DimOut = CGF.EmitLValue(Arg); + Value *Elem = DimValue; + if (NumRetComps > 1) + Elem = CGF.Builder.CreateExtractElement(DimValue, i); + + // Handle float casting if needed + if (Arg->getType()->isFloatingType()) + Elem = CGF.Builder.CreateUIToFP( + Elem, llvm::Type::getFloatTy(CGF.getLLVMContext())); + + LastStore = CGF.Builder.CreateStore(Elem, DimOut.getAddress()); + } + return LastStore; +} + Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, const CallExpr *E, ReturnValueSlot ReturnValue) { @@ -882,15 +913,21 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, RetTy, CGM.getHLSLRuntime().getNonUniformResourceIndexIntrinsic(), ArrayRef{IndexOp}); } - case Builtin::BI__builtin_hlsl_resource_getdimensions_x: { - Value *Handle = EmitScalarExpr(E->getArg(0)); - LValue Dim = EmitLValue(E->getArg(1)); - llvm::Type *RetTy = llvm::Type::getInt32Ty(getLLVMContext()); - Value *DimValue = Builder.CreateIntrinsic( - RetTy, CGM.getHLSLRuntime().getGetDimensionsXIntrinsic(), - ArrayRef{Handle}); - return Builder.CreateStore(DimValue, Dim.getAddress()); - } + case Builtin::BI__builtin_hlsl_resource_getdimensions_x: + case Builtin::BI__builtin_hlsl_resource_getdimensions_x_float: + return emitGetDimensions(*this, E, + CGM.getHLSLRuntime().getGetDimensionsXIntrinsic(), + 1, /*HasLod=*/false); + case Builtin::BI__builtin_hlsl_resource_getdimensions_xy: + case Builtin::BI__builtin_hlsl_resource_getdimensions_xy_float: + return emitGetDimensions(*this, E, + CGM.getHLSLRuntime().getGetDimensionsXYIntrinsic(), + 2, /*HasLod=*/false); + case Builtin::BI__builtin_hlsl_resource_getdimensions_levels_xy: + case Builtin::BI__builtin_hlsl_resource_getdimensions_levels_xy_float: + return emitGetDimensions( + *this, E, CGM.getHLSLRuntime().getGetDimensionsLevelsXYIntrinsic(), 3, + /*HasLod=*/true); case Builtin::BI__builtin_hlsl_resource_getstride: { LValue Stride = EmitLValue(E->getArg(1)); return emitBufferStride(this, E->getArg(0), Stride); diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h index f473ac13816c0..b1c5b3318a11e 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.h +++ b/clang/lib/CodeGen/CGHLSLRuntime.h @@ -193,6 +193,9 @@ class CGHLSLRuntime { GENERATE_HLSL_INTRINSIC_FUNCTION(GroupMemoryBarrierWithGroupSync, group_memory_barrier_with_group_sync) GENERATE_HLSL_INTRINSIC_FUNCTION(GetDimensionsX, resource_getdimensions_x) + GENERATE_HLSL_INTRINSIC_FUNCTION(GetDimensionsXY, resource_getdimensions_xy) + GENERATE_HLSL_INTRINSIC_FUNCTION(GetDimensionsLevelsXY, + resource_getdimensions_levels_xy) GENERATE_HLSL_INTRINSIC_FUNCTION(LoadLevel, resource_load_level) GENERATE_HLSL_INTRINSIC_FUNCTION(CalculateLod, resource_calculate_lod) GENERATE_HLSL_INTRINSIC_FUNCTION(CalculateLodUnclamped, diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp index 0e3b640fa060a..4c8b0283b0f1e 100644 --- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp +++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp @@ -1885,6 +1885,53 @@ BuiltinTypeDeclBuilder::addSampleCmpLevelZeroMethods(ResourceDimension Dim) { .finalize(); } +BuiltinTypeDeclBuilder & +BuiltinTypeDeclBuilder::addGetDimensionsMethods(ResourceDimension Dim) { + assert(!Record->isCompleteDefinition() && "record is already complete"); + using PH = BuiltinTypeMethodBuilder::PlaceHolder; + ASTContext &AST = SemaRef.getASTContext(); + QualType UIntTy = AST.UnsignedIntTy; + + assert(Dim != ResourceDimension::Unknown); + + QualType FloatTy = AST.FloatTy; + // Add overloads for uint and float. + QualType Params[] = {UIntTy, FloatTy}; + + for (QualType OutTy : Params) { + if (Dim == ResourceDimension::Dim2D) { + StringRef XYName = "__builtin_hlsl_resource_getdimensions_xy"; + StringRef LevelsXYName = + "__builtin_hlsl_resource_getdimensions_levels_xy"; + + if (OutTy == FloatTy) { + XYName = "__builtin_hlsl_resource_getdimensions_xy_float"; + LevelsXYName = "__builtin_hlsl_resource_getdimensions_levels_xy_float"; + } + + // void GetDimensions(out [uint|float] width, out [uint|float] height) + BuiltinTypeMethodBuilder(*this, "GetDimensions", AST.VoidTy) + .addParam("width", OutTy, HLSLParamModifierAttr::Keyword_out) + .addParam("height", OutTy, HLSLParamModifierAttr::Keyword_out) + .callBuiltin(XYName, QualType(), PH::Handle, PH::_0, PH::_1) + .finalize(); + + // void GetDimensions(uint mipLevel, out [uint|float] width, out + // [uint|float] height, out [uint|float] numberOfLevels) + BuiltinTypeMethodBuilder(*this, "GetDimensions", AST.VoidTy) + .addParam("mipLevel", UIntTy) + .addParam("width", OutTy, HLSLParamModifierAttr::Keyword_out) + .addParam("height", OutTy, HLSLParamModifierAttr::Keyword_out) + .addParam("numberOfLevels", OutTy, HLSLParamModifierAttr::Keyword_out) + .callBuiltin(LevelsXYName, QualType(), PH::Handle, PH::_0, PH::_1, + PH::_2, PH::_3) + .finalize(); + } + } + + return *this; +} + BuiltinTypeDeclBuilder & BuiltinTypeDeclBuilder::addCalculateLodMethods(ResourceDimension Dim) { assert(!Record->isCompleteDefinition() && "record is already complete"); diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h index 6f64d751a5811..1ffe5d9a624ef 100644 --- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h +++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h @@ -126,6 +126,7 @@ class BuiltinTypeDeclBuilder { BuiltinTypeDeclBuilder &addConsumeMethod(); BuiltinTypeDeclBuilder &addGetDimensionsMethodForBuffer(); + BuiltinTypeDeclBuilder &addGetDimensionsMethods(ResourceDimension Dim); BuiltinTypeDeclBuilder &addMipsMember(ResourceDimension Dim); private: diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp index 926c3d80e3bd9..235ede8eb0bf0 100644 --- a/clang/lib/Sema/HLSLExternalSemaSource.cpp +++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp @@ -272,6 +272,7 @@ static BuiltinTypeDeclBuilder setupTextureType(CXXRecordDecl *Decl, Sema &S, .addSampleCmpMethods(Dim) .addSampleCmpLevelZeroMethods(Dim) .addCalculateLodMethods(Dim) + .addGetDimensionsMethods(Dim) .addGatherMethods(Dim) .addGatherCmpMethods(Dim); } diff --git a/clang/test/AST/HLSL/Texture2D-scalar-AST.hlsl b/clang/test/AST/HLSL/Texture2D-scalar-AST.hlsl index 10ae411f474b6..f737b3279456b 100644 --- a/clang/test/AST/HLSL/Texture2D-scalar-AST.hlsl +++ b/clang/test/AST/HLSL/Texture2D-scalar-AST.hlsl @@ -508,6 +508,88 @@ // CHECK-NEXT: DeclRefExpr {{.*}} 'vector' lvalue ParmVar {{.*}} 'Location' 'vector' // CHECK-NEXT: AlwaysInlineAttr +// CHECK: CXXMethodDecl {{.*}} GetDimensions 'void (out unsigned int, out unsigned int)' +// CHECK-NEXT: ParmVarDecl {{.*}} width 'unsigned int &__restrict' +// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out +// CHECK-NEXT: ParmVarDecl {{.*}} height 'unsigned int &__restrict' +// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out +// CHECK-NEXT: CompoundStmt +// CHECK-NEXT: CallExpr {{.*}} '' +// CHECK-NEXT: DeclRefExpr {{.*}} '' Function {{.*}} '__builtin_hlsl_resource_getdimensions_xy' 'void (__hlsl_resource_t, unsigned int &, unsigned int &) noexcept' +// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t +// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]] +// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]] +// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]] +// CHECK-SAME: ' lvalue .__handle +// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2D' lvalue implicit this +// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'width' 'unsigned int &__restrict' +// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'height' 'unsigned int &__restrict' +// CHECK-NEXT: AlwaysInlineAttr + +// CHECK: CXXMethodDecl {{.*}} GetDimensions 'void (unsigned int, out unsigned int, out unsigned int, out unsigned int)' +// CHECK-NEXT: ParmVarDecl {{.*}} mipLevel 'unsigned int' +// CHECK-NEXT: ParmVarDecl {{.*}} width 'unsigned int &__restrict' +// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out +// CHECK-NEXT: ParmVarDecl {{.*}} height 'unsigned int &__restrict' +// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out +// CHECK-NEXT: ParmVarDecl {{.*}} numberOfLevels 'unsigned int &__restrict' +// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out +// CHECK-NEXT: CompoundStmt +// CHECK-NEXT: CallExpr {{.*}} '' +// CHECK-NEXT: DeclRefExpr {{.*}} '' Function {{.*}} '__builtin_hlsl_resource_getdimensions_levels_xy' 'void (__hlsl_resource_t, unsigned int, unsigned int &, unsigned int &, unsigned int &) noexcept' +// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t +// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]] +// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]] +// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]] +// CHECK-SAME: ' lvalue .__handle +// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2D' lvalue implicit this +// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'mipLevel' 'unsigned int' +// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'width' 'unsigned int &__restrict' +// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'height' 'unsigned int &__restrict' +// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'numberOfLevels' 'unsigned int &__restrict' +// CHECK-NEXT: AlwaysInlineAttr + +// CHECK: CXXMethodDecl {{.*}} GetDimensions 'void (out float, out float)' +// CHECK-NEXT: ParmVarDecl {{.*}} width 'float &__restrict' +// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out +// CHECK-NEXT: ParmVarDecl {{.*}} height 'float &__restrict' +// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out +// CHECK-NEXT: CompoundStmt +// CHECK-NEXT: CallExpr {{.*}} '' +// CHECK-NEXT: DeclRefExpr {{.*}} '' Function {{.*}} '__builtin_hlsl_resource_getdimensions_xy_float' 'void (__hlsl_resource_t, float &, float &) noexcept' +// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t +// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]] +// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]] +// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]] +// CHECK-SAME: ' lvalue .__handle +// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2D' lvalue implicit this +// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'width' 'float &__restrict' +// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'height' 'float &__restrict' +// CHECK-NEXT: AlwaysInlineAttr + +// CHECK: CXXMethodDecl {{.*}} GetDimensions 'void (unsigned int, out float, out float, out float)' +// CHECK-NEXT: ParmVarDecl {{.*}} mipLevel 'unsigned int' +// CHECK-NEXT: ParmVarDecl {{.*}} width 'float &__restrict' +// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out +// CHECK-NEXT: ParmVarDecl {{.*}} height 'float &__restrict' +// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out +// CHECK-NEXT: ParmVarDecl {{.*}} numberOfLevels 'float &__restrict' +// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out +// CHECK-NEXT: CompoundStmt +// CHECK-NEXT: CallExpr {{.*}} '' +// CHECK-NEXT: DeclRefExpr {{.*}} '' Function {{.*}} '__builtin_hlsl_resource_getdimensions_levels_xy_float' 'void (__hlsl_resource_t, unsigned int, float &, float &, float &) noexcept' +// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t +// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]] +// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]] +// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]] +// CHECK-SAME: ' lvalue .__handle +// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2D' lvalue implicit this +// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'mipLevel' 'unsigned int' +// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'width' 'float &__restrict' +// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'height' 'float &__restrict' +// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'numberOfLevels' 'float &__restrict' +// CHECK-NEXT: AlwaysInlineAttr + // CHECK: CXXMethodDecl {{.*}} Gather 'vector (hlsl::SamplerState, vector)' inline // CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState' // CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector' @@ -814,4 +896,10 @@ void main(float2 loc, float cmp) { t.CalculateLevelOfDetail(s, loc); t.CalculateLevelOfDetailUnclamped(s, loc); t.Gather(s, loc); + uint u_w, u_h, u_l; + float f_w, f_h, f_l; + t.GetDimensions(u_w, u_h); + t.GetDimensions(0, u_w, u_h, u_l); + t.GetDimensions(f_w, f_h); + t.GetDimensions(0, f_w, f_h, f_l); } diff --git a/clang/test/AST/HLSL/Texture2D-vector-AST.hlsl b/clang/test/AST/HLSL/Texture2D-vector-AST.hlsl index 36b569def89e1..5cd8976f5de8d 100644 --- a/clang/test/AST/HLSL/Texture2D-vector-AST.hlsl +++ b/clang/test/AST/HLSL/Texture2D-vector-AST.hlsl @@ -512,6 +512,84 @@ // CHECK-NEXT: DeclRefExpr {{.*}} 'vector' lvalue ParmVar {{.*}} 'Location' 'vector' // CHECK-NEXT: AlwaysInlineAttr +// CHECK: CXXMethodDecl {{.*}} GetDimensions 'void (out unsigned int, out unsigned int)' +// CHECK-NEXT: ParmVarDecl {{.*}} width 'unsigned int &__restrict' +// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out +// CHECK-NEXT: ParmVarDecl {{.*}} height 'unsigned int &__restrict' +// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out +// CHECK-NEXT: CompoundStmt +// CHECK-NEXT: CallExpr {{.*}} +// CHECK-NEXT: DeclRefExpr {{.*}} '__builtin_hlsl_resource_getdimensions_xy' 'void (__hlsl_resource_t, unsigned int &, unsigned int &) noexcept' +// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t +// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]] +// CHECK-SAME{LITERAL}: [[hlsl::contained_type(vector)]] +// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]] +// CHECK-SAME: ' lvalue .__handle +// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2D>' lvalue implicit this +// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'width' 'unsigned int &__restrict' +// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'height' 'unsigned int &__restrict' + +// CHECK: CXXMethodDecl {{.*}} GetDimensions 'void (unsigned int, out unsigned int, out unsigned int, out unsigned int)' +// CHECK-NEXT: ParmVarDecl {{.*}} mipLevel 'unsigned int' +// CHECK-NEXT: ParmVarDecl {{.*}} width 'unsigned int &__restrict' +// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out +// CHECK-NEXT: ParmVarDecl {{.*}} height 'unsigned int &__restrict' +// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out +// CHECK-NEXT: ParmVarDecl {{.*}} numberOfLevels 'unsigned int &__restrict' +// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out +// CHECK-NEXT: CompoundStmt +// CHECK-NEXT: CallExpr {{.*}} +// CHECK-NEXT: DeclRefExpr {{.*}} '__builtin_hlsl_resource_getdimensions_levels_xy' 'void (__hlsl_resource_t, unsigned int, unsigned int &, unsigned int &, unsigned int &) noexcept' +// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t +// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]] +// CHECK-SAME{LITERAL}: [[hlsl::contained_type(vector)]] +// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]] +// CHECK-SAME: ' lvalue .__handle +// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2D>' lvalue implicit this +// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'mipLevel' 'unsigned int' +// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'width' 'unsigned int &__restrict' +// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'height' 'unsigned int &__restrict' +// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'numberOfLevels' 'unsigned int &__restrict' + +// CHECK: CXXMethodDecl {{.*}} GetDimensions 'void (out float, out float)' +// CHECK-NEXT: ParmVarDecl {{.*}} width 'float &__restrict' +// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out +// CHECK-NEXT: ParmVarDecl {{.*}} height 'float &__restrict' +// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out +// CHECK-NEXT: CompoundStmt +// CHECK-NEXT: CallExpr {{.*}} +// CHECK-NEXT: DeclRefExpr {{.*}} '__builtin_hlsl_resource_getdimensions_xy_float' 'void (__hlsl_resource_t, float &, float &) noexcept' +// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t +// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]] +// CHECK-SAME{LITERAL}: [[hlsl::contained_type(vector)]] +// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]] +// CHECK-SAME: ' lvalue .__handle +// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2D>' lvalue implicit this +// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'width' 'float &__restrict' +// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'height' 'float &__restrict' + +// CHECK: CXXMethodDecl {{.*}} GetDimensions 'void (unsigned int, out float, out float, out float)' +// CHECK-NEXT: ParmVarDecl {{.*}} mipLevel 'unsigned int' +// CHECK-NEXT: ParmVarDecl {{.*}} width 'float &__restrict' +// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out +// CHECK-NEXT: ParmVarDecl {{.*}} height 'float &__restrict' +// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out +// CHECK-NEXT: ParmVarDecl {{.*}} numberOfLevels 'float &__restrict' +// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out +// CHECK-NEXT: CompoundStmt +// CHECK-NEXT: CallExpr {{.*}} +// CHECK-NEXT: DeclRefExpr {{.*}} '__builtin_hlsl_resource_getdimensions_levels_xy_float' 'void (__hlsl_resource_t, unsigned int, float &, float &, float &) noexcept' +// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t +// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]] +// CHECK-SAME{LITERAL}: [[hlsl::contained_type(vector)]] +// CHECK-SAME{LITERAL}: [[hlsl::resource_dimension(2D)]] +// CHECK-SAME: ' lvalue .__handle +// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::Texture2D>' lvalue implicit this +// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' lvalue ParmVar {{.*}} 'mipLevel' 'unsigned int' +// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'width' 'float &__restrict' +// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'height' 'float &__restrict' +// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'numberOfLevels' 'float &__restrict' + // CHECK: CXXMethodDecl {{.*}} Gather 'vector (hlsl::SamplerState, vector)' inline // CHECK-NEXT: ParmVarDecl {{.*}} Sampler 'hlsl::SamplerState' // CHECK-NEXT: ParmVarDecl {{.*}} Location 'vector' @@ -818,4 +896,10 @@ void main(float2 loc, float cmp) { t.CalculateLevelOfDetail(s, loc); t.CalculateLevelOfDetailUnclamped(s, loc); t.Gather(s, loc); + uint u_w, u_h, u_l; + float f_w, f_h, f_l; + t.GetDimensions(u_w, u_h); + t.GetDimensions(0, u_w, u_h, u_l); + t.GetDimensions(f_w, f_h); + t.GetDimensions(0, f_w, f_h, f_l); } diff --git a/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl b/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl index d4a5e74aaa087..fa04d82d54fb0 100644 --- a/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl +++ b/clang/test/CodeGenHLSL/resources/ByteAddressBuffers-methods.hlsl @@ -188,16 +188,16 @@ export uint TestGetDimensions() { // CHECK: define {{.*}} void @hlsl::ByteAddressBuffer::GetDimensions(unsigned int&)(ptr {{.*}} %this, {{.*}} %dim) // CHECK: %[[HANDLE_PTR:.*]] = getelementptr inbounds nuw %"class.hlsl::ByteAddressBuffer", ptr %{{.*}}, i32 0, i32 0 // CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", i8, 0, 0), ptr %[[HANDLE_PTR]] -// CHECK-NEXT: %[[DIMPTR:.*]] = load ptr, ptr %dim.addr // DXIL-NEXT: %[[DIM:.*]] = call i32 @llvm.dx.resource.getdimensions.x.tdx.RawBuffer_i8_0_0t(target("dx.RawBuffer", i8, 0, 0) %[[HANDLE]]) +// CHECK-NEXT: %[[DIMPTR:.*]] = load ptr, ptr %dim.addr // CHECK-NEXT: store i32 %[[DIM]], ptr %[[DIMPTR]] // CHECK-NEXT: ret void // CHECK: define {{.*}} void @hlsl::RWByteAddressBuffer::GetDimensions(unsigned int&)(ptr {{.*}} %this, ptr noalias {{.*}} %dim) // CHECK: %[[HANDLE_PTR:.*]] = getelementptr inbounds nuw %"class.hlsl::RWByteAddressBuffer", ptr %{{.*}}, i32 0, i32 0 // CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", i8, 1, 0), ptr %[[HANDLE_PTR]] -// CHECK-NEXT: %[[DIMPTR:.*]] = load ptr, ptr %dim.addr // DXIL-NEXT: %[[DIM:.*]] = call i32 @llvm.dx.resource.getdimensions.x.tdx.RawBuffer_i8_1_0t(target("dx.RawBuffer", i8, 1, 0) %[[HANDLE]]) +// CHECK-NEXT: %[[DIMPTR:.*]] = load ptr, ptr %dim.addr // CHECK-NEXT: store i32 %[[DIM]], ptr %[[DIMPTR]] // CHECK-NEXT: ret void diff --git a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl index f62dec5d07984..12a644b4d4355 100644 --- a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl +++ b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl @@ -159,8 +159,8 @@ export uint TestGetDimensions() { // CHECK: define {{.*}} void @hlsl::StructuredBuffer::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}}, ptr {{.*}} %numStructs, ptr {{.*}} %stride) // CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::StructuredBuffer", ptr %{{.*}}, i32 0, i32 0 // CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", float, 0, 0), ptr %__handle -// CHECK-NEXT: %[[NUMSTRUCTS_PTR:.*]] = load ptr, ptr %numStructs.addr // DXIL-NEXT: %[[NUMSTRUCTS:.*]] = call i32 @llvm.dx.resource.getdimensions.x.tdx.RawBuffer_f32_0_0t(target("dx.RawBuffer", float, 0, 0) %[[HANDLE]]) +// CHECK-NEXT: %[[NUMSTRUCTS_PTR:.*]] = load ptr, ptr %numStructs.addr // CHECK-NEXT: store i32 %[[NUMSTRUCTS]], ptr %[[NUMSTRUCTS_PTR]] // CHECK-NEXT: %[[STRIDEPTR:.*]] = load ptr, ptr %stride.addr // CHECK-NEXT: store i32 4, ptr %[[STRIDEPTR]] @@ -169,8 +169,8 @@ export uint TestGetDimensions() { // CHECK: define {{.*}} void @hlsl::RWStructuredBuffer::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}} %this, {{.*}} %numStructs, {{.*}} %stride) // CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RWStructuredBuffer.0", ptr %{{.*}}, i32 0, i32 0 // CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", <4 x i32>, 1, 0), ptr %__handle -// CHECK-NEXT: %[[NUMSTRUCTS_PTR:.*]] = load ptr, ptr %numStructs.addr // DXIL-NEXT: %[[NUMSTRUCTS:.*]] = call i32 @llvm.dx.resource.getdimensions.x.tdx.RawBuffer_v4i32_1_0t(target("dx.RawBuffer", <4 x i32>, 1, 0) %[[HANDLE]]) +// CHECK-NEXT: %[[NUMSTRUCTS_PTR:.*]] = load ptr, ptr %numStructs.addr // CHECK-NEXT: store i32 %[[NUMSTRUCTS]], ptr %[[NUMSTRUCTS_PTR]] // CHECK-NEXT: %[[STRIDEPTR:.*]] = load ptr, ptr %stride.addr // CHECK-NEXT: store i32 16, ptr %[[STRIDEPTR]] @@ -179,8 +179,8 @@ export uint TestGetDimensions() { // CHECK: define {{.*}} void @hlsl::ConsumeStructuredBuffer::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}} %this, {{.*}} %numStructs, {{.*}} %stride) // CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::ConsumeStructuredBuffer", ptr %{{.*}}, i32 0, i32 0 // CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", double, 1, 0), ptr %__handle -// CHECK-NEXT: %[[NUMSTRUCTS_PTR:.*]] = load ptr, ptr %numStructs.addr // DXIL-NEXT: %[[NUMSTRUCTS:.*]] = call i32 @llvm.dx.resource.getdimensions.x.tdx.RawBuffer_f64_1_0t(target("dx.RawBuffer", double, 1, 0) %[[HANDLE]]) +// CHECK-NEXT: %[[NUMSTRUCTS_PTR:.*]] = load ptr, ptr %numStructs.addr // CHECK-NEXT: store i32 %[[NUMSTRUCTS]], ptr %[[NUMSTRUCTS_PTR]] // CHECK-NEXT: %[[STRIDEPTR:.*]] = load ptr, ptr %stride.addr // CHECK-NEXT: store i32 8, ptr %[[STRIDEPTR]] diff --git a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-ps.hlsl b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-ps.hlsl index 9712f8768b639..85ca449bc6ea3 100644 --- a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-ps.hlsl +++ b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-ps.hlsl @@ -117,8 +117,8 @@ export uint TestGetDimensions() { // CHECK: define {{.*}} void @hlsl::RasterizerOrderedStructuredBuffer::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}}, ptr {{.*}} %numStructs, ptr {{.*}} %stride) // CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RasterizerOrderedStructuredBuffer", ptr %{{.*}}, i32 0, i32 0 // DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", float, 1, 1), ptr %__handle -// CHECK-NEXT: %[[NUMSTRUCTS_PTR:.*]] = load ptr, ptr %numStructs.addr // DXIL-NEXT: %[[NUMSTRUCTS:.*]] = call i32 @llvm.dx.resource.getdimensions.x.tdx.RawBuffer_f32_1_1t(target("dx.RawBuffer", float, 1, 1) %[[HANDLE]]) +// CHECK-NEXT: %[[NUMSTRUCTS_PTR:.*]] = load ptr, ptr %numStructs.addr // CHECK-NEXT: store i32 %[[NUMSTRUCTS]], ptr %[[NUMSTRUCTS_PTR]] // CHECK-NEXT: %[[STRIDEPTR:.*]] = load ptr, ptr %stride.addr // CHECK-NEXT: store i32 4, ptr %[[STRIDEPTR]] @@ -127,8 +127,8 @@ export uint TestGetDimensions() { // CHECK: define {{.*}} void @hlsl::RasterizerOrderedStructuredBuffer::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}}, ptr {{.*}} %numStructs, ptr {{.*}} %stride) // CHECK: %__handle = getelementptr inbounds nuw %"class.hlsl::RasterizerOrderedStructuredBuffer.0", ptr %{{.*}}, i32 0, i32 0 // DXIL-NEXT: %[[HANDLE:.*]] = load target("dx.RawBuffer", <2 x i32>, 1, 1), ptr %__handle -// CHECK-NEXT: %[[NUMSTRUCTS_PTR:.*]] = load ptr, ptr %numStructs.addr // DXIL-NEXT: %[[NUMSTRUCTS:.*]] = call i32 @llvm.dx.resource.getdimensions.x.tdx.RawBuffer_v2i32_1_1t(target("dx.RawBuffer", <2 x i32>, 1, 1) %[[HANDLE]]) +// CHECK-NEXT: %[[NUMSTRUCTS_PTR:.*]] = load ptr, ptr %numStructs.addr // CHECK-NEXT: store i32 %[[NUMSTRUCTS]], ptr %[[NUMSTRUCTS_PTR]] // CHECK-NEXT: %[[STRIDEPTR:.*]] = load ptr, ptr %stride.addr // CHECK-NEXT: store i32 8, ptr %[[STRIDEPTR]] diff --git a/clang/test/CodeGenHLSL/resources/Texture2D-GetDimensions.hlsl b/clang/test/CodeGenHLSL/resources/Texture2D-GetDimensions.hlsl new file mode 100644 index 0000000000000..27e847fb91ed3 --- /dev/null +++ b/clang/test/CodeGenHLSL/resources/Texture2D-GetDimensions.hlsl @@ -0,0 +1,103 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -emit-llvm -disable-llvm-passes -finclude-default-header -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,DXIL +// RUN: %clang_cc1 -triple spirv-vulkan-library -x hlsl -emit-llvm -disable-llvm-passes -finclude-default-header -o - %s | llvm-cxxfilt | FileCheck %s --check-prefixes=CHECK,SPIRV + +Texture2D Tex : register(t0); + +// CHECK: define {{.*}} void @test_uint_dims() +// CHECK: call void @hlsl::Texture2D::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}} @Tex, ptr {{.*}}, ptr {{.*}}) +void test_uint_dims() { + uint w, h; + Tex.GetDimensions(w, h); +} + +// TODO: The test will have to be updated because the return type for the getdimensions intrinsic will no longer a overloaded. + +// CHECK: define linkonce_odr hidden void @hlsl::Texture2D::GetDimensions(unsigned int&, unsigned int&)(ptr {{.*}} %[[THIS:.*]], ptr {{.*}} %[[WIDTH:.*]], ptr {{.*}} %[[HEIGHT:.*]]) +// CHECK: %[[THIS_VAL:.*]] = load ptr, ptr %[[THIS]] +// CHECK: %[[HANDLE_GEP:.*]] = getelementptr inbounds nuw %"class.hlsl::Texture2D", ptr %[[THIS_VAL]], i32 0, i32 0 +// DXIL: %[[HANDLE:.*]] = load target("dx.Texture", <4 x float>, 0, 0, 0, 2), ptr %[[HANDLE_GEP]] +// SPIRV: %[[HANDLE:.*]] = load target("spirv.Image", float, 1, 2, 0, 0, 1, 0), ptr %[[HANDLE_GEP]] +// DXIL: %[[RES:.*]] = call <2 x i32> @llvm.dx.resource.getdimensions.xy.tdx.Texture_v4f32_0_0_0_2t(target("dx.Texture", <4 x float>, 0, 0, 0, 2) %[[HANDLE]]) +// SPIRV: %[[RES:.*]] = call <2 x i32> @llvm.spv.resource.getdimensions.xy.tspirv.Image_f32_1_2_0_0_1_0t(target("spirv.Image", float, 1, 2, 0, 0, 1, 0) %[[HANDLE]]) +// CHECK: %[[W_PTR:.*]] = load ptr, ptr %[[WIDTH]] +// CHECK: %[[W_VAL:.*]] = extractelement <2 x i32> %[[RES]], i64 0 +// CHECK: store i32 %[[W_VAL]], ptr %[[W_PTR]] +// CHECK: %[[H_PTR:.*]] = load ptr, ptr %[[HEIGHT]] +// CHECK: %[[H_VAL:.*]] = extractelement <2 x i32> %[[RES]], i64 1 +// CHECK: store i32 %[[H_VAL]], ptr %[[H_PTR]] + +// CHECK: define {{.*}} void @test_uint_levels_dims{{.*}}(i32 noundef %[[MIP_LEVEL:.*]]) +// CHECK: call void @hlsl::Texture2D::GetDimensions(unsigned int, unsigned int&, unsigned int&, unsigned int&)(ptr {{.*}} @Tex, i32 noundef %{{.*}}, ptr {{.*}}, ptr {{.*}}, ptr {{.*}}) +void test_uint_levels_dims(uint mipLevel) { + uint w, h, l; + Tex.GetDimensions(mipLevel, w, h, l); +} + +// CHECK: define linkonce_odr hidden void @hlsl::Texture2D::GetDimensions(unsigned int, unsigned int&, unsigned int&, unsigned int&)(ptr {{.*}} %[[THIS:.*]], i32 {{.*}} %[[MIP:.*]], ptr {{.*}} %[[WIDTH:.*]], ptr {{.*}} %[[HEIGHT:.*]], ptr {{.*}} %[[LEVELS:.*]]) +// CHECK: %[[THIS_VAL:.*]] = load ptr, ptr %[[THIS]] +// CHECK: %[[HANDLE_GEP:.*]] = getelementptr inbounds nuw %"class.hlsl::Texture2D", ptr %[[THIS_VAL]], i32 0, i32 0 +// DXIL: %[[HANDLE:.*]] = load target("dx.Texture", <4 x float>, 0, 0, 0, 2), ptr %[[HANDLE_GEP]] +// SPIRV: %[[HANDLE:.*]] = load target("spirv.Image", float, 1, 2, 0, 0, 1, 0), ptr %[[HANDLE_GEP]] +// CHECK: %[[MIP_VAL:.*]] = load i32, ptr %[[MIP]] +// DXIL: %[[RES:.*]] = call <3 x i32> @llvm.dx.resource.getdimensions.levels.xy.tdx.Texture_v4f32_0_0_0_2t(target("dx.Texture", <4 x float>, 0, 0, 0, 2) %[[HANDLE]], i32 %[[MIP_VAL]]) +// SPIRV: %[[RES:.*]] = call <3 x i32> @llvm.spv.resource.getdimensions.levels.xy.tspirv.Image_f32_1_2_0_0_1_0t(target("spirv.Image", float, 1, 2, 0, 0, 1, 0) %[[HANDLE]], i32 %[[MIP_VAL]]) +// CHECK: %[[W_PTR:.*]] = load ptr, ptr %[[WIDTH]] +// CHECK: %[[W_VAL:.*]] = extractelement <3 x i32> %[[RES]], i64 0 +// CHECK: store i32 %[[W_VAL]], ptr %[[W_PTR]] +// CHECK: %[[H_PTR:.*]] = load ptr, ptr %[[HEIGHT]] +// CHECK: %[[H_VAL:.*]] = extractelement <3 x i32> %[[RES]], i64 1 +// CHECK: store i32 %[[H_VAL]], ptr %[[H_PTR]] +// CHECK: %[[L_PTR:.*]] = load ptr, ptr %[[LEVELS]] +// CHECK: %[[L_VAL:.*]] = extractelement <3 x i32> %[[RES]], i64 2 +// CHECK: store i32 %[[L_VAL]], ptr %[[L_PTR]] + +// CHECK: define {{.*}} void @test_float_dims() +// CHECK: call void @hlsl::Texture2D::GetDimensions(float&, float&)(ptr {{.*}} @Tex, ptr {{.*}}, ptr {{.*}}) +void test_float_dims() { + float w, h; + Tex.GetDimensions(w, h); +} + +// CHECK: define linkonce_odr hidden void @hlsl::Texture2D::GetDimensions(float&, float&)(ptr {{.*}} %[[THIS:.*]], ptr {{.*}} %[[WIDTH:.*]], ptr {{.*}} %[[HEIGHT:.*]]) +// CHECK: %[[THIS_VAL:.*]] = load ptr, ptr %[[THIS]] +// CHECK: %[[HANDLE_GEP:.*]] = getelementptr inbounds nuw %"class.hlsl::Texture2D", ptr %[[THIS_VAL]], i32 0, i32 0 +// DXIL: %[[HANDLE:.*]] = load target("dx.Texture", <4 x float>, 0, 0, 0, 2), ptr %[[HANDLE_GEP]] +// SPIRV: %[[HANDLE:.*]] = load target("spirv.Image", float, 1, 2, 0, 0, 1, 0), ptr %[[HANDLE_GEP]] +// DXIL: %[[RES:.*]] = call <2 x i32> @llvm.dx.resource.getdimensions.xy.tdx.Texture_v4f32_0_0_0_2t(target("dx.Texture", <4 x float>, 0, 0, 0, 2) %[[HANDLE]]) +// SPIRV: %[[RES:.*]] = call <2 x i32> @llvm.spv.resource.getdimensions.xy.tspirv.Image_f32_1_2_0_0_1_0t(target("spirv.Image", float, 1, 2, 0, 0, 1, 0) %[[HANDLE]]) +// CHECK: %[[W_PTR:.*]] = load ptr, ptr %[[WIDTH]] +// CHECK: %[[W_VAL:.*]] = extractelement <2 x i32> %[[RES]], i64 0 +// CHECK: %[[W_F:.*]] = uitofp i32 %[[W_VAL]] to float +// CHECK: store float %[[W_F]], ptr %[[W_PTR]] +// CHECK: %[[H_PTR:.*]] = load ptr, ptr %[[HEIGHT]] +// CHECK: %[[H_VAL:.*]] = extractelement <2 x i32> %[[RES]], i64 1 +// CHECK: %[[H_F:.*]] = uitofp i32 %[[H_VAL]] to float +// CHECK: store float %[[H_F]], ptr %[[H_PTR]] + +// CHECK: define {{.*}} void @test_float_levels_dims{{.*}}(i32 noundef %[[MIP_LEVEL:.*]]) +// CHECK: call void @hlsl::Texture2D::GetDimensions(unsigned int, float&, float&, float&)(ptr {{.*}} @Tex, i32 noundef %{{.*}}, ptr {{.*}}, ptr {{.*}}, ptr {{.*}}) +void test_float_levels_dims(uint mipLevel) { + float w, h, l; + Tex.GetDimensions(mipLevel, w, h, l); +} + +// CHECK: define linkonce_odr hidden void @hlsl::Texture2D::GetDimensions(unsigned int, float&, float&, float&)(ptr {{.*}} %[[THIS:.*]], i32 {{.*}} %[[MIP:.*]], ptr {{.*}} %[[WIDTH:.*]], ptr {{.*}} %[[HEIGHT:.*]], ptr {{.*}} %[[LEVELS:.*]]) +// CHECK: %[[THIS_VAL:.*]] = load ptr, ptr %[[THIS]] +// CHECK: %[[HANDLE_GEP:.*]] = getelementptr inbounds nuw %"class.hlsl::Texture2D", ptr %[[THIS_VAL]], i32 0, i32 0 +// DXIL: %[[HANDLE:.*]] = load target("dx.Texture", <4 x float>, 0, 0, 0, 2), ptr %[[HANDLE_GEP]] +// SPIRV: %[[HANDLE:.*]] = load target("spirv.Image", float, 1, 2, 0, 0, 1, 0), ptr %[[HANDLE_GEP]] +// CHECK: %[[MIP_VAL:.*]] = load i32, ptr %[[MIP]] +// DXIL: %[[RES:.*]] = call <3 x i32> @llvm.dx.resource.getdimensions.levels.xy.tdx.Texture_v4f32_0_0_0_2t(target("dx.Texture", <4 x float>, 0, 0, 0, 2) %[[HANDLE]], i32 %[[MIP_VAL]]) +// SPIRV: %[[RES:.*]] = call <3 x i32> @llvm.spv.resource.getdimensions.levels.xy.tspirv.Image_f32_1_2_0_0_1_0t(target("spirv.Image", float, 1, 2, 0, 0, 1, 0) %[[HANDLE]], i32 %[[MIP_VAL]]) +// CHECK: %[[W_PTR:.*]] = load ptr, ptr %[[WIDTH]] +// CHECK: %[[W_VAL:.*]] = extractelement <3 x i32> %[[RES]], i64 0 +// CHECK: %[[W_F:.*]] = uitofp i32 %[[W_VAL]] to float +// CHECK: store float %[[W_F]], ptr %[[W_PTR]] +// CHECK: %[[H_PTR:.*]] = load ptr, ptr %[[HEIGHT]] +// CHECK: %[[H_VAL:.*]] = extractelement <3 x i32> %[[RES]], i64 1 +// CHECK: %[[H_F:.*]] = uitofp i32 %[[H_VAL]] to float +// CHECK: store float %[[H_F]], ptr %[[H_PTR]] +// CHECK: %[[L_PTR:.*]] = load ptr, ptr %[[LEVELS]] +// CHECK: %[[L_VAL:.*]] = extractelement <3 x i32> %[[RES]], i64 2 +// CHECK: %[[L_F:.*]] = uitofp i32 %[[L_VAL]] to float +// CHECK: store float %[[L_F]], ptr %[[L_PTR]] diff --git a/clang/test/CodeGenHLSL/resources/TypedBuffers-methods.hlsl b/clang/test/CodeGenHLSL/resources/TypedBuffers-methods.hlsl index 8f255100159a9..bdf7f4d7fd388 100644 --- a/clang/test/CodeGenHLSL/resources/TypedBuffers-methods.hlsl +++ b/clang/test/CodeGenHLSL/resources/TypedBuffers-methods.hlsl @@ -92,16 +92,16 @@ export uint TestGetDimensions() { // CHECK: define {{.*}} void @hlsl::Buffer::GetDimensions(unsigned int&)(ptr {{.*}} %this, ptr noalias {{.*}} %dim) // CHECK: %[[HANDLE_PTR:.*]] = getelementptr inbounds nuw %"class.hlsl::Buffer", ptr %this1, i32 0, i32 0 // CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.TypedBuffer", float, 0, 0, 0), ptr %[[HANDLE_PTR]] -// CHECK-NEXT: %[[DIMPTR:.*]] = load ptr, ptr %dim.addr // DXIL-NEXT: %[[DIM:.*]] = call i32 @llvm.dx.resource.getdimensions.x.tdx.TypedBuffer_f32_0_0_0t(target("dx.TypedBuffer", float, 0, 0, 0) %[[HANDLE]]) +// CHECK-NEXT: %[[DIMPTR:.*]] = load ptr, ptr %dim.addr // CHECK-NEXT: store i32 %[[DIM]], ptr %[[DIMPTR]] // CHECK-NEXT: ret void // CHECK: define {{.*}} void @hlsl::RWBuffer::GetDimensions(unsigned int&)(ptr {{.*}} %this, {{.*}} %dim) // CHECK: %[[HANDLE_PTR:.*]] = getelementptr inbounds nuw %"class.hlsl::RWBuffer", ptr %{{.*}}, i32 0, i32 0 // CHECK-NEXT: %[[HANDLE:.*]] = load target("dx.TypedBuffer", <4 x i32>, 1, 0, 0), ptr %[[HANDLE_PTR]] -// CHECK-NEXT: %[[DIMPTR:.*]] = load ptr, ptr %dim.addr // DXIL-NEXT: %[[DIM:.*]] = call i32 @llvm.dx.resource.getdimensions.x.tdx.TypedBuffer_v4i32_1_0_0t(target("dx.TypedBuffer", <4 x i32>, 1, 0, 0) %[[HANDLE]]) +// CHECK-NEXT: %[[DIMPTR:.*]] = load ptr, ptr %dim.addr // CHECK-NEXT: store i32 %[[DIM]], ptr %[[DIMPTR]] // CHECK-NEXT: ret void diff --git a/clang/test/SemaHLSL/Resources/Texture2D-GetDimensions.hlsl b/clang/test/SemaHLSL/Resources/Texture2D-GetDimensions.hlsl new file mode 100644 index 0000000000000..c6886f975ea59 --- /dev/null +++ b/clang/test/SemaHLSL/Resources/Texture2D-GetDimensions.hlsl @@ -0,0 +1,80 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -finclude-default-header -fsyntax-only -verify %s + +Texture2D tex; + +void main() { + uint u_w, u_h, u_l; + float f_w, f_h, f_l; + + // Valid calls + tex.GetDimensions(u_w, u_h); + tex.GetDimensions(0, u_w, u_h, u_l); + tex.GetDimensions(f_w, f_h); + tex.GetDimensions(0, f_w, f_h, f_l); + + // Invalid number of arguments + // expected-error@+1 {{no matching member function for call to 'GetDimensions'}} + tex.GetDimensions(); + // expected-note@*:* 2 {{candidate function not viable: requires 2 arguments, but 0 were provided}} + // expected-note@*:* 2 {{candidate function not viable: requires 4 arguments, but 0 were provided}} + + // expected-error@+1 {{no matching member function for call to 'GetDimensions'}} + tex.GetDimensions(u_w); + // expected-note@*:* 2 {{candidate function not viable: requires 2 arguments, but 1 was provided}} + // expected-note@*:* 2 {{candidate function not viable: requires 4 arguments, but 1 was provided}} + + // expected-error@+1 {{no matching member function for call to 'GetDimensions'}} + tex.GetDimensions(u_w, u_h, u_l); + // expected-note@*:* 2 {{candidate function not viable: requires 2 arguments, but 3 were provided}} + // expected-note@*:* 2 {{candidate function not viable: requires 4 arguments, but 3 were provided}} + + // expected-error@+1 {{no matching member function for call to 'GetDimensions'}} + tex.GetDimensions(0, u_w, u_h, u_l, 0); + // expected-note@*:* 2 {{candidate function not viable: requires 4 arguments, but 5 were provided}} + // expected-note@*:* 2 {{candidate function not viable: requires 2 arguments, but 5 were provided}} + + // Invalid types + int i_w, i_h; + // expected-error@+1 {{no matching member function for call to 'GetDimensions'}} + tex.GetDimensions(i_w, i_h); + // expected-note@*:* {{candidate function not viable: no known conversion from 'int' to 'unsigned int &__restrict' for 1st argument}} + // expected-note@*:* {{candidate function not viable: no known conversion from 'int' to 'float &__restrict' for 1st argument}} + // expected-note@*:* 2 {{candidate function not viable: requires 4 arguments, but 2 were provided}} + + // expected-error@+1 {{no matching member function for call to 'GetDimensions'}} + tex.GetDimensions(u_w, i_h); + // expected-note@*:* {{candidate function not viable: no known conversion from 'int' to 'unsigned int &__restrict' for 2nd argument}} + // expected-note@*:* {{candidate function not viable: no known conversion from 'uint' (aka 'unsigned int') to 'float &__restrict' for 1st argument}} + // expected-note@*:* 2 {{candidate function not viable: requires 4 arguments, but 2 were provided}} + + // Invalid lvalues + // expected-error@+1 {{no matching member function for call to 'GetDimensions'}} + tex.GetDimensions(0u, u_h); + // expected-note@*:* {{candidate function not viable: expects an lvalue for 1st argument}} + // expected-note@*:* {{candidate function not viable: no known conversion from 'unsigned int' to 'float &__restrict' for 1st argument}} + // expected-note@*:* 2 {{candidate function not viable: requires 4 arguments, but 2 were provided}} + + // expected-error@+1 {{no matching member function for call to 'GetDimensions'}} + tex.GetDimensions(u_w, 0u); + // expected-note@*:* {{candidate function not viable: expects an lvalue for 2nd argument}} + // expected-note@*:* {{candidate function not viable: no known conversion from 'uint' (aka 'unsigned int') to 'float &__restrict' for 1st argument}} + // expected-note@*:* 2 {{candidate function not viable: requires 4 arguments, but 2 were provided}} + + // expected-error@+1 {{no matching member function for call to 'GetDimensions'}} + tex.GetDimensions(0, 0u, u_h, u_l); + // expected-note@*:* {{candidate function not viable: expects an lvalue for 2nd argument}} + // expected-note@*:* {{candidate function not viable: no known conversion from 'unsigned int' to 'float &__restrict' for 2nd argument}} + // expected-note@*:* 2 {{candidate function not viable: requires 2 arguments, but 4 were provided}} + + // expected-error@+1 {{no matching member function for call to 'GetDimensions'}} + tex.GetDimensions(0, u_w, 0u, u_l); + // expected-note@*:* {{candidate function not viable: expects an lvalue for 3rd argument}} + // expected-note@*:* {{candidate function not viable: no known conversion from 'uint' (aka 'unsigned int') to 'float &__restrict' for 2nd argument}} + // expected-note@*:* 2 {{candidate function not viable: requires 2 arguments, but 4 were provided}} + + // expected-error@+1 {{no matching member function for call to 'GetDimensions'}} + tex.GetDimensions(0, u_w, u_h, 0u); + // expected-note@*:* {{candidate function not viable: expects an lvalue for 4th argument}} + // expected-note@*:* {{candidate function not viable: no known conversion from 'uint' (aka 'unsigned int') to 'float &__restrict' for 2nd argument}} + // expected-note@*:* 2 {{candidate function not viable: requires 2 arguments, but 4 were provided}} +} diff --git a/llvm/include/llvm/IR/IntrinsicsDirectX.td b/llvm/include/llvm/IR/IntrinsicsDirectX.td index 8350922193338..728bf47a17516 100644 --- a/llvm/include/llvm/IR/IntrinsicsDirectX.td +++ b/llvm/include/llvm/IR/IntrinsicsDirectX.td @@ -79,6 +79,10 @@ def int_dx_resource_updatecounter def int_dx_resource_getdimensions_x : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_any_ty], [IntrReadMem]>; +def int_dx_resource_getdimensions_xy + : DefaultAttrsIntrinsic<[llvm_v2i32_ty], [llvm_any_ty], [IntrReadMem]>; +def int_dx_resource_getdimensions_levels_xy + : DefaultAttrsIntrinsic<[llvm_v3i32_ty], [llvm_any_ty, llvm_i32_ty], [IntrReadMem]>; def int_dx_resource_sample : DefaultAttrsIntrinsic<