17#include "llvm/IR/IntrinsicsDirectX.h"
23#define DEBUG_TYPE "dxil-resource"
30 case ResourceClass::SRV:
32 case ResourceClass::UAV:
34 case ResourceClass::CBuffer:
36 case ResourceClass::Sampler:
44 case ResourceKind::Texture1D:
46 case ResourceKind::Texture2D:
48 case ResourceKind::Texture2DMS:
50 case ResourceKind::Texture3D:
52 case ResourceKind::TextureCube:
54 case ResourceKind::Texture1DArray:
55 return "Texture1DArray";
56 case ResourceKind::Texture2DArray:
57 return "Texture2DArray";
58 case ResourceKind::Texture2DMSArray:
59 return "Texture2DMSArray";
60 case ResourceKind::TextureCubeArray:
61 return "TextureCubeArray";
62 case ResourceKind::TypedBuffer:
64 case ResourceKind::RawBuffer:
66 case ResourceKind::StructuredBuffer:
67 return "StructuredBuffer";
68 case ResourceKind::CBuffer:
70 case ResourceKind::Sampler:
72 case ResourceKind::TBuffer:
74 case ResourceKind::RTAccelerationStructure:
75 return "RTAccelerationStructure";
76 case ResourceKind::FeedbackTexture2D:
77 return "FeedbackTexture2D";
78 case ResourceKind::FeedbackTexture2DArray:
79 return "FeedbackTexture2DArray";
80 case ResourceKind::NumEntries:
81 case ResourceKind::Invalid:
91 case ElementType::I16:
93 case ElementType::U16:
95 case ElementType::I32:
97 case ElementType::U32:
99 case ElementType::I64:
101 case ElementType::U64:
103 case ElementType::F16:
105 case ElementType::F32:
107 case ElementType::F64:
109 case ElementType::SNormF16:
111 case ElementType::UNormF16:
113 case ElementType::SNormF32:
115 case ElementType::UNormF32:
117 case ElementType::SNormF64:
119 case ElementType::UNormF64:
121 case ElementType::PackedS8x32:
123 case ElementType::PackedU8x32:
125 case ElementType::Invalid:
133 case SamplerType::Default:
135 case SamplerType::Comparison:
137 case SamplerType::Mono:
145 case SamplerFeedbackType::MinMip:
147 case SamplerFeedbackType::MipRegionUsed:
148 return "MipRegionUsed";
160 return IsSigned ? ElementType::I16 : ElementType::U16;
162 return IsSigned ? ElementType::I32 : ElementType::U32;
164 return IsSigned ? ElementType::I64 : ElementType::U64;
167 return ElementType::Invalid;
170 return ElementType::F32;
172 return ElementType::F64;
174 return ElementType::F16;
177 return ElementType::Invalid;
183 bool GloballyCoherent,
bool HasCounter)
184 : HandleTy(HandleTy), GloballyCoherent(GloballyCoherent),
185 HasCounter(HasCounter) {
193 if (
auto *Ty = dyn_cast<RawBufferExtType>(HandleTy)) {
197 }
else if (
auto *Ty = dyn_cast<TypedBufferExtType>(HandleTy)) {
200 }
else if (
auto *Ty = dyn_cast<TextureExtType>(HandleTy)) {
202 Kind = Ty->getDimension();
203 }
else if (
auto *Ty = dyn_cast<MSTextureExtType>(HandleTy)) {
205 Kind = Ty->getDimension();
206 }
else if (
auto *Ty = dyn_cast<FeedbackTextureExtType>(HandleTy)) {
208 Kind = Ty->getDimension();
209 }
else if (isa<CBufferExtType>(HandleTy)) {
212 }
else if (isa<SamplerExtType>(HandleTy)) {
220 bool isWriteable,
bool isROV) {
221 Dest = isWriteable ? (
isROV ?
"RasterizerOrdered" :
"RW") :
"";
236 auto *RTy = cast<TextureExtType>(HandleTy);
243 auto *RTy = cast<MSTextureExtType>(HandleTy);
249 auto *RTy = cast<TypedBufferExtType>(HandleTy);
255 auto *RTy = cast<RawBufferExtType>(HandleTy);
262 auto *RTy = cast<RawBufferExtType>(HandleTy);
269 auto *RTy = cast<FeedbackTextureExtType>(HandleTy);
278 auto *RTy = cast<SamplerExtType>(HandleTy);
279 TypeName =
formatv(
"SamplerState<{0}>",
356 return cast<TextureExtType>(Ty)->isROV();
358 return cast<TypedBufferExtType>(Ty)->isROV();
361 return cast<RawBufferExtType>(Ty)->isROV();
380 return {GloballyCoherent, HasCounter,
isROV(Kind, HandleTy)};
385 return cast<CBufferExtType>(HandleTy)->getCBufferSize();
390 return cast<SamplerExtType>(HandleTy)->getSamplerType();
397 Type *ElTy = cast<RawBufferExtType>(HandleTy)->getResourceType();
401 if (
auto *STy = dyn_cast<StructType>(ElTy))
404 return {Stride, AlignLog2};
417 auto *RTy = cast<TextureExtType>(Ty);
418 return {RTy->getResourceType(), RTy->isSigned()};
422 auto *RTy = cast<MSTextureExtType>(Ty);
423 return {RTy->getResourceType(), RTy->isSigned()};
426 auto *RTy = cast<TypedBufferExtType>(Ty);
427 return {RTy->getResourceType(), RTy->isSigned()};
450 if (
auto *VTy = dyn_cast<FixedVectorType>(ElTy))
451 Count = VTy->getNumElements();
457 return cast<FeedbackTextureExtType>(HandleTy)->getFeedbackType();
461 return cast<MSTextureExtType>(HandleTy)->getSampleCount();
465 return std::tie(HandleTy, GloballyCoherent, HasCounter) ==
466 std::tie(
RHS.HandleTy,
RHS.GloballyCoherent,
RHS.HasCounter);
472 if (std::tie(RC, Kind) < std::tie(
RHS.RC,
RHS.Kind))
507 <<
" HasCounter: " << UAVFlags.
HasCounter <<
"\n"
508 <<
" IsROV: " << UAVFlags.
IsROV <<
"\n";
515 OS <<
" Buffer Stride: " <<
Struct.Stride <<
"\n";
516 OS <<
" Alignment: " <<
Struct.AlignLog2 <<
"\n";
529 assert(!Symbol &&
"Symbol has already been created");
545 auto getIntMD = [&I32Ty](
uint32_t V) {
549 auto getBoolMD = [&I1Ty](
uint32_t V) {
555 assert(Symbol &&
"Cannot yet create useful resource metadata without symbol");
605std::pair<uint32_t, uint32_t>
612 bool IsUAV = RTI.
isUAV();
615 bool IsROV = IsUAV && UAVFlags.
IsROV;
617 uint8_t SamplerCmpOrHasCounter = 0;
627 Word0 |= (AlignLog2 & 0xF) << 8;
628 Word0 |= (IsUAV & 1) << 12;
629 Word0 |= (IsROV & 1) << 13;
630 Word0 |= (IsGloballyCoherent & 1) << 14;
631 Word0 |= (SamplerCmpOrHasCounter & 1) << 15;
646 Word1 |= (CompType & 0xFF) << 0;
647 Word1 |= (CompCount & 0xFF) << 8;
648 Word1 |= (SampleCount & 0xFF) << 16;
651 return {Word0, Word1};
663 <<
" Record ID: " << Binding.
RecordID <<
"\n"
664 <<
" Space: " << Binding.
Space <<
"\n"
665 <<
" Lower Bound: " << Binding.
LowerBound <<
"\n"
666 <<
" Size: " << Binding.
Size <<
"\n";
677 return !PAC.preservedWhenStateless();
687 if (!
F.isDeclaration())
694 case Intrinsic::dx_resource_handlefrombinding: {
695 auto *HandleTy = cast<TargetExtType>(
F.getReturnType());
698 for (
User *U :
F.users())
699 if (
CallInst *CI = dyn_cast<CallInst>(U)) {
702 cast<ConstantInt>(CI->getArgOperand(0))->getZExtValue();
704 cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
706 cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
708 0, Space, LowerBound,
Size, HandleTy};
719 const auto &[LCI, LRBI, LRTI] =
LHS;
720 const auto &[RCI, RRBI, RRTI] =
RHS;
726 return std::tie(LRC, LRBI, LRTI) < std::tie(RRC, RRBI, RRTI);
728 for (
auto [CI, RBI, RTI] : CIToInfos) {
729 if (Infos.empty() || RBI != Infos.back())
730 Infos.push_back(RBI);
731 CallMap[CI] = Infos.size() - 1;
734 unsigned Size = Infos.size();
736 FirstUAV = FirstCBuffer = FirstSampler =
Size;
738 for (
unsigned I = 0, E =
Size;
I != E; ++
I) {
759 for (
unsigned I = 0, E = Infos.size();
I != E; ++
I) {
760 OS <<
"Binding " <<
I <<
":\n";
766 for (
const auto &[CI, Index] : CallMap) {
767 OS <<
"Call bound to " << Index <<
":";
782 Data.populate(M, DRTM);
791 DBM.
print(
OS, DRTM, M.getDataLayout());
795void DXILResourceTypeWrapperPass::anchor() {}
802 "DXIL Resource Type Analysis",
false,
true)
825 DRTM = &getAnalysis<DXILResourceTypeWrapperPass>().getResourceTypeMap();
826 Map->populate(M, *DRTM);
836 OS <<
"No resource map has been built!\n";
839 Map->print(
OS, *DRTM, M->getDataLayout());
842#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
848 "DXIL Resource Binding Analysis",
false,
true)
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static dxil::ElementType toDXILElementType(Type *Ty, bool IsSigned)
static StringRef getResourceClassName(ResourceClass RC)
static StringRef getElementTypeName(ElementType ET)
static void formatTypeName(SmallString< 64 > &Dest, StringRef Name, bool isWriteable, bool isROV)
static std::pair< Type *, bool > getTypedElementType(dxil::ResourceKind Kind, TargetExtType *Ty)
static bool isROV(dxil::ResourceKind Kind, TargetExtType *Ty)
static StringRef getResourceKindName(ResourceKind RK)
static StringRef getSamplerTypeName(SamplerType ST)
static StringRef getSamplerFeedbackTypeName(SamplerFeedbackType SFT)
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Module.h This file contains the declarations for the Module class.
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallString class.
Class for arbitrary precision integers.
API to communicate dependencies between analyses during invalidation.
A container for analyses that lazily runs them and caches their results.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
void setPreservesAll()
Set by analyses that do not transform their input at all.
AnalysisUsage & addRequiredTransitive()
This class represents a function call, abstracting a target machine's calling convention.
static Constant * getIntegerValue(Type *Ty, const APInt &V)
Return the value for an integer or pointer constant, or a vector thereof, with the given scalar value...
void print(raw_ostream &OS, DXILResourceTypeMap &DRTM, const DataLayout &DL) const
DXILBindingMap run(Module &M, ModuleAnalysisManager &AM)
Gather resource info for the module M.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
bool runOnModule(Module &M) override
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
~DXILResourceBindingWrapperPass() override
DXILResourceBindingWrapperPass()
void print(raw_ostream &OS, const Module *M) const override
print - Print out the internal state of the pass.
void releaseMemory() override
releaseMemory() - This member can be implemented by a pass if it wants to be able to release its memo...
bool invalidate(Module &M, const PreservedAnalyses &PA, ModuleAnalysisManager::Invalidator &Inv)
DXILResourceTypeWrapperPass()
A parsed version of the target data layout string in and methods for querying it.
@ ExternalLinkage
Externally visible function.
ImmutablePass class - This class is used to provide information that does not need to be run.
This is an important class for using LLVM in a threaded context.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
static MDString * get(LLVMContext &Context, StringRef Str)
Align getAlignment() const
Return alignment of the basic block.
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
A Module instance is used to store all the information related to an LLVM module.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalysisChecker getChecker() const
Build a checker for this PreservedAnalyses and the specified analysis type.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Class to represent struct types.
static StructType * create(LLVMContext &Context, StringRef Name)
This creates an identified struct.
Class to represent target extensions types, which are generally unintrospectable from target-independ...
The instances of the Type class are immutable: once they are created, they are never changed.
unsigned getIntegerBitWidth() const
static IntegerType * getInt1Ty(LLVMContext &C)
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
bool isHalfTy() const
Return true if this is 'half', a 16-bit IEEE fp type.
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
static IntegerType * getInt32Ty(LLVMContext &C)
bool isIntegerTy() const
True if this is an instance of IntegerType.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
void printAsOperand(raw_ostream &O, bool PrintType=true, const Module *M=nullptr) const
Print the name of this Value out to the specified raw_ostream.
StringRef getName() const
Return a constant reference to the value's name.
void setBindingID(unsigned ID)
GlobalVariable * createSymbol(Module &M, StructType *Ty, StringRef Name="")
std::pair< uint32_t, uint32_t > getAnnotateProps(Module &M, dxil::ResourceTypeInfo &RTI) const
TargetExtType * getHandleTy() const
MDTuple * getAsMetadata(Module &M, dxil::ResourceTypeInfo &RTI) const
void print(raw_ostream &OS, dxil::ResourceTypeInfo &RTI, const DataLayout &DL) const
uint32_t getMultiSampleCount() const
uint32_t getCBufferSize(const DataLayout &DL) const
bool operator<(const ResourceTypeInfo &RHS) const
bool isMultiSample() const
dxil::SamplerType getSamplerType() const
TypedInfo getTyped() const
StructType * createElementStruct()
StructInfo getStruct(const DataLayout &DL) const
ResourceTypeInfo(TargetExtType *HandleTy, const dxil::ResourceClass RC, const dxil::ResourceKind Kind, bool GloballyCoherent=false, bool HasCounter=false)
dxil::SamplerFeedbackType getFeedbackType() const
bool operator==(const ResourceTypeInfo &RHS) const
dxil::ResourceKind getResourceKind() const
void print(raw_ostream &OS, const DataLayout &DL) const
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ RRC
Y = RRC X, rotate right via carry.
ResourceKind
The kind of resource for an SRV or UAV resource.
@ RTAccelerationStructure
ElementType
The element type of an SRV or UAV resource.
This is an optimization pass for GlobalISel generic memory operations.
void stable_sort(R &&Range)
void initializeDXILResourceTypeWrapperPassPass(PassRegistry &)
ModulePass * createDXILResourceTypeWrapperPassPass()
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
void initializeDXILResourceBindingWrapperPassPass(PassRegistry &)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr std::underlying_type_t< Enum > to_underlying(Enum E)
Returns underlying integer value of an enum.
unsigned Log2(Align A)
Returns the log2 of the alignment.
ModulePass * createDXILResourceBindingWrapperPassPass()
A special type used by analysis passes to provide an address that identifies that particular analysis...
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
dxil::ElementType ElementTy