1//===- DXILResource.cpp - Representations of DXIL resources ---------------===// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7//===----------------------------------------------------------------------===// 17#include "llvm/IR/IntrinsicsDirectX.h" 23#define DEBUG_TYPE "dxil-resource" 30case ResourceClass::SRV:
32case ResourceClass::UAV:
34case ResourceClass::CBuffer:
36case ResourceClass::Sampler:
44case ResourceKind::Texture1D:
46case ResourceKind::Texture2D:
48case ResourceKind::Texture2DMS:
50case ResourceKind::Texture3D:
52case ResourceKind::TextureCube:
54case ResourceKind::Texture1DArray:
55return"Texture1DArray";
56case ResourceKind::Texture2DArray:
57return"Texture2DArray";
58case ResourceKind::Texture2DMSArray:
59return"Texture2DMSArray";
60case ResourceKind::TextureCubeArray:
61return"TextureCubeArray";
62case ResourceKind::TypedBuffer:
64case ResourceKind::RawBuffer:
66case ResourceKind::StructuredBuffer:
67return"StructuredBuffer";
68case ResourceKind::CBuffer:
70case ResourceKind::Sampler:
72case ResourceKind::TBuffer:
74case ResourceKind::RTAccelerationStructure:
75return"RTAccelerationStructure";
76case ResourceKind::FeedbackTexture2D:
77return"FeedbackTexture2D";
78case ResourceKind::FeedbackTexture2DArray:
79return"FeedbackTexture2DArray";
80case ResourceKind::NumEntries:
81case ResourceKind::Invalid:
101case ElementType::U64:
103case ElementType::F16:
105case ElementType::F32:
107case ElementType::F64:
109case ElementType::SNormF16:
111case ElementType::UNormF16:
113case ElementType::SNormF32:
115case ElementType::UNormF32:
117case ElementType::SNormF64:
119case ElementType::UNormF64:
121case ElementType::PackedS8x32:
123case ElementType::PackedU8x32:
125case ElementType::Invalid:
133case SamplerType::Default:
135case SamplerType::Comparison:
137case SamplerType::Mono:
145case SamplerFeedbackType::MinMip:
147case SamplerFeedbackType::MipRegionUsed:
148return"MipRegionUsed";
154// TODO: Handle unorm, snorm, and packed. 160return IsSigned ? ElementType::I16 : ElementType::U16;
162return IsSigned ? ElementType::I32 : ElementType::U32;
164return IsSigned ? ElementType::I64 : ElementType::U64;
167return ElementType::Invalid;
170return ElementType::F32;
172return ElementType::F64;
174return ElementType::F16;
177return ElementType::Invalid;
183bool GloballyCoherent,
bool HasCounter)
184 : HandleTy(HandleTy), GloballyCoherent(GloballyCoherent),
185 HasCounter(HasCounter) {
186// If we're provided a resource class and kind, trust them. 193if (
auto *Ty = dyn_cast<RawBufferExtType>(HandleTy)) {
197 }
elseif (
auto *Ty = dyn_cast<TypedBufferExtType>(HandleTy)) {
200 }
elseif (
auto *Ty = dyn_cast<TextureExtType>(HandleTy)) {
202 Kind = Ty->getDimension();
203 }
elseif (
auto *Ty = dyn_cast<MSTextureExtType>(HandleTy)) {
205 Kind = Ty->getDimension();
206 }
elseif (
auto *Ty = dyn_cast<FeedbackTextureExtType>(HandleTy)) {
208 Kind = Ty->getDimension();
209 }
elseif (isa<CBufferExtType>(HandleTy)) {
212 }
elseif (isa<SamplerExtType>(HandleTy)) {
220bool isWriteable,
boolisROV) {
221 Dest = isWriteable ? (
isROV ?
"RasterizerOrdered" :
"RW") :
"";
236auto *RTy = cast<TextureExtType>(HandleTy);
243auto *RTy = cast<MSTextureExtType>(HandleTy);
249auto *RTy = cast<TypedBufferExtType>(HandleTy);
255auto *RTy = cast<RawBufferExtType>(HandleTy);
262auto *RTy = cast<RawBufferExtType>(HandleTy);
269auto *RTy = cast<FeedbackTextureExtType>(HandleTy);
278auto *RTy = cast<SamplerExtType>(HandleTy);
279 TypeName =
formatv(
"SamplerState<{0}>",
356return cast<TextureExtType>(Ty)->isROV();
358return cast<TypedBufferExtType>(Ty)->isROV();
361return cast<RawBufferExtType>(Ty)->isROV();
380return {GloballyCoherent, HasCounter,
isROV(Kind, HandleTy)};
385return cast<CBufferExtType>(HandleTy)->getCBufferSize();
390return cast<SamplerExtType>(HandleTy)->getSamplerType();
397Type *ElTy = cast<RawBufferExtType>(HandleTy)->getResourceType();
401if (
auto *STy = dyn_cast<StructType>(ElTy))
404return {Stride, AlignLog2};
417auto *RTy = cast<TextureExtType>(Ty);
418return {RTy->getResourceType(), RTy->isSigned()};
422auto *RTy = cast<MSTextureExtType>(Ty);
423return {RTy->getResourceType(), RTy->isSigned()};
426auto *RTy = cast<TypedBufferExtType>(Ty);
427return {RTy->getResourceType(), RTy->isSigned()};
450if (
auto *VTy = dyn_cast<FixedVectorType>(ElTy))
451 Count = VTy->getNumElements();
457return cast<FeedbackTextureExtType>(HandleTy)->getFeedbackType();
461return cast<MSTextureExtType>(HandleTy)->getSampleCount();
465return std::tie(HandleTy, GloballyCoherent, HasCounter) ==
466 std::tie(
RHS.HandleTy,
RHS.GloballyCoherent,
RHS.HasCounter);
470// An empty datalayout is sufficient for sorting purposes. 472if (std::tie(RC, Kind) < std::tie(
RHS.RC,
RHS.Kind))
507 <<
" HasCounter: " << UAVFlags.
HasCounter <<
"\n" 508 <<
" IsROV: " << UAVFlags.
IsROV <<
"\n";
515OS <<
" Buffer Stride: " <<
Struct.Stride <<
"\n";
516OS <<
" Alignment: " <<
Struct.AlignLog2 <<
"\n";
529assert(!Symbol &&
"Symbol has already been created");
532/*Initializer=*/nullptr,
Name);
545auto getIntMD = [&I32Ty](
uint32_t V) {
549auto getBoolMD = [&I1Ty](
uint32_t V) {
555assert(Symbol &&
"Cannot yet create useful resource metadata without symbol");
577// All SRVs include sample count in the metadata, but it's only meaningful 578// for multi-sampled textured. Also, UAVs can be multisampled in SM6.7+, 579// but this just isn't reflected in the metadata at all. 585// Further properties are attached to a metadata list of tag-value pairs. 605std::pair<uint32_t, uint32_t>
612bool IsUAV = RTI.
isUAV();
615bool IsROV = IsUAV && UAVFlags.
IsROV;
617uint8_t SamplerCmpOrHasCounter = 0;
623// TODO: Document this format. Currently the only reference is the 624// implementation of dxc's DxilResourceProperties struct. 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;
651return {Word0, Word1};
663 <<
" Record ID: " << Binding.
RecordID <<
"\n" 664 <<
" Space: " << Binding.
Space <<
"\n" 665 <<
" Lower Bound: " << Binding.
LowerBound <<
"\n" 666 <<
" Size: " << Binding.
Size <<
"\n";
671//===----------------------------------------------------------------------===// 675// Passes that introduce resource types must explicitly invalidate this pass. 677return !PAC.preservedWhenStateless();
680//===----------------------------------------------------------------------===// 687if (!
F.isDeclaration())
694case Intrinsic::dx_resource_handlefrombinding: {
695auto *HandleTy = cast<TargetExtType>(
F.getReturnType());
698for (
User *U :
F.users())
699if (
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/*RecordID=*/0, Space, LowerBound,
Size, HandleTy};
719constauto &[LCI, LRBI, LRTI] =
LHS;
720constauto &[RCI, RRBI, RRTI] =
RHS;
721// Sort by resource class first for grouping purposes, and then by the 722// binding and type so we can remove duplicates. 726return std::tie(LRC, LRBI, LRTI) < std::tie(RRC, RRBI, RRTI);
728for (
auto [CI, RBI, RTI] : CIToInfos) {
729if (Infos.empty() || RBI != Infos.back())
730 Infos.push_back(RBI);
731 CallMap[CI] = Infos.size() - 1;
734unsignedSize = Infos.size();
735// In DXC, Record ID is unique per resource type. Match that. 736 FirstUAV = FirstCBuffer = FirstSampler =
Size;
738for (
unsignedI = 0, E =
Size;
I != E; ++
I) {
752// Adjust the resource binding to use the next ID. 759for (
unsignedI = 0, E = Infos.size();
I != E; ++
I) {
760OS <<
"Binding " <<
I <<
":\n";
766for (
constauto &[CI, Index] : CallMap) {
767OS <<
"Call bound to " << Index <<
":";
773//===----------------------------------------------------------------------===// 782Data.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);
836OS <<
"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.
This file contains the declarations for metadata subclasses.
#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 ConstantAsMetadata * get(Constant *C)
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'.
static ValueAsMetadata * get(Value *V)
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