• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "VkPipelineCache.hpp"
16 
17 #include <cstring>
18 
19 namespace vk {
20 
SpirvBinaryKey(const sw::SpirvBinary & spirv,const VkSpecializationInfo * specializationInfo,bool optimize)21 PipelineCache::SpirvBinaryKey::SpirvBinaryKey(const sw::SpirvBinary &spirv,
22                                               const VkSpecializationInfo *specializationInfo,
23                                               bool optimize)
24     : spirv(spirv)
25     , specializationInfo(specializationInfo)
26     , optimize(optimize)
27 {
28 }
29 
operator <(const SpirvBinaryKey & other) const30 bool PipelineCache::SpirvBinaryKey::operator<(const SpirvBinaryKey &other) const
31 {
32 	if(spirv.size() != other.spirv.size())
33 	{
34 		return spirv.size() < other.spirv.size();
35 	}
36 
37 	int cmp = memcmp(spirv.data(), other.spirv.data(), spirv.size() * sizeof(uint32_t));
38 	if(cmp != 0)
39 	{
40 		return cmp < 0;
41 	}
42 
43 	if(optimize != other.optimize)
44 	{
45 		return !optimize && other.optimize;
46 	}
47 
48 	return (specializationInfo < other.specializationInfo);
49 }
50 
ComputeProgramKey(uint64_t shaderIdentifier,uint32_t pipelineLayoutIdentifier)51 PipelineCache::ComputeProgramKey::ComputeProgramKey(uint64_t shaderIdentifier, uint32_t pipelineLayoutIdentifier)
52     : shaderIdentifier(shaderIdentifier)
53     , pipelineLayoutIdentifier(pipelineLayoutIdentifier)
54 {}
55 
operator <(const ComputeProgramKey & other) const56 bool PipelineCache::ComputeProgramKey::operator<(const ComputeProgramKey &other) const
57 {
58 	return std::tie(shaderIdentifier, pipelineLayoutIdentifier) < std::tie(other.shaderIdentifier, other.pipelineLayoutIdentifier);
59 }
60 
PipelineCache(const VkPipelineCacheCreateInfo * pCreateInfo,void * mem)61 PipelineCache::PipelineCache(const VkPipelineCacheCreateInfo *pCreateInfo, void *mem)
62     : dataSize(ComputeRequiredAllocationSize(pCreateInfo))
63     , data(reinterpret_cast<uint8_t *>(mem))
64 {
65 	CacheHeader *header = reinterpret_cast<CacheHeader *>(mem);
66 	header->headerLength = sizeof(CacheHeader);
67 	header->headerVersion = VK_PIPELINE_CACHE_HEADER_VERSION_ONE;
68 	header->vendorID = VENDOR_ID;
69 	header->deviceID = DEVICE_ID;
70 	memcpy(header->pipelineCacheUUID, SWIFTSHADER_UUID, VK_UUID_SIZE);
71 
72 	if(pCreateInfo->pInitialData && (pCreateInfo->initialDataSize > 0))
73 	{
74 		memcpy(data + sizeof(CacheHeader), pCreateInfo->pInitialData, pCreateInfo->initialDataSize);
75 	}
76 }
77 
~PipelineCache()78 PipelineCache::~PipelineCache()
79 {
80 	spirvShaders.clear();
81 	computePrograms.clear();
82 }
83 
destroy(const VkAllocationCallbacks * pAllocator)84 void PipelineCache::destroy(const VkAllocationCallbacks *pAllocator)
85 {
86 	vk::freeHostMemory(data, pAllocator);
87 }
88 
ComputeRequiredAllocationSize(const VkPipelineCacheCreateInfo * pCreateInfo)89 size_t PipelineCache::ComputeRequiredAllocationSize(const VkPipelineCacheCreateInfo *pCreateInfo)
90 {
91 	return pCreateInfo->initialDataSize + sizeof(CacheHeader);
92 }
93 
getData(size_t * pDataSize,void * pData)94 VkResult PipelineCache::getData(size_t *pDataSize, void *pData)
95 {
96 	if(!pData)
97 	{
98 		*pDataSize = dataSize;
99 		return VK_SUCCESS;
100 	}
101 
102 	if(*pDataSize != dataSize)
103 	{
104 		*pDataSize = 0;
105 		return VK_INCOMPLETE;
106 	}
107 
108 	if(*pDataSize > 0)
109 	{
110 		memcpy(pData, data, *pDataSize);
111 	}
112 
113 	return VK_SUCCESS;
114 }
115 
merge(uint32_t srcCacheCount,const VkPipelineCache * pSrcCaches)116 VkResult PipelineCache::merge(uint32_t srcCacheCount, const VkPipelineCache *pSrcCaches)
117 {
118 	for(uint32_t i = 0; i < srcCacheCount; i++)
119 	{
120 		PipelineCache *srcCache = Cast(pSrcCaches[i]);
121 
122 		{
123 			marl::lock thisLock(spirvShadersMutex);
124 			marl::lock srcLock(srcCache->spirvShadersMutex);
125 			spirvShaders.insert(srcCache->spirvShaders.begin(), srcCache->spirvShaders.end());
126 		}
127 
128 		{
129 			marl::lock thisLock(computeProgramsMutex);
130 			marl::lock srcLock(srcCache->computeProgramsMutex);
131 			computePrograms.insert(srcCache->computePrograms.begin(), srcCache->computePrograms.end());
132 		}
133 	}
134 
135 	return VK_SUCCESS;
136 }
137 
138 }  // namespace vk
139