LLVM: lib/ObjectYAML/DXContainerEmitter.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
22
23using namespace llvm;
24
25namespace {
26class DXContainerWriter {
27public:
28 DXContainerWriter(DXContainerYAML::Object &ObjectFile)
29 : ObjectFile(ObjectFile) {}
30
32
33private:
34 DXContainerYAML::Object &ObjectFile;
35
36 Error computePartOffsets();
37 Error validatePartOffsets();
38 Error validateSize(uint32_t Computed);
39
40 void writeHeader(raw_ostream &OS);
41 Error writeParts(raw_ostream &OS);
42};
43}
44
45Error DXContainerWriter::validateSize(uint32_t Computed) {
47 ObjectFile.Header.FileSize = Computed;
48 else if (*ObjectFile.Header.FileSize < Computed)
50 "File size specified is too small.");
52}
53
54Error DXContainerWriter::validatePartOffsets() {
57 errc::invalid_argument,
58 "Mismatch between number of parts and part offsets.");
59 uint32_t RollingOffset =
60 sizeof(dxbc::Header) + (ObjectFile.Header.PartCount * sizeof(uint32_t));
62 if (RollingOffset > std::get<1>(I))
64 "Offset mismatch, not enough space for data.");
65 RollingOffset =
66 std::get<1>(I) + sizeof(dxbc::PartHeader) + std::get<0>(I).Size;
67 }
68 if (Error Err = validateSize(RollingOffset))
69 return Err;
70
72}
73
74Error DXContainerWriter::computePartOffsets() {
76 return validatePartOffsets();
77 uint32_t RollingOffset =
78 sizeof(dxbc::Header) + (ObjectFile.Header.PartCount * sizeof(uint32_t));
79 ObjectFile.Header.PartOffsets = std::vector<uint32_t>();
80 for (const auto &Part : ObjectFile.Parts) {
81 ObjectFile.Header.PartOffsets->push_back(RollingOffset);
82 RollingOffset += sizeof(dxbc::PartHeader) + Part.Size;
83 }
84 if (Error Err = validateSize(RollingOffset))
85 return Err;
86
88}
89
90void DXContainerWriter::writeHeader(raw_ostream &OS) {
91 dxbc::Header Header;
92 memcpy(Header.Magic, "DXBC", 4);
93 memcpy(Header.FileHash.Digest, ObjectFile.Header.Hash.data(), 16);
94 Header.Version.Major = ObjectFile.Header.Version.Major;
95 Header.Version.Minor = ObjectFile.Header.Version.Minor;
96 Header.FileSize = *ObjectFile.Header.FileSize;
97 Header.PartCount = ObjectFile.Parts.size();
99 Header.swapBytes();
100 OS.write(reinterpret_cast<char *>(&Header), sizeof(Header));
101 SmallVector<uint32_t> Offsets(ObjectFile.Header.PartOffsets->begin(),
102 ObjectFile.Header.PartOffsets->end());
104 for (auto &O : Offsets)
106 OS.write(reinterpret_cast<char *>(Offsets.data()),
107 Offsets.size() * sizeof(uint32_t));
108}
109
110Error DXContainerWriter::writeParts(raw_ostream &OS) {
111 uint32_t RollingOffset =
112 sizeof(dxbc::Header) + (ObjectFile.Header.PartCount * sizeof(uint32_t));
114 if (RollingOffset < std::get<1>(I)) {
115 uint32_t PadBytes = std::get<1>(I) - RollingOffset;
117 }
118 DXContainerYAML::Part P = std::get<0>(I);
119 RollingOffset = std::get<1>(I) + sizeof(dxbc::PartHeader);
120 uint32_t PartSize = P.Size;
121
122 OS.write(P.Name.c_str(), 4);
125 OS.write(reinterpret_cast<const char *>(&P.Size), sizeof(uint32_t));
126
128
129 uint64_t DataStart = OS.tell();
130 switch (PT) {
131 case dxbc::PartType::DXIL: {
132 if (.Program)
133 continue;
134 dxbc::ProgramHeader Header;
136 P.Program->MinorVersion);
137 Header.Unused = 0;
138 Header.ShaderKind = P.Program->ShaderKind;
139 memcpy(Header.Bitcode.Magic, "DXIL", 4);
140 Header.Bitcode.MajorVersion = P.Program->DXILMajorVersion;
141 Header.Bitcode.MinorVersion = P.Program->DXILMinorVersion;
142 Header.Bitcode.Unused = 0;
143
144
145 if (P.Program->DXILOffset)
146 Header.Bitcode.Offset = *P.Program->DXILOffset;
147 else
148 Header.Bitcode.Offset = sizeof(dxbc::BitcodeHeader);
149
150 if (P.Program->DXILSize)
151 Header.Bitcode.Size = *P.Program->DXILSize;
152 else
153 Header.Bitcode.Size = P.Program->DXIL ? P.Program->DXIL->size() : 0;
154
155 if (P.Program->Size)
156 Header.Size = *P.Program->Size;
157 else
158 Header.Size = sizeof(dxbc::ProgramHeader) + Header.Bitcode.Size;
159
160 uint32_t BitcodeOffset = Header.Bitcode.Offset;
162 Header.swapBytes();
163 OS.write(reinterpret_cast<const char *>(&Header),
164 sizeof(dxbc::ProgramHeader));
165 if (P.Program->DXIL) {
166 if (BitcodeOffset > sizeof(dxbc::BitcodeHeader)) {
167 uint32_t PadBytes = BitcodeOffset - sizeof(dxbc::BitcodeHeader);
169 }
170 OS.write(reinterpret_cast<char *>(P.Program->DXIL->data()),
171 P.Program->DXIL->size());
172 }
173 break;
174 }
175 case dxbc::PartType::SFI0: {
176
177
178 if (.Flags.has_value())
179 continue;
180 uint64_t Flags = P.Flags->getEncodedFlags();
183 OS.write(reinterpret_cast<char *>(&Flags), sizeof(uint64_t));
184 break;
185 }
186 case dxbc::PartType::HASH: {
187 if (.Hash.has_value())
188 continue;
189 dxbc::ShaderHash Hash = {0, {0}};
190 if (P.Hash->IncludesSource)
191 Hash.Flags |= static_cast<uint32_t>(dxbc::HashFlags::IncludesSource);
192 memcpy(&Hash.Digest[0], &P.Hash->Digest[0], 16);
195 OS.write(reinterpret_cast<char *>(&Hash), sizeof(dxbc::ShaderHash));
196 break;
197 }
198 case dxbc::PartType::PSV0: {
199 if (.Info.has_value())
200 continue;
201 mcdxbc::PSVRuntimeInfo PSV;
202 memcpy(&PSV.BaseData, &P.Info->Info, sizeof(dxbc::PSV::v3::RuntimeInfo));
205
206 for (auto El : P.Info->SigInputElements)
207 PSV.InputElements.push_back(mcdxbc::PSVSignatureElement{
208 El.Name, El.Indices, El.StartRow, El.Cols, El.StartCol,
209 El.Allocated, El.Kind, El.Type, El.Mode, El.DynamicMask,
210 El.Stream});
211
212 for (auto El : P.Info->SigOutputElements)
213 PSV.OutputElements.push_back(mcdxbc::PSVSignatureElement{
214 El.Name, El.Indices, El.StartRow, El.Cols, El.StartCol,
215 El.Allocated, El.Kind, El.Type, El.Mode, El.DynamicMask,
216 El.Stream});
217
218 for (auto El : P.Info->SigPatchOrPrimElements)
220 El.Name, El.Indices, El.StartRow, El.Cols, El.StartCol,
221 El.Allocated, El.Kind, El.Type, El.Mode, El.DynamicMask,
222 El.Stream});
223
227 P.Info->OutputVectorMasks[I].begin(),
228 P.Info->OutputVectorMasks[I].end());
230 P.Info->InputOutputMap[I].begin(),
231 P.Info->InputOutputMap[I].end());
232 }
233
235 P.Info->PatchOrPrimMasks.begin(),
236 P.Info->PatchOrPrimMasks.end());
238 P.Info->InputPatchMap.begin(),
239 P.Info->InputPatchMap.end());
241 P.Info->PatchOutputMap.begin(),
242 P.Info->PatchOutputMap.end());
243
246 PSV.write(OS, P.Info->Version);
247 break;
248 }
249 case dxbc::PartType::ISG1:
250 case dxbc::PartType::OSG1:
251 case dxbc::PartType::PSG1: {
252 mcdxbc::Signature Sig;
253 if (P.Signature.has_value()) {
254 for (const auto &Param : P.Signature->Parameters) {
257 Param.ExclusiveMask, Param.MinPrecision);
258 }
259 }
261 break;
262 }
263 case dxbc::PartType::Unknown:
264 break;
265 case dxbc::PartType::RTS0:
266 if (.RootSignature.has_value())
267 continue;
268
269 mcdxbc::RootSignatureDesc RS;
270 RS.Flags = P.RootSignature->getEncodedFlags();
271 RS.Version = P.RootSignature->Version;
272 RS.NumStaticSamplers = P.RootSignature->NumStaticSamplers;
273
274 for (DXContainerYAML::RootParameterLocationYaml &L :
275 P.RootSignature->Parameters.Locations) {
276
279
280 switch (Type) {
281 case dxbc::RootParameterType::Constants32Bit: {
282 const DXContainerYAML::RootConstantsYaml &ConstantYaml =
283 P.RootSignature->Parameters.getOrInsertConstants(L);
285
289 RS.ParametersContainer.addParameter(Type, Visibility, Constants);
290 break;
291 }
292 case dxbc::RootParameterType::CBV:
293 case dxbc::RootParameterType::SRV:
294 case dxbc::RootParameterType::UAV: {
295 const DXContainerYAML::RootDescriptorYaml &DescriptorYaml =
296 P.RootSignature->Parameters.getOrInsertDescriptor(L);
297
298 mcdxbc::RootDescriptor Descriptor;
301 if (RS.Version > 1)
303 RS.ParametersContainer.addParameter(Type, Visibility, Descriptor);
304 break;
305 }
306 case dxbc::RootParameterType::DescriptorTable: {
307 const DXContainerYAML::DescriptorTableYaml &TableYaml =
308 P.RootSignature->Parameters.getOrInsertTable(L);
309 mcdxbc::DescriptorTable Table;
310 for (const auto &R : TableYaml.Ranges) {
311 mcdxbc::DescriptorRange Range;
312 Range.RangeType = R.RangeType;
313 Range.NumDescriptors = R.NumDescriptors;
314 Range.BaseShaderRegister = R.BaseShaderRegister;
315 Range.RegisterSpace = R.RegisterSpace;
316 Range.OffsetInDescriptorsFromTableStart =
317 R.OffsetInDescriptorsFromTableStart;
318
319 if (RS.Version > 1)
320 Range.Flags = R.getEncodedFlags();
321
323 }
324 RS.ParametersContainer.addParameter(Type, Visibility, Table);
325 break;
326 }
327 }
328 }
329
330 for (const auto &Param : P.RootSignature->samplers()) {
331 mcdxbc::StaticSampler NewSampler;
345
346 if (RS.Version > 2)
347 NewSampler.Flags = Param.getEncodedFlags();
348
349 RS.StaticSamplers.push_back(NewSampler);
350 }
351
352
353 RS.RootParameterOffset = RS.computeRootParametersOffset();
354 if (P.RootSignature->RootParametersOffset &&
355 P.RootSignature->RootParametersOffset.value() !=
356 RS.RootParameterOffset) {
358 errc::invalid_argument,
359 "Specified RootParametersOffset does not match required value: %d.",
360 RS.RootParameterOffset);
361 }
362
363 RS.StaticSamplersOffset = RS.computeStaticSamplersOffset();
364 if (P.RootSignature->StaticSamplersOffset &&
365 P.RootSignature->StaticSamplersOffset.value() !=
366 RS.StaticSamplersOffset) {
368 errc::invalid_argument,
369 "Specified StaticSamplersOffset does not match computed value: %d.",
370 RS.StaticSamplersOffset);
371 }
372
373 RS.write(OS);
374 break;
375 }
376 uint64_t BytesWritten = OS.tell() - DataStart;
377 RollingOffset += BytesWritten;
378 if (BytesWritten < PartSize)
380 RollingOffset += PartSize;
381 }
382
384}
385
386Error DXContainerWriter::write(raw_ostream &OS) {
387 if (Error Err = computePartOffsets())
388 return Err;
389 writeHeader(OS);
390 return writeParts(OS);
391}
392
393namespace llvm {
394namespace yaml {
395
398 DXContainerWriter Writer(Doc);
399 if (Error Err = Writer.write(Out)) {
401 [&](const ErrorInfoBase &Err) { EH(Err.message()); });
402 return false;
403 }
404 return true;
405}
406
407}
408}
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
Base class for error info classes.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
iterator insert(iterator I, T &&Elt)
void addParam(uint32_t Stream, StringRef Name, uint32_t Index, dxbc::D3DSystemValue SystemValue, dxbc::SigComponentType CompType, uint32_t Register, uint8_t Mask, uint8_t ExclusiveMask, dxbc::SigMinPrecision MinPrecision)
void write(raw_ostream &OS)
This class implements an extremely fast bulk output stream that can only output to a stream.
raw_ostream & write_zeros(unsigned NumZeros)
write_zeros - Insert 'NumZeros' nulls.
uint64_t tell() const
tell - Return the current offset with the file.
raw_ostream & write(unsigned char C)
Offsets
Offsets in bytes from the start of the input buffer.
LLVM_ABI PartType parsePartType(StringRef S)
constexpr bool IsBigEndianHost
void swapByteOrder(T &Value)
LLVM_ABI bool yaml2dxcontainer(DXContainerYAML::Object &Doc, raw_ostream &Out, ErrorHandler EH)
Definition DXContainerEmitter.cpp:396
llvm::function_ref< void(const Twine &Msg)> ErrorHandler
This is an optimization pass for GlobalISel generic memory operations.
detail::zippy< detail::zip_shortest, T, U, Args... > zip(T &&t, U &&u, Args &&...args)
zip iterator for two or more iteratable types.
void handleAllErrors(Error E, HandlerTs &&... Handlers)
Behaves the same as handleErrors, except that by contract all errors must be handled by the given han...
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
LLVM_ABI Error write(MCStreamer &Out, ArrayRef< std::string > Inputs, OnCuIndexOverflow OverflowOptValue, Dwarf64StrOffsetsPromotion StrOffsetsOptValue)
SmallVector< DescriptorRangeYaml > Ranges
LLVM_ABI uint32_t getEncodedFlags() const
SmallVector< DescriptorRange > Ranges
dxbc::PSV::v3::RuntimeInfo BaseData
llvm::StringRef EntryName
SmallVector< uint32_t > PatchOrPrimMasks
SmallVector< uint32_t > PatchOutputMap
SmallVector< dxbc::PSV::v2::ResourceBindInfo > Resources
void finalize(Triple::EnvironmentType Stage)
SmallVector< PSVSignatureElement > InputElements
SmallVector< uint32_t > InputPatchMap
SmallVector< PSVSignatureElement > OutputElements
SmallVector< PSVSignatureElement > PatchOrPrimElements
void write(raw_ostream &OS, uint32_t Version=std::numeric_limits< uint32_t >::max()) const
std::array< SmallVector< uint32_t >, 4 > OutputVectorMasks
std::array< SmallVector< uint32_t >, 4 > InputOutputMap
dxbc::TextureAddressMode AddressU
dxbc::TextureAddressMode AddressV
dxbc::StaticBorderColor BorderColor
dxbc::TextureAddressMode AddressW
dxbc::ShaderVisibility ShaderVisibility
dxbc::SamplerFilter Filter
dxbc::ComparisonFunc ComparisonFunc
Common declarations for yaml2obj.