1e5c31af7Sopenharmony_ci#ifndef _VKBINARYREGISTRY_HPP 2e5c31af7Sopenharmony_ci#define _VKBINARYREGISTRY_HPP 3e5c31af7Sopenharmony_ci/*------------------------------------------------------------------------- 4e5c31af7Sopenharmony_ci * Vulkan CTS Framework 5e5c31af7Sopenharmony_ci * -------------------- 6e5c31af7Sopenharmony_ci * 7e5c31af7Sopenharmony_ci * Copyright (c) 2015 Google Inc. 8e5c31af7Sopenharmony_ci * 9e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 10e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License. 11e5c31af7Sopenharmony_ci * You may obtain a copy of the License at 12e5c31af7Sopenharmony_ci * 13e5c31af7Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 14e5c31af7Sopenharmony_ci * 15e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 16e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 17e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and 19e5c31af7Sopenharmony_ci * limitations under the License. 20e5c31af7Sopenharmony_ci * 21e5c31af7Sopenharmony_ci *//*! 22e5c31af7Sopenharmony_ci * \file 23e5c31af7Sopenharmony_ci * \brief Program binary registry. 24e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 25e5c31af7Sopenharmony_ci 26e5c31af7Sopenharmony_ci#include "vkDefs.hpp" 27e5c31af7Sopenharmony_ci#include "vkPrograms.hpp" 28e5c31af7Sopenharmony_ci#include "tcuResource.hpp" 29e5c31af7Sopenharmony_ci#include "deMemPool.hpp" 30e5c31af7Sopenharmony_ci#include "dePoolHash.h" 31e5c31af7Sopenharmony_ci#include "deUniquePtr.hpp" 32e5c31af7Sopenharmony_ci 33e5c31af7Sopenharmony_ci#include <map> 34e5c31af7Sopenharmony_ci#include <vector> 35e5c31af7Sopenharmony_ci#include <stdexcept> 36e5c31af7Sopenharmony_ci 37e5c31af7Sopenharmony_cinamespace vk 38e5c31af7Sopenharmony_ci{ 39e5c31af7Sopenharmony_cinamespace BinaryRegistryDetail 40e5c31af7Sopenharmony_ci{ 41e5c31af7Sopenharmony_ci 42e5c31af7Sopenharmony_cistruct ProgramIdentifier 43e5c31af7Sopenharmony_ci{ 44e5c31af7Sopenharmony_ci std::string testCasePath; 45e5c31af7Sopenharmony_ci std::string programName; 46e5c31af7Sopenharmony_ci 47e5c31af7Sopenharmony_ci ProgramIdentifier (const std::string& testCasePath_, const std::string& programName_) 48e5c31af7Sopenharmony_ci : testCasePath (testCasePath_) 49e5c31af7Sopenharmony_ci , programName (programName_) 50e5c31af7Sopenharmony_ci { 51e5c31af7Sopenharmony_ci } 52e5c31af7Sopenharmony_ci}; 53e5c31af7Sopenharmony_ci 54e5c31af7Sopenharmony_ciinline bool operator< (const ProgramIdentifier& a, const ProgramIdentifier& b) 55e5c31af7Sopenharmony_ci{ 56e5c31af7Sopenharmony_ci return (a.testCasePath < b.testCasePath) || ((a.testCasePath == b.testCasePath) && (a.programName < b.programName)); 57e5c31af7Sopenharmony_ci} 58e5c31af7Sopenharmony_ci 59e5c31af7Sopenharmony_ciclass ProgramNotFoundException : public tcu::ResourceError 60e5c31af7Sopenharmony_ci{ 61e5c31af7Sopenharmony_cipublic: 62e5c31af7Sopenharmony_ci ProgramNotFoundException (const ProgramIdentifier& id, const std::string& reason) 63e5c31af7Sopenharmony_ci : tcu::ResourceError("Program " + id.testCasePath + " / '" + id.programName + "' not found: " + reason) 64e5c31af7Sopenharmony_ci { 65e5c31af7Sopenharmony_ci } 66e5c31af7Sopenharmony_ci}; 67e5c31af7Sopenharmony_ci 68e5c31af7Sopenharmony_ci// Program Binary Index 69e5c31af7Sopenharmony_ci// -------------------- 70e5c31af7Sopenharmony_ci// 71e5c31af7Sopenharmony_ci// When SPIR-V binaries are stored on disk, duplicate binaries are eliminated 72e5c31af7Sopenharmony_ci// to save a significant amount of space. Many tests use identical binaries and 73e5c31af7Sopenharmony_ci// just storing each compiled binary without de-duplication would be incredibly 74e5c31af7Sopenharmony_ci// wasteful. 75e5c31af7Sopenharmony_ci// 76e5c31af7Sopenharmony_ci// To locate binary that corresponds given ProgramIdentifier, a program binary 77e5c31af7Sopenharmony_ci// index is needed. Since that index is accessed every time a test requests shader 78e5c31af7Sopenharmony_ci// binary, it must be fast to load (to reduce statup cost), and fast to access. 79e5c31af7Sopenharmony_ci// 80e5c31af7Sopenharmony_ci// Simple trie is used to store binary indices. It is laid out as an array of 81e5c31af7Sopenharmony_ci// BinaryIndexNodes. Nodes store 4-byte pieces (words) of search string, rather 82e5c31af7Sopenharmony_ci// than just a single character. This gives more regular memory layout in exchange 83e5c31af7Sopenharmony_ci// of a little wasted storage. 84e5c31af7Sopenharmony_ci// 85e5c31af7Sopenharmony_ci// Search strings are created by splitting original string into 4-byte words and 86e5c31af7Sopenharmony_ci// appending one or more terminating 0 bytes. 87e5c31af7Sopenharmony_ci// 88e5c31af7Sopenharmony_ci// For each node where word doesn't have trailing 0 bytes (not terminated), the 89e5c31af7Sopenharmony_ci// index points into a offset of its child list. Children for each node are stored 90e5c31af7Sopenharmony_ci// consecutively, and the list is terminated by child with word = 0. 91e5c31af7Sopenharmony_ci// 92e5c31af7Sopenharmony_ci// If word contains one or more trailing 0 bytes, index denotes the binary index 93e5c31af7Sopenharmony_ci// instead of index of the child list. 94e5c31af7Sopenharmony_ci 95e5c31af7Sopenharmony_cistruct BinaryIndexNode 96e5c31af7Sopenharmony_ci{ 97e5c31af7Sopenharmony_ci deUint32 word; //!< 4 bytes of search string. 98e5c31af7Sopenharmony_ci deUint32 index; //!< Binary index if word ends with 0 bytes, or index of first child node otherwise. 99e5c31af7Sopenharmony_ci}; 100e5c31af7Sopenharmony_ci 101e5c31af7Sopenharmony_citemplate<typename Element> 102e5c31af7Sopenharmony_ciclass LazyResource 103e5c31af7Sopenharmony_ci{ 104e5c31af7Sopenharmony_cipublic: 105e5c31af7Sopenharmony_ci LazyResource (de::MovePtr<tcu::Resource> resource); 106e5c31af7Sopenharmony_ci 107e5c31af7Sopenharmony_ci const Element& operator[] (size_t ndx); 108e5c31af7Sopenharmony_ci size_t size (void) const { return m_elements.size(); } 109e5c31af7Sopenharmony_ci 110e5c31af7Sopenharmony_ciprivate: 111e5c31af7Sopenharmony_ci enum 112e5c31af7Sopenharmony_ci { 113e5c31af7Sopenharmony_ci ELEMENTS_PER_PAGE_LOG2 = 10 114e5c31af7Sopenharmony_ci }; 115e5c31af7Sopenharmony_ci 116e5c31af7Sopenharmony_ci inline size_t getPageForElement (size_t elemNdx) const { return elemNdx >> ELEMENTS_PER_PAGE_LOG2; } 117e5c31af7Sopenharmony_ci inline bool isPageResident (size_t pageNdx) const { return m_isPageResident[pageNdx]; } 118e5c31af7Sopenharmony_ci 119e5c31af7Sopenharmony_ci void makePageResident (size_t pageNdx); 120e5c31af7Sopenharmony_ci 121e5c31af7Sopenharmony_ci de::UniquePtr<tcu::Resource> m_resource; 122e5c31af7Sopenharmony_ci 123e5c31af7Sopenharmony_ci std::vector<Element> m_elements; 124e5c31af7Sopenharmony_ci std::vector<bool> m_isPageResident; 125e5c31af7Sopenharmony_ci}; 126e5c31af7Sopenharmony_ci 127e5c31af7Sopenharmony_citemplate<typename Element> 128e5c31af7Sopenharmony_ciLazyResource<Element>::LazyResource (de::MovePtr<tcu::Resource> resource) 129e5c31af7Sopenharmony_ci : m_resource(resource) 130e5c31af7Sopenharmony_ci{ 131e5c31af7Sopenharmony_ci const size_t resSize = m_resource->getSize(); 132e5c31af7Sopenharmony_ci const size_t numElements = resSize/sizeof(Element); 133e5c31af7Sopenharmony_ci const size_t numPages = (numElements >> ELEMENTS_PER_PAGE_LOG2) + ((numElements & ((1u<<ELEMENTS_PER_PAGE_LOG2)-1u)) == 0 ? 0 : 1); 134e5c31af7Sopenharmony_ci 135e5c31af7Sopenharmony_ci TCU_CHECK_INTERNAL(numElements*sizeof(Element) == resSize); 136e5c31af7Sopenharmony_ci 137e5c31af7Sopenharmony_ci m_elements.resize(numElements); 138e5c31af7Sopenharmony_ci m_isPageResident.resize(numPages, false); 139e5c31af7Sopenharmony_ci} 140e5c31af7Sopenharmony_ci 141e5c31af7Sopenharmony_citemplate<typename Element> 142e5c31af7Sopenharmony_ciconst Element& LazyResource<Element>::operator[] (size_t ndx) 143e5c31af7Sopenharmony_ci{ 144e5c31af7Sopenharmony_ci const size_t pageNdx = getPageForElement(ndx); 145e5c31af7Sopenharmony_ci 146e5c31af7Sopenharmony_ci if (ndx >= m_elements.size()) 147e5c31af7Sopenharmony_ci throw std::out_of_range(""); 148e5c31af7Sopenharmony_ci 149e5c31af7Sopenharmony_ci if (!isPageResident(pageNdx)) 150e5c31af7Sopenharmony_ci makePageResident(pageNdx); 151e5c31af7Sopenharmony_ci 152e5c31af7Sopenharmony_ci return m_elements[ndx]; 153e5c31af7Sopenharmony_ci} 154e5c31af7Sopenharmony_ci 155e5c31af7Sopenharmony_citemplate<typename Element> 156e5c31af7Sopenharmony_civoid LazyResource<Element>::makePageResident (size_t pageNdx) 157e5c31af7Sopenharmony_ci{ 158e5c31af7Sopenharmony_ci const size_t pageSize = (size_t)(1<<ELEMENTS_PER_PAGE_LOG2)*sizeof(Element); 159e5c31af7Sopenharmony_ci const size_t pageOffset = pageNdx*pageSize; 160e5c31af7Sopenharmony_ci const size_t numBytesToRead = de::min(m_elements.size()*sizeof(Element) - pageOffset, pageSize); 161e5c31af7Sopenharmony_ci 162e5c31af7Sopenharmony_ci DE_ASSERT(!isPageResident(pageNdx)); 163e5c31af7Sopenharmony_ci 164e5c31af7Sopenharmony_ci if ((size_t)m_resource->getPosition() != pageOffset) 165e5c31af7Sopenharmony_ci m_resource->setPosition((int)pageOffset); 166e5c31af7Sopenharmony_ci 167e5c31af7Sopenharmony_ci m_resource->read((deUint8*)&m_elements[pageNdx << ELEMENTS_PER_PAGE_LOG2], (int)numBytesToRead); 168e5c31af7Sopenharmony_ci m_isPageResident[pageNdx] = true; 169e5c31af7Sopenharmony_ci} 170e5c31af7Sopenharmony_ci 171e5c31af7Sopenharmony_citypedef LazyResource<BinaryIndexNode> BinaryIndexAccess; 172e5c31af7Sopenharmony_ci 173e5c31af7Sopenharmony_ciclass BinaryRegistryReader 174e5c31af7Sopenharmony_ci{ 175e5c31af7Sopenharmony_cipublic: 176e5c31af7Sopenharmony_ci BinaryRegistryReader (const tcu::Archive& archive, const std::string& srcPath); 177e5c31af7Sopenharmony_ci ~BinaryRegistryReader (void); 178e5c31af7Sopenharmony_ci 179e5c31af7Sopenharmony_ci ProgramBinary* loadProgram (const ProgramIdentifier& id) const; 180e5c31af7Sopenharmony_ci 181e5c31af7Sopenharmony_ciprivate: 182e5c31af7Sopenharmony_ci typedef de::MovePtr<BinaryIndexAccess> BinaryIndexPtr; 183e5c31af7Sopenharmony_ci 184e5c31af7Sopenharmony_ci const tcu::Archive& m_archive; 185e5c31af7Sopenharmony_ci const std::string m_srcPath; 186e5c31af7Sopenharmony_ci 187e5c31af7Sopenharmony_ci mutable BinaryIndexPtr m_binaryIndex; 188e5c31af7Sopenharmony_ci}; 189e5c31af7Sopenharmony_ci 190e5c31af7Sopenharmony_cistruct ProgramIdentifierIndex 191e5c31af7Sopenharmony_ci{ 192e5c31af7Sopenharmony_ci ProgramIdentifier id; 193e5c31af7Sopenharmony_ci deUint32 index; 194e5c31af7Sopenharmony_ci 195e5c31af7Sopenharmony_ci ProgramIdentifierIndex (const ProgramIdentifier& id_, 196e5c31af7Sopenharmony_ci deUint32 index_) 197e5c31af7Sopenharmony_ci : id (id_) 198e5c31af7Sopenharmony_ci , index (index_) 199e5c31af7Sopenharmony_ci {} 200e5c31af7Sopenharmony_ci}; 201e5c31af7Sopenharmony_ci 202e5c31af7Sopenharmony_ciDE_DECLARE_POOL_HASH(BinaryIndexHashImpl, const ProgramBinary*, deUint32); 203e5c31af7Sopenharmony_ci 204e5c31af7Sopenharmony_ciclass BinaryIndexHash 205e5c31af7Sopenharmony_ci{ 206e5c31af7Sopenharmony_cipublic: 207e5c31af7Sopenharmony_ci BinaryIndexHash (void); 208e5c31af7Sopenharmony_ci ~BinaryIndexHash (void); 209e5c31af7Sopenharmony_ci 210e5c31af7Sopenharmony_ci deUint32* find (const ProgramBinary* binary) const; 211e5c31af7Sopenharmony_ci void insert (const ProgramBinary* binary, deUint32 index); 212e5c31af7Sopenharmony_ci 213e5c31af7Sopenharmony_ciprivate: 214e5c31af7Sopenharmony_ci BinaryIndexHash (const BinaryIndexHash&); 215e5c31af7Sopenharmony_ci BinaryIndexHash& operator= (const BinaryIndexHash&); 216e5c31af7Sopenharmony_ci 217e5c31af7Sopenharmony_ci de::MemPool m_memPool; 218e5c31af7Sopenharmony_ci BinaryIndexHashImpl* const m_hash; 219e5c31af7Sopenharmony_ci}; 220e5c31af7Sopenharmony_ci 221e5c31af7Sopenharmony_ciclass BinaryRegistryWriter 222e5c31af7Sopenharmony_ci{ 223e5c31af7Sopenharmony_cipublic: 224e5c31af7Sopenharmony_ci BinaryRegistryWriter (const std::string& dstPath); 225e5c31af7Sopenharmony_ci ~BinaryRegistryWriter (void); 226e5c31af7Sopenharmony_ci 227e5c31af7Sopenharmony_ci void addProgram (const ProgramIdentifier& id, const ProgramBinary& binary); 228e5c31af7Sopenharmony_ci void write (void) const; 229e5c31af7Sopenharmony_ci 230e5c31af7Sopenharmony_ciprivate: 231e5c31af7Sopenharmony_ci void initFromPath (const std::string& srcPath); 232e5c31af7Sopenharmony_ci void writeToPath (const std::string& dstPath) const; 233e5c31af7Sopenharmony_ci 234e5c31af7Sopenharmony_ci deUint32* findBinary (const ProgramBinary& binary) const; 235e5c31af7Sopenharmony_ci deUint32 getNextSlot (void) const; 236e5c31af7Sopenharmony_ci void addBinary (deUint32 index, const ProgramBinary& binary); 237e5c31af7Sopenharmony_ci 238e5c31af7Sopenharmony_ci struct BinarySlot 239e5c31af7Sopenharmony_ci { 240e5c31af7Sopenharmony_ci ProgramBinary* binary; 241e5c31af7Sopenharmony_ci size_t referenceCount; 242e5c31af7Sopenharmony_ci 243e5c31af7Sopenharmony_ci BinarySlot (ProgramBinary* binary_, size_t referenceCount_) 244e5c31af7Sopenharmony_ci : binary (binary_) 245e5c31af7Sopenharmony_ci , referenceCount(referenceCount_) 246e5c31af7Sopenharmony_ci {} 247e5c31af7Sopenharmony_ci 248e5c31af7Sopenharmony_ci BinarySlot (void) 249e5c31af7Sopenharmony_ci : binary (DE_NULL) 250e5c31af7Sopenharmony_ci , referenceCount(0) 251e5c31af7Sopenharmony_ci {} 252e5c31af7Sopenharmony_ci }; 253e5c31af7Sopenharmony_ci 254e5c31af7Sopenharmony_ci typedef std::vector<BinarySlot> BinaryVector; 255e5c31af7Sopenharmony_ci typedef std::vector<ProgramIdentifierIndex> ProgIdIndexVector; 256e5c31af7Sopenharmony_ci 257e5c31af7Sopenharmony_ci const std::string& m_dstPath; 258e5c31af7Sopenharmony_ci 259e5c31af7Sopenharmony_ci ProgIdIndexVector m_binaryIndices; //!< ProgramIdentifier -> slot in m_binaries 260e5c31af7Sopenharmony_ci BinaryIndexHash m_binaryHash; //!< ProgramBinary -> slot in m_binaries 261e5c31af7Sopenharmony_ci BinaryVector m_binaries; 262e5c31af7Sopenharmony_ci}; 263e5c31af7Sopenharmony_ci 264e5c31af7Sopenharmony_ci} // BinaryRegistryDetail 265e5c31af7Sopenharmony_ci 266e5c31af7Sopenharmony_ciusing BinaryRegistryDetail::BinaryRegistryReader; 267e5c31af7Sopenharmony_ciusing BinaryRegistryDetail::BinaryRegistryWriter; 268e5c31af7Sopenharmony_ciusing BinaryRegistryDetail::ProgramIdentifier; 269e5c31af7Sopenharmony_ciusing BinaryRegistryDetail::ProgramNotFoundException; 270e5c31af7Sopenharmony_ci 271e5c31af7Sopenharmony_ci} // vk 272e5c31af7Sopenharmony_ci 273e5c31af7Sopenharmony_ci#endif // _VKBINARYREGISTRY_HPP 274