21#include "llvm/IR/IntrinsicsDirectX.h"
29#define DEBUG_TYPE "dxil-resource"
36 case ResourceKind::Texture1D:
38 case ResourceKind::Texture2D:
40 case ResourceKind::Texture2DMS:
42 case ResourceKind::Texture3D:
44 case ResourceKind::TextureCube:
46 case ResourceKind::Texture1DArray:
47 return "Texture1DArray";
48 case ResourceKind::Texture2DArray:
49 return "Texture2DArray";
50 case ResourceKind::Texture2DMSArray:
51 return "Texture2DMSArray";
52 case ResourceKind::TextureCubeArray:
53 return "TextureCubeArray";
54 case ResourceKind::TypedBuffer:
56 case ResourceKind::RawBuffer:
58 case ResourceKind::StructuredBuffer:
59 return "StructuredBuffer";
60 case ResourceKind::CBuffer:
62 case ResourceKind::Sampler:
64 case ResourceKind::TBuffer:
66 case ResourceKind::RTAccelerationStructure:
67 return "RTAccelerationStructure";
68 case ResourceKind::FeedbackTexture2D:
69 return "FeedbackTexture2D";
70 case ResourceKind::FeedbackTexture2DArray:
71 return "FeedbackTexture2DArray";
72 case ResourceKind::NumEntries:
73 case ResourceKind::Invalid:
83 case ElementType::I16:
85 case ElementType::U16:
87 case ElementType::I32:
89 case ElementType::U32:
91 case ElementType::I64:
93 case ElementType::U64:
95 case ElementType::F16:
97 case ElementType::F32:
99 case ElementType::F64:
101 case ElementType::SNormF16:
103 case ElementType::UNormF16:
105 case ElementType::SNormF32:
107 case ElementType::UNormF32:
109 case ElementType::SNormF64:
111 case ElementType::UNormF64:
113 case ElementType::PackedS8x32:
115 case ElementType::PackedU8x32:
117 case ElementType::Invalid:
125 case ElementType::I1:
127 case ElementType::I16:
129 case ElementType::U16:
131 case ElementType::I32:
133 case ElementType::U32:
135 case ElementType::I64:
137 case ElementType::U64:
139 case ElementType::F16:
140 case ElementType::SNormF16:
141 case ElementType::UNormF16:
143 case ElementType::F32:
144 case ElementType::SNormF32:
145 case ElementType::UNormF32:
147 case ElementType::F64:
148 case ElementType::SNormF64:
149 case ElementType::UNormF64:
151 case ElementType::PackedS8x32:
152 return "int8_t4_packed";
153 case ElementType::PackedU8x32:
154 return "uint8_t4_packed";
155 case ElementType::Invalid:
163 case SamplerType::Default:
165 case SamplerType::Comparison:
167 case SamplerType::Mono:
175 case SamplerFeedbackType::MinMip:
177 case SamplerFeedbackType::MipRegionUsed:
178 return "MipRegionUsed";
185 Ty = Ty->getScalarType();
187 if (Ty->isIntegerTy()) {
188 switch (Ty->getIntegerBitWidth()) {
190 return IsSigned ? ElementType::I16 : ElementType::U16;
192 return IsSigned ? ElementType::I32 : ElementType::U32;
194 return IsSigned ? ElementType::I64 : ElementType::U64;
197 return ElementType::Invalid;
199 }
else if (Ty->isFloatTy()) {
200 return ElementType::F32;
201 }
else if (Ty->isDoubleTy()) {
202 return ElementType::F64;
203 }
else if (Ty->isHalfTy()) {
204 return ElementType::F16;
207 return ElementType::Invalid;
221 : HandleTy(HandleTy) {
238 Kind = Ty->getDimension();
241 Kind = Ty->getDimension();
244 Kind = Ty->getDimension();
256 bool IsWriteable,
bool IsROV,
257 Type *ContainedType =
nullptr,
258 bool IsSigned =
true) {
261 DestStream << (IsROV ?
"RasterizerOrdered" :
"RW");
269 ArrayDimensions.
push_back(AT->getNumElements());
270 ContainedType = AT->getElementType();
279 "invalid element type for raw buffer");
283 ElementName = ST->getStructName();
286 DestStream <<
"<" << ElementName;
288 DestStream << VTy->getNumElements();
289 for (
uint64_t Dim : ArrayDimensions)
290 DestStream <<
"[" << Dim <<
"]";
296 if (Ty && Ty->getNumElements() == 1 && Ty->getElementType(0) == ElemType)
306 ElementTypes.
reserve(ST->getNumElements());
307 for (
Type *ElTy : ST->elements()) {
314 if (ElementTypes.
size() == 2)
316 if (ElementTypes[1] == AT->getElementType())
320 if (ElementTypes.
size() == 1)
321 return ElementTypes[0];
328 AT->getNumElements());
346 RTy->isROV(), RTy->getResourceType(), RTy->isSigned());
353 false, RTy->getResourceType(), RTy->isSigned());
359 RTy->isROV(), RTy->getResourceType(), RTy->isSigned());
371 Type *Ty = RTy->getResourceType();
373 RTy->isROV(), RTy->getResourceType(),
true);
387 if (!CBufferName.
empty()) {
389 Name.append(CBufferName);
404 TypeName =
formatv(
"SamplerState<{0}>",
505 return {
isROV(Kind, HandleTy)};
515 return LayoutTy->getSize();
517 return DL.getTypeAllocSize(ElTy);
534 Alignment =
DL.getStructLayout(STy)->getAlignment();
536 return {Stride, AlignLog2};
550 return {RTy->getResourceType(), RTy->isSigned()};
555 return {RTy->getResourceType(), RTy->isSigned()};
559 return {RTy->getResourceType(), RTy->isSigned()};
584 Count = VTy->getNumElements();
585 return {ET, DXILStorageTy,
Count};
598 return HandleTy == RHS.HandleTy;
604 if (std::tie(RC, Kind) < std::tie(RHS.RC, RHS.Kind))
611 if (
isUAV() && RHS.isUAV() &&
getUAV() < RHS.getUAV())
614 getStruct(DummyDL) < RHS.getStruct(DummyDL))
638 OS <<
" IsROV: " << UAVFlags.
IsROV <<
"\n";
645 OS <<
" Buffer Stride: " << Struct.Stride <<
"\n";
646 OS <<
" Alignment: " << Struct.AlignLog2 <<
"\n";
661 assert(!Symbol &&
"Symbol has already been created");
663 int64_t
Size = Binding.Size;
682 auto getIntMD = [&I32Ty](
uint32_t V) {
686 auto getBoolMD = [&I1Ty](
uint32_t V) {
691 MDVals.
push_back(getIntMD(Binding.RecordID));
692 assert(Symbol &&
"Cannot yet create useful resource metadata without symbol");
695 MDVals.
push_back(getIntMD(Binding.Space));
696 MDVals.
push_back(getIntMD(Binding.LowerBound));
697 MDVals.
push_back(getIntMD(Binding.Size == 0 ? ~0u : Binding.Size));
743std::pair<uint32_t, uint32_t>
749 bool IsUAV = RTI.
isUAV();
752 bool IsROV = IsUAV && UAVFlags.
IsROV;
754 uint8_t SamplerCmpOrHasCounter = 0;
764 Word0 |= (AlignLog2 & 0xF) << 8;
765 Word0 |= (IsUAV & 1) << 12;
766 Word0 |= (IsROV & 1) << 13;
767 Word0 |= (IsGloballyCoherent & 1) << 14;
768 Word0 |= (SamplerCmpOrHasCounter & 1) << 15;
783 Word1 |= (CompType & 0xFF) << 0;
784 Word1 |= (CompCount & 0xFF) << 8;
785 Word1 |= (SampleCount & 0xFF) << 16;
788 return {Word0, Word1};
794 OS <<
" Name: " << Name <<
"\n";
798 Symbol->printAsOperand(OS);
803 <<
" Record ID: " << Binding.RecordID <<
"\n"
804 <<
" Space: " << Binding.Space <<
"\n"
805 <<
" Lower Bound: " << Binding.LowerBound <<
"\n"
806 <<
" Size: " << Binding.Size <<
"\n";
810 OS <<
" Counter Direction: ";
833 ModuleAnalysisManager::Invalidator &Inv) {
836 return !PAC.preservedWhenStateless();
845 case Intrinsic::dx_resource_handlefrombinding:
846 case Intrinsic::dx_resource_handlefromimplicitbinding:
856 assert(CA && CA->isString() &&
"expected constant string");
859 if (Name.ends_with(
'\0'))
860 Name = Name.drop_back(1);
864void DXILResourceMap::populateResourceInfos(
Module &M,
869 if (!
F.isDeclaration())
876 case Intrinsic::dx_resource_handlefrombinding: {
880 for (
User *U :
F.users())
893 Size, HandleTy, Name};
904 const auto &[LCI, LRI, LRTI] =
LHS;
905 const auto &[RCI, RRI, RRTI] =
RHS;
911 return std::tie(LRC, LRI, LRTI) < std::tie(RRC, RRI, RRTI);
913 for (
auto [CI, RI, RTI] : CIToInfos) {
914 if (Infos.empty() || RI != Infos.back())
916 CallMap[CI] = Infos.size() - 1;
921 FirstUAV = FirstCBuffer = FirstSampler =
Size;
923 for (
unsigned I = 0,
E =
Size;
I !=
E; ++
I) {
939 FirstCBuffer = std::min({FirstCBuffer, FirstSampler});
940 FirstUAV = std::min({FirstUAV, FirstCBuffer});
950 Ptr =
GEP->getPointerOperand()->stripPointerCasts();
952 if (
II &&
II->getIntrinsicID() == Intrinsic::dx_resource_getpointer)
953 return II->getArgOperand(0);
957void DXILResourceMap::populateAtomicUses(Instruction &
I) {
958 auto MarkFromHandle = [
this](
Value *Handle) {
968 if (AI->getValOperand()->getType()->isIntegerTy(64))
973 if (CX->getNewValOperand()->getType()->isIntegerTy(64))
978 if (CI->getIntrinsicID() == Intrinsic::dx_resource_atomic_binop &&
979 CI->getType()->isIntegerTy(64))
980 MarkFromHandle(CI->getArgOperand(0));
984void DXILResourceMap::populateRecordCounterDirection(Instruction &
I) {
986 if (!CI || CI->getIntrinsicID() != Intrinsic::dx_resource_updatecounter)
990 if (CountLiteral == 0)
995 for (
ResourceInfo *RBInfo : findByUse(CI->getArgOperand(0))) {
998 else if (RBInfo->CounterDirection !=
Direction) {
1000 HasInvalidDirection =
true;
1005void DXILResourceMap::populateFromInstructions(
Module &M) {
1006 for (Function &
F :
M.functions()) {
1008 populateAtomicUses(
I);
1009 populateRecordCounterDirection(
I);
1014void DXILResourceMap::populate(
Module &M, DXILResourceTypeMap &DRTM) {
1015 populateResourceInfos(M, DRTM);
1016 populateFromInstructions(M);
1021 for (
unsigned I = 0, E = Infos.size();
I != E; ++
I) {
1022 OS <<
"Resource " <<
I <<
":\n";
1028 for (
const auto &[CI, Index] : CallMap) {
1029 OS <<
"Call bound to " << Index <<
":";
1038 for (
const Value *V : Phi->operands()) {
1039 Children.append(findByUse(V));
1050 case Intrinsic::dx_resource_handlefrombinding: {
1051 auto Pos = CallMap.find(CI);
1052 assert(Pos != CallMap.end() &&
"HandleFromBinding must be in resource map");
1053 return {&Infos[Pos->second]};
1064 if (
V->getType() != UseType)
1075void DXILResourceBindingInfo::populate(
Module &M, DXILResourceTypeMap &DRTM) {
1076 hlsl::BindingInfoBuilder Builder;
1080 for (Function &
F :
M.functions()) {
1081 if (!
F.isDeclaration())
1084 switch (
F.getIntrinsicID()) {
1087 case Intrinsic::dx_resource_handlefrombinding: {
1091 for (User *U :
F.users())
1095 uint32_t LowerBound =
1103 assert((
Size == 0 || (uint64_t)LowerBound + (uint64_t)
Size - 1ULL <=
1104 (uint64_t)UINT32_MAX) &&
1105 "upper bound register overflow");
1106 uint32_t UpperBound =
Size == 0 ? UINT32_MAX : LowerBound +
Size - 1;
1112 case Intrinsic::dx_resource_handlefromimplicitbinding: {
1113 HasImplicitBinding =
true;
1120 [
this](
auto,
auto) { this->HasOverlappingBinding =
true; });
1125AnalysisKey DXILResourceTypeAnalysis::Key;
1126AnalysisKey DXILResourceAnalysis::Key;
1127AnalysisKey DXILResourceBindingAnalysis::Key;
1133 Data.populate(M, DRTM);
1141 Data.populate(M, DRTM);
1150 DRM.
print(OS, DRTM, M.getDataLayout());
1154void DXILResourceTypeWrapperPass::anchor() {}
1160 "DXIL Resource Type Analysis",
false,
true)
1180 Map->populate(M, *DRTM);
1189 OS <<
"No resource map has been built!\n";
1192 Map->print(OS, *DRTM, M->getDataLayout());
1195#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1201 "DXIL Resources Analysis",
false,
true)
1223 BindingInfo->populate(M, DRTM);
1231 "DXIL Resource Binding Analysis",
false,
true)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Expand Atomic instructions
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#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...
static dxil::ElementType toDXILElementType(Type *Ty, bool IsSigned)
static StructType * getOrCreateElementStruct(Type *ElemType, StringRef Name)
static void formatTypeName(SmallString< 64 > &Dest, StringRef Name, bool IsWriteable, bool IsROV, Type *ContainedType=nullptr, bool IsSigned=true)
static StringRef getElementTypeName(ElementType ET)
static std::pair< Type *, bool > getTypedElementType(dxil::ResourceKind Kind, TargetExtType *Ty)
static dxil::ElementType toDXILStorageType(dxil::ElementType ET)
static bool isROV(dxil::ResourceKind Kind, TargetExtType *Ty)
static Type * getTypeWithoutPadding(Type *Ty)
static StringRef getResourceKindName(ResourceKind RK)
static StringRef getSamplerTypeName(SamplerType ST)
static StringRef getSamplerFeedbackTypeName(SamplerFeedbackType SFT)
static StringRef getElementTypeNameForTemplate(ElementType ET)
static Value * findResourceHandleFromPointer(Value *Ptr)
Module.h This file contains the declarations for the Module class.
Loop::LoopBounds::Direction Direction
Machine Check Debug Module
uint64_t IntrinsicInst * II
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
This file defines the SmallString class.
This file defines the SmallVector class.
Class for arbitrary precision integers.
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()
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
Value * getArgOperand(unsigned i) const
LLVM_ABI Intrinsic::ID getIntrinsicID() const
Returns the intrinsic ID of the intrinsic called or Intrinsic::not_intrinsic if the called function i...
iterator_range< User::op_iterator > args()
Iteration adapter for range-for loops.
This class represents a function call, abstracting a target machine's calling convention.
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
static LLVM_ABI 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...
LLVM_ABI DXILResourceMap run(Module &M, ModuleAnalysisManager &AM)
Gather resource info for the module M.
LLVM_ABI DXILResourceBindingInfo 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 releaseMemory() override
releaseMemory() - This member can be implemented by a pass if it wants to be able to release its memo...
LLVM_ABI void print(raw_ostream &OS, DXILResourceTypeMap &DRTM, const DataLayout &DL) const
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
LLVM_ABI bool invalidate(Module &M, const PreservedAnalyses &PA, ModuleAnalysisManager::Invalidator &Inv)
DXILResourceTypeWrapperPass()
DXILResourceWrapperPass()
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...
~DXILResourceWrapperPass() override
void releaseMemory() override
releaseMemory() - This member can be implemented by a pass if it wants to be able to release its memo...
void print(raw_ostream &OS, const Module *M) const override
print - Print out the internal state of the pass.
A parsed version of the target data layout string in and methods for querying it.
Class to represent fixed width SIMD vectors.
Intrinsic::ID getIntrinsicID() const LLVM_READONLY
getIntrinsicID - This method returns the ID number of the specified function, or Intrinsic::not_intri...
@ ExternalLinkage
Externally visible function.
This is an important class for using LLVM in a threaded context.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
static LLVM_ABI MDString * get(LLVMContext &Context, StringRef Str)
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.
AnalysisType & getAnalysis() const
getAnalysis<AnalysisType>() - This function is used by subclasses to get to the analysis information ...
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 reserve(size_type N)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
constexpr bool empty() const
Check if the string is empty.
Class to represent struct types.
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
static LLVM_ABI StructType * getTypeByName(LLVMContext &C, StringRef Name)
Return the type with the specified name, or null if there is none by that name.
static LLVM_ABI 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.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
static LLVM_ABI IntegerType * getInt1Ty(LLVMContext &C)
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
The dx.Layout target extension type.
TargetExtType * getHandleTy() const
LLVM_ABI std::pair< uint32_t, uint32_t > getAnnotateProps(Module &M, dxil::ResourceTypeInfo &RTI) const
LLVM_ABI void print(raw_ostream &OS, dxil::ResourceTypeInfo &RTI, const DataLayout &DL) const
void setBindingID(unsigned ID)
LLVM_ABI GlobalVariable * createSymbol(Module &M, StructType *Ty)
LLVM_ABI MDTuple * getAsMetadata(Module &M, dxil::ResourceTypeInfo &RTI) const
ResourceCounterDirection CounterDirection
dxil::ResourceClass getResourceClass() const
LLVM_ABI uint32_t getMultiSampleCount() const
LLVM_ABI uint32_t getCBufferSize(const DataLayout &DL) const
LLVM_ABI bool operator<(const ResourceTypeInfo &RHS) const
LLVM_ABI bool isUAV() const
LLVM_ABI bool isMultiSample() const
LLVM_ABI bool isSampler() const
LLVM_ABI bool isTyped() const
LLVM_ABI dxil::SamplerType getSamplerType() const
LLVM_ABI ResourceTypeInfo(TargetExtType *HandleTy, const dxil::ResourceClass RC, const dxil::ResourceKind Kind)
LLVM_ABI bool isCBuffer() const
LLVM_ABI TypedInfo getTyped() const
LLVM_ABI StructType * createElementStruct(StringRef CBufferName="")
LLVM_ABI bool isFeedback() const
LLVM_ABI UAVInfo getUAV() const
LLVM_ABI StructInfo getStruct(const DataLayout &DL) const
LLVM_ABI bool isStruct() const
LLVM_ABI dxil::SamplerFeedbackType getFeedbackType() const
LLVM_ABI bool operator==(const ResourceTypeInfo &RHS) const
dxil::ResourceKind getResourceKind() const
LLVM_ABI void print(raw_ostream &OS, const DataLayout &DL) const
void trackBinding(dxil::ResourceClass RC, uint32_t Space, uint32_t LowerBound, uint32_t UpperBound, const void *Cookie)
LLVM_ABI BindingInfo calculateBindingInfo(llvm::function_ref< void(const BindingInfoBuilder &Builder, const Binding &Overlapping)> ReportOverlap)
Calculate the binding info - ReportOverlap will be called once for each overlapping binding.
This class implements an extremely fast bulk output stream that can only output to a stream.
A raw_ostream that writes to an SmallVector or SmallString.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
LLVM_ABI StringRef getResourceClassName(ResourceClass RC)
ResourceKind
The kind of resource for an SRV or UAV resource.
@ RTAccelerationStructure
ElementType
The element type of an SRV or UAV resource.
LLVM_ABI StringRef getResourceNameFromBindingCall(CallInst *CI)
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI ModulePass * createDXILResourceBindingWrapperPassPass()
void stable_sort(R &&Range)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI ModulePass * createDXILResourceTypeWrapperPassPass()
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
LLVM_ABI 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.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
unsigned Log2(Align A)
Returns the log2 of the alignment.
LLVM_ABI ModulePass * createDXILResourceWrapperPassPass()
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
dxil::ElementType DXILStorageTy
dxil::ElementType ElementTy