1*0fca6ea1SDimitry Andric //===- DXILResource.cpp - Tools to translate DXIL resources ---------------===// 2*0fca6ea1SDimitry Andric // 3*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0fca6ea1SDimitry Andric // 7*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 8*0fca6ea1SDimitry Andric 9*0fca6ea1SDimitry Andric #include "llvm/Transforms/Utils/DXILResource.h" 10*0fca6ea1SDimitry Andric #include "llvm/ADT/APInt.h" 11*0fca6ea1SDimitry Andric #include "llvm/IR/DerivedTypes.h" 12*0fca6ea1SDimitry Andric 13*0fca6ea1SDimitry Andric using namespace llvm; 14*0fca6ea1SDimitry Andric using namespace dxil; 15*0fca6ea1SDimitry Andric 16*0fca6ea1SDimitry Andric bool ResourceInfo::isUAV() const { return RC == ResourceClass::UAV; } 17*0fca6ea1SDimitry Andric 18*0fca6ea1SDimitry Andric bool ResourceInfo::isCBuffer() const { return RC == ResourceClass::CBuffer; } 19*0fca6ea1SDimitry Andric 20*0fca6ea1SDimitry Andric bool ResourceInfo::isSampler() const { return RC == ResourceClass::Sampler; } 21*0fca6ea1SDimitry Andric 22*0fca6ea1SDimitry Andric bool ResourceInfo::isStruct() const { 23*0fca6ea1SDimitry Andric return Kind == ResourceKind::StructuredBuffer; 24*0fca6ea1SDimitry Andric } 25*0fca6ea1SDimitry Andric 26*0fca6ea1SDimitry Andric bool ResourceInfo::isTyped() const { 27*0fca6ea1SDimitry Andric switch (Kind) { 28*0fca6ea1SDimitry Andric case ResourceKind::Texture1D: 29*0fca6ea1SDimitry Andric case ResourceKind::Texture2D: 30*0fca6ea1SDimitry Andric case ResourceKind::Texture2DMS: 31*0fca6ea1SDimitry Andric case ResourceKind::Texture3D: 32*0fca6ea1SDimitry Andric case ResourceKind::TextureCube: 33*0fca6ea1SDimitry Andric case ResourceKind::Texture1DArray: 34*0fca6ea1SDimitry Andric case ResourceKind::Texture2DArray: 35*0fca6ea1SDimitry Andric case ResourceKind::Texture2DMSArray: 36*0fca6ea1SDimitry Andric case ResourceKind::TextureCubeArray: 37*0fca6ea1SDimitry Andric case ResourceKind::TypedBuffer: 38*0fca6ea1SDimitry Andric return true; 39*0fca6ea1SDimitry Andric case ResourceKind::RawBuffer: 40*0fca6ea1SDimitry Andric case ResourceKind::StructuredBuffer: 41*0fca6ea1SDimitry Andric case ResourceKind::FeedbackTexture2D: 42*0fca6ea1SDimitry Andric case ResourceKind::FeedbackTexture2DArray: 43*0fca6ea1SDimitry Andric case ResourceKind::CBuffer: 44*0fca6ea1SDimitry Andric case ResourceKind::Sampler: 45*0fca6ea1SDimitry Andric case ResourceKind::TBuffer: 46*0fca6ea1SDimitry Andric case ResourceKind::RTAccelerationStructure: 47*0fca6ea1SDimitry Andric return false; 48*0fca6ea1SDimitry Andric case ResourceKind::Invalid: 49*0fca6ea1SDimitry Andric case ResourceKind::NumEntries: 50*0fca6ea1SDimitry Andric llvm_unreachable("Invalid resource kind"); 51*0fca6ea1SDimitry Andric } 52*0fca6ea1SDimitry Andric llvm_unreachable("Unhandled ResourceKind enum"); 53*0fca6ea1SDimitry Andric } 54*0fca6ea1SDimitry Andric 55*0fca6ea1SDimitry Andric bool ResourceInfo::isFeedback() const { 56*0fca6ea1SDimitry Andric return Kind == ResourceKind::FeedbackTexture2D || 57*0fca6ea1SDimitry Andric Kind == ResourceKind::FeedbackTexture2DArray; 58*0fca6ea1SDimitry Andric } 59*0fca6ea1SDimitry Andric 60*0fca6ea1SDimitry Andric bool ResourceInfo::isMultiSample() const { 61*0fca6ea1SDimitry Andric return Kind == ResourceKind::Texture2DMS || 62*0fca6ea1SDimitry Andric Kind == ResourceKind::Texture2DMSArray; 63*0fca6ea1SDimitry Andric } 64*0fca6ea1SDimitry Andric 65*0fca6ea1SDimitry Andric ResourceInfo ResourceInfo::SRV(Value *Symbol, StringRef Name, 66*0fca6ea1SDimitry Andric ResourceBinding Binding, uint32_t UniqueID, 67*0fca6ea1SDimitry Andric ElementType ElementTy, uint32_t ElementCount, 68*0fca6ea1SDimitry Andric ResourceKind Kind) { 69*0fca6ea1SDimitry Andric ResourceInfo RI(ResourceClass::SRV, Kind, Symbol, Name, Binding, UniqueID); 70*0fca6ea1SDimitry Andric assert(RI.isTyped() && !(RI.isStruct() || RI.isMultiSample()) && 71*0fca6ea1SDimitry Andric "Invalid ResourceKind for SRV constructor."); 72*0fca6ea1SDimitry Andric RI.Typed.ElementTy = ElementTy; 73*0fca6ea1SDimitry Andric RI.Typed.ElementCount = ElementCount; 74*0fca6ea1SDimitry Andric return RI; 75*0fca6ea1SDimitry Andric } 76*0fca6ea1SDimitry Andric 77*0fca6ea1SDimitry Andric ResourceInfo ResourceInfo::RawBuffer(Value *Symbol, StringRef Name, 78*0fca6ea1SDimitry Andric ResourceBinding Binding, 79*0fca6ea1SDimitry Andric uint32_t UniqueID) { 80*0fca6ea1SDimitry Andric ResourceInfo RI(ResourceClass::SRV, ResourceKind::RawBuffer, Symbol, Name, 81*0fca6ea1SDimitry Andric Binding, UniqueID); 82*0fca6ea1SDimitry Andric return RI; 83*0fca6ea1SDimitry Andric } 84*0fca6ea1SDimitry Andric 85*0fca6ea1SDimitry Andric ResourceInfo ResourceInfo::StructuredBuffer(Value *Symbol, StringRef Name, 86*0fca6ea1SDimitry Andric ResourceBinding Binding, 87*0fca6ea1SDimitry Andric uint32_t UniqueID, uint32_t Stride, 88*0fca6ea1SDimitry Andric Align Alignment) { 89*0fca6ea1SDimitry Andric ResourceInfo RI(ResourceClass::SRV, ResourceKind::StructuredBuffer, Symbol, 90*0fca6ea1SDimitry Andric Name, Binding, UniqueID); 91*0fca6ea1SDimitry Andric RI.Struct.Stride = Stride; 92*0fca6ea1SDimitry Andric RI.Struct.Alignment = Alignment; 93*0fca6ea1SDimitry Andric return RI; 94*0fca6ea1SDimitry Andric } 95*0fca6ea1SDimitry Andric 96*0fca6ea1SDimitry Andric ResourceInfo ResourceInfo::Texture2DMS(Value *Symbol, StringRef Name, 97*0fca6ea1SDimitry Andric ResourceBinding Binding, 98*0fca6ea1SDimitry Andric uint32_t UniqueID, ElementType ElementTy, 99*0fca6ea1SDimitry Andric uint32_t ElementCount, 100*0fca6ea1SDimitry Andric uint32_t SampleCount) { 101*0fca6ea1SDimitry Andric ResourceInfo RI(ResourceClass::SRV, ResourceKind::Texture2DMS, Symbol, Name, 102*0fca6ea1SDimitry Andric Binding, UniqueID); 103*0fca6ea1SDimitry Andric RI.Typed.ElementTy = ElementTy; 104*0fca6ea1SDimitry Andric RI.Typed.ElementCount = ElementCount; 105*0fca6ea1SDimitry Andric RI.MultiSample.Count = SampleCount; 106*0fca6ea1SDimitry Andric return RI; 107*0fca6ea1SDimitry Andric } 108*0fca6ea1SDimitry Andric 109*0fca6ea1SDimitry Andric ResourceInfo ResourceInfo::Texture2DMSArray( 110*0fca6ea1SDimitry Andric Value *Symbol, StringRef Name, ResourceBinding Binding, uint32_t UniqueID, 111*0fca6ea1SDimitry Andric ElementType ElementTy, uint32_t ElementCount, uint32_t SampleCount) { 112*0fca6ea1SDimitry Andric ResourceInfo RI(ResourceClass::SRV, ResourceKind::Texture2DMSArray, Symbol, 113*0fca6ea1SDimitry Andric Name, Binding, UniqueID); 114*0fca6ea1SDimitry Andric RI.Typed.ElementTy = ElementTy; 115*0fca6ea1SDimitry Andric RI.Typed.ElementCount = ElementCount; 116*0fca6ea1SDimitry Andric RI.MultiSample.Count = SampleCount; 117*0fca6ea1SDimitry Andric return RI; 118*0fca6ea1SDimitry Andric } 119*0fca6ea1SDimitry Andric 120*0fca6ea1SDimitry Andric ResourceInfo ResourceInfo::UAV(Value *Symbol, StringRef Name, 121*0fca6ea1SDimitry Andric ResourceBinding Binding, uint32_t UniqueID, 122*0fca6ea1SDimitry Andric ElementType ElementTy, uint32_t ElementCount, 123*0fca6ea1SDimitry Andric bool GloballyCoherent, bool IsROV, 124*0fca6ea1SDimitry Andric ResourceKind Kind) { 125*0fca6ea1SDimitry Andric ResourceInfo RI(ResourceClass::UAV, Kind, Symbol, Name, Binding, UniqueID); 126*0fca6ea1SDimitry Andric assert(RI.isTyped() && !(RI.isStruct() || RI.isMultiSample()) && 127*0fca6ea1SDimitry Andric "Invalid ResourceKind for UAV constructor."); 128*0fca6ea1SDimitry Andric RI.Typed.ElementTy = ElementTy; 129*0fca6ea1SDimitry Andric RI.Typed.ElementCount = ElementCount; 130*0fca6ea1SDimitry Andric RI.UAVFlags.GloballyCoherent = GloballyCoherent; 131*0fca6ea1SDimitry Andric RI.UAVFlags.IsROV = IsROV; 132*0fca6ea1SDimitry Andric RI.UAVFlags.HasCounter = false; 133*0fca6ea1SDimitry Andric return RI; 134*0fca6ea1SDimitry Andric } 135*0fca6ea1SDimitry Andric 136*0fca6ea1SDimitry Andric ResourceInfo ResourceInfo::RWRawBuffer(Value *Symbol, StringRef Name, 137*0fca6ea1SDimitry Andric ResourceBinding Binding, 138*0fca6ea1SDimitry Andric uint32_t UniqueID, bool GloballyCoherent, 139*0fca6ea1SDimitry Andric bool IsROV) { 140*0fca6ea1SDimitry Andric ResourceInfo RI(ResourceClass::UAV, ResourceKind::RawBuffer, Symbol, Name, 141*0fca6ea1SDimitry Andric Binding, UniqueID); 142*0fca6ea1SDimitry Andric RI.UAVFlags.GloballyCoherent = GloballyCoherent; 143*0fca6ea1SDimitry Andric RI.UAVFlags.IsROV = IsROV; 144*0fca6ea1SDimitry Andric RI.UAVFlags.HasCounter = false; 145*0fca6ea1SDimitry Andric return RI; 146*0fca6ea1SDimitry Andric } 147*0fca6ea1SDimitry Andric 148*0fca6ea1SDimitry Andric ResourceInfo ResourceInfo::RWStructuredBuffer(Value *Symbol, StringRef Name, 149*0fca6ea1SDimitry Andric ResourceBinding Binding, 150*0fca6ea1SDimitry Andric uint32_t UniqueID, 151*0fca6ea1SDimitry Andric uint32_t Stride, Align Alignment, 152*0fca6ea1SDimitry Andric bool GloballyCoherent, bool IsROV, 153*0fca6ea1SDimitry Andric bool HasCounter) { 154*0fca6ea1SDimitry Andric ResourceInfo RI(ResourceClass::UAV, ResourceKind::StructuredBuffer, Symbol, 155*0fca6ea1SDimitry Andric Name, Binding, UniqueID); 156*0fca6ea1SDimitry Andric RI.Struct.Stride = Stride; 157*0fca6ea1SDimitry Andric RI.Struct.Alignment = Alignment; 158*0fca6ea1SDimitry Andric RI.UAVFlags.GloballyCoherent = GloballyCoherent; 159*0fca6ea1SDimitry Andric RI.UAVFlags.IsROV = IsROV; 160*0fca6ea1SDimitry Andric RI.UAVFlags.HasCounter = HasCounter; 161*0fca6ea1SDimitry Andric return RI; 162*0fca6ea1SDimitry Andric } 163*0fca6ea1SDimitry Andric 164*0fca6ea1SDimitry Andric ResourceInfo 165*0fca6ea1SDimitry Andric ResourceInfo::RWTexture2DMS(Value *Symbol, StringRef Name, 166*0fca6ea1SDimitry Andric ResourceBinding Binding, uint32_t UniqueID, 167*0fca6ea1SDimitry Andric ElementType ElementTy, uint32_t ElementCount, 168*0fca6ea1SDimitry Andric uint32_t SampleCount, bool GloballyCoherent) { 169*0fca6ea1SDimitry Andric ResourceInfo RI(ResourceClass::UAV, ResourceKind::Texture2DMS, Symbol, Name, 170*0fca6ea1SDimitry Andric Binding, UniqueID); 171*0fca6ea1SDimitry Andric RI.Typed.ElementTy = ElementTy; 172*0fca6ea1SDimitry Andric RI.Typed.ElementCount = ElementCount; 173*0fca6ea1SDimitry Andric RI.UAVFlags.GloballyCoherent = GloballyCoherent; 174*0fca6ea1SDimitry Andric RI.UAVFlags.IsROV = false; 175*0fca6ea1SDimitry Andric RI.UAVFlags.HasCounter = false; 176*0fca6ea1SDimitry Andric RI.MultiSample.Count = SampleCount; 177*0fca6ea1SDimitry Andric return RI; 178*0fca6ea1SDimitry Andric } 179*0fca6ea1SDimitry Andric 180*0fca6ea1SDimitry Andric ResourceInfo 181*0fca6ea1SDimitry Andric ResourceInfo::RWTexture2DMSArray(Value *Symbol, StringRef Name, 182*0fca6ea1SDimitry Andric ResourceBinding Binding, uint32_t UniqueID, 183*0fca6ea1SDimitry Andric ElementType ElementTy, uint32_t ElementCount, 184*0fca6ea1SDimitry Andric uint32_t SampleCount, bool GloballyCoherent) { 185*0fca6ea1SDimitry Andric ResourceInfo RI(ResourceClass::UAV, ResourceKind::Texture2DMSArray, Symbol, 186*0fca6ea1SDimitry Andric Name, Binding, UniqueID); 187*0fca6ea1SDimitry Andric RI.Typed.ElementTy = ElementTy; 188*0fca6ea1SDimitry Andric RI.Typed.ElementCount = ElementCount; 189*0fca6ea1SDimitry Andric RI.UAVFlags.GloballyCoherent = GloballyCoherent; 190*0fca6ea1SDimitry Andric RI.UAVFlags.IsROV = false; 191*0fca6ea1SDimitry Andric RI.UAVFlags.HasCounter = false; 192*0fca6ea1SDimitry Andric RI.MultiSample.Count = SampleCount; 193*0fca6ea1SDimitry Andric return RI; 194*0fca6ea1SDimitry Andric } 195*0fca6ea1SDimitry Andric 196*0fca6ea1SDimitry Andric ResourceInfo ResourceInfo::FeedbackTexture2D(Value *Symbol, StringRef Name, 197*0fca6ea1SDimitry Andric ResourceBinding Binding, 198*0fca6ea1SDimitry Andric uint32_t UniqueID, 199*0fca6ea1SDimitry Andric SamplerFeedbackType FeedbackTy) { 200*0fca6ea1SDimitry Andric ResourceInfo RI(ResourceClass::UAV, ResourceKind::FeedbackTexture2D, Symbol, 201*0fca6ea1SDimitry Andric Name, Binding, UniqueID); 202*0fca6ea1SDimitry Andric RI.UAVFlags.GloballyCoherent = false; 203*0fca6ea1SDimitry Andric RI.UAVFlags.IsROV = false; 204*0fca6ea1SDimitry Andric RI.UAVFlags.HasCounter = false; 205*0fca6ea1SDimitry Andric RI.Feedback.Type = FeedbackTy; 206*0fca6ea1SDimitry Andric return RI; 207*0fca6ea1SDimitry Andric } 208*0fca6ea1SDimitry Andric 209*0fca6ea1SDimitry Andric ResourceInfo 210*0fca6ea1SDimitry Andric ResourceInfo::FeedbackTexture2DArray(Value *Symbol, StringRef Name, 211*0fca6ea1SDimitry Andric ResourceBinding Binding, uint32_t UniqueID, 212*0fca6ea1SDimitry Andric SamplerFeedbackType FeedbackTy) { 213*0fca6ea1SDimitry Andric ResourceInfo RI(ResourceClass::UAV, ResourceKind::FeedbackTexture2DArray, 214*0fca6ea1SDimitry Andric Symbol, Name, Binding, UniqueID); 215*0fca6ea1SDimitry Andric RI.UAVFlags.GloballyCoherent = false; 216*0fca6ea1SDimitry Andric RI.UAVFlags.IsROV = false; 217*0fca6ea1SDimitry Andric RI.UAVFlags.HasCounter = false; 218*0fca6ea1SDimitry Andric RI.Feedback.Type = FeedbackTy; 219*0fca6ea1SDimitry Andric return RI; 220*0fca6ea1SDimitry Andric } 221*0fca6ea1SDimitry Andric 222*0fca6ea1SDimitry Andric ResourceInfo ResourceInfo::CBuffer(Value *Symbol, StringRef Name, 223*0fca6ea1SDimitry Andric ResourceBinding Binding, uint32_t UniqueID, 224*0fca6ea1SDimitry Andric uint32_t Size) { 225*0fca6ea1SDimitry Andric ResourceInfo RI(ResourceClass::CBuffer, ResourceKind::CBuffer, Symbol, Name, 226*0fca6ea1SDimitry Andric Binding, UniqueID); 227*0fca6ea1SDimitry Andric RI.CBufferSize = Size; 228*0fca6ea1SDimitry Andric return RI; 229*0fca6ea1SDimitry Andric } 230*0fca6ea1SDimitry Andric 231*0fca6ea1SDimitry Andric ResourceInfo ResourceInfo::Sampler(Value *Symbol, StringRef Name, 232*0fca6ea1SDimitry Andric ResourceBinding Binding, uint32_t UniqueID, 233*0fca6ea1SDimitry Andric SamplerType SamplerTy) { 234*0fca6ea1SDimitry Andric ResourceInfo RI(ResourceClass::Sampler, ResourceKind::Sampler, Symbol, Name, 235*0fca6ea1SDimitry Andric Binding, UniqueID); 236*0fca6ea1SDimitry Andric RI.SamplerTy = SamplerTy; 237*0fca6ea1SDimitry Andric return RI; 238*0fca6ea1SDimitry Andric } 239*0fca6ea1SDimitry Andric 240*0fca6ea1SDimitry Andric bool ResourceInfo::operator==(const ResourceInfo &RHS) const { 241*0fca6ea1SDimitry Andric if (std::tie(Symbol, Name, Binding, UniqueID, RC, Kind) != 242*0fca6ea1SDimitry Andric std::tie(RHS.Symbol, RHS.Name, RHS.Binding, RHS.UniqueID, RHS.RC, 243*0fca6ea1SDimitry Andric RHS.Kind)) 244*0fca6ea1SDimitry Andric return false; 245*0fca6ea1SDimitry Andric if (isCBuffer()) 246*0fca6ea1SDimitry Andric return CBufferSize == RHS.CBufferSize; 247*0fca6ea1SDimitry Andric if (isSampler()) 248*0fca6ea1SDimitry Andric return SamplerTy == RHS.SamplerTy; 249*0fca6ea1SDimitry Andric if (isUAV() && UAVFlags != RHS.UAVFlags) 250*0fca6ea1SDimitry Andric return false; 251*0fca6ea1SDimitry Andric 252*0fca6ea1SDimitry Andric if (isStruct()) 253*0fca6ea1SDimitry Andric return Struct == RHS.Struct; 254*0fca6ea1SDimitry Andric if (isFeedback()) 255*0fca6ea1SDimitry Andric return Feedback == RHS.Feedback; 256*0fca6ea1SDimitry Andric if (isTyped() && Typed != RHS.Typed) 257*0fca6ea1SDimitry Andric return false; 258*0fca6ea1SDimitry Andric 259*0fca6ea1SDimitry Andric if (isMultiSample()) 260*0fca6ea1SDimitry Andric return MultiSample == RHS.MultiSample; 261*0fca6ea1SDimitry Andric 262*0fca6ea1SDimitry Andric assert((Kind == ResourceKind::RawBuffer) && "Unhandled resource kind"); 263*0fca6ea1SDimitry Andric return true; 264*0fca6ea1SDimitry Andric } 265*0fca6ea1SDimitry Andric 266*0fca6ea1SDimitry Andric MDTuple *ResourceInfo::getAsMetadata(LLVMContext &Ctx) const { 267*0fca6ea1SDimitry Andric SmallVector<Metadata *, 11> MDVals; 268*0fca6ea1SDimitry Andric 269*0fca6ea1SDimitry Andric Type *I32Ty = Type::getInt32Ty(Ctx); 270*0fca6ea1SDimitry Andric Type *I1Ty = Type::getInt1Ty(Ctx); 271*0fca6ea1SDimitry Andric auto getIntMD = [&I32Ty](uint32_t V) { 272*0fca6ea1SDimitry Andric return ConstantAsMetadata::get( 273*0fca6ea1SDimitry Andric Constant::getIntegerValue(I32Ty, APInt(32, V))); 274*0fca6ea1SDimitry Andric }; 275*0fca6ea1SDimitry Andric auto getBoolMD = [&I1Ty](uint32_t V) { 276*0fca6ea1SDimitry Andric return ConstantAsMetadata::get( 277*0fca6ea1SDimitry Andric Constant::getIntegerValue(I1Ty, APInt(1, V))); 278*0fca6ea1SDimitry Andric }; 279*0fca6ea1SDimitry Andric 280*0fca6ea1SDimitry Andric MDVals.push_back(getIntMD(UniqueID)); 281*0fca6ea1SDimitry Andric MDVals.push_back(ValueAsMetadata::get(Symbol)); 282*0fca6ea1SDimitry Andric MDVals.push_back(MDString::get(Ctx, Name)); 283*0fca6ea1SDimitry Andric MDVals.push_back(getIntMD(Binding.Space)); 284*0fca6ea1SDimitry Andric MDVals.push_back(getIntMD(Binding.LowerBound)); 285*0fca6ea1SDimitry Andric MDVals.push_back(getIntMD(Binding.Size)); 286*0fca6ea1SDimitry Andric 287*0fca6ea1SDimitry Andric if (isCBuffer()) { 288*0fca6ea1SDimitry Andric MDVals.push_back(getIntMD(CBufferSize)); 289*0fca6ea1SDimitry Andric MDVals.push_back(nullptr); 290*0fca6ea1SDimitry Andric } else if (isSampler()) { 291*0fca6ea1SDimitry Andric MDVals.push_back(getIntMD(llvm::to_underlying(SamplerTy))); 292*0fca6ea1SDimitry Andric MDVals.push_back(nullptr); 293*0fca6ea1SDimitry Andric } else { 294*0fca6ea1SDimitry Andric MDVals.push_back(getIntMD(llvm::to_underlying(Kind))); 295*0fca6ea1SDimitry Andric 296*0fca6ea1SDimitry Andric if (isUAV()) { 297*0fca6ea1SDimitry Andric MDVals.push_back(getBoolMD(UAVFlags.GloballyCoherent)); 298*0fca6ea1SDimitry Andric MDVals.push_back(getBoolMD(UAVFlags.HasCounter)); 299*0fca6ea1SDimitry Andric MDVals.push_back(getBoolMD(UAVFlags.IsROV)); 300*0fca6ea1SDimitry Andric } else { 301*0fca6ea1SDimitry Andric // All SRVs include sample count in the metadata, but it's only meaningful 302*0fca6ea1SDimitry Andric // for multi-sampled textured. Also, UAVs can be multisampled in SM6.7+, 303*0fca6ea1SDimitry Andric // but this just isn't reflected in the metadata at all. 304*0fca6ea1SDimitry Andric uint32_t SampleCount = isMultiSample() ? MultiSample.Count : 0; 305*0fca6ea1SDimitry Andric MDVals.push_back(getIntMD(SampleCount)); 306*0fca6ea1SDimitry Andric } 307*0fca6ea1SDimitry Andric 308*0fca6ea1SDimitry Andric // Further properties are attached to a metadata list of tag-value pairs. 309*0fca6ea1SDimitry Andric SmallVector<Metadata *> Tags; 310*0fca6ea1SDimitry Andric if (isStruct()) { 311*0fca6ea1SDimitry Andric Tags.push_back( 312*0fca6ea1SDimitry Andric getIntMD(llvm::to_underlying(ExtPropTags::StructuredBufferStride))); 313*0fca6ea1SDimitry Andric Tags.push_back(getIntMD(Struct.Stride)); 314*0fca6ea1SDimitry Andric } else if (isTyped()) { 315*0fca6ea1SDimitry Andric Tags.push_back(getIntMD(llvm::to_underlying(ExtPropTags::ElementType))); 316*0fca6ea1SDimitry Andric Tags.push_back(getIntMD(llvm::to_underlying(Typed.ElementTy))); 317*0fca6ea1SDimitry Andric } else if (isFeedback()) { 318*0fca6ea1SDimitry Andric Tags.push_back( 319*0fca6ea1SDimitry Andric getIntMD(llvm::to_underlying(ExtPropTags::SamplerFeedbackKind))); 320*0fca6ea1SDimitry Andric Tags.push_back(getIntMD(llvm::to_underlying(Feedback.Type))); 321*0fca6ea1SDimitry Andric } 322*0fca6ea1SDimitry Andric MDVals.push_back(Tags.empty() ? nullptr : MDNode::get(Ctx, Tags)); 323*0fca6ea1SDimitry Andric } 324*0fca6ea1SDimitry Andric 325*0fca6ea1SDimitry Andric return MDNode::get(Ctx, MDVals); 326*0fca6ea1SDimitry Andric } 327*0fca6ea1SDimitry Andric 328*0fca6ea1SDimitry Andric std::pair<uint32_t, uint32_t> ResourceInfo::getAnnotateProps() const { 329*0fca6ea1SDimitry Andric uint32_t ResourceKind = llvm::to_underlying(Kind); 330*0fca6ea1SDimitry Andric uint32_t AlignLog2 = isStruct() ? Log2(Struct.Alignment) : 0; 331*0fca6ea1SDimitry Andric bool IsUAV = isUAV(); 332*0fca6ea1SDimitry Andric bool IsROV = IsUAV && UAVFlags.IsROV; 333*0fca6ea1SDimitry Andric bool IsGloballyCoherent = IsUAV && UAVFlags.GloballyCoherent; 334*0fca6ea1SDimitry Andric uint8_t SamplerCmpOrHasCounter = 0; 335*0fca6ea1SDimitry Andric if (IsUAV) 336*0fca6ea1SDimitry Andric SamplerCmpOrHasCounter = UAVFlags.HasCounter; 337*0fca6ea1SDimitry Andric else if (isSampler()) 338*0fca6ea1SDimitry Andric SamplerCmpOrHasCounter = SamplerTy == SamplerType::Comparison; 339*0fca6ea1SDimitry Andric 340*0fca6ea1SDimitry Andric // TODO: Document this format. Currently the only reference is the 341*0fca6ea1SDimitry Andric // implementation of dxc's DxilResourceProperties struct. 342*0fca6ea1SDimitry Andric uint32_t Word0 = 0; 343*0fca6ea1SDimitry Andric Word0 |= ResourceKind & 0xFF; 344*0fca6ea1SDimitry Andric Word0 |= (AlignLog2 & 0xF) << 8; 345*0fca6ea1SDimitry Andric Word0 |= (IsUAV & 1) << 12; 346*0fca6ea1SDimitry Andric Word0 |= (IsROV & 1) << 13; 347*0fca6ea1SDimitry Andric Word0 |= (IsGloballyCoherent & 1) << 14; 348*0fca6ea1SDimitry Andric Word0 |= (SamplerCmpOrHasCounter & 1) << 15; 349*0fca6ea1SDimitry Andric 350*0fca6ea1SDimitry Andric uint32_t Word1 = 0; 351*0fca6ea1SDimitry Andric if (isStruct()) 352*0fca6ea1SDimitry Andric Word1 = Struct.Stride; 353*0fca6ea1SDimitry Andric else if (isCBuffer()) 354*0fca6ea1SDimitry Andric Word1 = CBufferSize; 355*0fca6ea1SDimitry Andric else if (isFeedback()) 356*0fca6ea1SDimitry Andric Word1 = llvm::to_underlying(Feedback.Type); 357*0fca6ea1SDimitry Andric else if (isTyped()) { 358*0fca6ea1SDimitry Andric uint32_t CompType = llvm::to_underlying(Typed.ElementTy); 359*0fca6ea1SDimitry Andric uint32_t CompCount = Typed.ElementCount; 360*0fca6ea1SDimitry Andric uint32_t SampleCount = isMultiSample() ? MultiSample.Count : 0; 361*0fca6ea1SDimitry Andric 362*0fca6ea1SDimitry Andric Word1 |= (CompType & 0xFF) << 0; 363*0fca6ea1SDimitry Andric Word1 |= (CompCount & 0xFF) << 8; 364*0fca6ea1SDimitry Andric Word1 |= (SampleCount & 0xFF) << 16; 365*0fca6ea1SDimitry Andric } 366*0fca6ea1SDimitry Andric 367*0fca6ea1SDimitry Andric return {Word0, Word1}; 368*0fca6ea1SDimitry Andric } 369*0fca6ea1SDimitry Andric 370*0fca6ea1SDimitry Andric #define DEBUG_TYPE "dxil-resource" 371