-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[HLSL] Add Load overload with status #166449
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
Changes from 7 commits
99c9788
06ad11a
ec4e3a9
2a49c36
0d0b79f
8cc846b
673c1a5
3f124ba
5bbfc7f
cc885d0
84d5ca1
1e10b23
48957a3
5852461
4fdb463
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -353,6 +353,57 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, | |
| RetTy, CGM.getHLSLRuntime().getCreateResourceGetPointerIntrinsic(), | ||
| ArrayRef<Value *>{HandleOp, IndexOp}); | ||
| } | ||
| case Builtin::BI__builtin_hlsl_resource_load_with_status: { | ||
| Value *HandleOp = EmitScalarExpr(E->getArg(0)); | ||
| Value *IndexOp = EmitScalarExpr(E->getArg(1)); | ||
|
|
||
| // Get the *address* of the status argument to write to it by reference | ||
| LValue StatusLVal = EmitLValue(E->getArg(2)); | ||
| Address StatusAddr = StatusLVal.getAddress(); | ||
|
|
||
| QualType HandleTy = E->getArg(0)->getType(); | ||
| const HLSLAttributedResourceType *RT = | ||
| HandleTy->getAs<HLSLAttributedResourceType>(); | ||
| assert(RT && "Expected a resource type as first parameter"); | ||
| assert(CGM.getTarget().getTriple().getArch() == llvm::Triple::dxil && | ||
| "Only DXIL currently implements load with status"); | ||
|
|
||
| Intrinsic::ID IntrID = RT->getAttrs().RawBuffer | ||
| ? llvm::Intrinsic::dx_resource_load_rawbuffer | ||
| : llvm::Intrinsic::dx_resource_load_typedbuffer; | ||
bogner marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| llvm::Type *DataTy = ConvertType(E->getType()); | ||
| llvm::Type *RetTy = llvm::StructType::get(Builder.getContext(), | ||
| {DataTy, Builder.getInt1Ty()}); | ||
|
|
||
| SmallVector<Value *, 3> Args; | ||
| Args.push_back(HandleOp); | ||
| Args.push_back(IndexOp); | ||
|
|
||
| if (RT->getAttrs().RawBuffer) { | ||
| Value *Offset = Builder.getInt32(0); | ||
| Args.push_back(Offset); | ||
| } | ||
|
|
||
| // Call the intrinsic (returns a struct), | ||
| // Extract the loaded value and status bit (elements within the struct) | ||
| // Extend the status bit to a 32-bit integer | ||
| // Store the extended status into the user's reference variable | ||
| // Return the loaded value | ||
|
||
| Value *ResRet = | ||
| Builder.CreateIntrinsic(RetTy, IntrID, Args, {}, "ld.struct"); | ||
|
|
||
| Value *LoadedValue = Builder.CreateExtractValue(ResRet, {0}, "ld.value"); | ||
|
|
||
| Value *StatusBit = Builder.CreateExtractValue(ResRet, {1}, "ld.status"); | ||
|
|
||
| Value *ExtendedStatus = | ||
| Builder.CreateZExt(StatusBit, Builder.getInt32Ty(), "ld.status.ext"); | ||
|
|
||
|
||
| Builder.CreateStore(ExtendedStatus, StatusAddr); | ||
|
|
||
| return LoadedValue; | ||
| } | ||
| case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: { | ||
| llvm::Type *HandleTy = CGM.getTypes().ConvertType(E->getType()); | ||
| return llvm::PoisonValue::get(HandleTy); | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -202,7 +202,7 @@ struct BuiltinTypeMethodBuilder { | |||||||||||||||||||
| BuiltinTypeMethodBuilder &declareLocalVar(LocalVar &Var); | ||||||||||||||||||||
| template <typename... Ts> | ||||||||||||||||||||
| BuiltinTypeMethodBuilder &callBuiltin(StringRef BuiltinName, | ||||||||||||||||||||
| QualType ReturnType, Ts... ArgSpecs); | ||||||||||||||||||||
| QualType ReturnType, Ts &&...ArgSpecs); | ||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you please explain why is this change needed?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was originally needed to pass in a local variable to the callBuiltin function, but since your change no longer requires passing in a local variable, we don't need this change anymore.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We really should make this change anyway (maybe in a follow up?). The current logic here is incorrect, but it doesn't come up because we never pass a reference in to this function.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed. |
||||||||||||||||||||
| template <typename TLHS, typename TRHS> | ||||||||||||||||||||
| BuiltinTypeMethodBuilder &assign(TLHS LHS, TRHS RHS); | ||||||||||||||||||||
| template <typename T> BuiltinTypeMethodBuilder &dereference(T Ptr); | ||||||||||||||||||||
|
|
@@ -572,7 +572,7 @@ BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::returnThis() { | |||||||||||||||||||
| template <typename... Ts> | ||||||||||||||||||||
| BuiltinTypeMethodBuilder & | ||||||||||||||||||||
| BuiltinTypeMethodBuilder::callBuiltin(StringRef BuiltinName, | ||||||||||||||||||||
| QualType ReturnType, Ts... ArgSpecs) { | ||||||||||||||||||||
| QualType ReturnType, Ts &&...ArgSpecs) { | ||||||||||||||||||||
| ensureCompleteDecl(); | ||||||||||||||||||||
|
|
||||||||||||||||||||
| std::array<Expr *, sizeof...(ArgSpecs)> Args{ | ||||||||||||||||||||
|
|
@@ -1140,6 +1140,7 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addLoadMethods() { | |||||||||||||||||||
| DeclarationName Load(&II); | ||||||||||||||||||||
| // TODO: We also need versions with status for CheckAccessFullyMapped. | ||||||||||||||||||||
| addHandleAccessFunction(Load, /*IsConst=*/false, /*IsRef=*/false); | ||||||||||||||||||||
| addLoadWithStatusFunction(Load, /*IsConst=*/false); | ||||||||||||||||||||
|
|
||||||||||||||||||||
| return *this; | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
@@ -1232,6 +1233,30 @@ BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addDecrementCounterMethod() { | |||||||||||||||||||
| .finalize(); | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| BuiltinTypeDeclBuilder & | ||||||||||||||||||||
| BuiltinTypeDeclBuilder::addLoadWithStatusFunction(DeclarationName &Name, | ||||||||||||||||||||
| bool IsConst) { | ||||||||||||||||||||
| assert(!Record->isCompleteDefinition() && "record is already complete"); | ||||||||||||||||||||
| ASTContext &AST = SemaRef.getASTContext(); | ||||||||||||||||||||
| using PH = BuiltinTypeMethodBuilder::PlaceHolder; | ||||||||||||||||||||
|
|
||||||||||||||||||||
| QualType ReturnTy = getHandleElementType(); | ||||||||||||||||||||
| BuiltinTypeMethodBuilder::LocalVar ResultVar("Result", ReturnTy); | ||||||||||||||||||||
| BuiltinTypeMethodBuilder::LocalVar StatusVar("StatusBool", AST.BoolTy); | ||||||||||||||||||||
|
|
||||||||||||||||||||
| return BuiltinTypeMethodBuilder(*this, Name, ReturnTy, IsConst) | ||||||||||||||||||||
| .addParam("Index", AST.UnsignedIntTy) | ||||||||||||||||||||
| .addParam("Status", AST.UnsignedIntTy, HLSLParamModifierAttr::Keyword_out) | ||||||||||||||||||||
| .declareLocalVar(ResultVar) | ||||||||||||||||||||
| .declareLocalVar(StatusVar) | ||||||||||||||||||||
| .callBuiltin("__builtin_hlsl_resource_load_with_status", ReturnTy, | ||||||||||||||||||||
| PH::Handle, PH::_0, StatusVar) | ||||||||||||||||||||
| .assign(ResultVar, PH::LastStmt) | ||||||||||||||||||||
| .assign(PH::_1, StatusVar) | ||||||||||||||||||||
| .returnValue(ResultVar) | ||||||||||||||||||||
|
||||||||||||||||||||
| .declareLocalVar(ResultVar) | |
| .declareLocalVar(StatusVar) | |
| .callBuiltin("__builtin_hlsl_resource_load_with_status", ReturnTy, | |
| PH::Handle, PH::_0, StatusVar) | |
| .assign(ResultVar, PH::LastStmt) | |
| .assign(PH::_1, StatusVar) | |
| .returnValue(ResultVar) | |
| .callBuiltin("__builtin_hlsl_resource_load_with_status", ReturnTy, | |
| PH::Handle, PH::_0, PH::_1) |
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.
This plays pretty fast and loose with the types, but I guess it's okay in practice based on looking what gets generated in the tests. Note that with this AST we're explicitly passing in a uint to a bool parameter, which is generally pretty unsafe. I think it doesn't cause any problems because we're calling into a builtin and custom lowering everything anyway, so the issue gets papered over.
Uh oh!
There was an error while loading. Please reload this page.