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::PRIV: {
211 OS.
write(
reinterpret_cast<char *
>(
P.PrivateData->data()),
212 P.PrivateData->size());
215 case dxbc::PartType::SFI0: {
218 if (!
P.Flags.has_value())
223 OS.
write(
reinterpret_cast<char *
>(&Flags),
sizeof(
uint64_t));
226 case dxbc::PartType::HASH: {
227 if (!
P.Hash.has_value())
229 dxbc::ShaderHash Hash = {0, {0}};
230 if (
P.Hash->IncludesSource)
231 Hash.
Flags |=
static_cast<uint32_t
>(dxbc::HashFlags::IncludesSource);
232 memcpy(&Hash.
Digest[0], &
P.Hash->Digest[0], 16);
235 OS.
write(
reinterpret_cast<char *
>(&Hash),
sizeof(dxbc::ShaderHash));
238 case dxbc::PartType::PSV0: {
239 if (!
P.Info.has_value())
241 mcdxbc::PSVRuntimeInfo PSV;
242 memcpy(&PSV.
BaseData, &
P.Info->Info,
sizeof(dxbc::PSV::v3::RuntimeInfo));
246 for (
auto El :
P.Info->SigInputElements)
248 El.Name, El.Indices, El.StartRow, El.Cols, El.StartCol,
249 El.Allocated, El.Kind, El.Type, El.Mode, El.DynamicMask,
252 for (
auto El :
P.Info->SigOutputElements)
254 El.Name, El.Indices, El.StartRow, El.Cols, El.StartCol,
255 El.Allocated, El.Kind, El.Type, El.Mode, El.DynamicMask,
258 for (
auto El :
P.Info->SigPatchOrPrimElements)
260 El.Name, El.Indices, El.StartRow, El.Cols, El.StartCol,
261 El.Allocated, El.Kind, El.Type, El.Mode, El.DynamicMask,
267 P.Info->OutputVectorMasks[
I].begin(),
268 P.Info->OutputVectorMasks[
I].end());
270 P.Info->InputOutputMap[
I].begin(),
271 P.Info->InputOutputMap[
I].end());
275 P.Info->PatchOrPrimMasks.begin(),
276 P.Info->PatchOrPrimMasks.end());
278 P.Info->InputPatchMap.begin(),
279 P.Info->InputPatchMap.end());
281 P.Info->PatchOutputMap.begin(),
282 P.Info->PatchOutputMap.end());
287 PSV.
write(OS,
P.Info->Version);
290 case dxbc::PartType::ISG1:
291 case dxbc::PartType::OSG1:
292 case dxbc::PartType::PSG1: {
293 mcdxbc::Signature Sig;
294 if (
P.Signature.has_value()) {
295 for (
const auto &Param :
P.Signature->Parameters) {
303 Sig.
write(OS,
false);
306 case dxbc::PartType::Unknown:
308 case dxbc::PartType::RTS0: {
309 if (!
P.RootSignature.has_value())
312 mcdxbc::RootSignatureDesc
RS;
313 RS.Flags =
P.RootSignature->getEncodedFlags();
314 RS.Version =
P.RootSignature->Version;
315 RS.NumStaticSamplers =
P.RootSignature->NumStaticSamplers;
317 for (DXContainerYAML::RootParameterLocationYaml &L :
318 P.RootSignature->Parameters.Locations) {
324 case dxbc::RootParameterType::Constants32Bit: {
325 const DXContainerYAML::RootConstantsYaml &ConstantYaml =
326 P.RootSignature->Parameters.getOrInsertConstants(L);
332 RS.ParametersContainer.addParameter(
Type, Visibility, Constants);
335 case dxbc::RootParameterType::CBV:
336 case dxbc::RootParameterType::SRV:
337 case dxbc::RootParameterType::UAV: {
338 const DXContainerYAML::RootDescriptorYaml &DescriptorYaml =
339 P.RootSignature->Parameters.getOrInsertDescriptor(L);
341 mcdxbc::RootDescriptor Descriptor;
346 RS.ParametersContainer.addParameter(
Type, Visibility, Descriptor);
349 case dxbc::RootParameterType::DescriptorTable: {
350 const DXContainerYAML::DescriptorTableYaml &TableYaml =
351 P.RootSignature->Parameters.getOrInsertTable(L);
352 mcdxbc::DescriptorTable
Table;
353 for (
const auto &R : TableYaml.
Ranges) {
354 mcdxbc::DescriptorRange
Range;
355 Range.RangeType =
R.RangeType;
356 Range.NumDescriptors =
R.NumDescriptors;
357 Range.BaseShaderRegister =
R.BaseShaderRegister;
358 Range.RegisterSpace =
R.RegisterSpace;
359 Range.OffsetInDescriptorsFromTableStart =
360 R.OffsetInDescriptorsFromTableStart;
363 Range.Flags =
R.getEncodedFlags();
367 RS.ParametersContainer.addParameter(
Type, Visibility,
Table);
373 for (
const auto &Param :
P.RootSignature->samplers()) {
374 mcdxbc::StaticSampler NewSampler;
392 RS.StaticSamplers.push_back(NewSampler);
396 RS.RootParameterOffset =
RS.computeRootParametersOffset();
397 if (
P.RootSignature->RootParametersOffset &&
398 P.RootSignature->RootParametersOffset.value() !=
399 RS.RootParameterOffset) {
401 errc::invalid_argument,
402 "Specified RootParametersOffset does not match required value: %d.",
403 RS.RootParameterOffset);
406 RS.StaticSamplersOffset =
RS.computeStaticSamplersOffset();
407 if (
P.RootSignature->StaticSamplersOffset &&
408 P.RootSignature->StaticSamplersOffset.value() !=
409 RS.StaticSamplersOffset) {
411 errc::invalid_argument,
412 "Specified StaticSamplersOffset does not match computed value: %d.",
413 RS.StaticSamplersOffset);
419 case dxbc::PartType::SRCI: {
420 if (!
P.SourceInfo.has_value())
422 mcdxbc::SourceInfoBuilder SourceInfo;
423 auto &ContentsYAML =
P.SourceInfo->Contents;
426 if (ContentsYAML.Entries.size() !=
P.SourceInfo->Names.Entries.size())
428 errc::invalid_argument,
429 "number of entries in Names section must match number of entries "
430 "in Contents section in SRCI part");
432 for (
size_t I :
llvm::seq(ContentsYAML.Entries.size()))
433 SourceInfo.
addFile(
P.SourceInfo->Names.Entries[
I].FileName,
434 ContentsYAML.Entries[
I].FileContent);
435 for (
auto &ArgEntry :
P.SourceInfo->Args.Args)
436 SourceInfo.
addArg(ArgEntry.first, ArgEntry.second);
442 for (
size_t I :
llvm::seq(ContentsYAML.Entries.size())) {
443 auto &ContentEntryYAML = ContentsYAML.Entries[
I];
445 assign_if(ContentEntry.Parameters.AlignedSizeInBytes,
446 ContentEntryYAML.AlignedSizeInBytes);
447 assign_if(ContentEntry.Parameters.Flags, ContentEntryYAML.Flags);
448 assign_if(ContentEntry.Parameters.ContentSizeInBytes,
449 ContentEntryYAML.ContentSizeInBytes);
451 auto &NameEntryYAML =
P.SourceInfo->Names.Entries[
I];
453 assign_if(NameEntry.Parameters.AlignedSizeInBytes,
454 NameEntryYAML.AlignedSizeInBytes);
455 assign_if(NameEntry.Parameters.Flags, NameEntryYAML.Flags);
456 assign_if(NameEntry.Parameters.NameSizeInBytes,
457 NameEntryYAML.NameSizeInBytes);
458 assign_if(NameEntry.Parameters.ContentSizeInBytes,
459 NameEntryYAML.ContentSizeInBytes);
468 assign_if(Contents.Parameters.AlignedSizeInBytes,
469 ContentsYAML.Parameters.AlignedSizeInBytes);
470 assign_if(Contents.Parameters.Flags, ContentsYAML.Parameters.Flags);
471 assign_if(Contents.Parameters.EntriesSizeInBytes,
472 ContentsYAML.Parameters.EntriesSizeInBytes);
473 assign_if(Contents.Parameters.UncompressedEntriesSizeInBytes,
474 ContentsYAML.Parameters.UncompressedEntriesSizeInBytes);
475 if (ContentsYAML.Parameters.Count &&
476 ContentsYAML.Parameters.Count != Contents.Parameters.Count)
478 errc::invalid_argument,
479 "the value of Count field in Contents header must match the number "
480 "of entries in Contents section");
482 auto &NamesYAML =
P.SourceInfo->Names;
485 assign_if(Names.Parameters.Flags, NamesYAML.Parameters.Flags);
486 assign_if(Names.Parameters.EntriesSizeInBytes,
487 NamesYAML.Parameters.EntriesSizeInBytes);
488 if (NamesYAML.Parameters.Count &&
489 NamesYAML.Parameters.Count != Names.Parameters.Count)
491 errc::invalid_argument,
492 "the value of Count field in Names header must match the number of "
493 "entries in Names section");
495 auto &ArgsYAML =
P.SourceInfo->Args;
499 assign_if(
Args.Parameters.SizeInBytes, ArgsYAML.Parameters.SizeInBytes);
500 if (ArgsYAML.Parameters.Count &&
501 ArgsYAML.Parameters.Count !=
Args.Parameters.Count)
503 "the value of Count field in Args header must "
504 "match the number of entries in Args section");
507 P.SourceInfo->Parameters.AlignedSizeInBytes);
509 P.SourceInfo->Parameters.Flags);
511 P.SourceInfo->Parameters.SectionCount);
513 SourceInfo.
write(OS);
516 case dxbc::PartType::VERS: {
517 if (!
P.CompilerVersion)
520 mcdxbc::CompilerVersion CompilerVersion;
526 if (
P.CompilerVersion->IsDebugBuild ||
P.CompilerVersion->IsValidated)
527 CompilerVersion.
Parameters.
Flags = dxbc::CompilerVersionFlags::Default;
528 if (
P.CompilerVersion->IsDebugBuild.value_or(
false))
530 if (
P.CompilerVersion->IsValidated.value_or(
false))
532 dxbc::CompilerVersionFlags::Internal;
535 P.CompilerVersion->CommitCount.value_or(
538 if (
P.CompilerVersion->CommitSha)
540 if (
P.CompilerVersion->CustomVersionString)
542 *
P.CompilerVersion->CustomVersionString);
545 P.CompilerVersion->ContentSizeInBytes.value_or(
548 CompilerVersion.
write(OS);
553 RollingOffset += BytesWritten;
554 if (BytesWritten < PartSize)
556 RollingOffset += PartSize;
562Error DXContainerWriter::write(raw_ostream &OS) {
563 if (
Error Err = computePartOffsets())
566 return writeParts(OS);
574 DXContainerWriter Writer(Doc);
575 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)
LLVM_ABI void write(raw_ostream &OS, bool PadToDword=true)
Legacy validator versions through 1.6 require unpadded signature parts.
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)
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.
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr DataStart
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
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.