1 #ifndef _VKRESOURCEINTERFACE_HPP
2 #define _VKRESOURCEINTERFACE_HPP
3 /*-------------------------------------------------------------------------
4 * Vulkan CTS Framework
5 * --------------------
6 *
7 * Copyright (c) 2021 The Khronos Group Inc.
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 *//*!
22 * \file
23 * \brief Defines class for handling resources ( programs, pipelines, files, etc. )
24 *//*--------------------------------------------------------------------*/
25
26 #include "vkDefs.hpp"
27 #include "tcuTestLog.hpp"
28 #include "tcuTestContext.hpp"
29 #include "vkPrograms.hpp"
30 #include "vkBinaryRegistry.hpp"
31 #include "deSharedPtr.hpp"
32 #include "deDefs.hpp"
33 #include <map>
34 #ifdef CTS_USES_VULKANSC
35 #include "vksClient.hpp"
36 #include "tcuMaybe.hpp"
37 // #include "vksStructsVKSC.hpp"
38 #endif // CTS_USES_VULKANSC
39
40 namespace vk
41 {
42
43 class ResourceInterface
44 {
45 public:
46 ResourceInterface(tcu::TestContext &testCtx);
47 virtual ~ResourceInterface();
48
49 virtual void initDevice(DeviceInterface &deviceInterface, VkDevice device) = 0;
50 // use deinitDevice when your DeviceDriverSC is created and removed inside TestInstance
51 virtual void deinitDevice(VkDevice device) = 0;
52
53 virtual void initTestCase(const std::string &casePath);
54 const std::string &getCasePath() const;
55
56 // buildProgram
57 template <typename InfoType, typename IteratorType>
58 vk::ProgramBinary *buildProgram(const std::string &casePath, IteratorType iter,
59 const vk::BinaryRegistryReader &prebuiltBinRegistry,
60 vk::BinaryCollection *progCollection);
61
62 #ifdef CTS_USES_VULKANSC
63 void initApiVersion(const uint32_t version);
64 bool isVulkanSC(void) const;
65
66 uint64_t incResourceCounter();
67 std::mutex &getStatMutex();
68 VkDeviceObjectReservationCreateInfo &getStatCurrent();
69 VkDeviceObjectReservationCreateInfo &getStatMax();
70 const VkDeviceObjectReservationCreateInfo &getStatMax() const;
71 void setHandleDestroy(bool value);
72 bool isEnabledHandleDestroy() const;
73
74 virtual void registerDeviceFeatures(VkDevice device, const VkDeviceCreateInfo *pCreateInfo) const = 0;
75 virtual void unregisterDeviceFeatures(VkDevice device) const = 0;
76 virtual VkResult createShaderModule(VkDevice device, const VkShaderModuleCreateInfo *pCreateInfo,
77 const VkAllocationCallbacks *pAllocator, VkShaderModule *pShaderModule,
78 bool normalMode) const = 0;
79 virtual VkResult createGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount,
80 const VkGraphicsPipelineCreateInfo *pCreateInfos,
81 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
82 bool normalMode) const = 0;
83 virtual VkResult createComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount,
84 const VkComputePipelineCreateInfo *pCreateInfos,
85 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
86 bool normalMode) const = 0;
87 virtual void destroyPipeline(VkDevice device, VkPipeline pipeline,
88 const VkAllocationCallbacks *pAllocator) const = 0;
89 virtual void createRenderPass(VkDevice device, const VkRenderPassCreateInfo *pCreateInfo,
90 const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass) const = 0;
91 virtual void createRenderPass2(VkDevice device, const VkRenderPassCreateInfo2 *pCreateInfo,
92 const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass) const = 0;
93 virtual void createPipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo,
94 const VkAllocationCallbacks *pAllocator,
95 VkPipelineLayout *pPipelineLayout) const = 0;
96 virtual void createDescriptorSetLayout(VkDevice device, const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
97 const VkAllocationCallbacks *pAllocator,
98 VkDescriptorSetLayout *pSetLayout) const = 0;
99 virtual void createSampler(VkDevice device, const VkSamplerCreateInfo *pCreateInfo,
100 const VkAllocationCallbacks *pAllocator, VkSampler *pSampler) const = 0;
101 virtual void createSamplerYcbcrConversion(VkDevice device, const VkSamplerYcbcrConversionCreateInfo *pCreateInfo,
102 const VkAllocationCallbacks *pAllocator,
103 VkSamplerYcbcrConversion *pYcbcrConversion) const = 0;
104 virtual void createCommandPool(VkDevice device, const VkCommandPoolCreateInfo *pCreateInfo,
105 const VkAllocationCallbacks *pAllocator, VkCommandPool *pCommandPool) const = 0;
106 virtual void allocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo *pAllocateInfo,
107 VkCommandBuffer *pCommandBuffers) const = 0;
108 virtual void increaseCommandBufferSize(VkCommandBuffer commandBuffer, VkDeviceSize commandSize) const = 0;
109 virtual void resetCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolResetFlags flags) const = 0;
110
111 void removeRedundantObjects();
112 void finalizeCommandBuffers();
113 std::vector<uint8_t> exportData() const;
114 void importData(std::vector<uint8_t> &importText) const;
115 virtual void importPipelineCacheData(const PlatformInterface &vkp, VkInstance instance,
116 const InstanceInterface &vki, VkPhysicalDevice physicalDevice,
117 uint32_t queueIndex) = 0;
118 void registerObjectHash(uint64_t handle, std::size_t hashValue) const;
119 const std::map<uint64_t, std::size_t> &getObjectHashes() const;
120
121 void preparePipelinePoolSizes();
122 std::vector<VkPipelinePoolSize> getPipelinePoolSizes() const;
123 void fillPoolEntrySize(vk::VkPipelineOfflineCreateInfo &pipelineIdentifier) const;
124 vksc_server::VulkanCommandMemoryConsumption getNextCommandPoolSize();
125 std::size_t getCacheDataSize() const;
126 const uint8_t *getCacheData() const;
127 VkPipelineCache getPipelineCache(VkDevice device) const;
128 virtual void resetObjects() = 0;
129 virtual void resetPipelineCaches() = 0;
130 #endif // CTS_USES_VULKANSC
131
132 protected:
133 virtual vk::ProgramBinary *compileProgram(const vk::ProgramIdentifier &progId, const vk::GlslSource &source,
134 glu::ShaderProgramInfo *buildInfo,
135 const tcu::CommandLine &commandLine) = 0;
136 virtual vk::ProgramBinary *compileProgram(const vk::ProgramIdentifier &progId, const vk::HlslSource &source,
137 glu::ShaderProgramInfo *buildInfo,
138 const tcu::CommandLine &commandLine) = 0;
139 virtual vk::ProgramBinary *compileProgram(const vk::ProgramIdentifier &progId, const vk::SpirVAsmSource &source,
140 vk::SpirVProgramInfo *buildInfo, const tcu::CommandLine &commandLine) = 0;
141
142 tcu::TestContext &m_testCtx;
143 std::string m_currentTestPath;
144
145 #ifdef CTS_USES_VULKANSC
146 mutable vksc_server::VulkanPipelineCacheInput m_pipelineInput;
147 mutable std::map<uint64_t, std::size_t> m_objectHashes;
148 mutable std::vector<vksc_server::VulkanCommandMemoryConsumption> m_commandPoolMemoryConsumption;
149 mutable uint32_t m_commandPoolIndex;
150 mutable std::map<VkCommandBuffer, vksc_server::VulkanCommandMemoryConsumption> m_commandBufferMemoryConsumption;
151 mutable std::map<VkDevice, std::string> m_deviceFeatures;
152 mutable std::map<VkDevice, std::vector<std::string>> m_deviceExtensions;
153
154 std::map<VkDevice, de::SharedPtr<Move<VkPipelineCache>>> m_pipelineCache;
155
156 mutable std::mutex m_mutex;
157 mutable uint64_t m_resourceCounter;
158 mutable VkDeviceObjectReservationCreateInfo m_statCurrent;
159 mutable VkDeviceObjectReservationCreateInfo m_statMax;
160
161 std::vector<uint8_t> m_cacheData;
162 mutable std::map<VkPipeline, VkPipelineOfflineCreateInfo> m_pipelineIdentifiers;
163 mutable std::vector<vksc_server::VulkanPipelineSize> m_pipelineSizes;
164 std::vector<VkPipelinePoolSize> m_pipelinePoolSizes;
165 tcu::Maybe<uint32_t> m_version;
166 tcu::Maybe<bool> m_vulkanSC;
167 bool m_enabledHandleDestroy;
168 #endif // CTS_USES_VULKANSC
169 };
170
171 typedef VKAPI_ATTR VkResult(VKAPI_CALL *CreateSamplerYcbcrConversionFunc)(
172 VkDevice device, const VkSamplerYcbcrConversionCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
173 VkSamplerYcbcrConversion *pYcbcrConversion);
174 typedef VKAPI_ATTR void(VKAPI_CALL *DestroySamplerYcbcrConversionFunc)(VkDevice device,
175 VkSamplerYcbcrConversion ycbcrConversion,
176 const VkAllocationCallbacks *pAllocator);
177 typedef VKAPI_ATTR VkResult(VKAPI_CALL *CreateSamplerFunc)(VkDevice device, const VkSamplerCreateInfo *pCreateInfo,
178 const VkAllocationCallbacks *pAllocator,
179 VkSampler *pSampler);
180 typedef VKAPI_ATTR void(VKAPI_CALL *DestroySamplerFunc)(VkDevice device, VkSampler sampler,
181 const VkAllocationCallbacks *pAllocator);
182 typedef VKAPI_ATTR VkResult(VKAPI_CALL *CreateShaderModuleFunc)(VkDevice device,
183 const VkShaderModuleCreateInfo *pCreateInfo,
184 const VkAllocationCallbacks *pAllocator,
185 VkShaderModule *pShaderModule);
186 typedef VKAPI_ATTR void(VKAPI_CALL *DestroyShaderModuleFunc)(VkDevice device, VkShaderModule shaderModule,
187 const VkAllocationCallbacks *pAllocator);
188 typedef VKAPI_ATTR VkResult(VKAPI_CALL *CreateRenderPassFunc)(VkDevice device,
189 const VkRenderPassCreateInfo *pCreateInfo,
190 const VkAllocationCallbacks *pAllocator,
191 VkRenderPass *pRenderPass);
192 typedef VKAPI_ATTR VkResult(VKAPI_CALL *CreateRenderPass2Func)(VkDevice device,
193 const VkRenderPassCreateInfo2 *pCreateInfo,
194 const VkAllocationCallbacks *pAllocator,
195 VkRenderPass *pRenderPass);
196 typedef VKAPI_ATTR void(VKAPI_CALL *DestroyRenderPassFunc)(VkDevice device, VkRenderPass renderPass,
197 const VkAllocationCallbacks *pAllocator);
198 typedef VKAPI_ATTR VkResult(VKAPI_CALL *CreateDescriptorSetLayoutFunc)(
199 VkDevice device, const VkDescriptorSetLayoutCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
200 VkDescriptorSetLayout *pSetLayout);
201 typedef VKAPI_ATTR void(VKAPI_CALL *DestroyDescriptorSetLayoutFunc)(VkDevice device,
202 VkDescriptorSetLayout descriptorSetLayout,
203 const VkAllocationCallbacks *pAllocator);
204 typedef VKAPI_ATTR VkResult(VKAPI_CALL *CreatePipelineLayoutFunc)(VkDevice device,
205 const VkPipelineLayoutCreateInfo *pCreateInfo,
206 const VkAllocationCallbacks *pAllocator,
207 VkPipelineLayout *pPipelineLayout);
208 typedef VKAPI_ATTR void(VKAPI_CALL *DestroyPipelineLayoutFunc)(VkDevice device, VkPipelineLayout pipelineLayout,
209 const VkAllocationCallbacks *pAllocator);
210 typedef VKAPI_ATTR VkResult(VKAPI_CALL *CreateGraphicsPipelinesFunc)(VkDevice device, VkPipelineCache pipelineCache,
211 uint32_t createInfoCount,
212 const VkGraphicsPipelineCreateInfo *pCreateInfos,
213 const VkAllocationCallbacks *pAllocator,
214 VkPipeline *pPipelines);
215 typedef VKAPI_ATTR VkResult(VKAPI_CALL *CreateComputePipelinesFunc)(VkDevice device, VkPipelineCache pipelineCache,
216 uint32_t createInfoCount,
217 const VkComputePipelineCreateInfo *pCreateInfos,
218 const VkAllocationCallbacks *pAllocator,
219 VkPipeline *pPipelines);
220 typedef VKAPI_ATTR void(VKAPI_CALL *DestroyPipelineFunc)(VkDevice device, VkPipeline pipeline,
221 const VkAllocationCallbacks *pAllocator);
222 typedef VKAPI_ATTR VkResult(VKAPI_CALL *CreatePipelineCacheFunc)(VkDevice device,
223 const VkPipelineCacheCreateInfo *pCreateInfo,
224 const VkAllocationCallbacks *pAllocator,
225 VkPipelineCache *pPipelineCache);
226 typedef VKAPI_ATTR void(VKAPI_CALL *DestroyPipelineCacheFunc)(VkDevice device, VkPipelineCache pipelineCache,
227 const VkAllocationCallbacks *pAllocator);
228 typedef VKAPI_ATTR VkResult(VKAPI_CALL *GetPipelineCacheDataFunc)(VkDevice device, VkPipelineCache pipelineCache,
229 uintptr_t *pDataSize, void *pData);
230 #ifdef CTS_USES_VULKANSC
231 typedef VKAPI_ATTR void(VKAPI_CALL *GetCommandPoolMemoryConsumptionFunc)(VkDevice device, VkCommandPool commandPool,
232 VkCommandBuffer commandBuffer,
233 VkCommandPoolMemoryConsumption *pConsumption);
234 #endif // CTS_USES_VULKANSC
235
236 class ResourceInterfaceStandard : public ResourceInterface
237 {
238 public:
239 ResourceInterfaceStandard(tcu::TestContext &testCtx);
240
241 void initDevice(DeviceInterface &deviceInterface, VkDevice device) override;
242 void deinitDevice(VkDevice device) override;
243
244 #ifdef CTS_USES_VULKANSC
245 void registerDeviceFeatures(VkDevice device, const VkDeviceCreateInfo *pCreateInfo) const override;
246 void unregisterDeviceFeatures(VkDevice device) const override;
247 VkResult createShaderModule(VkDevice device, const VkShaderModuleCreateInfo *pCreateInfo,
248 const VkAllocationCallbacks *pAllocator, VkShaderModule *pShaderModule,
249 bool normalMode) const override;
250 VkResult createGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount,
251 const VkGraphicsPipelineCreateInfo *pCreateInfos,
252 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
253 bool normalMode) const override;
254 VkResult createComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount,
255 const VkComputePipelineCreateInfo *pCreateInfos,
256 const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines,
257 bool normalMode) const override;
258 void destroyPipeline(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks *pAllocator) const override;
259 void createRenderPass(VkDevice device, const VkRenderPassCreateInfo *pCreateInfo,
260 const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass) const override;
261 void createRenderPass2(VkDevice device, const VkRenderPassCreateInfo2 *pCreateInfo,
262 const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass) const override;
263 void createPipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo,
264 const VkAllocationCallbacks *pAllocator,
265 VkPipelineLayout *pPipelineLayout) const override;
266 void createDescriptorSetLayout(VkDevice device, const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
267 const VkAllocationCallbacks *pAllocator,
268 VkDescriptorSetLayout *pSetLayout) const override;
269 void createSampler(VkDevice device, const VkSamplerCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
270 VkSampler *pSampler) const override;
271 void createSamplerYcbcrConversion(VkDevice device, const VkSamplerYcbcrConversionCreateInfo *pCreateInfo,
272 const VkAllocationCallbacks *pAllocator,
273 VkSamplerYcbcrConversion *pYcbcrConversion) const override;
274 void createCommandPool(VkDevice device, const VkCommandPoolCreateInfo *pCreateInfo,
275 const VkAllocationCallbacks *pAllocator, VkCommandPool *pCommandPool) const override;
276 void allocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo *pAllocateInfo,
277 VkCommandBuffer *pCommandBuffers) const override;
278 void increaseCommandBufferSize(VkCommandBuffer commandBuffer, VkDeviceSize commandSize) const override;
279 void resetCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolResetFlags flags) const override;
280 void importPipelineCacheData(const PlatformInterface &vkp, VkInstance instance, const InstanceInterface &vki,
281 VkPhysicalDevice physicalDevice, uint32_t queueIndex) override;
282 void resetObjects() override;
283 void resetPipelineCaches() override;
284 #endif // CTS_USES_VULKANSC
285
286 protected:
287 vk::ProgramBinary *compileProgram(const vk::ProgramIdentifier &progId, const vk::GlslSource &source,
288 glu::ShaderProgramInfo *buildInfo, const tcu::CommandLine &commandLine) override;
289 vk::ProgramBinary *compileProgram(const vk::ProgramIdentifier &progId, const vk::HlslSource &source,
290 glu::ShaderProgramInfo *buildInfo, const tcu::CommandLine &commandLine) override;
291 vk::ProgramBinary *compileProgram(const vk::ProgramIdentifier &progId, const vk::SpirVAsmSource &source,
292 vk::SpirVProgramInfo *buildInfo, const tcu::CommandLine &commandLine) override;
293
294 std::map<VkDevice, CreateShaderModuleFunc> m_createShaderModuleFunc;
295 std::map<VkDevice, CreateGraphicsPipelinesFunc> m_createGraphicsPipelinesFunc;
296 std::map<VkDevice, CreateComputePipelinesFunc> m_createComputePipelinesFunc;
297 };
298
299 #ifdef CTS_USES_VULKANSC
300
301 class ResourceInterfaceVKSC : public ResourceInterfaceStandard
302 {
303 public:
304 ResourceInterfaceVKSC(tcu::TestContext &testCtx);
305
306 VkResult createShaderModule(VkDevice device, const VkShaderModuleCreateInfo *pCreateInfo,
307 const VkAllocationCallbacks *pAllocator, VkShaderModule *pShaderModule,
308 bool normalMode) const override;
309
310 void importPipelineCacheData(const PlatformInterface &vkp, VkInstance instance, const InstanceInterface &vki,
311 VkPhysicalDevice physicalDevice, uint32_t queueIndex) override;
312
313 protected:
314 vk::ProgramBinary *compileProgram(const vk::ProgramIdentifier &progId, const vk::GlslSource &source,
315 glu::ShaderProgramInfo *buildInfo, const tcu::CommandLine &commandLine) override;
316 vk::ProgramBinary *compileProgram(const vk::ProgramIdentifier &progId, const vk::HlslSource &source,
317 glu::ShaderProgramInfo *buildInfo, const tcu::CommandLine &commandLine) override;
318 vk::ProgramBinary *compileProgram(const vk::ProgramIdentifier &progId, const vk::SpirVAsmSource &source,
319 vk::SpirVProgramInfo *buildInfo, const tcu::CommandLine &commandLine) override;
320
321 private:
322 vksc_server::Server *getServer();
323 bool noServer() const;
324
325 std::string m_address;
326 std::shared_ptr<vksc_server::Server> m_server;
327 };
328
329 class MultithreadedDestroyGuard
330 {
331 public:
332 MultithreadedDestroyGuard(de::SharedPtr<vk::ResourceInterface> resourceInterface);
333 ~MultithreadedDestroyGuard();
334
335 private:
336 de::SharedPtr<vk::ResourceInterface> m_resourceInterface;
337 };
338
339 #endif // CTS_USES_VULKANSC
340
341 template <typename InfoType, typename IteratorType>
buildProgram(const std::string & casePath,IteratorType iter,const vk::BinaryRegistryReader & prebuiltBinRegistry,vk::BinaryCollection * progCollection)342 vk::ProgramBinary *ResourceInterface::buildProgram(const std::string &casePath, IteratorType iter,
343 const vk::BinaryRegistryReader &prebuiltBinRegistry,
344 vk::BinaryCollection *progCollection)
345 {
346 const vk::ProgramIdentifier progId(casePath, iter.getName());
347 tcu::TestLog &log = m_testCtx.getLog();
348 const tcu::CommandLine &commandLine = m_testCtx.getCommandLine();
349 const tcu::ScopedLogSection progSection(log, iter.getName(), "Program: " + iter.getName());
350 de::MovePtr<vk::ProgramBinary> binProg;
351 InfoType buildInfo;
352
353 try
354 {
355 binProg = de::MovePtr<vk::ProgramBinary>(compileProgram(progId, iter.getProgram(), &buildInfo, commandLine));
356 log << buildInfo;
357 }
358 catch (const tcu::NotSupportedError &err)
359 {
360 // Try to load from cache
361 log << err << tcu::TestLog::Message << "Building from source not supported, loading stored binary instead"
362 << tcu::TestLog::EndMessage;
363
364 binProg = de::MovePtr<vk::ProgramBinary>(prebuiltBinRegistry.loadProgram(progId));
365
366 log << iter.getProgram();
367 }
368 catch (const tcu::Exception &)
369 {
370 // Build failed for other reason
371 log << buildInfo;
372 throw;
373 }
374
375 TCU_CHECK_INTERNAL(binProg);
376
377 {
378 vk::ProgramBinary *const returnBinary = binProg.get();
379
380 progCollection->add(progId.programName, binProg);
381
382 return returnBinary;
383 }
384 }
385
386 } // namespace vk
387
388 #endif // _VKRESOURCEINTERFACE_HPP
389