Path: blob/main/contrib/llvm-project/llvm/lib/MC/DXContainerPSVInfo.cpp
35233 views
//===- llvm/MC/DXContainerPSVInfo.cpp - DXContainer PSVInfo -----*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/MC/DXContainerPSVInfo.h"9#include "llvm/BinaryFormat/DXContainer.h"10#include "llvm/MC/StringTableBuilder.h"11#include "llvm/Support/EndianStream.h"12#include "llvm/Support/raw_ostream.h"1314using namespace llvm;15using namespace llvm::mcdxbc;16using namespace llvm::dxbc::PSV;1718static constexpr size_t npos = StringRef::npos;1920static size_t FindSequence(ArrayRef<uint32_t> Buffer,21ArrayRef<uint32_t> Sequence) {22if (Buffer.size() < Sequence.size())23return npos;24for (size_t Idx = 0; Idx <= Buffer.size() - Sequence.size(); ++Idx) {25if (0 == memcmp(static_cast<const void *>(&Buffer[Idx]),26static_cast<const void *>(Sequence.begin()),27Sequence.size() * sizeof(uint32_t)))28return Idx;29}30return npos;31}3233static void34ProcessElementList(StringTableBuilder &StrTabBuilder,35SmallVectorImpl<uint32_t> &IndexBuffer,36SmallVectorImpl<v0::SignatureElement> &FinalElements,37SmallVectorImpl<StringRef> &SemanticNames,38ArrayRef<PSVSignatureElement> Elements) {39for (const auto &El : Elements) {40// Put the name in the string table and the name list.41StrTabBuilder.add(El.Name);42SemanticNames.push_back(El.Name);4344v0::SignatureElement FinalElement;45memset(&FinalElement, 0, sizeof(v0::SignatureElement));46FinalElement.Rows = static_cast<uint8_t>(El.Indices.size());47FinalElement.StartRow = El.StartRow;48FinalElement.Cols = El.Cols;49FinalElement.StartCol = El.StartCol;50FinalElement.Allocated = El.Allocated;51FinalElement.Kind = El.Kind;52FinalElement.Type = El.Type;53FinalElement.Mode = El.Mode;54FinalElement.DynamicMask = El.DynamicMask;55FinalElement.Stream = El.Stream;5657size_t Idx = FindSequence(IndexBuffer, El.Indices);58if (Idx == npos) {59FinalElement.IndicesOffset = static_cast<uint32_t>(IndexBuffer.size());60IndexBuffer.insert(IndexBuffer.end(), El.Indices.begin(),61El.Indices.end());62} else63FinalElement.IndicesOffset = static_cast<uint32_t>(Idx);64FinalElements.push_back(FinalElement);65}66}6768void PSVRuntimeInfo::write(raw_ostream &OS, uint32_t Version) const {69assert(IsFinalized && "finalize must be called before write");7071uint32_t InfoSize;72uint32_t BindingSize;73switch (Version) {74case 0:75InfoSize = sizeof(dxbc::PSV::v0::RuntimeInfo);76BindingSize = sizeof(dxbc::PSV::v0::ResourceBindInfo);77break;78case 1:79InfoSize = sizeof(dxbc::PSV::v1::RuntimeInfo);80BindingSize = sizeof(dxbc::PSV::v0::ResourceBindInfo);81break;82case 2:83InfoSize = sizeof(dxbc::PSV::v2::RuntimeInfo);84BindingSize = sizeof(dxbc::PSV::v2::ResourceBindInfo);85break;86case 3:87default:88InfoSize = sizeof(dxbc::PSV::v3::RuntimeInfo);89BindingSize = sizeof(dxbc::PSV::v2::ResourceBindInfo);90}9192// Write the size of the info.93support::endian::write(OS, InfoSize, llvm::endianness::little);9495// Write the info itself.96OS.write(reinterpret_cast<const char *>(&BaseData), InfoSize);9798uint32_t ResourceCount = static_cast<uint32_t>(Resources.size());99100support::endian::write(OS, ResourceCount, llvm::endianness::little);101if (ResourceCount > 0)102support::endian::write(OS, BindingSize, llvm::endianness::little);103104for (const auto &Res : Resources)105OS.write(reinterpret_cast<const char *>(&Res), BindingSize);106107// PSV Version 0 stops after the resource list.108if (Version == 0)109return;110111support::endian::write(OS,112static_cast<uint32_t>(DXConStrTabBuilder.getSize()),113llvm::endianness::little);114115// Write the string table.116DXConStrTabBuilder.write(OS);117118// Write the index table size, then table.119support::endian::write(OS, static_cast<uint32_t>(IndexBuffer.size()),120llvm::endianness::little);121for (auto I : IndexBuffer)122support::endian::write(OS, I, llvm::endianness::little);123124if (SignatureElements.size() > 0) {125// write the size of the signature elements.126support::endian::write(OS,127static_cast<uint32_t>(sizeof(v0::SignatureElement)),128llvm::endianness::little);129130// write the signature elements.131OS.write(reinterpret_cast<const char *>(&SignatureElements[0]),132SignatureElements.size() * sizeof(v0::SignatureElement));133}134135for (const auto &MaskVector : OutputVectorMasks)136support::endian::write_array(OS, ArrayRef<uint32_t>(MaskVector),137llvm::endianness::little);138support::endian::write_array(OS, ArrayRef<uint32_t>(PatchOrPrimMasks),139llvm::endianness::little);140for (const auto &MaskVector : InputOutputMap)141support::endian::write_array(OS, ArrayRef<uint32_t>(MaskVector),142llvm::endianness::little);143support::endian::write_array(OS, ArrayRef<uint32_t>(InputPatchMap),144llvm::endianness::little);145support::endian::write_array(OS, ArrayRef<uint32_t>(PatchOutputMap),146llvm::endianness::little);147}148149void PSVRuntimeInfo::finalize(Triple::EnvironmentType Stage) {150IsFinalized = true;151BaseData.SigInputElements = static_cast<uint32_t>(InputElements.size());152BaseData.SigOutputElements = static_cast<uint32_t>(OutputElements.size());153BaseData.SigPatchOrPrimElements =154static_cast<uint32_t>(PatchOrPrimElements.size());155156SmallVector<StringRef, 32> SemanticNames;157158// Build a string table and set associated offsets to be written when159// write() is called160ProcessElementList(DXConStrTabBuilder, IndexBuffer, SignatureElements,161SemanticNames, InputElements);162ProcessElementList(DXConStrTabBuilder, IndexBuffer, SignatureElements,163SemanticNames, OutputElements);164ProcessElementList(DXConStrTabBuilder, IndexBuffer, SignatureElements,165SemanticNames, PatchOrPrimElements);166167DXConStrTabBuilder.add(EntryName);168169DXConStrTabBuilder.finalize();170for (auto ElAndName : zip(SignatureElements, SemanticNames)) {171llvm::dxbc::PSV::v0::SignatureElement &El = std::get<0>(ElAndName);172StringRef Name = std::get<1>(ElAndName);173El.NameOffset = static_cast<uint32_t>(DXConStrTabBuilder.getOffset(Name));174if (sys::IsBigEndianHost)175El.swapBytes();176}177178BaseData.EntryNameOffset =179static_cast<uint32_t>(DXConStrTabBuilder.getOffset(EntryName));180181if (!sys::IsBigEndianHost)182return;183BaseData.swapBytes();184BaseData.swapBytes(Stage);185for (auto &Res : Resources)186Res.swapBytes();187}188189void Signature::write(raw_ostream &OS) {190SmallVector<dxbc::ProgramSignatureElement> SigParams;191SigParams.reserve(Params.size());192StringTableBuilder StrTabBuilder((StringTableBuilder::DWARF));193194// Name offsets are from the start of the part. Pre-calculate the offset to195// the start of the string table so that it can be added to the table offset.196uint32_t TableStart = sizeof(dxbc::ProgramSignatureHeader) +197(sizeof(dxbc::ProgramSignatureElement) * Params.size());198199for (const auto &P : Params) {200// zero out the data201dxbc::ProgramSignatureElement FinalElement;202memset(&FinalElement, 0, sizeof(dxbc::ProgramSignatureElement));203FinalElement.Stream = P.Stream;204FinalElement.NameOffset =205static_cast<uint32_t>(StrTabBuilder.add(P.Name)) + TableStart;206FinalElement.Index = P.Index;207FinalElement.SystemValue = P.SystemValue;208FinalElement.CompType = P.CompType;209FinalElement.Register = P.Register;210FinalElement.Mask = P.Mask;211FinalElement.ExclusiveMask = P.ExclusiveMask;212FinalElement.MinPrecision = P.MinPrecision;213SigParams.push_back(FinalElement);214}215216StrTabBuilder.finalizeInOrder();217stable_sort(SigParams, [&](const dxbc::ProgramSignatureElement &L,218const dxbc::ProgramSignatureElement R) {219return std::tie(L.Stream, L.Register, L.NameOffset) <220std::tie(R.Stream, R.Register, R.NameOffset);221});222if (sys::IsBigEndianHost)223for (auto &El : SigParams)224El.swapBytes();225226dxbc::ProgramSignatureHeader Header = {static_cast<uint32_t>(Params.size()),227sizeof(dxbc::ProgramSignatureHeader)};228if (sys::IsBigEndianHost)229Header.swapBytes();230OS.write(reinterpret_cast<const char *>(&Header),231sizeof(dxbc::ProgramSignatureHeader));232OS.write(reinterpret_cast<const char *>(SigParams.data()),233sizeof(dxbc::ProgramSignatureElement) * SigParams.size());234StrTabBuilder.write(OS);235}236237238