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 (P.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 (P.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 (P.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 (P.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 (P.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.