27class DXContainerWriter {
29 DXContainerWriter(DXContainerYAML::Object &ObjectFile)
30 : ObjectFile(ObjectFile) {}
35 DXContainerYAML::Object &ObjectFile;
37 Error computePartOffsets();
38 Error validatePartOffsets();
39 Error validateSize(uint32_t Computed);
42 Error writeParts(raw_ostream &OS);
49 else if (*
ObjectFile.Header.FileSize < Computed)
51 "File size specified is too small.");
55Error DXContainerWriter::validatePartOffsets() {
58 errc::invalid_argument,
59 "Mismatch between number of parts and part offsets.");
60 uint32_t RollingOffset =
61 sizeof(dxbc::Header) + (
ObjectFile.Header.PartCount *
sizeof(uint32_t));
63 if (RollingOffset > std::get<1>(
I))
65 "Offset mismatch, not enough space for data.");
67 std::get<1>(
I) +
sizeof(dxbc::PartHeader) + std::get<0>(
I).Size;
69 if (
Error Err = validateSize(RollingOffset))
75Error DXContainerWriter::computePartOffsets() {
77 return validatePartOffsets();
78 uint32_t RollingOffset =
79 sizeof(dxbc::Header) + (
ObjectFile.Header.PartCount *
sizeof(uint32_t));
80 ObjectFile.Header.PartOffsets = std::vector<uint32_t>();
82 ObjectFile.Header.PartOffsets->push_back(RollingOffset);
83 RollingOffset +=
sizeof(dxbc::PartHeader) + Part.Size;
85 if (
Error Err = validateSize(RollingOffset))
91void DXContainerWriter::writeHeader(raw_ostream &OS) {
93 memcpy(Header.Magic,
"DXBC", 4);
94 memcpy(Header.FileHash.Digest,
ObjectFile.Header.Hash.data(), 16);
95 Header.Version.Major =
ObjectFile.Header.Version.Major;
96 Header.Version.Minor =
ObjectFile.Header.Version.Minor;
101 OS.
write(
reinterpret_cast<char *
>(&Header),
sizeof(Header));
105 for (
auto &O : Offsets)
108 Offsets.size() *
sizeof(uint32_t));
111Error DXContainerWriter::writeParts(raw_ostream &OS) {
112 uint32_t RollingOffset =
113 sizeof(dxbc::Header) + (
ObjectFile.Header.PartCount *
sizeof(uint32_t));
115 if (RollingOffset < std::get<1>(
I)) {
116 uint32_t PadBytes = std::get<1>(
I) - RollingOffset;
119 DXContainerYAML::Part
P = std::get<0>(
I);
120 RollingOffset = std::get<1>(
I) +
sizeof(dxbc::PartHeader);
121 uint32_t PartSize =
P.Size;
123 OS.
write(
P.Name.c_str(), 4);
126 OS.
write(
reinterpret_cast<const char *
>(&
P.Size),
sizeof(uint32_t));
132 case dxbc::PartType::DXIL:
133 case dxbc::PartType::ILDB: {
136 dxbc::ProgramHeader Header;
138 P.Program->MinorVersion);
140 Header.ShaderKind =
P.Program->ShaderKind;
141 memcpy(Header.Bitcode.Magic,
"DXIL", 4);
142 Header.Bitcode.MajorVersion =
P.Program->DXILMajorVersion;
143 Header.Bitcode.MinorVersion =
P.Program->DXILMinorVersion;
144 Header.Bitcode.Unused = 0;
147 if (
P.Program->DXILOffset)
148 Header.Bitcode.Offset = *
P.Program->DXILOffset;
150 Header.Bitcode.Offset =
sizeof(dxbc::BitcodeHeader);
152 if (
P.Program->DXILSize)
153 Header.Bitcode.Size = *
P.Program->DXILSize;
155 Header.Bitcode.Size =
P.Program->DXIL ?
P.Program->DXIL->size() : 0;
158 Header.Size = *
P.Program->Size;
160 Header.Size =
sizeof(dxbc::ProgramHeader) + Header.Bitcode.Size;
162 uint32_t BitcodeOffset = Header.Bitcode.Offset;
165 OS.
write(
reinterpret_cast<const char *
>(&Header),
166 sizeof(dxbc::ProgramHeader));
167 if (
P.Program->DXIL) {
168 if (BitcodeOffset >
sizeof(dxbc::BitcodeHeader)) {
169 uint32_t PadBytes = BitcodeOffset -
sizeof(dxbc::BitcodeHeader);
172 OS.
write(
reinterpret_cast<char *
>(
P.Program->DXIL->data()),
173 P.Program->DXIL->size());
177 case dxbc::PartType::ILDN: {
181 mcdxbc::DebugName DebugName;
184 if (
P.DebugName->Flags)
187 if (
P.DebugName->NameLength)
192 case dxbc::PartType::SFI0: {
195 if (!
P.Flags.has_value())
197 uint64_t
Flags =
P.Flags->getEncodedFlags();
200 OS.
write(
reinterpret_cast<char *
>(&Flags),
sizeof(uint64_t));
203 case dxbc::PartType::HASH: {
204 if (!
P.Hash.has_value())
206 dxbc::ShaderHash Hash = {0, {0}};
207 if (
P.Hash->IncludesSource)
208 Hash.
Flags |=
static_cast<uint32_t
>(dxbc::HashFlags::IncludesSource);
209 memcpy(&Hash.
Digest[0], &
P.Hash->Digest[0], 16);
212 OS.
write(
reinterpret_cast<char *
>(&Hash),
sizeof(dxbc::ShaderHash));
215 case dxbc::PartType::PSV0: {
216 if (!
P.Info.has_value())
218 mcdxbc::PSVRuntimeInfo PSV;
219 memcpy(&PSV.
BaseData, &
P.Info->Info,
sizeof(dxbc::PSV::v3::RuntimeInfo));
223 for (
auto El :
P.Info->SigInputElements)
225 El.Name, El.Indices, El.StartRow, El.Cols, El.StartCol,
226 El.Allocated, El.Kind, El.Type, El.Mode, El.DynamicMask,
229 for (
auto El :
P.Info->SigOutputElements)
231 El.Name, El.Indices, El.StartRow, El.Cols, El.StartCol,
232 El.Allocated, El.Kind, El.Type, El.Mode, El.DynamicMask,
235 for (
auto El :
P.Info->SigPatchOrPrimElements)
237 El.Name, El.Indices, El.StartRow, El.Cols, El.StartCol,
238 El.Allocated, El.Kind, El.Type, El.Mode, El.DynamicMask,
244 P.Info->OutputVectorMasks[
I].begin(),
245 P.Info->OutputVectorMasks[
I].end());
247 P.Info->InputOutputMap[
I].begin(),
248 P.Info->InputOutputMap[
I].end());
252 P.Info->PatchOrPrimMasks.begin(),
253 P.Info->PatchOrPrimMasks.end());
255 P.Info->InputPatchMap.begin(),
256 P.Info->InputPatchMap.end());
258 P.Info->PatchOutputMap.begin(),
259 P.Info->PatchOutputMap.end());
264 PSV.
write(OS,
P.Info->Version);
267 case dxbc::PartType::ISG1:
268 case dxbc::PartType::OSG1:
269 case dxbc::PartType::PSG1: {
270 mcdxbc::Signature Sig;
271 if (
P.Signature.has_value()) {
272 for (
const auto &Param :
P.Signature->Parameters) {
281 case dxbc::PartType::Unknown:
283 case dxbc::PartType::RTS0:
284 if (!
P.RootSignature.has_value())
287 mcdxbc::RootSignatureDesc
RS;
288 RS.Flags =
P.RootSignature->getEncodedFlags();
289 RS.Version =
P.RootSignature->Version;
290 RS.NumStaticSamplers =
P.RootSignature->NumStaticSamplers;
292 for (DXContainerYAML::RootParameterLocationYaml &L :
293 P.RootSignature->Parameters.Locations) {
299 case dxbc::RootParameterType::Constants32Bit: {
300 const DXContainerYAML::RootConstantsYaml &ConstantYaml =
301 P.RootSignature->Parameters.getOrInsertConstants(L);
307 RS.ParametersContainer.addParameter(
Type, Visibility, Constants);
310 case dxbc::RootParameterType::CBV:
311 case dxbc::RootParameterType::SRV:
312 case dxbc::RootParameterType::UAV: {
313 const DXContainerYAML::RootDescriptorYaml &DescriptorYaml =
314 P.RootSignature->Parameters.getOrInsertDescriptor(L);
316 mcdxbc::RootDescriptor Descriptor;
321 RS.ParametersContainer.addParameter(
Type, Visibility, Descriptor);
324 case dxbc::RootParameterType::DescriptorTable: {
325 const DXContainerYAML::DescriptorTableYaml &TableYaml =
326 P.RootSignature->Parameters.getOrInsertTable(L);
327 mcdxbc::DescriptorTable Table;
328 for (
const auto &R : TableYaml.
Ranges) {
329 mcdxbc::DescriptorRange
Range;
330 Range.RangeType =
R.RangeType;
331 Range.NumDescriptors =
R.NumDescriptors;
332 Range.BaseShaderRegister =
R.BaseShaderRegister;
333 Range.RegisterSpace =
R.RegisterSpace;
334 Range.OffsetInDescriptorsFromTableStart =
335 R.OffsetInDescriptorsFromTableStart;
338 Range.Flags =
R.getEncodedFlags();
342 RS.ParametersContainer.addParameter(
Type, Visibility, Table);
348 for (
const auto &Param :
P.RootSignature->samplers()) {
349 mcdxbc::StaticSampler NewSampler;
367 RS.StaticSamplers.push_back(NewSampler);
371 RS.RootParameterOffset =
RS.computeRootParametersOffset();
372 if (
P.RootSignature->RootParametersOffset &&
373 P.RootSignature->RootParametersOffset.value() !=
374 RS.RootParameterOffset) {
376 errc::invalid_argument,
377 "Specified RootParametersOffset does not match required value: %d.",
378 RS.RootParameterOffset);
381 RS.StaticSamplersOffset =
RS.computeStaticSamplersOffset();
382 if (
P.RootSignature->StaticSamplersOffset &&
383 P.RootSignature->StaticSamplersOffset.value() !=
384 RS.StaticSamplersOffset) {
386 errc::invalid_argument,
387 "Specified StaticSamplersOffset does not match computed value: %d.",
388 RS.StaticSamplersOffset);
395 RollingOffset += BytesWritten;
396 if (BytesWritten < PartSize)
398 RollingOffset += PartSize;
404Error DXContainerWriter::write(raw_ostream &OS) {
405 if (
Error Err = computePartOffsets())
408 return writeParts(OS);
416 DXContainerWriter Writer(Doc);
417 if (
Error Err = Writer.write(Out)) {
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)
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
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
dxbc::DebugNameHeader Parameters
void setFilename(StringRef DebugFilename)
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
void finalize(Triple::EnvironmentType Stage, uint32_t Version=std::numeric_limits< uint32_t >::max())
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.