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())
220 uint64_t
Flags =
P.Flags->getEncodedFlags();
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) {
304 case dxbc::PartType::Unknown:
306 case dxbc::PartType::RTS0: {
307 if (!
P.RootSignature.has_value())
310 mcdxbc::RootSignatureDesc
RS;
311 RS.Flags =
P.RootSignature->getEncodedFlags();
312 RS.Version =
P.RootSignature->Version;
313 RS.NumStaticSamplers =
P.RootSignature->NumStaticSamplers;
315 for (DXContainerYAML::RootParameterLocationYaml &L :
316 P.RootSignature->Parameters.Locations) {
322 case dxbc::RootParameterType::Constants32Bit: {
323 const DXContainerYAML::RootConstantsYaml &ConstantYaml =
324 P.RootSignature->Parameters.getOrInsertConstants(L);
330 RS.ParametersContainer.addParameter(
Type, Visibility, Constants);
333 case dxbc::RootParameterType::CBV:
334 case dxbc::RootParameterType::SRV:
335 case dxbc::RootParameterType::UAV: {
336 const DXContainerYAML::RootDescriptorYaml &DescriptorYaml =
337 P.RootSignature->Parameters.getOrInsertDescriptor(L);
339 mcdxbc::RootDescriptor Descriptor;
344 RS.ParametersContainer.addParameter(
Type, Visibility, Descriptor);
347 case dxbc::RootParameterType::DescriptorTable: {
348 const DXContainerYAML::DescriptorTableYaml &TableYaml =
349 P.RootSignature->Parameters.getOrInsertTable(L);
350 mcdxbc::DescriptorTable Table;
351 for (
const auto &R : TableYaml.
Ranges) {
352 mcdxbc::DescriptorRange
Range;
353 Range.RangeType =
R.RangeType;
354 Range.NumDescriptors =
R.NumDescriptors;
355 Range.BaseShaderRegister =
R.BaseShaderRegister;
356 Range.RegisterSpace =
R.RegisterSpace;
357 Range.OffsetInDescriptorsFromTableStart =
358 R.OffsetInDescriptorsFromTableStart;
361 Range.Flags =
R.getEncodedFlags();
365 RS.ParametersContainer.addParameter(
Type, Visibility, Table);
371 for (
const auto &Param :
P.RootSignature->samplers()) {
372 mcdxbc::StaticSampler NewSampler;
390 RS.StaticSamplers.push_back(NewSampler);
394 RS.RootParameterOffset =
RS.computeRootParametersOffset();
395 if (
P.RootSignature->RootParametersOffset &&
396 P.RootSignature->RootParametersOffset.value() !=
397 RS.RootParameterOffset) {
399 errc::invalid_argument,
400 "Specified RootParametersOffset does not match required value: %d.",
401 RS.RootParameterOffset);
404 RS.StaticSamplersOffset =
RS.computeStaticSamplersOffset();
405 if (
P.RootSignature->StaticSamplersOffset &&
406 P.RootSignature->StaticSamplersOffset.value() !=
407 RS.StaticSamplersOffset) {
409 errc::invalid_argument,
410 "Specified StaticSamplersOffset does not match computed value: %d.",
411 RS.StaticSamplersOffset);
417 case dxbc::PartType::SRCI: {
418 if (!
P.SourceInfo.has_value())
420 mcdxbc::SourceInfoBuilder SourceInfo;
421 auto &ContentsYAML =
P.SourceInfo->Contents;
424 if (ContentsYAML.Entries.size() !=
P.SourceInfo->Names.Entries.size())
426 errc::invalid_argument,
427 "number of entries in Names section must match number of entries "
428 "in Contents section in SRCI part");
430 for (
size_t I :
llvm::seq(ContentsYAML.Entries.size()))
431 SourceInfo.
addFile(
P.SourceInfo->Names.Entries[
I].FileName,
432 ContentsYAML.Entries[
I].FileContent);
433 for (
auto &ArgEntry :
P.SourceInfo->Args.Args)
434 SourceInfo.
addArg(ArgEntry.first, ArgEntry.second);
440 for (
size_t I :
llvm::seq(ContentsYAML.Entries.size())) {
441 auto &ContentEntryYAML = ContentsYAML.Entries[
I];
443 assign_if(ContentEntry.Parameters.AlignedSizeInBytes,
444 ContentEntryYAML.AlignedSizeInBytes);
445 assign_if(ContentEntry.Parameters.Flags, ContentEntryYAML.Flags);
446 assign_if(ContentEntry.Parameters.ContentSizeInBytes,
447 ContentEntryYAML.ContentSizeInBytes);
449 auto &NameEntryYAML =
P.SourceInfo->Names.Entries[
I];
451 assign_if(NameEntry.Parameters.AlignedSizeInBytes,
452 NameEntryYAML.AlignedSizeInBytes);
453 assign_if(NameEntry.Parameters.Flags, NameEntryYAML.Flags);
454 assign_if(NameEntry.Parameters.NameSizeInBytes,
455 NameEntryYAML.NameSizeInBytes);
456 assign_if(NameEntry.Parameters.ContentSizeInBytes,
457 NameEntryYAML.ContentSizeInBytes);
466 assign_if(Contents.Parameters.AlignedSizeInBytes,
467 ContentsYAML.Parameters.AlignedSizeInBytes);
468 assign_if(Contents.Parameters.Flags, ContentsYAML.Parameters.Flags);
469 assign_if(Contents.Parameters.EntriesSizeInBytes,
470 ContentsYAML.Parameters.EntriesSizeInBytes);
471 assign_if(Contents.Parameters.UncompressedEntriesSizeInBytes,
472 ContentsYAML.Parameters.UncompressedEntriesSizeInBytes);
473 if (ContentsYAML.Parameters.Count &&
474 ContentsYAML.Parameters.Count != Contents.Parameters.Count)
476 errc::invalid_argument,
477 "the value of Count field in Contents header must match the number "
478 "of entries in Contents section");
480 auto &NamesYAML =
P.SourceInfo->Names;
483 assign_if(Names.Parameters.Flags, NamesYAML.Parameters.Flags);
484 assign_if(Names.Parameters.EntriesSizeInBytes,
485 NamesYAML.Parameters.EntriesSizeInBytes);
486 if (NamesYAML.Parameters.Count &&
487 NamesYAML.Parameters.Count != Names.Parameters.Count)
489 errc::invalid_argument,
490 "the value of Count field in Names header must match the number of "
491 "entries in Names section");
493 auto &ArgsYAML =
P.SourceInfo->Args;
497 assign_if(
Args.Parameters.SizeInBytes, ArgsYAML.Parameters.SizeInBytes);
498 if (ArgsYAML.Parameters.Count &&
499 ArgsYAML.Parameters.Count !=
Args.Parameters.Count)
501 "the value of Count field in Args header must "
502 "match the number of entries in Args section");
505 P.SourceInfo->Parameters.AlignedSizeInBytes);
507 P.SourceInfo->Parameters.Flags);
509 P.SourceInfo->Parameters.SectionCount);
511 SourceInfo.
write(OS);
514 case dxbc::PartType::VERS: {
515 if (!
P.CompilerVersion)
518 mcdxbc::CompilerVersion CompilerVersion;
524 if (
P.CompilerVersion->IsDebugBuild ||
P.CompilerVersion->IsValidated)
525 CompilerVersion.
Parameters.
Flags = dxbc::CompilerVersionFlags::Default;
526 if (
P.CompilerVersion->IsDebugBuild.value_or(
false))
528 if (
P.CompilerVersion->IsValidated.value_or(
false))
530 dxbc::CompilerVersionFlags::Internal;
533 P.CompilerVersion->CommitCount.value_or(
536 if (
P.CompilerVersion->CommitSha)
538 if (
P.CompilerVersion->CustomVersionString)
540 *
P.CompilerVersion->CustomVersionString);
543 P.CompilerVersion->ContentSizeInBytes.value_or(
546 CompilerVersion.
write(OS);
551 RollingOffset += BytesWritten;
552 if (BytesWritten < PartSize)
554 RollingOffset += PartSize;
560Error DXContainerWriter::write(raw_ostream &OS) {
561 if (
Error Err = computePartOffsets())
564 return writeParts(OS);
572 DXContainerWriter Writer(Doc);
573 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.
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
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.