1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2024 The Khronos Group Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Utilities for pipeline binaries.
22 *//*--------------------------------------------------------------------*/
23
24 #include "vkPipelineBinaryUtil.hpp"
25 #include "vkQueryUtil.hpp"
26 #include "deSTLUtil.hpp"
27 #include <vector>
28
29 #ifndef CTS_USES_VULKANSC
30
31 namespace vk
32 {
33
makeMovablePipelineBinary(const DeviceInterface & vk,const VkDevice device,VkPipelineBinaryKHR rawPipelineBinary)34 Move<VkPipelineBinaryKHR> makeMovablePipelineBinary(const DeviceInterface &vk, const VkDevice device,
35 VkPipelineBinaryKHR rawPipelineBinary)
36 {
37 return Move<VkPipelineBinaryKHR>(check<VkPipelineBinaryKHR>(rawPipelineBinary),
38 Deleter<VkPipelineBinaryKHR>(vk, device, DE_NULL));
39 }
40
PipelineBinaryWrapper(const DeviceInterface & vk,const VkDevice device)41 PipelineBinaryWrapper::PipelineBinaryWrapper(const DeviceInterface &vk, const VkDevice device)
42 : m_vk(vk)
43 , m_device(device)
44 {
45 }
46
getPipelineKey(const void * pPipelineCreateInfo) const47 VkPipelineBinaryKeyKHR PipelineBinaryWrapper::getPipelineKey(const void *pPipelineCreateInfo) const
48 {
49 VkPipelineBinaryKeyKHR pipelineKey = initVulkanStructure();
50 VkPipelineCreateInfoKHR pipelineCreateInfo = initVulkanStructure(const_cast<void *>(pPipelineCreateInfo));
51
52 VK_CHECK(m_vk.getPipelineKeyKHR(m_device, &pipelineCreateInfo, &pipelineKey));
53
54 return pipelineKey;
55 }
56
createPipelineBinariesFromPipeline(VkPipeline pipeline)57 VkResult PipelineBinaryWrapper::createPipelineBinariesFromPipeline(VkPipeline pipeline)
58 {
59 VkPipelineBinaryCreateInfoKHR pipelineBinaryCreateInfo = initVulkanStructure();
60 pipelineBinaryCreateInfo.pipeline = pipeline;
61
62 return createPipelineBinariesFromCreateInfo(pipelineBinaryCreateInfo);
63 }
64
createPipelineBinariesFromInternalCache(const void * pPipelineCreateInfo)65 VkResult PipelineBinaryWrapper::createPipelineBinariesFromInternalCache(const void *pPipelineCreateInfo)
66 {
67 VkPipelineCreateInfoKHR pipelineCreateInfo = initVulkanStructure();
68 pipelineCreateInfo.pNext = const_cast<void *>(pPipelineCreateInfo);
69
70 VkPipelineBinaryCreateInfoKHR pipelineBinaryCreateInfo = initVulkanStructure();
71 pipelineBinaryCreateInfo.pPipelineCreateInfo = &pipelineCreateInfo;
72
73 return createPipelineBinariesFromCreateInfo(pipelineBinaryCreateInfo);
74 }
75
createPipelineBinariesFromBinaryData(const std::vector<VkPipelineBinaryDataKHR> & pipelineDataInfo)76 VkResult PipelineBinaryWrapper::createPipelineBinariesFromBinaryData(
77 const std::vector<VkPipelineBinaryDataKHR> &pipelineDataInfo)
78 {
79 // for graphics pipeline libraries not all pipeline stages have to have binaries
80 std::size_t keyCount = m_binaryKeys.size();
81 if (keyCount == 0)
82 return VK_SUCCESS;
83
84 VkPipelineBinaryKeysAndDataKHR binaryKeysAndData{
85 (uint32_t)keyCount, // uint32_t binaryCount;
86 m_binaryKeys.data(), // const VkPipelineBinaryKeyKHR* pPipelineBinaryKeys;
87 pipelineDataInfo.data() // const VkPipelineBinaryDataKHR* pPipelineBinaryData;
88 };
89 VkPipelineBinaryCreateInfoKHR pipelineBinaryCreateInfo = initVulkanStructure();
90 pipelineBinaryCreateInfo.pKeysAndDataInfo = &binaryKeysAndData;
91
92 return createPipelineBinariesFromCreateInfo(pipelineBinaryCreateInfo);
93 }
94
createPipelineBinariesFromCreateInfo(const VkPipelineBinaryCreateInfoKHR & createInfos)95 VkResult PipelineBinaryWrapper::createPipelineBinariesFromCreateInfo(const VkPipelineBinaryCreateInfoKHR &createInfos)
96 {
97 // check how many binaries will be created
98 VkPipelineBinaryHandlesInfoKHR binaryHandlesInfo = initVulkanStructure();
99 VkResult result = m_vk.createPipelineBinariesKHR(m_device, &createInfos, NULL, &binaryHandlesInfo);
100 if (result != VK_SUCCESS)
101 return result;
102
103 // create pipeline binary objects
104 std::size_t binaryCount = binaryHandlesInfo.pipelineBinaryCount;
105 m_binariesRaw.resize(binaryCount);
106 binaryHandlesInfo.pPipelineBinaries = m_binariesRaw.data();
107 result = m_vk.createPipelineBinariesKHR(m_device, &createInfos, DE_NULL, &binaryHandlesInfo);
108 if (result != VK_SUCCESS)
109 return result;
110
111 // wrap pipeline binaries to movable references to avoid leaks
112 m_binaries.resize(binaryCount);
113 for (std::size_t i = 0; i < binaryCount; ++i)
114 m_binaries[i] = makeMovablePipelineBinary(m_vk, m_device, m_binariesRaw[i]);
115
116 return result;
117 }
118
getPipelineBinaryData(std::vector<VkPipelineBinaryDataKHR> & pipelineDataInfo,std::vector<std::vector<uint8_t>> & pipelineDataBlob)119 void PipelineBinaryWrapper::getPipelineBinaryData(std::vector<VkPipelineBinaryDataKHR> &pipelineDataInfo,
120 std::vector<std::vector<uint8_t>> &pipelineDataBlob)
121 {
122 // for graphics pipeline libraries not all pipeline stages have to have binaries
123 const std::size_t binaryCount = m_binariesRaw.size();
124 if (binaryCount == 0)
125 return;
126
127 m_binaryKeys.resize(binaryCount);
128 pipelineDataInfo.resize(binaryCount);
129 pipelineDataBlob.resize(binaryCount);
130
131 for (std::size_t i = 0; i < binaryCount; ++i)
132 {
133 VkPipelineBinaryDataInfoKHR binaryInfo = initVulkanStructure();
134 binaryInfo.pipelineBinary = m_binariesRaw[i];
135
136 // get binary key and data size
137 size_t binaryDataSize = 0;
138 m_binaryKeys[i] = initVulkanStructure();
139 VK_CHECK(m_vk.getPipelineBinaryDataKHR(m_device, &binaryInfo, &m_binaryKeys[i], &binaryDataSize, NULL));
140 DE_ASSERT(binaryDataSize > 0);
141
142 pipelineDataInfo[i].dataSize = binaryDataSize;
143 pipelineDataBlob[i].resize(binaryDataSize);
144 pipelineDataInfo[i].pData = pipelineDataBlob[i].data();
145
146 // get binary data
147 VK_CHECK(m_vk.getPipelineBinaryDataKHR(m_device, &binaryInfo, &m_binaryKeys[i], &binaryDataSize,
148 pipelineDataBlob[i].data()));
149 }
150 }
151
deletePipelineBinariesAndKeys(void)152 void PipelineBinaryWrapper::deletePipelineBinariesAndKeys(void)
153 {
154 m_binaryKeys.clear();
155 m_binaries.clear();
156 m_binariesRaw.clear();
157 }
158
deletePipelineBinariesKeepKeys(void)159 void PipelineBinaryWrapper::deletePipelineBinariesKeepKeys(void)
160 {
161 m_binaries.clear();
162 m_binariesRaw.clear();
163 }
164
preparePipelineBinaryInfo(void) const165 VkPipelineBinaryInfoKHR PipelineBinaryWrapper::preparePipelineBinaryInfo(void) const
166 {
167 const std::size_t binaryCount = m_binariesRaw.size();
168
169 return {
170 VK_STRUCTURE_TYPE_PIPELINE_BINARY_INFO_KHR, DE_NULL,
171 static_cast<uint32_t>(binaryCount), // uint32_t binaryCount;
172 de::dataOrNull(m_binariesRaw) // const VkPipelineBinaryKHR* pPipelineBinaries;
173 };
174 }
175
getKeyCount() const176 uint32_t PipelineBinaryWrapper::getKeyCount() const
177 {
178 return static_cast<uint32_t>(m_binaryKeys.size());
179 }
180
getBinariesCount() const181 uint32_t PipelineBinaryWrapper::getBinariesCount() const
182 {
183 return static_cast<uint32_t>(m_binariesRaw.size());
184 }
185
getBinaryKeys() const186 const VkPipelineBinaryKeyKHR *PipelineBinaryWrapper::getBinaryKeys() const
187 {
188 return m_binaryKeys.data();
189 }
190
getPipelineBinaries() const191 const VkPipelineBinaryKHR *PipelineBinaryWrapper::getPipelineBinaries() const
192 {
193 return m_binariesRaw.data();
194 }
195
196 } // namespace vk
197
198 #endif
199