1111#include " dxc/DXIL/DxilShaderFlags.h"
1212#include " dxc/DXIL/DxilOperations.h"
1313#include " dxc/DXIL/DxilResource.h"
14+ #include " dxc/DXIL/DxilResourceBinding.h"
1415#include " dxc/Support/Global.h"
1516#include " llvm/IR/LLVMContext.h"
1617#include " llvm/IR/Instructions.h"
@@ -55,6 +56,7 @@ ShaderFlags::ShaderFlags():
5556, m_bAtomicInt64OnTypedResource(false )
5657, m_bAtomicInt64OnGroupShared(false )
5758, m_bDerivativesInMeshAndAmpShaders(false )
59+ , m_bAtomicInt64OnHeapResource(false )
5860, m_align0(0 )
5961, m_align1(0 )
6062{
@@ -109,6 +111,7 @@ uint64_t ShaderFlags::GetFeatureInfo() const {
109111 Flags |= m_bSamplerFeedback ? hlsl::DXIL::ShaderFeatureInfo_SamplerFeedback : 0 ;
110112 Flags |= m_bAtomicInt64OnTypedResource ? hlsl::DXIL::ShaderFeatureInfo_AtomicInt64OnTypedResource : 0 ;
111113 Flags |= m_bAtomicInt64OnGroupShared ? hlsl::DXIL::ShaderFeatureInfo_AtomicInt64OnGroupShared : 0 ;
114+ Flags |= m_bAtomicInt64OnHeapResource ? hlsl::DXIL::ShaderFeatureInfo_AtomicInt64OnHeapResource : 0 ;
112115 Flags |= m_bDerivativesInMeshAndAmpShaders ? hlsl::DXIL::ShaderFeatureInfo_DerivativesInMeshAndAmpShaders : 0 ;
113116
114117 return Flags;
@@ -166,6 +169,7 @@ uint64_t ShaderFlags::GetShaderFlagsRawForCollection() {
166169 Flags.SetSamplerFeedback (true );
167170 Flags.SetAtomicInt64OnTypedResource (true );
168171 Flags.SetAtomicInt64OnGroupShared (true );
172+ Flags.SetAtomicInt64OnHeapResource (true );
169173 Flags.SetDerivativesInMeshAndAmpShaders (true );
170174 return Flags.GetShaderFlagsRaw ();
171175}
@@ -261,14 +265,60 @@ DxilResourceProperties GetResourcePropertyFromHandleCall(const hlsl::DxilModule
261265 }
262266 } else if (handleOp == DXIL::OpCode::AnnotateHandle) {
263267 DxilInst_AnnotateHandle annotateHandle (cast<Instruction>(handleCall));
264- Type *ResPropTy = M->GetOP ()->GetResourcePropertiesType ();
265268
266- RP = resource_helper::loadPropsFromAnnotateHandle (annotateHandle, ResPropTy, *M->GetShaderModel ());
269+ RP = resource_helper::loadPropsFromAnnotateHandle (annotateHandle, *M->GetShaderModel ());
267270 }
268271
269272 return RP;
270273}
271274
275+ struct ResourceKey {
276+ uint8_t Class;
277+ uint32_t Space;
278+ uint32_t LowerBound;
279+ uint32_t UpperBound;
280+ };
281+
282+ struct ResKeyEq : public std ::binary_function<ResourceKey, ResourceKey, bool > {
283+ bool operator ()(const ResourceKey& k1, const ResourceKey& k2) const {
284+ return k1.Class == k2.Class && k1.Space == k2.Space &&
285+ k1.LowerBound == k2.LowerBound && k1.UpperBound == k2.UpperBound ;
286+ }
287+ };
288+
289+ struct ResKeyHash : public std ::unary_function<ResourceKey, std::size_t > {
290+ std::size_t operator ()(const ResourceKey& k) const {
291+ return std::hash<uint32_t >()(k.LowerBound ) ^ (std::hash<uint32_t >()(k.UpperBound )<<1 ) ^
292+ (std::hash<uint32_t >()(k.Space )<<2 ) ^ (std::hash<uint8_t >()(k.Class )<<3 );
293+ }
294+ };
295+
296+ // Limited to retrieving handles created by CreateHandleFromBinding. returns null otherwise
297+ // map should contain resources indexed by class, lower, and upper bounds
298+ DxilResource *GetResourceFromAnnotateHandle (CallInst *handleCall,
299+ std::unordered_map<ResourceKey, DxilResource *, ResKeyHash, ResKeyEq> resMap) {
300+ DxilResource *resource = nullptr ;
301+
302+ ConstantInt *HandleOpCodeConst = cast<ConstantInt>(
303+ handleCall->getArgOperand (DXIL::OperandIndex::kOpcodeIdx ));
304+ DXIL::OpCode handleOp = static_cast <DXIL::OpCode>(HandleOpCodeConst->getLimitedValue ());
305+ if (handleOp == DXIL::OpCode::AnnotateHandle) {
306+ DxilInst_AnnotateHandle annotateHandle (cast<Instruction>(handleCall));
307+ CallInst *createCall = cast<CallInst>(annotateHandle.get_res ());
308+ ConstantInt *HandleOpCodeConst = cast<ConstantInt>(
309+ createCall->getArgOperand (DXIL::OperandIndex::kOpcodeIdx ));
310+ DXIL::OpCode handleOp = static_cast <DXIL::OpCode>(HandleOpCodeConst->getLimitedValue ());
311+ if (handleOp == DXIL::OpCode::CreateHandleFromBinding) {
312+ DxilInst_CreateHandleFromBinding fromBind (createCall);
313+ DxilResourceBinding B = resource_helper::loadBindingFromConstant (*cast<Constant>(fromBind.get_bind ()));
314+ ResourceKey key = {B.resourceClass , B.spaceID , B.rangeLowerBound , B.rangeUpperBound };
315+ resource = resMap[key];
316+ }
317+ }
318+
319+ return resource;
320+ }
321+
272322
273323ShaderFlags ShaderFlags::CollectShaderFlags (const Function *F,
274324 const hlsl::DxilModule *M) {
@@ -298,6 +348,7 @@ ShaderFlags ShaderFlags::CollectShaderFlags(const Function *F,
298348 bool hasRaytracingTier1_1 = false ;
299349 bool hasAtomicInt64OnTypedResource = false ;
300350 bool hasAtomicInt64OnGroupShared = false ;
351+ bool hasAtomicInt64OnHeapResource = false ;
301352 bool hasDerivativesInMeshAndAmpShaders = false ;
302353
303354 // Try to maintain compatibility with a v1.0 validator if that's what we have.
@@ -309,6 +360,15 @@ ShaderFlags ShaderFlags::CollectShaderFlags(const Function *F,
309360 Type *int16Ty = Type::getInt16Ty (F->getContext ());
310361 Type *int64Ty = Type::getInt64Ty (F->getContext ());
311362
363+
364+ // Set up resource to binding handle map for 64-bit atomics usage
365+ std::unordered_map<ResourceKey, DxilResource *, ResKeyHash, ResKeyEq> resMap;
366+ for (auto &res : M->GetUAVs ()) {
367+ ResourceKey key = {(uint8_t )res->GetClass (), res->GetSpaceID (),
368+ res->GetLowerBound (), res->GetUpperBound ()};
369+ resMap.insert ({key, res.get ()});
370+ }
371+
312372 for (const BasicBlock &BB : F->getBasicBlockList ()) {
313373 for (const Instruction &I : BB.getInstList ()) {
314374 // Skip none dxil function call.
@@ -420,6 +480,13 @@ ShaderFlags ShaderFlags::CollectShaderFlags(const Function *F,
420480 DxilResourceProperties RP = GetResourcePropertyFromHandleCall (M, handleCall);
421481 if (DXIL::IsTyped (RP.getResourceKind ()))
422482 hasAtomicInt64OnTypedResource = true ;
483+ // set uses 64-bit flag if relevant
484+ if (DxilResource *res = GetResourceFromAnnotateHandle (handleCall, resMap)) {
485+ res->SetHasAtomic64Use (true );
486+ } else {
487+ // Assuming CreateHandleFromHeap, which indicates a descriptor
488+ hasAtomicInt64OnHeapResource = true ;
489+ }
423490 }
424491 break ;
425492 case DXIL::OpCode::DerivFineX:
@@ -543,6 +610,7 @@ ShaderFlags ShaderFlags::CollectShaderFlags(const Function *F,
543610 flag.SetRaytracingTier1_1 (hasRaytracingTier1_1);
544611 flag.SetAtomicInt64OnTypedResource (hasAtomicInt64OnTypedResource);
545612 flag.SetAtomicInt64OnGroupShared (hasAtomicInt64OnGroupShared);
613+ flag.SetAtomicInt64OnHeapResource (hasAtomicInt64OnHeapResource);
546614 flag.SetDerivativesInMeshAndAmpShaders (hasDerivativesInMeshAndAmpShaders);
547615
548616 return flag;
0 commit comments