28class DXContainerWriter {
30 DXContainerWriter(DXContainerYAML::Object &ObjectFile)
31 : ObjectFile(ObjectFile) {}
36 DXContainerYAML::Object &ObjectFile;
38 Error computePartOffsets();
39 Error validatePartOffsets();
40 Error validateSize(uint32_t Computed);
43 Error writeParts(raw_ostream &OS);
50 else if (*
ObjectFile.Header.FileSize < Computed)
52 "File size specified is too small.");
56Error DXContainerWriter::validatePartOffsets() {
59 errc::invalid_argument,
60 "Mismatch between number of parts and part offsets.");
61 uint32_t RollingOffset =
62 sizeof(dxbc::Header) + (
ObjectFile.Header.PartCount *
sizeof(uint32_t));
64 if (RollingOffset > std::get<1>(
I))
66 "Offset mismatch, not enough space for data.");
68 std::get<1>(
I) +
sizeof(dxbc::PartHeader) + std::get<0>(
I).Size;
70 if (
Error Err = validateSize(RollingOffset))
76Error DXContainerWriter::computePartOffsets() {
78 return validatePartOffsets();
79 uint32_t RollingOffset =
80 sizeof(dxbc::Header) + (
ObjectFile.Header.PartCount *
sizeof(uint32_t));
81 ObjectFile.Header.PartOffsets = std::vector<uint32_t>();
83 ObjectFile.Header.PartOffsets->push_back(RollingOffset);
84 RollingOffset +=
sizeof(dxbc::PartHeader) + Part.Size;
86 if (
Error Err = validateSize(RollingOffset))
92void DXContainerWriter::writeHeader(raw_ostream &OS) {
94 memcpy(Header.Magic,
"DXBC", 4);
95 memcpy(Header.FileHash.Digest,
ObjectFile.Header.Hash.data(), 16);
96 Header.Version.Major =
ObjectFile.Header.Version.Major;
97 Header.Version.Minor =
ObjectFile.Header.Version.Minor;
102 OS.
write(
reinterpret_cast<char *
>(&Header),
sizeof(Header));
106 for (
auto &O : Offsets)
109 Offsets.size() *
sizeof(uint32_t));
122 assign_if(Dst.AlignedSizeInBytes, Src.GenericHeader.AlignedSizeInBytes);
123 assign_if(Dst.Flags, Src.GenericHeader.Flags);
124 assign_if(Dst.Type, Src.GenericHeader.Type);
127Error DXContainerWriter::writeParts(raw_ostream &OS) {
128 uint32_t RollingOffset =
129 sizeof(dxbc::Header) + (
ObjectFile.Header.PartCount *
sizeof(uint32_t));
131 if (RollingOffset < std::get<1>(
I)) {
132 uint32_t PadBytes = std::get<1>(
I) - RollingOffset;
135 DXContainerYAML::Part
P = std::get<0>(
I);
136 RollingOffset = std::get<1>(
I) +
sizeof(dxbc::PartHeader);
137 uint32_t PartSize =
P.Size;
139 OS.
write(
P.Name.c_str(), 4);
142 OS.
write(
reinterpret_cast<const char *
>(&
P.Size),
sizeof(uint32_t));
148 case dxbc::PartType::DXIL:
149 case dxbc::PartType::ILDB: {
152 dxbc::ProgramHeader Header;
154 P.Program->MinorVersion);
156 Header.ShaderKind =
P.Program->ShaderKind;
157 memcpy(Header.Bitcode.Magic,
"DXIL", 4);
158 Header.Bitcode.MajorVersion =
P.Program->DXILMajorVersion;
159 Header.Bitcode.MinorVersion =
P.Program->DXILMinorVersion;
160 Header.Bitcode.Unused = 0;
163 if (
P.Program->DXILOffset)
164 Header.Bitcode.Offset = *
P.Program->DXILOffset;
166 Header.Bitcode.Offset =
sizeof(dxbc::BitcodeHeader);
168 if (
P.Program->DXILSize)
169 Header.Bitcode.Size = *
P.Program->DXILSize;
171 Header.Bitcode.Size =
P.Program->DXIL ?
P.Program->DXIL->size() : 0;
174 Header.Size = *
P.Program->Size;
176 Header.Size =
sizeof(dxbc::ProgramHeader) + Header.Bitcode.Size;
178 uint32_t BitcodeOffset = Header.Bitcode.Offset;
181 OS.
write(
reinterpret_cast<const char *
>(&Header),
182 sizeof(dxbc::ProgramHeader));
183 if (
P.Program->DXIL) {
184 if (BitcodeOffset >
sizeof(dxbc::BitcodeHeader)) {
185 uint32_t PadBytes = BitcodeOffset -
sizeof(dxbc::BitcodeHeader);
188 OS.
write(
reinterpret_cast<char *
>(
P.Program->DXIL->data()),
189 P.Program->DXIL->size());
193 case dxbc::PartType::ILDN: {
197 mcdxbc::DebugName DebugName;
200 if (
P.DebugName->Flags)
203 if (
P.DebugName->NameLength)
208 case dxbc::PartType::SFI0: {
211 if (!
P.Flags.has_value())
213 uint64_t
Flags =
P.Flags->getEncodedFlags();
216 OS.
write(
reinterpret_cast<char *
>(&Flags),
sizeof(uint64_t));
219 case dxbc::PartType::HASH: {
220 if (!
P.Hash.has_value())
222 dxbc::ShaderHash Hash = {0, {0}};
223 if (
P.Hash->IncludesSource)
224 Hash.
Flags |=
static_cast<uint32_t
>(dxbc::HashFlags::IncludesSource);
225 memcpy(&Hash.
Digest[0], &
P.Hash->Digest[0], 16);
228 OS.
write(
reinterpret_cast<char *
>(&Hash),
sizeof(dxbc::ShaderHash));
231 case dxbc::PartType::PSV0: {
232 if (!
P.Info.has_value())
234 mcdxbc::PSVRuntimeInfo PSV;
235 memcpy(&PSV.
BaseData, &
P.Info->Info,
sizeof(dxbc::PSV::v3::RuntimeInfo));
239 for (
auto El :
P.Info->SigInputElements)
241 El.Name, El.Indices, El.StartRow, El.Cols, El.StartCol,
242 El.Allocated, El.Kind, El.Type, El.Mode, El.DynamicMask,
245 for (
auto El :
P.Info->SigOutputElements)
247 El.Name, El.Indices, El.StartRow, El.Cols, El.StartCol,
248 El.Allocated, El.Kind, El.Type, El.Mode, El.DynamicMask,
251 for (
auto El :
P.Info->SigPatchOrPrimElements)
253 El.Name, El.Indices, El.StartRow, El.Cols, El.StartCol,
254 El.Allocated, El.Kind, El.Type, El.Mode, El.DynamicMask,
260 P.Info->OutputVectorMasks[
I].begin(),
261 P.Info->OutputVectorMasks[
I].end());
263 P.Info->InputOutputMap[
I].begin(),
264 P.Info->InputOutputMap[
I].end());
268 P.Info->PatchOrPrimMasks.begin(),
269 P.Info->PatchOrPrimMasks.end());
271 P.Info->InputPatchMap.begin(),
272 P.Info->InputPatchMap.end());
274 P.Info->PatchOutputMap.begin(),
275 P.Info->PatchOutputMap.end());
280 PSV.
write(OS,
P.Info->Version);
283 case dxbc::PartType::ISG1:
284 case dxbc::PartType::OSG1:
285 case dxbc::PartType::PSG1: {
286 mcdxbc::Signature Sig;
287 if (
P.Signature.has_value()) {
288 for (
const auto &Param :
P.Signature->Parameters) {
297 case dxbc::PartType::Unknown:
299 case dxbc::PartType::RTS0: {
300 if (!
P.RootSignature.has_value())
303 mcdxbc::RootSignatureDesc
RS;
304 RS.Flags =
P.RootSignature->getEncodedFlags();
305 RS.Version =
P.RootSignature->Version;
306 RS.NumStaticSamplers =
P.RootSignature->NumStaticSamplers;
308 for (DXContainerYAML::RootParameterLocationYaml &L :
309 P.RootSignature->Parameters.Locations) {
315 case dxbc::RootParameterType::Constants32Bit: {
316 const DXContainerYAML::RootConstantsYaml &ConstantYaml =
317 P.RootSignature->Parameters.getOrInsertConstants(L);
323 RS.ParametersContainer.addParameter(
Type, Visibility, Constants);
326 case dxbc::RootParameterType::CBV:
327 case dxbc::RootParameterType::SRV:
328 case dxbc::RootParameterType::UAV: {
329 const DXContainerYAML::RootDescriptorYaml &DescriptorYaml =
330 P.RootSignature->Parameters.getOrInsertDescriptor(L);
332 mcdxbc::RootDescriptor Descriptor;
337 RS.ParametersContainer.addParameter(
Type, Visibility, Descriptor);
340 case dxbc::RootParameterType::DescriptorTable: {
341 const DXContainerYAML::DescriptorTableYaml &TableYaml =
342 P.RootSignature->Parameters.getOrInsertTable(L);
343 mcdxbc::DescriptorTable Table;
344 for (
const auto &R : TableYaml.
Ranges) {
345 mcdxbc::DescriptorRange
Range;
346 Range.RangeType =
R.RangeType;
347 Range.NumDescriptors =
R.NumDescriptors;
348 Range.BaseShaderRegister =
R.BaseShaderRegister;
349 Range.RegisterSpace =
R.RegisterSpace;
350 Range.OffsetInDescriptorsFromTableStart =
351 R.OffsetInDescriptorsFromTableStart;
354 Range.Flags =
R.getEncodedFlags();
358 RS.ParametersContainer.addParameter(
Type, Visibility, Table);
364 for (
const auto &Param :
P.RootSignature->samplers()) {
365 mcdxbc::StaticSampler NewSampler;
383 RS.StaticSamplers.push_back(NewSampler);
387 RS.RootParameterOffset =
RS.computeRootParametersOffset();
388 if (
P.RootSignature->RootParametersOffset &&
389 P.RootSignature->RootParametersOffset.value() !=
390 RS.RootParameterOffset) {
392 errc::invalid_argument,
393 "Specified RootParametersOffset does not match required value: %d.",
394 RS.RootParameterOffset);
397 RS.StaticSamplersOffset =
RS.computeStaticSamplersOffset();
398 if (
P.RootSignature->StaticSamplersOffset &&
399 P.RootSignature->StaticSamplersOffset.value() !=
400 RS.StaticSamplersOffset) {
402 errc::invalid_argument,
403 "Specified StaticSamplersOffset does not match computed value: %d.",
404 RS.StaticSamplersOffset);
410 case dxbc::PartType::SRCI: {
411 if (!
P.SourceInfo.has_value())
413 mcdxbc::SourceInfoBuilder SourceInfo;
414 auto &ContentsYAML =
P.SourceInfo->Contents;
417 if (ContentsYAML.Entries.size() !=
P.SourceInfo->Names.Entries.size())
419 errc::invalid_argument,
420 "number of entries in Names section must match number of entries "
421 "in Contents section in SRCI part");
423 for (
size_t I :
llvm::seq(ContentsYAML.Entries.size()))
424 SourceInfo.
addFile(
P.SourceInfo->Names.Entries[
I].FileName,
425 ContentsYAML.Entries[
I].FileContent);
426 for (
auto &ArgEntry :
P.SourceInfo->Args.Args)
427 SourceInfo.
addArg(ArgEntry.first, ArgEntry.second);
433 for (
size_t I :
llvm::seq(ContentsYAML.Entries.size())) {
434 auto &ContentEntryYAML = ContentsYAML.Entries[
I];
436 assign_if(ContentEntry.Parameters.AlignedSizeInBytes,
437 ContentEntryYAML.AlignedSizeInBytes);
438 assign_if(ContentEntry.Parameters.Flags, ContentEntryYAML.Flags);
439 assign_if(ContentEntry.Parameters.ContentSizeInBytes,
440 ContentEntryYAML.ContentSizeInBytes);
442 auto &NameEntryYAML =
P.SourceInfo->Names.Entries[
I];
444 assign_if(NameEntry.Parameters.AlignedSizeInBytes,
445 NameEntryYAML.AlignedSizeInBytes);
446 assign_if(NameEntry.Parameters.Flags, NameEntryYAML.Flags);
447 assign_if(NameEntry.Parameters.NameSizeInBytes,
448 NameEntryYAML.NameSizeInBytes);
449 assign_if(NameEntry.Parameters.ContentSizeInBytes,
450 NameEntryYAML.ContentSizeInBytes);
459 assign_if(Contents.Parameters.AlignedSizeInBytes,
460 ContentsYAML.Parameters.AlignedSizeInBytes);
461 assign_if(Contents.Parameters.Flags, ContentsYAML.Parameters.Flags);
462 assign_if(Contents.Parameters.EntriesSizeInBytes,
463 ContentsYAML.Parameters.EntriesSizeInBytes);
464 assign_if(Contents.Parameters.UncompressedEntriesSizeInBytes,
465 ContentsYAML.Parameters.UncompressedEntriesSizeInBytes);
466 if (ContentsYAML.Parameters.Count &&
467 ContentsYAML.Parameters.Count != Contents.Parameters.Count)
469 errc::invalid_argument,
470 "the value of Count field in Contents header must match the number "
471 "of entries in Contents section");
473 auto &NamesYAML =
P.SourceInfo->Names;
476 assign_if(Names.Parameters.Flags, NamesYAML.Parameters.Flags);
477 assign_if(Names.Parameters.EntriesSizeInBytes,
478 NamesYAML.Parameters.EntriesSizeInBytes);
479 if (NamesYAML.Parameters.Count &&
480 NamesYAML.Parameters.Count != Names.Parameters.Count)
482 errc::invalid_argument,
483 "the value of Count field in Names header must match the number of "
484 "entries in Names section");
486 auto &ArgsYAML =
P.SourceInfo->Args;
490 assign_if(
Args.Parameters.SizeInBytes, ArgsYAML.Parameters.SizeInBytes);
491 if (ArgsYAML.Parameters.Count &&
492 ArgsYAML.Parameters.Count !=
Args.Parameters.Count)
494 "the value of Count field in Args header must "
495 "match the number of entries in Args section");
498 P.SourceInfo->Parameters.AlignedSizeInBytes);
500 P.SourceInfo->Parameters.Flags);
502 P.SourceInfo->Parameters.SectionCount);
504 SourceInfo.
write(OS);
507 case dxbc::PartType::VERS: {
508 if (!
P.CompilerVersion)
511 mcdxbc::CompilerVersion CompilerVersion;
517 if (
P.CompilerVersion->IsDebugBuild ||
P.CompilerVersion->IsValidated)
518 CompilerVersion.
Parameters.
Flags = dxbc::CompilerVersionFlags::Default;
519 if (
P.CompilerVersion->IsDebugBuild.value_or(
false))
521 if (
P.CompilerVersion->IsValidated.value_or(
false))
523 dxbc::CompilerVersionFlags::Internal;
526 P.CompilerVersion->CommitCount.value_or(
529 if (
P.CompilerVersion->CommitSha)
531 if (
P.CompilerVersion->CustomVersionString)
533 *
P.CompilerVersion->CustomVersionString);
536 P.CompilerVersion->ContentSizeInBytes.value_or(
539 CompilerVersion.
write(OS);
544 RollingOffset += BytesWritten;
545 if (BytesWritten < PartSize)
547 RollingOffset += PartSize;
553Error DXContainerWriter::write(raw_ostream &OS) {
554 if (
Error Err = computePartOffsets())
557 return writeParts(OS);
565 DXContainerWriter Writer(Doc);
566 if (
Error Err = Writer.write(Out)) {
static void assignSectionHeader(dxbc::SourceInfo::SectionHeader &Dst, const DXContainerYAML::SourceInfo::Section &Src)
static void assign_if(T &Dst, const std::optional< T > &Src)
This file declares classes for handling the YAML representation of DXContainer.
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
Provides some synthesis utilities to produce sequences of values.
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)
LLVM_ABI 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)
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
LLVM_ABI void writeHeader(support::endian::Writer &W, bool Is64Bit, uint8_t OSABI, uint8_t ABIVersion, uint16_t EMachine, uint32_t EFlags, uint64_t SHOff, uint16_t SHNum, uint16_t SHStrNdx)
Write an ELF file header (Elf32_Ehdr or Elf64_Ehdr) for an ET_REL object.
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)
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.
FunctionAddr VTableAddr DataStart
auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
LLVM_ABI Error write(DWPWriter &Out, ArrayRef< std::string > Inputs, OnCuIndexOverflow OverflowOptValue, Dwarf64StrOffsetsPromotion StrOffsetsOptValue, raw_pwrite_stream *OS=nullptr)
SmallVector< DescriptorRangeYaml > Ranges
LLVM_ABI uint32_t getEncodedFlags() const
LLVM_ABI void setCommitSha(StringRef CommitSha)
LLVM_ABI void setVersionString(StringRef VersionString)
LLVM_ABI void write(raw_ostream &OS) const
dxbc::CompilerVersionHeader Parameters
dxbc::DebugNameHeader Parameters
LLVM_ABI void setFilename(StringRef DebugFilename)
LLVM_ABI void write(raw_ostream &OS) const
SmallVector< DescriptorRange > Ranges
dxbc::PSV::v3::RuntimeInfo BaseData
SmallVector< uint32_t > PatchOrPrimMasks
SmallVector< uint32_t > PatchOutputMap
SmallVector< dxbc::PSV::v2::ResourceBindInfo > Resources
SmallVector< PSVSignatureElement > InputElements
LLVM_ABI void finalize(Triple::EnvironmentType Stage, uint32_t Version=std::numeric_limits< uint32_t >::max())
SmallVector< uint32_t > InputPatchMap
SmallVector< PSVSignatureElement > OutputElements
SmallVector< PSVSignatureElement > PatchOrPrimElements
LLVM_ABI 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
void addArg(StringRef Name, StringRef Value)
void setCompressionType(dxbc::SourceInfo::Contents::CompressionType Type)
LLVM_ABI void computeEntries()
LLVM_ABI void write(raw_ostream &OS) const
void addFile(StringRef Name, StringRef Content)
SmallVector< Entry > Entries
SmallVector< Entry > Entries
dxbc::SourceInfo::Header Parameters
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.