Path: blob/main/contrib/llvm-project/llvm/lib/Transforms/Utils/DXILResource.cpp
35271 views
//===- DXILResource.cpp - Tools to translate DXIL resources ---------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/Transforms/Utils/DXILResource.h"9#include "llvm/ADT/APInt.h"10#include "llvm/IR/DerivedTypes.h"1112using namespace llvm;13using namespace dxil;1415bool ResourceInfo::isUAV() const { return RC == ResourceClass::UAV; }1617bool ResourceInfo::isCBuffer() const { return RC == ResourceClass::CBuffer; }1819bool ResourceInfo::isSampler() const { return RC == ResourceClass::Sampler; }2021bool ResourceInfo::isStruct() const {22return Kind == ResourceKind::StructuredBuffer;23}2425bool ResourceInfo::isTyped() const {26switch (Kind) {27case ResourceKind::Texture1D:28case ResourceKind::Texture2D:29case ResourceKind::Texture2DMS:30case ResourceKind::Texture3D:31case ResourceKind::TextureCube:32case ResourceKind::Texture1DArray:33case ResourceKind::Texture2DArray:34case ResourceKind::Texture2DMSArray:35case ResourceKind::TextureCubeArray:36case ResourceKind::TypedBuffer:37return true;38case ResourceKind::RawBuffer:39case ResourceKind::StructuredBuffer:40case ResourceKind::FeedbackTexture2D:41case ResourceKind::FeedbackTexture2DArray:42case ResourceKind::CBuffer:43case ResourceKind::Sampler:44case ResourceKind::TBuffer:45case ResourceKind::RTAccelerationStructure:46return false;47case ResourceKind::Invalid:48case ResourceKind::NumEntries:49llvm_unreachable("Invalid resource kind");50}51llvm_unreachable("Unhandled ResourceKind enum");52}5354bool ResourceInfo::isFeedback() const {55return Kind == ResourceKind::FeedbackTexture2D ||56Kind == ResourceKind::FeedbackTexture2DArray;57}5859bool ResourceInfo::isMultiSample() const {60return Kind == ResourceKind::Texture2DMS ||61Kind == ResourceKind::Texture2DMSArray;62}6364ResourceInfo ResourceInfo::SRV(Value *Symbol, StringRef Name,65ResourceBinding Binding, uint32_t UniqueID,66ElementType ElementTy, uint32_t ElementCount,67ResourceKind Kind) {68ResourceInfo RI(ResourceClass::SRV, Kind, Symbol, Name, Binding, UniqueID);69assert(RI.isTyped() && !(RI.isStruct() || RI.isMultiSample()) &&70"Invalid ResourceKind for SRV constructor.");71RI.Typed.ElementTy = ElementTy;72RI.Typed.ElementCount = ElementCount;73return RI;74}7576ResourceInfo ResourceInfo::RawBuffer(Value *Symbol, StringRef Name,77ResourceBinding Binding,78uint32_t UniqueID) {79ResourceInfo RI(ResourceClass::SRV, ResourceKind::RawBuffer, Symbol, Name,80Binding, UniqueID);81return RI;82}8384ResourceInfo ResourceInfo::StructuredBuffer(Value *Symbol, StringRef Name,85ResourceBinding Binding,86uint32_t UniqueID, uint32_t Stride,87Align Alignment) {88ResourceInfo RI(ResourceClass::SRV, ResourceKind::StructuredBuffer, Symbol,89Name, Binding, UniqueID);90RI.Struct.Stride = Stride;91RI.Struct.Alignment = Alignment;92return RI;93}9495ResourceInfo ResourceInfo::Texture2DMS(Value *Symbol, StringRef Name,96ResourceBinding Binding,97uint32_t UniqueID, ElementType ElementTy,98uint32_t ElementCount,99uint32_t SampleCount) {100ResourceInfo RI(ResourceClass::SRV, ResourceKind::Texture2DMS, Symbol, Name,101Binding, UniqueID);102RI.Typed.ElementTy = ElementTy;103RI.Typed.ElementCount = ElementCount;104RI.MultiSample.Count = SampleCount;105return RI;106}107108ResourceInfo ResourceInfo::Texture2DMSArray(109Value *Symbol, StringRef Name, ResourceBinding Binding, uint32_t UniqueID,110ElementType ElementTy, uint32_t ElementCount, uint32_t SampleCount) {111ResourceInfo RI(ResourceClass::SRV, ResourceKind::Texture2DMSArray, Symbol,112Name, Binding, UniqueID);113RI.Typed.ElementTy = ElementTy;114RI.Typed.ElementCount = ElementCount;115RI.MultiSample.Count = SampleCount;116return RI;117}118119ResourceInfo ResourceInfo::UAV(Value *Symbol, StringRef Name,120ResourceBinding Binding, uint32_t UniqueID,121ElementType ElementTy, uint32_t ElementCount,122bool GloballyCoherent, bool IsROV,123ResourceKind Kind) {124ResourceInfo RI(ResourceClass::UAV, Kind, Symbol, Name, Binding, UniqueID);125assert(RI.isTyped() && !(RI.isStruct() || RI.isMultiSample()) &&126"Invalid ResourceKind for UAV constructor.");127RI.Typed.ElementTy = ElementTy;128RI.Typed.ElementCount = ElementCount;129RI.UAVFlags.GloballyCoherent = GloballyCoherent;130RI.UAVFlags.IsROV = IsROV;131RI.UAVFlags.HasCounter = false;132return RI;133}134135ResourceInfo ResourceInfo::RWRawBuffer(Value *Symbol, StringRef Name,136ResourceBinding Binding,137uint32_t UniqueID, bool GloballyCoherent,138bool IsROV) {139ResourceInfo RI(ResourceClass::UAV, ResourceKind::RawBuffer, Symbol, Name,140Binding, UniqueID);141RI.UAVFlags.GloballyCoherent = GloballyCoherent;142RI.UAVFlags.IsROV = IsROV;143RI.UAVFlags.HasCounter = false;144return RI;145}146147ResourceInfo ResourceInfo::RWStructuredBuffer(Value *Symbol, StringRef Name,148ResourceBinding Binding,149uint32_t UniqueID,150uint32_t Stride, Align Alignment,151bool GloballyCoherent, bool IsROV,152bool HasCounter) {153ResourceInfo RI(ResourceClass::UAV, ResourceKind::StructuredBuffer, Symbol,154Name, Binding, UniqueID);155RI.Struct.Stride = Stride;156RI.Struct.Alignment = Alignment;157RI.UAVFlags.GloballyCoherent = GloballyCoherent;158RI.UAVFlags.IsROV = IsROV;159RI.UAVFlags.HasCounter = HasCounter;160return RI;161}162163ResourceInfo164ResourceInfo::RWTexture2DMS(Value *Symbol, StringRef Name,165ResourceBinding Binding, uint32_t UniqueID,166ElementType ElementTy, uint32_t ElementCount,167uint32_t SampleCount, bool GloballyCoherent) {168ResourceInfo RI(ResourceClass::UAV, ResourceKind::Texture2DMS, Symbol, Name,169Binding, UniqueID);170RI.Typed.ElementTy = ElementTy;171RI.Typed.ElementCount = ElementCount;172RI.UAVFlags.GloballyCoherent = GloballyCoherent;173RI.UAVFlags.IsROV = false;174RI.UAVFlags.HasCounter = false;175RI.MultiSample.Count = SampleCount;176return RI;177}178179ResourceInfo180ResourceInfo::RWTexture2DMSArray(Value *Symbol, StringRef Name,181ResourceBinding Binding, uint32_t UniqueID,182ElementType ElementTy, uint32_t ElementCount,183uint32_t SampleCount, bool GloballyCoherent) {184ResourceInfo RI(ResourceClass::UAV, ResourceKind::Texture2DMSArray, Symbol,185Name, Binding, UniqueID);186RI.Typed.ElementTy = ElementTy;187RI.Typed.ElementCount = ElementCount;188RI.UAVFlags.GloballyCoherent = GloballyCoherent;189RI.UAVFlags.IsROV = false;190RI.UAVFlags.HasCounter = false;191RI.MultiSample.Count = SampleCount;192return RI;193}194195ResourceInfo ResourceInfo::FeedbackTexture2D(Value *Symbol, StringRef Name,196ResourceBinding Binding,197uint32_t UniqueID,198SamplerFeedbackType FeedbackTy) {199ResourceInfo RI(ResourceClass::UAV, ResourceKind::FeedbackTexture2D, Symbol,200Name, Binding, UniqueID);201RI.UAVFlags.GloballyCoherent = false;202RI.UAVFlags.IsROV = false;203RI.UAVFlags.HasCounter = false;204RI.Feedback.Type = FeedbackTy;205return RI;206}207208ResourceInfo209ResourceInfo::FeedbackTexture2DArray(Value *Symbol, StringRef Name,210ResourceBinding Binding, uint32_t UniqueID,211SamplerFeedbackType FeedbackTy) {212ResourceInfo RI(ResourceClass::UAV, ResourceKind::FeedbackTexture2DArray,213Symbol, Name, Binding, UniqueID);214RI.UAVFlags.GloballyCoherent = false;215RI.UAVFlags.IsROV = false;216RI.UAVFlags.HasCounter = false;217RI.Feedback.Type = FeedbackTy;218return RI;219}220221ResourceInfo ResourceInfo::CBuffer(Value *Symbol, StringRef Name,222ResourceBinding Binding, uint32_t UniqueID,223uint32_t Size) {224ResourceInfo RI(ResourceClass::CBuffer, ResourceKind::CBuffer, Symbol, Name,225Binding, UniqueID);226RI.CBufferSize = Size;227return RI;228}229230ResourceInfo ResourceInfo::Sampler(Value *Symbol, StringRef Name,231ResourceBinding Binding, uint32_t UniqueID,232SamplerType SamplerTy) {233ResourceInfo RI(ResourceClass::Sampler, ResourceKind::Sampler, Symbol, Name,234Binding, UniqueID);235RI.SamplerTy = SamplerTy;236return RI;237}238239bool ResourceInfo::operator==(const ResourceInfo &RHS) const {240if (std::tie(Symbol, Name, Binding, UniqueID, RC, Kind) !=241std::tie(RHS.Symbol, RHS.Name, RHS.Binding, RHS.UniqueID, RHS.RC,242RHS.Kind))243return false;244if (isCBuffer())245return CBufferSize == RHS.CBufferSize;246if (isSampler())247return SamplerTy == RHS.SamplerTy;248if (isUAV() && UAVFlags != RHS.UAVFlags)249return false;250251if (isStruct())252return Struct == RHS.Struct;253if (isFeedback())254return Feedback == RHS.Feedback;255if (isTyped() && Typed != RHS.Typed)256return false;257258if (isMultiSample())259return MultiSample == RHS.MultiSample;260261assert((Kind == ResourceKind::RawBuffer) && "Unhandled resource kind");262return true;263}264265MDTuple *ResourceInfo::getAsMetadata(LLVMContext &Ctx) const {266SmallVector<Metadata *, 11> MDVals;267268Type *I32Ty = Type::getInt32Ty(Ctx);269Type *I1Ty = Type::getInt1Ty(Ctx);270auto getIntMD = [&I32Ty](uint32_t V) {271return ConstantAsMetadata::get(272Constant::getIntegerValue(I32Ty, APInt(32, V)));273};274auto getBoolMD = [&I1Ty](uint32_t V) {275return ConstantAsMetadata::get(276Constant::getIntegerValue(I1Ty, APInt(1, V)));277};278279MDVals.push_back(getIntMD(UniqueID));280MDVals.push_back(ValueAsMetadata::get(Symbol));281MDVals.push_back(MDString::get(Ctx, Name));282MDVals.push_back(getIntMD(Binding.Space));283MDVals.push_back(getIntMD(Binding.LowerBound));284MDVals.push_back(getIntMD(Binding.Size));285286if (isCBuffer()) {287MDVals.push_back(getIntMD(CBufferSize));288MDVals.push_back(nullptr);289} else if (isSampler()) {290MDVals.push_back(getIntMD(llvm::to_underlying(SamplerTy)));291MDVals.push_back(nullptr);292} else {293MDVals.push_back(getIntMD(llvm::to_underlying(Kind)));294295if (isUAV()) {296MDVals.push_back(getBoolMD(UAVFlags.GloballyCoherent));297MDVals.push_back(getBoolMD(UAVFlags.HasCounter));298MDVals.push_back(getBoolMD(UAVFlags.IsROV));299} else {300// All SRVs include sample count in the metadata, but it's only meaningful301// for multi-sampled textured. Also, UAVs can be multisampled in SM6.7+,302// but this just isn't reflected in the metadata at all.303uint32_t SampleCount = isMultiSample() ? MultiSample.Count : 0;304MDVals.push_back(getIntMD(SampleCount));305}306307// Further properties are attached to a metadata list of tag-value pairs.308SmallVector<Metadata *> Tags;309if (isStruct()) {310Tags.push_back(311getIntMD(llvm::to_underlying(ExtPropTags::StructuredBufferStride)));312Tags.push_back(getIntMD(Struct.Stride));313} else if (isTyped()) {314Tags.push_back(getIntMD(llvm::to_underlying(ExtPropTags::ElementType)));315Tags.push_back(getIntMD(llvm::to_underlying(Typed.ElementTy)));316} else if (isFeedback()) {317Tags.push_back(318getIntMD(llvm::to_underlying(ExtPropTags::SamplerFeedbackKind)));319Tags.push_back(getIntMD(llvm::to_underlying(Feedback.Type)));320}321MDVals.push_back(Tags.empty() ? nullptr : MDNode::get(Ctx, Tags));322}323324return MDNode::get(Ctx, MDVals);325}326327std::pair<uint32_t, uint32_t> ResourceInfo::getAnnotateProps() const {328uint32_t ResourceKind = llvm::to_underlying(Kind);329uint32_t AlignLog2 = isStruct() ? Log2(Struct.Alignment) : 0;330bool IsUAV = isUAV();331bool IsROV = IsUAV && UAVFlags.IsROV;332bool IsGloballyCoherent = IsUAV && UAVFlags.GloballyCoherent;333uint8_t SamplerCmpOrHasCounter = 0;334if (IsUAV)335SamplerCmpOrHasCounter = UAVFlags.HasCounter;336else if (isSampler())337SamplerCmpOrHasCounter = SamplerTy == SamplerType::Comparison;338339// TODO: Document this format. Currently the only reference is the340// implementation of dxc's DxilResourceProperties struct.341uint32_t Word0 = 0;342Word0 |= ResourceKind & 0xFF;343Word0 |= (AlignLog2 & 0xF) << 8;344Word0 |= (IsUAV & 1) << 12;345Word0 |= (IsROV & 1) << 13;346Word0 |= (IsGloballyCoherent & 1) << 14;347Word0 |= (SamplerCmpOrHasCounter & 1) << 15;348349uint32_t Word1 = 0;350if (isStruct())351Word1 = Struct.Stride;352else if (isCBuffer())353Word1 = CBufferSize;354else if (isFeedback())355Word1 = llvm::to_underlying(Feedback.Type);356else if (isTyped()) {357uint32_t CompType = llvm::to_underlying(Typed.ElementTy);358uint32_t CompCount = Typed.ElementCount;359uint32_t SampleCount = isMultiSample() ? MultiSample.Count : 0;360361Word1 |= (CompType & 0xFF) << 0;362Word1 |= (CompCount & 0xFF) << 8;363Word1 |= (SampleCount & 0xFF) << 16;364}365366return {Word0, Word1};367}368369#define DEBUG_TYPE "dxil-resource"370371372