1 // Copyright 2020 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 #include <cstring>
17 
18 namespace vk {
19 
SpecializationInfo(const VkSpecializationInfo * specializationInfo)20 SpecializationInfo::SpecializationInfo(const VkSpecializationInfo *specializationInfo)
21 {
22 	if(specializationInfo)
23 	{
24 		auto ptr = reinterpret_cast<VkSpecializationInfo *>(
25 		    allocate(sizeof(VkSpecializationInfo), REQUIRED_MEMORY_ALIGNMENT, DEVICE_MEMORY));
26 
27 		info = std::shared_ptr<VkSpecializationInfo>(ptr, Deleter());
28 
29 		info->mapEntryCount = specializationInfo->mapEntryCount;
30 		if(specializationInfo->mapEntryCount > 0)
31 		{
32 			size_t entriesSize = specializationInfo->mapEntryCount * sizeof(VkSpecializationMapEntry);
33 			VkSpecializationMapEntry *mapEntries = reinterpret_cast<VkSpecializationMapEntry *>(
34 			    allocate(entriesSize, REQUIRED_MEMORY_ALIGNMENT, DEVICE_MEMORY));
35 			memcpy(mapEntries, specializationInfo->pMapEntries, entriesSize);
36 			info->pMapEntries = mapEntries;
37 		}
38 
39 		info->dataSize = specializationInfo->dataSize;
40 		if(specializationInfo->dataSize > 0)
41 		{
42 			void *data = allocate(specializationInfo->dataSize, REQUIRED_MEMORY_ALIGNMENT, DEVICE_MEMORY);
43 			memcpy(data, specializationInfo->pData, specializationInfo->dataSize);
44 			info->pData = data;
45 		}
46 		else
47 		{
48 			info->pData = nullptr;
49 		}
50 	}
51 }
52 
operator ()(VkSpecializationInfo * info) const53 void SpecializationInfo::Deleter::operator()(VkSpecializationInfo *info) const
54 {
55 	if(info)
56 	{
57 		deallocate(const_cast<VkSpecializationMapEntry *>(info->pMapEntries), DEVICE_MEMORY);
58 		deallocate(const_cast<void *>(info->pData), DEVICE_MEMORY);
59 		deallocate(info, DEVICE_MEMORY);
60 	}
61 }
62 
operator <(const SpecializationInfo & specializationInfo) const63 bool SpecializationInfo::operator<(const SpecializationInfo &specializationInfo) const
64 {
65 	// Check that either both or neither keys have specialization info.
66 	if((info.get() == nullptr) != (specializationInfo.info.get() == nullptr))
67 	{
68 		return info.get() == nullptr;
69 	}
70 
71 	if(!info)
72 	{
73 		ASSERT(!specializationInfo.info);
74 		return false;
75 	}
76 
77 	if(info->mapEntryCount != specializationInfo.info->mapEntryCount)
78 	{
79 		return info->mapEntryCount < specializationInfo.info->mapEntryCount;
80 	}
81 
82 	if(info->dataSize != specializationInfo.info->dataSize)
83 	{
84 		return info->dataSize < specializationInfo.info->dataSize;
85 	}
86 
87 	if(info->mapEntryCount > 0)
88 	{
89 		int cmp = memcmp(info->pMapEntries, specializationInfo.info->pMapEntries, info->mapEntryCount * sizeof(VkSpecializationMapEntry));
90 		if(cmp != 0)
91 		{
92 			return cmp < 0;
93 		}
94 	}
95 
96 	if(info->dataSize > 0)
97 	{
98 		int cmp = memcmp(info->pData, specializationInfo.info->pData, info->dataSize);
99 		if(cmp != 0)
100 		{
101 			return cmp < 0;
102 		}
103 	}
104 
105 	return false;
106 }
107 
108 }  // namespace vk
109