|
| 1 | +//===- DXILResource.cpp - DXIL Resource helper objects --------------------===// |
| 2 | +// |
| 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 |
| 6 | +// |
| 7 | +//===----------------------------------------------------------------------===// |
| 8 | +/// |
| 9 | +/// \file This file contains helper objects for working with DXIL Resources. |
| 10 | +/// |
| 11 | +//===----------------------------------------------------------------------===// |
| 12 | + |
| 13 | +#include "DXILResource.h" |
| 14 | +#include "llvm/ADT/StringSwitch.h" |
| 15 | +#include "llvm/IR/IRBuilder.h" |
| 16 | +#include "llvm/IR/Metadata.h" |
| 17 | +#include "llvm/IR/Module.h" |
| 18 | + |
| 19 | +using namespace llvm; |
| 20 | +using namespace llvm::dxil; |
| 21 | + |
| 22 | +GlobalVariable *FrontendResource::getGlobalVariable() { |
| 23 | + return cast<GlobalVariable>( |
| 24 | + cast<ConstantAsMetadata>(Entry->getOperand(0))->getValue()); |
| 25 | +} |
| 26 | + |
| 27 | +StringRef FrontendResource::getSourceType() { |
| 28 | + return cast<MDString>(Entry->getOperand(1))->getString(); |
| 29 | +} |
| 30 | + |
| 31 | +Constant *FrontendResource::getID() { |
| 32 | + return cast<ConstantAsMetadata>(Entry->getOperand(2))->getValue(); |
| 33 | +} |
| 34 | + |
| 35 | +void Resources::collectUAVs() { |
| 36 | + NamedMDNode *Entry = Mod.getNamedMetadata("hlsl.uavs"); |
| 37 | + if (!Entry || Entry->getNumOperands() == 0) |
| 38 | + return; |
| 39 | + |
| 40 | + uint32_t Counter = 0; |
| 41 | + for (auto *UAV : Entry->operands()) { |
| 42 | + UAVs.push_back(UAVResource(Counter++, FrontendResource(cast<MDNode>(UAV)))); |
| 43 | + } |
| 44 | +} |
| 45 | + |
| 46 | +ResourceBase::ResourceBase(uint32_t I, FrontendResource R) |
| 47 | + : ID(I), GV(R.getGlobalVariable()), Name(""), Space(0), LowerBound(0), |
| 48 | + RangeSize(1) { |
| 49 | + if (auto *ArrTy = dyn_cast<ArrayType>(GV->getInitializer()->getType())) |
| 50 | + RangeSize = ArrTy->getNumElements(); |
| 51 | +} |
| 52 | + |
| 53 | +UAVResource::UAVResource(uint32_t I, FrontendResource R) |
| 54 | + : ResourceBase(I, R), Shape(Kinds::Invalid), GloballyCoherent(false), |
| 55 | + HasCounter(false), IsROV(false), ExtProps() { |
| 56 | + parseSourceType(R.getSourceType()); |
| 57 | +} |
| 58 | + |
| 59 | +// FIXME: Capture this in HLSL source. I would go do this right now, but I want |
| 60 | +// to get this in first so that I can make sure to capture all the extra |
| 61 | +// information we need to remove the source type string from here (See issue: |
| 62 | +// https://github.com/llvm/llvm-project/issues/57991). |
| 63 | +void UAVResource::parseSourceType(StringRef S) { |
| 64 | + IsROV = S.startswith("RasterizerOrdered"); |
| 65 | + if (IsROV) |
| 66 | + S = S.substr(strlen("RasterizerOrdered")); |
| 67 | + if (S.startswith("RW")) |
| 68 | + S = S.substr(strlen("RW")); |
| 69 | + |
| 70 | + // Note: I'm deliberately not handling any of the Texture buffer types at the |
| 71 | + // moment. I want to resolve the issue above before adding Texture or Sampler |
| 72 | + // support. |
| 73 | + Shape = StringSwitch<ResourceBase::Kinds>(S) |
| 74 | + .StartsWith("Buffer<", Kinds::TypedBuffer) |
| 75 | + .StartsWith("ByteAddressBuffer<", Kinds::RawBuffer) |
| 76 | + .StartsWith("StructuredBuffer<", Kinds::StructuredBuffer) |
| 77 | + .Default(Kinds::Invalid); |
| 78 | + assert(Shape != Kinds::Invalid && "Unsupported buffer type"); |
| 79 | + |
| 80 | + S = S.substr(S.find("<") + 1); |
| 81 | + |
| 82 | + constexpr size_t PrefixLen = StringRef("vector<").size(); |
| 83 | + if (S.startswith("vector<")) |
| 84 | + S = S.substr(PrefixLen, S.find(",") - PrefixLen); |
| 85 | + else |
| 86 | + S = S.substr(0, S.find(">")); |
| 87 | + |
| 88 | + ComponentType ElTy = StringSwitch<ResourceBase::ComponentType>(S) |
| 89 | + .Case("bool", ComponentType::I1) |
| 90 | + .Case("int16_t", ComponentType::I16) |
| 91 | + .Case("uint16_t", ComponentType::U16) |
| 92 | + .Case("int32_t", ComponentType::I32) |
| 93 | + .Case("uint32_t", ComponentType::U32) |
| 94 | + .Case("int64_t", ComponentType::I64) |
| 95 | + .Case("uint64_t", ComponentType::U64) |
| 96 | + .Case("half", ComponentType::F16) |
| 97 | + .Case("float", ComponentType::F32) |
| 98 | + .Case("double", ComponentType::F64) |
| 99 | + .Default(ComponentType::Invalid); |
| 100 | + if (ElTy != ComponentType::Invalid) |
| 101 | + ExtProps.ElementType = ElTy; |
| 102 | +} |
| 103 | + |
| 104 | +MDNode *ResourceBase::ExtendedProperties::write(LLVMContext &Ctx) { |
| 105 | + IRBuilder<> B(Ctx); |
| 106 | + SmallVector<Metadata *> Entries; |
| 107 | + if (ElementType) { |
| 108 | + Entries.emplace_back( |
| 109 | + ConstantAsMetadata::get(B.getInt32(TypedBufferElementType))); |
| 110 | + Entries.emplace_back(ConstantAsMetadata::get( |
| 111 | + B.getInt32(static_cast<uint32_t>(*ElementType)))); |
| 112 | + } |
| 113 | + if (Entries.empty()) |
| 114 | + return nullptr; |
| 115 | + return MDNode::get(Ctx, Entries); |
| 116 | +} |
| 117 | + |
| 118 | +void ResourceBase::write(LLVMContext &Ctx, |
| 119 | + MutableArrayRef<Metadata *> Entries) { |
| 120 | + IRBuilder<> B(Ctx); |
| 121 | + Entries[0] = ConstantAsMetadata::get(B.getInt32(ID)); |
| 122 | + Entries[1] = ConstantAsMetadata::get(GV); |
| 123 | + Entries[2] = MDString::get(Ctx, Name); |
| 124 | + Entries[3] = ConstantAsMetadata::get(B.getInt32(Space)); |
| 125 | + Entries[4] = ConstantAsMetadata::get(B.getInt32(LowerBound)); |
| 126 | + Entries[5] = ConstantAsMetadata::get(B.getInt32(RangeSize)); |
| 127 | +} |
| 128 | + |
| 129 | +MDNode *UAVResource::write() { |
| 130 | + auto &Ctx = GV->getContext(); |
| 131 | + IRBuilder<> B(Ctx); |
| 132 | + Metadata *Entries[11]; |
| 133 | + ResourceBase::write(Ctx, Entries); |
| 134 | + Entries[6] = |
| 135 | + ConstantAsMetadata::get(B.getInt32(static_cast<uint32_t>(Shape))); |
| 136 | + Entries[7] = ConstantAsMetadata::get(B.getInt1(GloballyCoherent)); |
| 137 | + Entries[8] = ConstantAsMetadata::get(B.getInt1(HasCounter)); |
| 138 | + Entries[9] = ConstantAsMetadata::get(B.getInt1(IsROV)); |
| 139 | + Entries[10] = ExtProps.write(Ctx); |
| 140 | + return MDNode::get(Ctx, Entries); |
| 141 | +} |
| 142 | + |
| 143 | +void Resources::write() { |
| 144 | + Metadata *ResourceMDs[4] = {nullptr, nullptr, nullptr, nullptr}; |
| 145 | + SmallVector<Metadata *> UAVMDs; |
| 146 | + for (auto &UAV : UAVs) |
| 147 | + UAVMDs.emplace_back(UAV.write()); |
| 148 | + |
| 149 | + if (!UAVMDs.empty()) |
| 150 | + ResourceMDs[1] = MDNode::get(Mod.getContext(), UAVMDs); |
| 151 | + |
| 152 | + NamedMDNode *DXResMD = Mod.getOrInsertNamedMetadata("dx.resources"); |
| 153 | + DXResMD->addOperand(MDNode::get(Mod.getContext(), ResourceMDs)); |
| 154 | + |
| 155 | + NamedMDNode *Entry = Mod.getNamedMetadata("hlsl.uavs"); |
| 156 | + if (Entry) |
| 157 | + Entry->eraseFromParent(); |
| 158 | +} |
0 commit comments