-
Notifications
You must be signed in to change notification settings - Fork 14.9k
[HLSL] GetDimensions methods for buffer resources #161929
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Refactoring structured buffer tests to make it clearer that - the test functions call the buffer methods - the buffer methods are defined after each test function - show what the buffer methods bodies look like - use buffers with different element types, not just `float` - use `llvm-cxxfilt` tool to de-mangle names
Test coverage for `Buffer` resource class was not sufficient. All of the typed buffer tests were using RWBuffer. This change adds `Buffer` tests cases to several existing `RWBuffer-*.test` files and renames them to `TypedBuffer-*.test`. Also adds new `TypedBuffers-methods.tests`.
…m/hekota/llvm-project into users/hekota/pr161909+pr161908
@llvm/pr-subscribers-hlsl @llvm/pr-subscribers-clang Author: Helena Kotas (hekota) ChangesAdds GetDimensions methods on all supported buffer resources. Patch is 32.14 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/161929.diff 13 Files Affected:
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 468121f7d20ab..0b1587be51217 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4951,6 +4951,18 @@ def HLSLResourceNonUniformIndex : LangBuiltin<"HLSL_LANG"> {
let Prototype = "uint32_t(uint32_t)";
}
+def HLSLResourceGetDimensions : LangBuiltin<"HLSL_LANG"> {
+ let Spellings = ["__builtin_hlsl_buffer_getdimensions"];
+ let Attributes = [NoThrow];
+ let Prototype = "void(...)";
+}
+
+def HLSLResourceGetStride : LangBuiltin<"HLSL_LANG"> {
+ let Spellings = ["__builtin_hlsl_buffer_getstride"];
+ let Attributes = [NoThrow];
+ let Prototype = "void(...)";
+}
+
def HLSLAll : LangBuiltin<"HLSL_LANG"> {
let Spellings = ["__builtin_hlsl_all"];
let Attributes = [NoThrow, Const];
diff --git a/clang/lib/CodeGen/CGHLSLBuiltins.cpp b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
index 6c0fc8d7f07be..373153e01c128 100644
--- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp
+++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp
@@ -160,6 +160,58 @@ static Value *handleHlslSplitdouble(const CallExpr *E, CodeGenFunction *CGF) {
return LastInst;
}
+static Value *emitDXILGetDimensions(CodeGenFunction *CGF, Value *Handle,
+ Value *MipLevel, LValue *OutArg0,
+ LValue *OutArg1 = nullptr,
+ LValue *OutArg2 = nullptr,
+ LValue *OutArg3 = nullptr) {
+ assert(OutArg0 && "first output argument is required");
+
+ llvm::Type *I32 = CGF->Int32Ty;
+ StructType *RetTy = llvm::StructType::get(I32, I32, I32, I32);
+
+ CallInst *CI = CGF->Builder.CreateIntrinsic(
+ RetTy, llvm::Intrinsic::dx_resource_getdimensions,
+ ArrayRef<Value *>{Handle, MipLevel});
+
+ Value *LastInst = nullptr;
+ unsigned OutArgIndex = 0;
+ for (LValue *OutArg : {OutArg0, OutArg1, OutArg2, OutArg3}) {
+ if (OutArg) {
+ Value *OutArgVal = CGF->Builder.CreateExtractValue(CI, OutArgIndex);
+ LastInst = CGF->Builder.CreateStore(OutArgVal, OutArg->getAddress());
+ }
+ ++OutArgIndex;
+ }
+ assert(LastInst && "no output argument stored?");
+ return LastInst;
+}
+
+static Value *emitBufferGetDimensions(CodeGenFunction *CGF, Value *Handle,
+ LValue &Dim) {
+ // Generate the call to get the buffer dimension.
+ switch (CGF->CGM.getTarget().getTriple().getArch()) {
+ case llvm::Triple::dxil:
+ return emitDXILGetDimensions(CGF, Handle, PoisonValue::get(CGF->Int32Ty),
+ &Dim);
+ break;
+ case llvm::Triple::spirv:
+ llvm_unreachable("SPIR-V GetDimensions codegen not implemented yet.");
+ default:
+ llvm_unreachable("GetDimensions not supported by target architecture");
+ }
+}
+
+static Value *emitBufferStride(CodeGenFunction *CGF, const Expr *HandleExpr,
+ LValue &Stride) {
+ // Figure out the stride of the buffer elements from the handle type.
+ auto *HandleTy =
+ cast<HLSLAttributedResourceType>(HandleExpr->getType().getTypePtr());
+ QualType ElementTy = HandleTy->getContainedType();
+ Value *StrideValue = CGF->getTypeSize(ElementTy);
+ return CGF->Builder.CreateStore(StrideValue, Stride.getAddress());
+}
+
// Return dot product intrinsic that corresponds to the QT scalar type
static Intrinsic::ID getDotProductIntrinsic(CGHLSLRuntime &RT, QualType QT) {
if (QT->isFloatingType())
@@ -359,6 +411,15 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
RetTy, CGM.getHLSLRuntime().getNonUniformResourceIndexIntrinsic(),
ArrayRef<Value *>{IndexOp});
}
+ case Builtin::BI__builtin_hlsl_buffer_getdimensions: {
+ Value *Handle = EmitScalarExpr(E->getArg(0));
+ LValue Dim = EmitLValue(E->getArg(1));
+ return emitBufferGetDimensions(this, Handle, Dim);
+ }
+ case Builtin::BI__builtin_hlsl_buffer_getstride: {
+ LValue Stride = EmitLValue(E->getArg(1));
+ return emitBufferStride(this, E->getArg(0), Stride);
+ }
case Builtin::BI__builtin_hlsl_all: {
Value *Op0 = EmitScalarExpr(E->getArg(0));
return Builder.CreateIntrinsic(
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
index 3c20ccd799b2d..7c7c1e94dc1fe 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp
@@ -57,6 +57,28 @@ CXXConstructorDecl *lookupCopyConstructor(QualType ResTy) {
return CD;
return nullptr;
}
+
+ParameterABI convertParamModifierToParamABI(HLSLParamModifierAttr::Spelling Modifier) {
+ assert(Modifier != HLSLParamModifierAttr::Spelling::Keyword_in &&
+ "HLSL 'in' parameters modifier cannot be converted to ParameterABI");
+ switch (Modifier) {
+ case HLSLParamModifierAttr::Spelling::Keyword_out:
+ return ParameterABI::HLSLOut;
+ case HLSLParamModifierAttr::Spelling::Keyword_inout:
+ return ParameterABI::HLSLInOut;
+ default:
+ llvm_unreachable("Invalid HLSL parameter modifier");
+ }
+}
+
+QualType getInoutParameterType(ASTContext &AST, QualType Ty) {
+ assert(!Ty->isReferenceType() &&
+ "Pointer and reference types cannot be inout or out parameters");
+ Ty = AST.getLValueReferenceType(Ty);
+ Ty.addRestrict();
+ return Ty;
+}
+
} // namespace
// Builder for template arguments of builtin types. Used internally
@@ -421,13 +443,31 @@ BuiltinTypeMethodBuilder::addParam(StringRef Name, QualType Ty,
void BuiltinTypeMethodBuilder::createDecl() {
assert(Method == nullptr && "Method or constructor is already created");
- // create method or constructor type
+ // create function prototype
ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
SmallVector<QualType> ParamTypes;
- for (Param &MP : Params)
- ParamTypes.emplace_back(MP.Ty);
+ SmallVector<FunctionType::ExtParameterInfo> ParamExtInfos(Params.size());
+ uint32_t ArgIndex = 0;
+ bool IsTemplate = DeclBuilder.Template != nullptr;
+ bool UseParamExtInfo = false;
+ for (Param &MP : Params) {
+ QualType Ty = MP.Ty;
+ if (MP.Modifier != HLSLParamModifierAttr::Keyword_in) {
+ UseParamExtInfo = true;
+ ParamExtInfos[ArgIndex].withABI(convertParamModifierToParamABI(MP.Modifier));
+ // Only update types on inout and out parameters for non-templated
+ // methods. Templated types will have their inout/out parameters
+ // converted to references during template instantiation.
+ if (!IsTemplate)
+ Ty = getInoutParameterType(AST, Ty);
+ }
+ ParamTypes.emplace_back(Ty);
+ ++ArgIndex;
+ }
FunctionProtoType::ExtProtoInfo ExtInfo;
+ if (UseParamExtInfo)
+ ExtInfo.ExtParameterInfos = ParamExtInfos.data();
if (IsConst)
ExtInfo.TypeQuals.addConst();
@@ -459,8 +499,10 @@ void BuiltinTypeMethodBuilder::createDecl() {
AST.getTrivialTypeSourceInfo(MP.Ty, SourceLocation()), SC_None,
nullptr);
if (MP.Modifier != HLSLParamModifierAttr::Keyword_in) {
+ //Parm->setType(getInoutParameterType(AST, Parm->getType()));
auto *Mod =
HLSLParamModifierAttr::Create(AST, SourceRange(), MP.Modifier);
+ Parm->setType(getInoutParameterType(AST, Parm->getType()));
Parm->addAttr(Mod);
}
Parm->setScopeInfo(CurScopeDepth, I);
@@ -1127,5 +1169,37 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addConsumeMethod() {
.finalize();
}
+BuiltinTypeDeclBuilder &
+BuiltinTypeDeclBuilder::addGetDimensionsMethodForBuffer() {
+ using PH = BuiltinTypeMethodBuilder::PlaceHolder;
+ ASTContext &AST = SemaRef.getASTContext();
+ QualType UIntTy = AST.UnsignedIntTy;
+
+ QualType HandleTy = getResourceHandleField()->getType();
+ auto *AttrResTy = cast<HLSLAttributedResourceType>(HandleTy.getTypePtr());
+
+ // Structured buffers except {RW}ByteAddressBuffer have overload
+ // GetDimensions(out uint numStructs, out uint stride).
+ if (AttrResTy->getAttrs().RawBuffer &&
+ AttrResTy->getContainedType() != AST.Char8Ty) {
+ return BuiltinTypeMethodBuilder(*this, "GetDimensions", AST.VoidTy)
+ .addParam("numStructs", UIntTy, HLSLParamModifierAttr::Keyword_out)
+ .addParam("stride", UIntTy, HLSLParamModifierAttr::Keyword_out)
+ .callBuiltin("__builtin_hlsl_buffer_getdimensions", QualType(),
+ PH::Handle, PH::_0)
+ .callBuiltin("__builtin_hlsl_buffer_getstride", QualType(), PH::Handle,
+ PH::_1)
+ .finalize();
+ }
+
+ // Typed buffers and {RW}ByteAddressBuffer have overload
+ // GetDimensions(out uint dim).
+ return BuiltinTypeMethodBuilder(*this, "GetDimensions", AST.VoidTy)
+ .addParam("dim", UIntTy, HLSLParamModifierAttr::Keyword_out)
+ .callBuiltin("__builtin_hlsl_buffer_getdimensions", QualType(),
+ PH::Handle, PH::_0)
+ .finalize();
+}
+
} // namespace hlsl
} // namespace clang
diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
index a981602a50461..920a2f07a16ad 100644
--- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
+++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.h
@@ -95,6 +95,8 @@ class BuiltinTypeDeclBuilder {
BuiltinTypeDeclBuilder &addAppendMethod();
BuiltinTypeDeclBuilder &addConsumeMethod();
+ BuiltinTypeDeclBuilder &addGetDimensionsMethodForBuffer();
+
private:
BuiltinTypeDeclBuilder &addResourceMember(StringRef MemberName,
ResourceClass RC, bool IsROV,
diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp
index cc43e9474ea79..ce69e4987d6cd 100644
--- a/clang/lib/Sema/HLSLExternalSemaSource.cpp
+++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp
@@ -380,6 +380,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
/*RawBuffer=*/false, /*HasCounter=*/false)
.addArraySubscriptOperators()
.addLoadMethods()
+ .addGetDimensionsMethodForBuffer()
.completeDefinition();
});
@@ -392,6 +393,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
/*RawBuffer=*/false, /*HasCounter=*/false)
.addArraySubscriptOperators()
.addLoadMethods()
+ .addGetDimensionsMethodForBuffer()
.completeDefinition();
});
@@ -404,6 +406,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
/*RawBuffer=*/false, /*HasCounter=*/false)
.addArraySubscriptOperators()
.addLoadMethods()
+ .addGetDimensionsMethodForBuffer()
.completeDefinition();
});
@@ -415,6 +418,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
/*RawBuffer=*/true, /*HasCounter=*/false)
.addArraySubscriptOperators()
.addLoadMethods()
+ .addGetDimensionsMethodForBuffer()
.completeDefinition();
});
@@ -428,6 +432,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
.addLoadMethods()
.addIncrementCounterMethod()
.addDecrementCounterMethod()
+ .addGetDimensionsMethodForBuffer()
.completeDefinition();
});
@@ -439,6 +444,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, /*IsROV=*/false,
/*RawBuffer=*/true, /*HasCounter=*/true)
.addAppendMethod()
+ .addGetDimensionsMethodForBuffer()
.completeDefinition();
});
@@ -450,6 +456,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, /*IsROV=*/false,
/*RawBuffer=*/true, /*HasCounter=*/true)
.addConsumeMethod()
+ .addGetDimensionsMethodForBuffer()
.completeDefinition();
});
@@ -464,6 +471,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
.addLoadMethods()
.addIncrementCounterMethod()
.addDecrementCounterMethod()
+ .addGetDimensionsMethodForBuffer()
.completeDefinition();
});
@@ -472,6 +480,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
onCompletion(Decl, [this](CXXRecordDecl *Decl) {
setupBufferType(Decl, *SemaPtr, ResourceClass::SRV, /*IsROV=*/false,
/*RawBuffer=*/true, /*HasCounter=*/false)
+ .addGetDimensionsMethodForBuffer()
.completeDefinition();
});
Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RWByteAddressBuffer")
@@ -479,6 +488,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
onCompletion(Decl, [this](CXXRecordDecl *Decl) {
setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, /*IsROV=*/false,
/*RawBuffer=*/true, /*HasCounter=*/false)
+ .addGetDimensionsMethodForBuffer()
.completeDefinition();
});
Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace,
@@ -487,6 +497,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
onCompletion(Decl, [this](CXXRecordDecl *Decl) {
setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, /*IsROV=*/true,
/*RawBuffer=*/true, /*HasCounter=*/false)
+ .addGetDimensionsMethodForBuffer()
.completeDefinition();
});
}
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index fa30c66b62684..e3281c493da50 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -2978,6 +2978,24 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
TheCall->setType(ResourceTy);
break;
}
+ case Builtin::BI__builtin_hlsl_buffer_getdimensions: {
+ ASTContext &AST = SemaRef.getASTContext();
+ if (SemaRef.checkArgCount(TheCall, 2) ||
+ CheckResourceHandle(&SemaRef, TheCall, 0) ||
+ CheckArgTypeMatches(&SemaRef, TheCall->getArg(1), AST.UnsignedIntTy) ||
+ CheckModifiableLValue(&SemaRef, TheCall, 1))
+ return true;
+ break;
+ }
+ case Builtin::BI__builtin_hlsl_buffer_getstride: {
+ ASTContext &AST = SemaRef.getASTContext();
+ if (SemaRef.checkArgCount(TheCall, 2) ||
+ CheckResourceHandle(&SemaRef, TheCall, 0) ||
+ CheckArgTypeMatches(&SemaRef, TheCall->getArg(1), AST.UnsignedIntTy) ||
+ CheckModifiableLValue(&SemaRef, TheCall, 1))
+ return true;
+ break;
+ }
case Builtin::BI__builtin_hlsl_and:
case Builtin::BI__builtin_hlsl_or: {
if (SemaRef.checkArgCount(TheCall, 2))
diff --git a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
index 43d8ddee6ccad..a2058b29401c0 100644
--- a/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/ByteAddressBuffers-AST.hlsl
@@ -142,5 +142,19 @@ RESOURCE Buffer;
// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue Var {{.*}} 'tmp' 'hlsl::[[RESOURCE]]'
// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
+// GetDimensions method
+
+// CHECK-NEXT: CXXMethodDecl {{.*}} GetDimensions 'void (unsigned int &__restrict)'
+// CHECK-NEXT: ParmVarDecl {{.*}} dim 'unsigned int &__restrict'
+// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: CallExpr {{.*}} 'void'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_buffer_getdimensions' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle {{.*}}
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]' lvalue implicit this
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'dim' 'unsigned int &__restrict'
+// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
+
// CHECK-NOSUBSCRIPT-NOT: CXXMethodDecl {{.*}} operator[] 'const char8_t &(unsigned int) const'
// CHECK-NOSUBSCRIPT-NOT: CXXMethodDecl {{.*}} operator[] 'char8_t &(unsigned int)'
diff --git a/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl b/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
index 6779abb10bec4..e5f4b22fe2a10 100644
--- a/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/StructuredBuffers-AST.hlsl
@@ -334,6 +334,28 @@ RESOURCE<float> Buffer;
// CHECK-CONSUME-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
// CHECK-CONSUME-NEXT: IntegerLiteral {{.*}} 'int' -1
+// GetDimensions method
+
+// CHECK: CXXMethodDecl {{.*}} GetDimensions 'void (unsigned int, unsigned int)'
+// CHECK-NEXT: ParmVarDecl {{.*}} numStructs 'unsigned int &__restrict'
+// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out
+// CHECK-NEXT: ParmVarDecl {{.*}} stride 'unsigned int &__restrict'
+// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: CallExpr {{.*}} 'void'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_buffer_getdimensions' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle {{.*}}
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'numStructs' 'unsigned int &__restrict'
+// CHECK-NEXT: CallExpr {{.*}} 'void'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_buffer_getstride' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle {{.*}}
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'stride' 'unsigned int &__restrict'
+// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
+
// CHECK: ClassTemplateSpecializationDecl {{.*}} class [[RESOURCE]] definition
// CHECK: TemplateArgument type 'float'
// CHECK-NEXT: BuiltinType {{.*}} 'float'
diff --git a/clang/test/AST/HLSL/TypedBuffers-AST.hlsl b/clang/test/AST/HLSL/TypedBuffers-AST.hlsl
index 5182ce194cfb0..07f04001a58ae 100644
--- a/clang/test/AST/HLSL/TypedBuffers-AST.hlsl
+++ b/clang/test/AST/HLSL/TypedBuffers-AST.hlsl
@@ -214,6 +214,20 @@ RESOURCE<float> Buffer;
// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'Index' 'unsigned int'
// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
+// GetDimensions method
+
+// CHECK-NEXT: CXXMethodDecl {{.*}} GetDimensions 'void (unsigned int)'
+// CHECK-NEXT: ParmVarDecl {{.*}} dim 'unsigned int &__restrict'
+// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out
+// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: CallExpr {{.*}} 'void'
+// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(...) noexcept' <BuiltinFnToFnPtr>
+// CHECK-NEXT: DeclRefExpr {{.*}} '<builtin fn type>' Function {{.*}} '__builtin_hlsl_buffer_getdimensions' 'void (...) noexcept'
+// CHECK-NEXT: MemberExpr {{.*}} '__hlsl_resource_t {{.*}}' lvalue .__handle {{.*}}
+// CHECK-NEXT: CXXThisExpr {{.*}} 'hlsl::[[RESOURCE]]<element_type>' lvalue implicit this
+// CHECK-NEXT: DeclRefExpr {{.*}} 'unsigned int' ParmVar {{.*}} 'dim' 'unsigned int &__restrict'
+// CHECK-NEXT: AlwaysInlineAttr {{.*}} Implicit always_inline
+
// CHECK: ClassTemplateSpecializationDecl {{.*}} class [[RESOURCE]] definition
// CHECK: TemplateArgument type 'float'
diff --git a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl
index a506c2b50b1dc..c3bb147ad4a53 100644
--- a/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl
+++ b/clang/test/CodeGenHLSL/resources/StructuredBuffers-methods-lib.hlsl
@@ -82,7 +82,7 @@ export float TestLoad() {
return RWSB1.Load(1) + SB1.Load(2);
}
-// CHECK: define noundef nofpclass(nan inf) float @TestLoad()()
+// CHECK: define {{.*}} float @TestLoad()()
// CHECK: call {{.*}} float @hlsl::RWStructuredBuffer<float>::Load(unsigned int)(ptr {{.*}} @RWSB1, i32 noundef 1)
// CHECK: call {{.*}} float @hlsl::StructuredBuffer<float>::Load(unsigned int)(ptr ...
[truncated]
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
Adds GetDimensions methods on all supported buffer resources.
63dcefa
to
e509189
Compare
After conversation with @bogner and some testing I have realized it is better to have multiple LLVM intrinsic to implement the GetDimensions. I have updated this PR to use a getdimensions intrinsic specific just for buffers. |
} | ||
ParamTypes.emplace_back(Ty); | ||
++ArgIndex; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of doing this on the params here, could put the attributes on the ParmVarDecls in the loop over Params below?
At a minimum that would ensure that the AST for these functions matches the AST for user-written code, but it may also remove the need for the convertParamModifierToParamABI
function since you'll have a created ParameterABI
attribute in the AST.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried different combinations of the out
attribute, ABI param and when to add restrict &
on the function prototype or the method decl - this is the variation that works and does not have to 'coerce' the arguments. However, I did some testing now and found a bug in with out
parameters and templates:
https://godbolt.org/z/dKn1r4v4E
I'll file an issue #163648. We'll need to fix this bug first before revisiting this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug fix in review: #163832
I have updated createDecl
code always change the type of inout
and out
parameter to a reference - unless the parameter type is dependent on the template instantiation. It turns out it is needed for both the function prototype (ABI params & type) and for the param list on the decl.
I also had a bug in how the ABI params were set (or not set, actually), which is why the function prototype string did not include the out
modifier in the AST dump. This is now fixed.
Changing to draft until #163648 is resolved. |
…ers-get-dimensions
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/27/builds/17671 Here is the relevant piece of the build log for the reference
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/206/builds/7672 Here is the relevant piece of the build log for the reference
|
Adds
GetDimensions
methods to all supported buffer resource classes ({RW}Buffer
,*StructuredBuffer
,{RW}ByteAddressBuffer
) . The method is implemented by calling one of both built-in functions__building_hlsl_buffer_getdimensions
and__building_hlsl_buffer_getstride
as described in proposal llvm/wg-hlsl#350.The
__building_hlsl_buffer_getstride
is implemented directly by Clang codegen to set the buffer stride to the output variable.The
__building_hlsl_buffer_getdimensions
built-in function gets translated to LLVM intrinsic@llvm.dx.resource.getdimensions.buffer
. This intrinsic is specific to buffers and is going be translated to DXIL opop.dx.getDimensions
in #161753.Depends on #163605, #161909, and #163832.
Closes #112984