1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2016 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 Synchronization internally synchronized objects tests
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktSynchronizationInternallySynchronizedObjectsTests.hpp"
25 #include "vktTestCaseUtil.hpp"
26 #include "vktSynchronizationUtil.hpp"
27 #include "vktCustomInstancesDevices.hpp"
28
29 #include "vkRef.hpp"
30 #include "tcuDefs.hpp"
31 #include "vkTypeUtil.hpp"
32 #include "vkBarrierUtil.hpp"
33 #include "vkPlatform.hpp"
34 #include "vkBuilderUtil.hpp"
35 #include "vkImageUtil.hpp"
36 #include "vkCmdUtil.hpp"
37 #include "vkObjUtil.hpp"
38 #include "vkDeviceUtil.hpp"
39 #include "vkSafetyCriticalUtil.hpp"
40
41 #include "tcuResultCollector.hpp"
42 #include "tcuCommandLine.hpp"
43
44 #include "deThread.hpp"
45 #include "deMutex.hpp"
46 #include "deSharedPtr.hpp"
47 #include "deSpinBarrier.hpp"
48
49
50 #include <limits>
51 #include <iterator>
52
53 namespace vkt
54 {
55 namespace synchronization
56 {
57 namespace
58 {
59 using namespace vk;
60
61 using std::vector;
62 using std::string;
63 using std::map;
64 using std::exception;
65 using std::ostringstream;
66
67 using tcu::TestStatus;
68 using tcu::TestContext;
69 using tcu::ResultCollector;
70 using tcu::TestException;
71
72 using de::UniquePtr;
73 using de::MovePtr;
74 using de::SharedPtr;
75 using de::Mutex;
76 using de::Thread;
77 using de::clamp;
78
79 template<typename T>
makeVkSharedPtr(Move<T> move)80 inline SharedPtr<Move<T> > makeVkSharedPtr(Move<T> move)
81 {
82 return SharedPtr<Move<T> >(new Move<T>(move));
83 }
84
85 #ifndef CTS_USES_VULKANSC
86 enum
87 {
88 EXECUTION_PER_THREAD = 100,
89 BUFFER_ELEMENT_COUNT = 16,
90 BUFFER_SIZE = BUFFER_ELEMENT_COUNT*4
91 };
92 #else
93 enum
94 {
95 EXECUTION_PER_THREAD = 10,
96 BUFFER_ELEMENT_COUNT = 16,
97 BUFFER_SIZE = BUFFER_ELEMENT_COUNT*4
98 };
99 #endif // CTS_USES_VULKANSC
100
101 class MultiQueues
102 {
103 typedef struct QueueType
104 {
105 vector<VkQueue> queues;
106 vector<bool> available;
107 vector<SharedPtr<Move<VkCommandPool>>> commandPools;
108 } Queues;
109
110 public:
addQueueFamilyIndex(const deUint32 & queueFamilyIndex,const deUint32 & count)111 inline void addQueueFamilyIndex (const deUint32& queueFamilyIndex, const deUint32& count)
112 {
113 Queues temp;
114 vector<bool>::iterator it;
115 it = temp.available.begin();
116 temp.available.insert(it, count, false);
117
118 temp.queues.resize(count);
119
120 m_queues[queueFamilyIndex] = temp;
121 }
122
getQueueFamilyIndex(const int index) const123 deUint32 getQueueFamilyIndex (const int index) const
124 {
125 map<deUint32,Queues>::const_iterator it = begin(m_queues);
126 std::advance(it, index);
127 return it->first;
128 }
129
countQueueFamilyIndex(void)130 inline size_t countQueueFamilyIndex (void)
131 {
132 return m_queues.size();
133 }
134
getQueues(int index)135 Queues & getQueues (int index)
136 {
137 map<deUint32,Queues>::iterator it = m_queues.begin();
138 advance (it, index);
139 return it->second;
140 }
141
getFreeQueue(const DeviceInterface & vk,const VkDevice device,deUint32 & returnQueueFamilyIndex,VkQueue & returnQueues,Move<VkCommandBuffer> & commandBuffer,int & returnQueueIndex)142 bool getFreeQueue (const DeviceInterface& vk, const VkDevice device, deUint32& returnQueueFamilyIndex, VkQueue& returnQueues, Move<VkCommandBuffer>& commandBuffer, int& returnQueueIndex)
143 {
144 for (int queueFamilyIndexNdx = 0 ; queueFamilyIndexNdx < static_cast<int>(m_queues.size()); ++queueFamilyIndexNdx)
145 {
146 Queues& queue = m_queues[getQueueFamilyIndex(queueFamilyIndexNdx)];
147 for (int queueNdx = 0; queueNdx < static_cast<int>(queue.queues.size()); ++queueNdx)
148 {
149 m_mutex.lock();
150 if (queue.available[queueNdx])
151 {
152 queue.available[queueNdx] = false;
153 returnQueueFamilyIndex = getQueueFamilyIndex(queueFamilyIndexNdx);
154 returnQueues = queue.queues[queueNdx];
155 commandBuffer = makeCommandBuffer(vk, device, queue.commandPools[queueNdx]->get());
156 returnQueueIndex = queueNdx;
157 m_mutex.unlock();
158 return true;
159 }
160 m_mutex.unlock();
161 }
162 }
163 return false;
164 }
165
releaseQueue(const deUint32 & queueFamilyIndex,const int & queueIndex,Move<VkCommandBuffer> & commandBuffer)166 void releaseQueue (const deUint32& queueFamilyIndex, const int& queueIndex, Move<VkCommandBuffer>& commandBuffer)
167 {
168 m_mutex.lock();
169 commandBuffer = Move<VkCommandBuffer>();
170 m_queues[queueFamilyIndex].available[queueIndex] = true;
171 m_mutex.unlock();
172 }
173
setDevice(Move<VkDevice> device,const Context & context)174 inline void setDevice (Move<VkDevice> device, const Context& context)
175 {
176 m_logicalDevice = device;
177 #ifndef CTS_USES_VULKANSC
178 m_deviceDriver = de::MovePtr<DeviceDriver> (new DeviceDriver(context.getPlatformInterface(), context.getInstance(), *m_logicalDevice));
179 #else
180 m_deviceDriver = de::MovePtr<DeviceDriverSC, DeinitDeviceDeleter>(new DeviceDriverSC(context.getPlatformInterface(), context.getInstance(), *m_logicalDevice, context.getTestContext().getCommandLine(), context.getResourceInterface(), context.getDeviceVulkanSC10Properties(), context.getDeviceProperties()), vk::DeinitDeviceDeleter(context.getResourceInterface().get(), *m_logicalDevice));
181 #endif // CTS_USES_VULKANSC
182 }
183
getDevice(void)184 inline VkDevice getDevice (void)
185 {
186 return *m_logicalDevice;
187 }
188
getDeviceInterface(void)189 inline DeviceInterface& getDeviceInterface(void)
190 {
191 return *m_deviceDriver;
192 }
193
194 MovePtr<Allocator> m_allocator;
195 protected:
196 Move<VkDevice> m_logicalDevice;
197 #ifndef CTS_USES_VULKANSC
198 de::MovePtr<vk::DeviceDriver> m_deviceDriver;
199 #else
200 de::MovePtr<DeviceDriverSC, DeinitDeviceDeleter> m_deviceDriver;
201 #endif // CTS_USES_VULKANSC
202 map<deUint32,Queues> m_queues;
203 Mutex m_mutex;
204 };
205
createAllocator(const Context & context,const VkDevice & device)206 MovePtr<Allocator> createAllocator (const Context& context, const VkDevice& device)
207 {
208 const DeviceInterface& deviceInterface = context.getDeviceInterface();
209 const InstanceInterface& instance = context.getInstanceInterface();
210 const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
211 const VkPhysicalDeviceMemoryProperties deviceMemoryProperties = getPhysicalDeviceMemoryProperties(instance, physicalDevice);
212
213 // Create memory allocator for device
214 return MovePtr<Allocator> (new SimpleAllocator(deviceInterface, device, deviceMemoryProperties));
215 }
216
checkQueueFlags(const VkQueueFlags & availableFlag,const VkQueueFlags & neededFlag)217 bool checkQueueFlags (const VkQueueFlags& availableFlag, const VkQueueFlags& neededFlag)
218 {
219 if (VK_QUEUE_TRANSFER_BIT == neededFlag)
220 {
221 if ( (availableFlag & VK_QUEUE_GRAPHICS_BIT) == VK_QUEUE_GRAPHICS_BIT ||
222 (availableFlag & VK_QUEUE_COMPUTE_BIT) == VK_QUEUE_COMPUTE_BIT ||
223 (availableFlag & VK_QUEUE_TRANSFER_BIT) == VK_QUEUE_TRANSFER_BIT
224 )
225 return true;
226 }
227 else if ((availableFlag & neededFlag) == neededFlag)
228 {
229 return true;
230 }
231 return false;
232 }
233
createQueues(Context & context,const VkQueueFlags & queueFlag,const VkInstance & instance,const InstanceInterface & vki)234 MovePtr<MultiQueues> createQueues (Context& context, const VkQueueFlags& queueFlag, const VkInstance& instance, const InstanceInterface& vki)
235 {
236 const VkPhysicalDevice physicalDevice = chooseDevice(vki, instance, context.getTestContext().getCommandLine());
237 MovePtr<MultiQueues> moveQueues (new MultiQueues());
238 MultiQueues& queues = *moveQueues;
239 VkDeviceCreateInfo deviceInfo;
240 VkPhysicalDeviceFeatures deviceFeatures;
241 vector<VkQueueFamilyProperties> queueFamilyProperties;
242 vector<float> queuePriorities;
243 vector<VkDeviceQueueCreateInfo> queueInfos;
244
245 queueFamilyProperties = getPhysicalDeviceQueueFamilyProperties(vki, physicalDevice);
246
247 for (deUint32 queuePropertiesNdx = 0; queuePropertiesNdx < queueFamilyProperties.size(); ++queuePropertiesNdx)
248 {
249 if (checkQueueFlags(queueFamilyProperties[queuePropertiesNdx].queueFlags, queueFlag))
250 {
251 queues.addQueueFamilyIndex(queuePropertiesNdx, queueFamilyProperties[queuePropertiesNdx].queueCount);
252 }
253 }
254
255 if (queues.countQueueFamilyIndex() == 0)
256 {
257 TCU_THROW(NotSupportedError, "Queue not found");
258 }
259
260 {
261 vector<float>::iterator it = queuePriorities.begin();
262 unsigned int maxQueueCount = 0;
263 for (int queueFamilyIndexNdx = 0; queueFamilyIndexNdx < static_cast<int>(queues.countQueueFamilyIndex()); ++queueFamilyIndexNdx)
264 {
265 if (queues.getQueues(queueFamilyIndexNdx).queues.size() > maxQueueCount)
266 maxQueueCount = static_cast<unsigned int>(queues.getQueues(queueFamilyIndexNdx).queues.size());
267 }
268 queuePriorities.insert(it, maxQueueCount, 1.0);
269 }
270
271 for (int queueFamilyIndexNdx = 0; queueFamilyIndexNdx < static_cast<int>(queues.countQueueFamilyIndex()); ++queueFamilyIndexNdx)
272 {
273 VkDeviceQueueCreateInfo queueInfo;
274 const deUint32 queueCount = static_cast<deUint32>(queues.getQueues(queueFamilyIndexNdx).queues.size());
275
276 deMemset(&queueInfo, 0, sizeof(queueInfo));
277
278 queueInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
279 queueInfo.pNext = DE_NULL;
280 queueInfo.flags = (VkDeviceQueueCreateFlags)0u;
281 queueInfo.queueFamilyIndex = queues.getQueueFamilyIndex(queueFamilyIndexNdx);
282 queueInfo.queueCount = queueCount;
283 queueInfo.pQueuePriorities = &queuePriorities[0];
284
285 queueInfos.push_back(queueInfo);
286 }
287
288 deMemset(&deviceInfo, 0, sizeof(deviceInfo));
289 vki.getPhysicalDeviceFeatures(physicalDevice, &deviceFeatures);
290
291 void* pNext = DE_NULL;
292 #ifdef CTS_USES_VULKANSC
293 VkDeviceObjectReservationCreateInfo memReservationInfo = context.getTestContext().getCommandLine().isSubProcess() ? context.getResourceInterface()->getStatMax() : resetDeviceObjectReservationCreateInfo();
294 memReservationInfo.pNext = pNext;
295 pNext = &memReservationInfo;
296
297 VkPhysicalDeviceVulkanSC10Features sc10Features = createDefaultSC10Features();
298 sc10Features.pNext = pNext;
299 pNext = &sc10Features;
300
301 VkPipelineCacheCreateInfo pcCI;
302 std::vector<VkPipelinePoolSize> poolSizes;
303 if (context.getTestContext().getCommandLine().isSubProcess())
304 {
305 if (context.getResourceInterface()->getCacheDataSize() > 0)
306 {
307 pcCI =
308 {
309 VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO, // VkStructureType sType;
310 DE_NULL, // const void* pNext;
311 VK_PIPELINE_CACHE_CREATE_READ_ONLY_BIT |
312 VK_PIPELINE_CACHE_CREATE_USE_APPLICATION_STORAGE_BIT, // VkPipelineCacheCreateFlags flags;
313 context.getResourceInterface()->getCacheDataSize(), // deUintptr initialDataSize;
314 context.getResourceInterface()->getCacheData() // const void* pInitialData;
315 };
316 memReservationInfo.pipelineCacheCreateInfoCount = 1;
317 memReservationInfo.pPipelineCacheCreateInfos = &pcCI;
318 }
319
320 poolSizes = context.getResourceInterface()->getPipelinePoolSizes();
321 if (!poolSizes.empty())
322 {
323 memReservationInfo.pipelinePoolSizeCount = deUint32(poolSizes.size());
324 memReservationInfo.pPipelinePoolSizes = poolSizes.data();
325 }
326 }
327 #endif // CTS_USES_VULKANSC
328
329 deviceInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
330 deviceInfo.pNext = pNext;
331 deviceInfo.enabledExtensionCount = 0u;
332 deviceInfo.ppEnabledExtensionNames = DE_NULL;
333 deviceInfo.enabledLayerCount = 0u;
334 deviceInfo.ppEnabledLayerNames = DE_NULL;
335 deviceInfo.pEnabledFeatures = &deviceFeatures;
336 deviceInfo.queueCreateInfoCount = static_cast<deUint32>(queues.countQueueFamilyIndex());
337 deviceInfo.pQueueCreateInfos = &queueInfos[0];
338
339 queues.setDevice(createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), context.getPlatformInterface(), instance, vki, physicalDevice, &deviceInfo), context);
340 vk::DeviceInterface& vk = queues.getDeviceInterface();
341
342 for (deUint32 queueFamilyIndex = 0; queueFamilyIndex < queues.countQueueFamilyIndex(); ++queueFamilyIndex)
343 {
344 for (deUint32 queueReqNdx = 0; queueReqNdx < queues.getQueues(queueFamilyIndex).queues.size(); ++queueReqNdx)
345 {
346 vk.getDeviceQueue(queues.getDevice(), queues.getQueueFamilyIndex(queueFamilyIndex), queueReqNdx, &queues.getQueues(queueFamilyIndex).queues[queueReqNdx]);
347 queues.getQueues(queueFamilyIndex).available[queueReqNdx]=true;
348 queues.getQueues(queueFamilyIndex).commandPools.push_back(makeVkSharedPtr(createCommandPool(vk, queues.getDevice(), VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queues.getQueueFamilyIndex(queueFamilyIndex))));
349 }
350 }
351
352 queues.m_allocator = createAllocator(context, queues.getDevice());
353 return moveQueues;
354 }
355
executeComputePipeline(const Context & context,const VkPipeline & pipeline,const VkPipelineLayout & pipelineLayout,const VkDescriptorSetLayout & descriptorSetLayout,MultiQueues & queues,const deUint32 & shadersExecutions)356 TestStatus executeComputePipeline (const Context& context, const VkPipeline& pipeline, const VkPipelineLayout& pipelineLayout,
357 const VkDescriptorSetLayout& descriptorSetLayout, MultiQueues& queues, const deUint32& shadersExecutions)
358 {
359 DE_UNREF(context);
360 const DeviceInterface& vk = queues.getDeviceInterface();
361 const VkDevice device = queues.getDevice();
362 deUint32 queueFamilyIndex;
363 VkQueue queue;
364 int queueIndex;
365 Move<VkCommandBuffer> cmdBuffer;
366 while(!queues.getFreeQueue(vk, device, queueFamilyIndex, queue, cmdBuffer, queueIndex)){}
367
368 {
369 const Unique<VkDescriptorPool> descriptorPool (DescriptorPoolBuilder()
370 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
371 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
372 Buffer resultBuffer (vk, device, *queues.m_allocator, makeBufferCreateInfo(BUFFER_SIZE, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), MemoryRequirement::HostVisible);
373 const VkBufferMemoryBarrier bufferBarrier = makeBufferMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *resultBuffer, 0ull, BUFFER_SIZE);
374
375 {
376 const Allocation& alloc = resultBuffer.getAllocation();
377 deMemset(alloc.getHostPtr(), 0, BUFFER_SIZE);
378 flushAlloc(vk, device, alloc);
379 }
380
381 // Start recording commands
382 beginCommandBuffer(vk, *cmdBuffer);
383
384 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline);
385
386 // Create descriptor set
387 const Unique<VkDescriptorSet> descriptorSet(makeDescriptorSet(vk, device, *descriptorPool, descriptorSetLayout));
388
389 const VkDescriptorBufferInfo resultDescriptorInfo = makeDescriptorBufferInfo(*resultBuffer, 0ull, BUFFER_SIZE);
390
391 DescriptorSetUpdateBuilder()
392 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultDescriptorInfo)
393 .update(vk, device);
394
395 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
396
397 // Dispatch indirect compute command
398 vk.cmdDispatch(*cmdBuffer, shadersExecutions, 1u, 1u);
399
400 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0,
401 0, (const VkMemoryBarrier*)DE_NULL,
402 1, &bufferBarrier,
403 0, (const VkImageMemoryBarrier*)DE_NULL);
404
405 // End recording commands
406 endCommandBuffer(vk, *cmdBuffer);
407
408 // Wait for command buffer execution finish
409 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
410 queues.releaseQueue(queueFamilyIndex, queueIndex, cmdBuffer);
411
412 {
413 const Allocation& resultAlloc = resultBuffer.getAllocation();
414 invalidateAlloc(vk, device, resultAlloc);
415
416 const deInt32* ptr = reinterpret_cast<deInt32*>(resultAlloc.getHostPtr());
417 for (deInt32 ndx = 0; ndx < BUFFER_ELEMENT_COUNT; ++ndx)
418 {
419 if (ptr[ndx] != ndx)
420 {
421 return TestStatus::fail("The data don't match");
422 }
423 }
424 }
425 return TestStatus::pass("Passed");
426 }
427 }
428
429
executeGraphicPipeline(const Context & context,const VkPipeline & pipeline,const VkPipelineLayout & pipelineLayout,const VkDescriptorSetLayout & descriptorSetLayout,MultiQueues & queues,const VkRenderPass & renderPass,const deUint32 shadersExecutions)430 TestStatus executeGraphicPipeline (const Context& context, const VkPipeline& pipeline, const VkPipelineLayout& pipelineLayout,
431 const VkDescriptorSetLayout& descriptorSetLayout, MultiQueues& queues, const VkRenderPass& renderPass, const deUint32 shadersExecutions)
432 {
433 DE_UNREF(context);
434 const DeviceInterface& vk = queues.getDeviceInterface();
435 const VkDevice device = queues.getDevice();
436 deUint32 queueFamilyIndex;
437 VkQueue queue;
438 int queueIndex;
439 Move<VkCommandBuffer> cmdBuffer;
440 while (!queues.getFreeQueue(vk, device, queueFamilyIndex, queue, cmdBuffer, queueIndex)) {}
441
442 {
443 const Unique<VkDescriptorPool> descriptorPool (DescriptorPoolBuilder()
444 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
445 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
446 Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vk, device, *descriptorPool, descriptorSetLayout);
447 Buffer resultBuffer (vk, device, *queues.m_allocator, makeBufferCreateInfo(BUFFER_SIZE, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), MemoryRequirement::HostVisible);
448 const VkBufferMemoryBarrier bufferBarrier = makeBufferMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *resultBuffer, 0ull, BUFFER_SIZE);
449 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
450 const VkExtent3D colorImageExtent = makeExtent3D(1u, 1u, 1u);
451 const VkImageSubresourceRange colorImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
452 de::MovePtr<Image> colorAttachmentImage = de::MovePtr<Image>(new Image(vk, device, *queues.m_allocator,
453 makeImageCreateInfo(VK_IMAGE_TYPE_2D, colorImageExtent, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL),
454 MemoryRequirement::Any));
455 Move<VkImageView> colorAttachmentView = makeImageView(vk, device, **colorAttachmentImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorImageSubresourceRange);
456 Move<VkFramebuffer> framebuffer = makeFramebuffer(vk, device, renderPass, *colorAttachmentView, colorImageExtent.width, colorImageExtent.height);
457 const VkDescriptorBufferInfo outputBufferDescriptorInfo = makeDescriptorBufferInfo(*resultBuffer, 0ull, BUFFER_SIZE);
458
459 DescriptorSetUpdateBuilder()
460 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &outputBufferDescriptorInfo)
461 .update (vk, device);
462
463 {
464 const Allocation& alloc = resultBuffer.getAllocation();
465 deMemset(alloc.getHostPtr(), 0, BUFFER_SIZE);
466 flushAlloc(vk, device, alloc);
467 }
468
469 // Start recording commands
470 beginCommandBuffer(vk, *cmdBuffer);
471 // Change color attachment image layout
472 {
473 const VkImageMemoryBarrier colorAttachmentLayoutBarrier = makeImageMemoryBarrier(
474 (VkAccessFlags)0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
475 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
476 **colorAttachmentImage, colorImageSubresourceRange);
477
478 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (VkDependencyFlags)0,
479 0u, DE_NULL, 0u, DE_NULL, 1u, &colorAttachmentLayoutBarrier);
480 }
481
482 {
483 const VkRect2D renderArea = makeRect2D(1u, 1u);
484 const tcu::Vec4 clearColor = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
485 beginRenderPass(vk, *cmdBuffer, renderPass, *framebuffer, renderArea, clearColor);
486 }
487
488 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
489 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
490
491 vk.cmdDraw(*cmdBuffer, shadersExecutions, 1u, 0u, 0u);
492 endRenderPass(vk, *cmdBuffer);
493
494 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0,
495 0, (const VkMemoryBarrier*)DE_NULL,
496 1, &bufferBarrier,
497 0, (const VkImageMemoryBarrier*)DE_NULL);
498
499 // End recording commands
500 endCommandBuffer(vk, *cmdBuffer);
501
502 // Wait for command buffer execution finish
503 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
504 queues.releaseQueue(queueFamilyIndex, queueIndex, cmdBuffer);
505
506 {
507 const Allocation& resultAlloc = resultBuffer.getAllocation();
508 invalidateAlloc(vk, device, resultAlloc);
509
510 const deInt32* ptr = reinterpret_cast<deInt32*>(resultAlloc.getHostPtr());
511 for (deInt32 ndx = 0; ndx < BUFFER_ELEMENT_COUNT; ++ndx)
512 {
513 if (ptr[ndx] != ndx)
514 {
515 return TestStatus::fail("The data don't match");
516 }
517 }
518 }
519 return TestStatus::pass("Passed");
520 }
521 }
522
523 class ThreadGroupThread : private Thread
524 {
525 public:
ThreadGroupThread(const Context & context,VkPipelineCache pipelineCache,const VkPipelineLayout & pipelineLayout,const VkDescriptorSetLayout & descriptorSetLayout,MultiQueues & queues,const vector<deUint32> & shadersExecutions)526 ThreadGroupThread (const Context& context, VkPipelineCache pipelineCache, const VkPipelineLayout& pipelineLayout,
527 const VkDescriptorSetLayout& descriptorSetLayout, MultiQueues& queues, const vector<deUint32>& shadersExecutions)
528 : m_context (context)
529 , m_pipelineCache (pipelineCache)
530 , m_pipelineLayout (pipelineLayout)
531 , m_descriptorSetLayout (descriptorSetLayout)
532 , m_queues (queues)
533 , m_shadersExecutions (shadersExecutions)
534 , m_barrier (DE_NULL)
535 {
536 }
537
~ThreadGroupThread(void)538 virtual ~ThreadGroupThread (void)
539 {
540 }
541
getResultCollector(void)542 ResultCollector& getResultCollector (void)
543 {
544 return m_resultCollector;
545 }
546
547 void start (de::SpinBarrier* groupBarrier);
548 using Thread::join;
549
550 protected:
551 virtual TestStatus runThread () = 0;
552 const Context& m_context;
553 VkPipelineCache m_pipelineCache;
554 const VkPipelineLayout& m_pipelineLayout;
555 const VkDescriptorSetLayout& m_descriptorSetLayout;
556 MultiQueues& m_queues;
557 const vector<deUint32>& m_shadersExecutions;
558
559 void barrier (void);
560
561 private:
562 ThreadGroupThread (const ThreadGroupThread&);
563 ThreadGroupThread& operator= (const ThreadGroupThread&);
564
run(void)565 void run (void)
566 {
567 try
568 {
569 TestStatus result = runThread();
570 m_resultCollector.addResult(result.getCode(), result.getDescription());
571 }
572 catch (const TestException& e)
573 {
574 m_resultCollector.addResult(e.getTestResult(), e.getMessage());
575 }
576 catch (const exception& e)
577 {
578 m_resultCollector.addResult(QP_TEST_RESULT_FAIL, e.what());
579 }
580 catch (...)
581 {
582 m_resultCollector.addResult(QP_TEST_RESULT_FAIL, "Exception");
583 }
584
585 m_barrier->removeThread(de::SpinBarrier::WAIT_MODE_AUTO);
586 }
587
588 ResultCollector m_resultCollector;
589 de::SpinBarrier* m_barrier;
590 };
591
start(de::SpinBarrier * groupBarrier)592 void ThreadGroupThread::start (de::SpinBarrier* groupBarrier)
593 {
594 m_barrier = groupBarrier;
595 de::Thread::start();
596 }
597
barrier(void)598 inline void ThreadGroupThread::barrier (void)
599 {
600 m_barrier->sync(de::SpinBarrier::WAIT_MODE_AUTO);
601 }
602
603 class ThreadGroup
604 {
605 typedef vector<SharedPtr<ThreadGroupThread> > ThreadVector;
606 public:
ThreadGroup(void)607 ThreadGroup (void)
608 : m_barrier(1)
609 {
610 }
~ThreadGroup(void)611 ~ThreadGroup (void)
612 {
613 }
614
add(MovePtr<ThreadGroupThread> thread)615 void add (MovePtr<ThreadGroupThread> thread)
616 {
617 m_threads.push_back(SharedPtr<ThreadGroupThread>(thread.release()));
618 }
619
run(void)620 TestStatus run (void)
621 {
622 ResultCollector resultCollector;
623
624 m_barrier.reset((int)m_threads.size());
625
626 for (ThreadVector::iterator threadIter = m_threads.begin(); threadIter != m_threads.end(); ++threadIter)
627 (*threadIter)->start(&m_barrier);
628
629 for (ThreadVector::iterator threadIter = m_threads.begin(); threadIter != m_threads.end(); ++threadIter)
630 {
631 ResultCollector& threadResult = (*threadIter)->getResultCollector();
632 (*threadIter)->join();
633 resultCollector.addResult(threadResult.getResult(), threadResult.getMessage());
634 }
635
636 return TestStatus(resultCollector.getResult(), resultCollector.getMessage());
637 }
638
639 private:
640 ThreadVector m_threads;
641 de::SpinBarrier m_barrier;
642 };
643
644
645 class CreateComputeThread : public ThreadGroupThread
646 {
647 public:
CreateComputeThread(const Context & context,VkPipelineCache pipelineCache,vector<VkComputePipelineCreateInfo> & pipelineInfo,const VkPipelineLayout & pipelineLayout,const VkDescriptorSetLayout & descriptorSetLayout,MultiQueues & queues,const vector<deUint32> & shadersExecutions)648 CreateComputeThread (const Context& context, VkPipelineCache pipelineCache, vector<VkComputePipelineCreateInfo>& pipelineInfo,
649 const VkPipelineLayout& pipelineLayout, const VkDescriptorSetLayout& descriptorSetLayout,
650 MultiQueues& queues, const vector<deUint32>& shadersExecutions)
651 : ThreadGroupThread (context, pipelineCache, pipelineLayout, descriptorSetLayout, queues, shadersExecutions)
652 , m_pipelineInfo (pipelineInfo)
653 {
654 }
655
runThread(void)656 TestStatus runThread (void)
657 {
658 ResultCollector resultCollector;
659 for (int executionNdx = 0; executionNdx < EXECUTION_PER_THREAD; ++executionNdx)
660 {
661 const int shaderNdx = executionNdx % (int)m_pipelineInfo.size();
662 const DeviceInterface& vk = m_context.getDeviceInterface();
663 const VkDevice device = m_queues.getDevice();
664 Move<VkPipeline> pipeline = createComputePipeline(vk,device,m_pipelineCache, &m_pipelineInfo[shaderNdx]);
665
666 TestStatus result = executeComputePipeline(m_context, *pipeline, m_pipelineLayout, m_descriptorSetLayout, m_queues, m_shadersExecutions[shaderNdx]);
667
668 #ifdef CTS_USES_VULKANSC
669 // While collecting pipelines, synchronize between all threads for each pipeline that gets
670 // created, so we will reserve the maximum amount of pipeline pool space that could need.
671 if (!m_context.getTestContext().getCommandLine().isSubProcess()) {
672 barrier();
673 }
674 #endif
675
676 resultCollector.addResult(result.getCode(), result.getDescription());
677 }
678 return TestStatus(resultCollector.getResult(), resultCollector.getMessage());
679 }
680 private:
681 vector<VkComputePipelineCreateInfo>& m_pipelineInfo;
682 };
683
684 class CreateGraphicThread : public ThreadGroupThread
685 {
686 public:
CreateGraphicThread(const Context & context,VkPipelineCache pipelineCache,vector<VkGraphicsPipelineCreateInfo> & pipelineInfo,const VkPipelineLayout & pipelineLayout,const VkDescriptorSetLayout & descriptorSetLayout,MultiQueues & queues,const VkRenderPass & renderPass,const vector<deUint32> & shadersExecutions)687 CreateGraphicThread (const Context& context, VkPipelineCache pipelineCache, vector<VkGraphicsPipelineCreateInfo>& pipelineInfo,
688 const VkPipelineLayout& pipelineLayout, const VkDescriptorSetLayout& descriptorSetLayout,
689 MultiQueues& queues, const VkRenderPass& renderPass, const vector<deUint32>& shadersExecutions)
690 : ThreadGroupThread (context, pipelineCache, pipelineLayout, descriptorSetLayout, queues, shadersExecutions)
691 , m_pipelineInfo (pipelineInfo)
692 , m_renderPass (renderPass)
693 {}
694
runThread(void)695 TestStatus runThread (void)
696 {
697 ResultCollector resultCollector;
698 for (int executionNdx = 0; executionNdx < EXECUTION_PER_THREAD; ++executionNdx)
699 {
700 const int shaderNdx = executionNdx % (int)m_pipelineInfo.size();
701 const DeviceInterface& vk = m_context.getDeviceInterface();
702 const VkDevice device = m_queues.getDevice();
703 Move<VkPipeline> pipeline = createGraphicsPipeline(vk,device, m_pipelineCache, &m_pipelineInfo[shaderNdx]);
704
705 TestStatus result = executeGraphicPipeline(m_context, *pipeline, m_pipelineLayout, m_descriptorSetLayout, m_queues, m_renderPass, m_shadersExecutions[shaderNdx]);
706
707 #ifdef CTS_USES_VULKANSC
708 // While collecting pipelines, synchronize between all threads for each pipeline that gets
709 // created, so we will reserve the maximum amount of pipeline pool space that could need.
710 if (!m_context.getTestContext().getCommandLine().isSubProcess()) {
711 barrier();
712 }
713 #endif
714
715 resultCollector.addResult(result.getCode(), result.getDescription());
716 }
717 return TestStatus(resultCollector.getResult(), resultCollector.getMessage());
718 }
719
720 private:
721 vector<VkGraphicsPipelineCreateInfo>& m_pipelineInfo;
722 const VkRenderPass& m_renderPass;
723 };
724
725 class PipelineCacheComputeTestInstance : public TestInstance
726 {
727 typedef vector<SharedPtr<Unique<VkShaderModule> > > ShaderModuleVector;
728 public:
PipelineCacheComputeTestInstance(Context & context,const vector<deUint32> & shadersExecutions)729 PipelineCacheComputeTestInstance (Context& context, const vector<deUint32>& shadersExecutions)
730 : TestInstance (context)
731 , m_shadersExecutions (shadersExecutions)
732
733 {
734 }
735
iterate(void)736 TestStatus iterate (void)
737 {
738 #ifdef CTS_USES_VULKANSC
739 MultithreadedDestroyGuard mdGuard (m_context.getResourceInterface());
740 #endif // CTS_USES_VULKANSC
741 const CustomInstance instance (createCustomInstanceFromContext(m_context));
742 const InstanceDriver& instanceDriver (instance.getDriver());
743
744 MovePtr<MultiQueues> queues = createQueues(m_context, VK_QUEUE_COMPUTE_BIT, instance, instanceDriver);
745 const DeviceInterface& vk = queues->getDeviceInterface();
746 const VkDevice device = queues->getDevice();
747 ShaderModuleVector shaderCompModules = addShaderModules(device);
748 Buffer resultBuffer (vk, device, *queues->m_allocator, makeBufferCreateInfo(BUFFER_SIZE, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), MemoryRequirement::HostVisible);
749 const Move<VkDescriptorSetLayout> descriptorSetLayout (DescriptorSetLayoutBuilder()
750 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
751 .build(vk, device));
752 const Move<VkPipelineLayout> pipelineLayout (makePipelineLayout(vk, device, *descriptorSetLayout));
753 vector<VkPipelineShaderStageCreateInfo> shaderStageInfos = addShaderStageInfo(shaderCompModules);
754 vector<VkComputePipelineCreateInfo> pipelineInfo = addPipelineInfo(*pipelineLayout, shaderStageInfos);
755 const VkPipelineCacheCreateInfo pipelineCacheInfo =
756 {
757 VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO, // VkStructureType sType;
758 DE_NULL, // const void* pNext;
759 #ifndef CTS_USES_VULKANSC
760 0u, // VkPipelineCacheCreateFlags flags;
761 0u, // deUintptr initialDataSize;
762 DE_NULL, // const void* pInitialData;
763 #else
764 VK_PIPELINE_CACHE_CREATE_READ_ONLY_BIT |
765 VK_PIPELINE_CACHE_CREATE_USE_APPLICATION_STORAGE_BIT, // VkPipelineCacheCreateFlags flags;
766 m_context.getResourceInterface()->getCacheDataSize(), // deUintptr initialDataSize;
767 m_context.getResourceInterface()->getCacheData() // const void* pInitialData;
768 #endif // CTS_USES_VULKANSC
769 };
770 Move<VkPipelineCache> pipelineCache = createPipelineCache(vk, device, &pipelineCacheInfo);
771 Move<VkPipeline> pipeline = createComputePipeline(vk, device, *pipelineCache, &pipelineInfo[0]);
772 #ifndef CTS_USES_VULKANSC
773 const deUint32 numThreads = clamp(deGetNumAvailableLogicalCores(), 4u, 32u);
774 #else
775 const deUint32 numThreads = 2u;
776 #endif // CTS_USES_VULKANSC
777 ThreadGroup threads;
778
779 executeComputePipeline(m_context, *pipeline, *pipelineLayout, *descriptorSetLayout, *queues, m_shadersExecutions[0]);
780
781 for (deUint32 ndx = 0; ndx < numThreads; ++ndx)
782 threads.add(MovePtr<ThreadGroupThread>(new CreateComputeThread(
783 m_context, *pipelineCache, pipelineInfo, *pipelineLayout, *descriptorSetLayout, *queues, m_shadersExecutions)));
784
785 {
786 TestStatus thread_result = threads.run();
787 if(thread_result.getCode())
788 {
789 return thread_result;
790 }
791 }
792 return TestStatus::pass("Passed");
793 }
794
795 private:
addShaderModules(const VkDevice & device)796 ShaderModuleVector addShaderModules (const VkDevice& device)
797 {
798 const DeviceInterface& vk = m_context.getDeviceInterface();
799 ShaderModuleVector shaderCompModules;
800 shaderCompModules.resize(m_shadersExecutions.size());
801 for (int shaderNdx = 0; shaderNdx < static_cast<int>(m_shadersExecutions.size()); ++shaderNdx)
802 {
803 ostringstream shaderName;
804 shaderName<<"compute_"<<shaderNdx;
805 shaderCompModules[shaderNdx] = SharedPtr<Unique<VkShaderModule> > (new Unique<VkShaderModule>(createShaderModule(vk, device, m_context.getBinaryCollection().get(shaderName.str()), (VkShaderModuleCreateFlags)0)));
806 }
807 return shaderCompModules;
808 }
809
addShaderStageInfo(const ShaderModuleVector & shaderCompModules)810 vector<VkPipelineShaderStageCreateInfo> addShaderStageInfo (const ShaderModuleVector& shaderCompModules)
811 {
812 VkPipelineShaderStageCreateInfo shaderStageInfo;
813 vector<VkPipelineShaderStageCreateInfo> shaderStageInfos;
814 shaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
815 shaderStageInfo.pNext = DE_NULL;
816 shaderStageInfo.flags = (VkPipelineShaderStageCreateFlags)0;
817 shaderStageInfo.stage = VK_SHADER_STAGE_COMPUTE_BIT;
818 shaderStageInfo.pName = "main";
819 shaderStageInfo.pSpecializationInfo = DE_NULL;
820
821 for (int shaderNdx = 0; shaderNdx < static_cast<int>(m_shadersExecutions.size()); ++shaderNdx)
822 {
823 shaderStageInfo.module = *(*shaderCompModules[shaderNdx]);
824 shaderStageInfos.push_back(shaderStageInfo);
825 }
826 return shaderStageInfos;
827 }
828
addPipelineInfo(VkPipelineLayout pipelineLayout,const vector<VkPipelineShaderStageCreateInfo> & shaderStageInfos)829 vector<VkComputePipelineCreateInfo> addPipelineInfo (VkPipelineLayout pipelineLayout, const vector<VkPipelineShaderStageCreateInfo>& shaderStageInfos)
830 {
831 vector<VkComputePipelineCreateInfo> pipelineInfos;
832 VkComputePipelineCreateInfo computePipelineInfo;
833 computePipelineInfo.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
834 computePipelineInfo.pNext = DE_NULL;
835 computePipelineInfo.flags = (VkPipelineCreateFlags)0;
836 computePipelineInfo.layout = pipelineLayout;
837 computePipelineInfo.basePipelineHandle = DE_NULL;
838 computePipelineInfo.basePipelineIndex = 0;
839
840 for (int shaderNdx = 0; shaderNdx < static_cast<int>(m_shadersExecutions.size()); ++shaderNdx)
841 {
842 computePipelineInfo.stage = shaderStageInfos[shaderNdx];
843 pipelineInfos.push_back(computePipelineInfo);
844 }
845 return pipelineInfos;
846 }
847
848 const vector<deUint32> m_shadersExecutions;
849 };
850
851 class PipelineCacheGraphicTestInstance : public TestInstance
852 {
853 typedef vector<SharedPtr<Unique<VkShaderModule> > > ShaderModuleVector;
854 public:
PipelineCacheGraphicTestInstance(Context & context,const vector<deUint32> & shadersExecutions)855 PipelineCacheGraphicTestInstance (Context& context, const vector<deUint32>& shadersExecutions)
856 : TestInstance (context)
857 , m_shadersExecutions (shadersExecutions)
858
859 {
860 }
861
iterate(void)862 TestStatus iterate (void)
863 {
864 #ifdef CTS_USES_VULKANSC
865 MultithreadedDestroyGuard mdGuard (m_context.getResourceInterface());
866 #endif // CTS_USES_VULKANSC
867 const CustomInstance instance (createCustomInstanceFromContext(m_context));
868 const InstanceDriver& instanceDriver (instance.getDriver());
869 const VkPhysicalDevice physicalDevice = chooseDevice(instanceDriver, instance, m_context.getTestContext().getCommandLine());
870 requireFeatures(instanceDriver, physicalDevice, FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS);
871
872 MovePtr<MultiQueues> queues = createQueues(m_context, VK_QUEUE_GRAPHICS_BIT, instance, instanceDriver);
873 const DeviceInterface& vk = m_context.getDeviceInterface();
874 const VkDevice device = queues->getDevice();
875 VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
876 Move<VkRenderPass> renderPass = makeRenderPass(vk, device, colorFormat);
877 const Move<VkDescriptorSetLayout> descriptorSetLayout (DescriptorSetLayoutBuilder()
878 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_VERTEX_BIT)
879 .build(vk, device));
880 ShaderModuleVector shaderGraphicModules = addShaderModules(device);
881 const Move<VkPipelineLayout> pipelineLayout (makePipelineLayout(vk, device, *descriptorSetLayout));
882 vector<VkPipelineShaderStageCreateInfo> shaderStageInfos = addShaderStageInfo(shaderGraphicModules);
883 vector<VkGraphicsPipelineCreateInfo> pipelineInfo = addPipelineInfo(*pipelineLayout, shaderStageInfos, *renderPass);
884 const VkPipelineCacheCreateInfo pipelineCacheInfo =
885 {
886 VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO, // VkStructureType sType;
887 DE_NULL, // const void* pNext;
888 #ifndef CTS_USES_VULKANSC
889 0u, // VkPipelineCacheCreateFlags flags;
890 0u, // deUintptr initialDataSize;
891 DE_NULL // const void* pInitialData;
892 #else
893 VK_PIPELINE_CACHE_CREATE_READ_ONLY_BIT |
894 VK_PIPELINE_CACHE_CREATE_USE_APPLICATION_STORAGE_BIT, // VkPipelineCacheCreateFlags flags;
895 m_context.getResourceInterface()->getCacheDataSize(), // deUintptr initialDataSize;
896 m_context.getResourceInterface()->getCacheData() // const void* pInitialData;
897 #endif // CTS_USES_VULKANSC
898 };
899 Move<VkPipelineCache> pipelineCache = createPipelineCache(vk, device, &pipelineCacheInfo);
900 Move<VkPipeline> pipeline = createGraphicsPipeline(vk, device, *pipelineCache, &pipelineInfo[0]);
901 #ifndef CTS_USES_VULKANSC
902 const deUint32 numThreads = clamp(deGetNumAvailableLogicalCores(), 4u, 32u);
903 #else
904 const deUint32 numThreads = 2u;
905 #endif // CTS_USES_VULKANSC
906 ThreadGroup threads;
907
908 executeGraphicPipeline(m_context, *pipeline, *pipelineLayout, *descriptorSetLayout, *queues, *renderPass, m_shadersExecutions[0]);
909
910 for (deUint32 ndx = 0; ndx < numThreads; ++ndx)
911 threads.add(MovePtr<ThreadGroupThread>(new CreateGraphicThread(
912 m_context, *pipelineCache, pipelineInfo, *pipelineLayout, *descriptorSetLayout, *queues, *renderPass, m_shadersExecutions)));
913
914 {
915 TestStatus thread_result = threads.run();
916 if(thread_result.getCode())
917 {
918 return thread_result;
919 }
920 }
921 return TestStatus::pass("Passed");
922 }
923
924 private:
addShaderModules(const VkDevice & device)925 ShaderModuleVector addShaderModules (const VkDevice& device)
926 {
927 const DeviceInterface& vk = m_context.getDeviceInterface();
928 ShaderModuleVector shaderModules;
929 shaderModules.resize(m_shadersExecutions.size() + 1);
930 for (int shaderNdx = 0; shaderNdx < static_cast<int>(m_shadersExecutions.size()); ++shaderNdx)
931 {
932 ostringstream shaderName;
933 shaderName<<"vert_"<<shaderNdx;
934 shaderModules[shaderNdx] = SharedPtr<Unique<VkShaderModule> > (new Unique<VkShaderModule>(createShaderModule(vk, device, m_context.getBinaryCollection().get(shaderName.str()), (VkShaderModuleCreateFlags)0)));
935 }
936 shaderModules[m_shadersExecutions.size()] = SharedPtr<Unique<VkShaderModule> > (new Unique<VkShaderModule>(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), (VkShaderModuleCreateFlags)0)));
937 return shaderModules;
938 }
939
addShaderStageInfo(const ShaderModuleVector & shaderCompModules)940 vector<VkPipelineShaderStageCreateInfo> addShaderStageInfo (const ShaderModuleVector& shaderCompModules)
941 {
942 VkPipelineShaderStageCreateInfo shaderStageInfo;
943 vector<VkPipelineShaderStageCreateInfo> shaderStageInfos;
944 shaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
945 shaderStageInfo.pNext = DE_NULL;
946 shaderStageInfo.flags = (VkPipelineShaderStageCreateFlags)0;
947 shaderStageInfo.pName = "main";
948 shaderStageInfo.pSpecializationInfo = DE_NULL;
949
950 for (int shaderNdx = 0; shaderNdx < static_cast<int>(m_shadersExecutions.size()); ++shaderNdx)
951 {
952 shaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
953 shaderStageInfo.module = *(*shaderCompModules[shaderNdx]);
954 shaderStageInfos.push_back(shaderStageInfo);
955
956 shaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
957 shaderStageInfo.module = *(*shaderCompModules[m_shadersExecutions.size()]);
958 shaderStageInfos.push_back(shaderStageInfo);
959 }
960 return shaderStageInfos;
961 }
962
addPipelineInfo(VkPipelineLayout pipelineLayout,const vector<VkPipelineShaderStageCreateInfo> & shaderStageInfos,const VkRenderPass & renderPass)963 vector<VkGraphicsPipelineCreateInfo> addPipelineInfo (VkPipelineLayout pipelineLayout, const vector<VkPipelineShaderStageCreateInfo>& shaderStageInfos, const VkRenderPass& renderPass)
964 {
965 VkExtent3D colorImageExtent = makeExtent3D(1u, 1u, 1u);
966 vector<VkGraphicsPipelineCreateInfo> pipelineInfo;
967
968 m_vertexInputStateParams.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
969 m_vertexInputStateParams.pNext = DE_NULL;
970 m_vertexInputStateParams.flags = 0u;
971 m_vertexInputStateParams.vertexBindingDescriptionCount = 0u;
972 m_vertexInputStateParams.pVertexBindingDescriptions = DE_NULL;
973 m_vertexInputStateParams.vertexAttributeDescriptionCount = 0u;
974 m_vertexInputStateParams.pVertexAttributeDescriptions = DE_NULL;
975
976 m_inputAssemblyStateParams.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
977 m_inputAssemblyStateParams.pNext = DE_NULL;
978 m_inputAssemblyStateParams.flags = 0u;
979 m_inputAssemblyStateParams.topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
980 m_inputAssemblyStateParams.primitiveRestartEnable = VK_FALSE;
981
982 m_viewport.x = 0.0f;
983 m_viewport.y = 0.0f;
984 m_viewport.width = (float)colorImageExtent.width;
985 m_viewport.height = (float)colorImageExtent.height;
986 m_viewport.minDepth = 0.0f;
987 m_viewport.maxDepth = 1.0f;
988
989 //TODO
990 m_scissor.offset.x = 0;
991 m_scissor.offset.y = 0;
992 m_scissor.extent.width = colorImageExtent.width;
993 m_scissor.extent.height = colorImageExtent.height;
994
995 m_viewportStateParams.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
996 m_viewportStateParams.pNext = DE_NULL;
997 m_viewportStateParams.flags = 0u;
998 m_viewportStateParams.viewportCount = 1u;
999 m_viewportStateParams.pViewports = &m_viewport;
1000 m_viewportStateParams.scissorCount = 1u;
1001 m_viewportStateParams.pScissors = &m_scissor;
1002
1003 m_rasterStateParams.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
1004 m_rasterStateParams.pNext = DE_NULL;
1005 m_rasterStateParams.flags = 0u;
1006 m_rasterStateParams.depthClampEnable = VK_FALSE;
1007 m_rasterStateParams.rasterizerDiscardEnable = VK_FALSE;
1008 m_rasterStateParams.polygonMode = VK_POLYGON_MODE_FILL;
1009 m_rasterStateParams.cullMode = VK_CULL_MODE_NONE;
1010 m_rasterStateParams.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
1011 m_rasterStateParams.depthBiasEnable = VK_FALSE;
1012 m_rasterStateParams.depthBiasConstantFactor = 0.0f;
1013 m_rasterStateParams.depthBiasClamp = 0.0f;
1014 m_rasterStateParams.depthBiasSlopeFactor = 0.0f;
1015 m_rasterStateParams.lineWidth = 1.0f;
1016
1017 m_colorBlendAttachmentState.blendEnable = VK_FALSE;
1018 m_colorBlendAttachmentState.srcColorBlendFactor = VK_BLEND_FACTOR_ONE;
1019 m_colorBlendAttachmentState.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO;
1020 m_colorBlendAttachmentState.colorBlendOp = VK_BLEND_OP_ADD;
1021 m_colorBlendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
1022 m_colorBlendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
1023 m_colorBlendAttachmentState.alphaBlendOp = VK_BLEND_OP_ADD;
1024 m_colorBlendAttachmentState.colorWriteMask = VK_COLOR_COMPONENT_R_BIT |
1025 VK_COLOR_COMPONENT_G_BIT |
1026 VK_COLOR_COMPONENT_B_BIT |
1027 VK_COLOR_COMPONENT_A_BIT;
1028
1029 m_colorBlendStateParams.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
1030 m_colorBlendStateParams.pNext = DE_NULL;
1031 m_colorBlendStateParams.flags = 0u;
1032 m_colorBlendStateParams.logicOpEnable = VK_FALSE;
1033 m_colorBlendStateParams.logicOp = VK_LOGIC_OP_COPY;
1034 m_colorBlendStateParams.attachmentCount = 1u;
1035 m_colorBlendStateParams.pAttachments = &m_colorBlendAttachmentState;
1036 m_colorBlendStateParams.blendConstants[0] = 0.0f;
1037 m_colorBlendStateParams.blendConstants[1] = 0.0f;
1038 m_colorBlendStateParams.blendConstants[2] = 0.0f;
1039 m_colorBlendStateParams.blendConstants[3] = 0.0f;
1040
1041 m_multisampleStateParams.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
1042 m_multisampleStateParams.pNext = DE_NULL;
1043 m_multisampleStateParams.flags = 0u;
1044 m_multisampleStateParams.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
1045 m_multisampleStateParams.sampleShadingEnable = VK_FALSE;
1046 m_multisampleStateParams.minSampleShading = 0.0f;
1047 m_multisampleStateParams.pSampleMask = DE_NULL;
1048 m_multisampleStateParams.alphaToCoverageEnable = VK_FALSE;
1049 m_multisampleStateParams.alphaToOneEnable = VK_FALSE;
1050
1051 m_depthStencilStateParams.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
1052 m_depthStencilStateParams.pNext = DE_NULL;
1053 m_depthStencilStateParams.flags = 0u;
1054 m_depthStencilStateParams.depthTestEnable = VK_TRUE;
1055 m_depthStencilStateParams.depthWriteEnable = VK_TRUE;
1056 m_depthStencilStateParams.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
1057 m_depthStencilStateParams.depthBoundsTestEnable = VK_FALSE;
1058 m_depthStencilStateParams.stencilTestEnable = VK_FALSE;
1059 m_depthStencilStateParams.front.failOp = VK_STENCIL_OP_KEEP;
1060 m_depthStencilStateParams.front.passOp = VK_STENCIL_OP_KEEP;
1061 m_depthStencilStateParams.front.depthFailOp = VK_STENCIL_OP_KEEP;
1062 m_depthStencilStateParams.front.compareOp = VK_COMPARE_OP_NEVER;
1063 m_depthStencilStateParams.front.compareMask = 0u;
1064 m_depthStencilStateParams.front.writeMask = 0u;
1065 m_depthStencilStateParams.front.reference = 0u;
1066 m_depthStencilStateParams.back.failOp = VK_STENCIL_OP_KEEP;
1067 m_depthStencilStateParams.back.passOp = VK_STENCIL_OP_KEEP;
1068 m_depthStencilStateParams.back.depthFailOp = VK_STENCIL_OP_KEEP;
1069 m_depthStencilStateParams.back.compareOp = VK_COMPARE_OP_NEVER;
1070 m_depthStencilStateParams.back.compareMask = 0u;
1071 m_depthStencilStateParams.back.writeMask = 0u;
1072 m_depthStencilStateParams.back.reference = 0u;
1073 m_depthStencilStateParams.minDepthBounds = 0.0f;
1074 m_depthStencilStateParams.maxDepthBounds = 1.0f;
1075
1076 VkGraphicsPipelineCreateInfo graphicsPipelineParams =
1077 {
1078 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
1079 DE_NULL, // const void* pNext;
1080 0u, // VkPipelineCreateFlags flags;
1081 2u, // deUint32 stageCount;
1082 DE_NULL, // const VkPipelineShaderStageCreateInfo* pStages;
1083 &m_vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
1084 &m_inputAssemblyStateParams, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
1085 DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
1086 &m_viewportStateParams, // const VkPipelineViewportStateCreateInfo* pViewportState;
1087 &m_rasterStateParams, // const VkPipelineRasterizationStateCreateInfo* pRasterState;
1088 &m_multisampleStateParams, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
1089 &m_depthStencilStateParams, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
1090 &m_colorBlendStateParams, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
1091 (const VkPipelineDynamicStateCreateInfo*)DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
1092 pipelineLayout, // VkPipelineLayout layout;
1093 renderPass, // VkRenderPass renderPass;
1094 0u, // deUint32 subpass;
1095 DE_NULL, // VkPipeline basePipelineHandle;
1096 0, // deInt32 basePipelineIndex;
1097 };
1098 for (int shaderNdx = 0; shaderNdx < static_cast<int>(m_shadersExecutions.size()) * 2; shaderNdx+=2)
1099 {
1100 graphicsPipelineParams.pStages = &shaderStageInfos[shaderNdx];
1101 pipelineInfo.push_back(graphicsPipelineParams);
1102 }
1103 return pipelineInfo;
1104 }
1105
1106 const vector<deUint32> m_shadersExecutions;
1107 VkPipelineVertexInputStateCreateInfo m_vertexInputStateParams;
1108 VkPipelineInputAssemblyStateCreateInfo m_inputAssemblyStateParams;
1109 VkViewport m_viewport;
1110 VkRect2D m_scissor;
1111 VkPipelineViewportStateCreateInfo m_viewportStateParams;
1112 VkPipelineRasterizationStateCreateInfo m_rasterStateParams;
1113 VkPipelineColorBlendAttachmentState m_colorBlendAttachmentState;
1114 VkPipelineColorBlendStateCreateInfo m_colorBlendStateParams;
1115 VkPipelineMultisampleStateCreateInfo m_multisampleStateParams;
1116 VkPipelineDepthStencilStateCreateInfo m_depthStencilStateParams;
1117 };
1118
1119 class PipelineCacheComputeTest : public TestCase
1120 {
1121 public:
PipelineCacheComputeTest(TestContext & testCtx,const string & name,const string & description)1122 PipelineCacheComputeTest (TestContext& testCtx,
1123 const string& name,
1124 const string& description)
1125 :TestCase (testCtx, name, description)
1126 {
1127 }
1128
initPrograms(SourceCollections & programCollection) const1129 void initPrograms (SourceCollections& programCollection) const
1130 {
1131 ostringstream buffer;
1132 buffer << "layout(set = 0, binding = 0, std430) buffer Output\n"
1133 << "{\n"
1134 << " int result[];\n"
1135 << "} sb_out;\n";
1136 {
1137 ostringstream src;
1138 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
1139 << "\n"
1140 << "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1141 << "\n"
1142 << buffer.str()
1143 << "void main (void)\n"
1144 << "{\n"
1145 << " highp uint ndx = gl_GlobalInvocationID.x;\n"
1146 << " sb_out.result[ndx] = int(ndx);\n"
1147 << "}\n";
1148 programCollection.glslSources.add("compute_0") << glu::ComputeSource(src.str());
1149 }
1150 {
1151 ostringstream src;
1152 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
1153 << "\n"
1154 << "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1155 << "\n"
1156 << buffer.str()
1157 << "void main (void)\n"
1158 << "{\n"
1159 << " for (highp uint ndx = 0u; ndx < "<<BUFFER_ELEMENT_COUNT<<"u; ndx++)\n"
1160 << " {\n"
1161 << " sb_out.result[ndx] = int(ndx);\n"
1162 << " }\n"
1163 << "}\n";
1164 programCollection.glslSources.add("compute_1") << glu::ComputeSource(src.str());
1165 }
1166 {
1167 ostringstream src;
1168 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
1169 << "\n"
1170 << "layout(local_size_x = "<<BUFFER_ELEMENT_COUNT<<", local_size_y = 1, local_size_z = 1) in;\n"
1171 << "\n"
1172 << buffer.str()
1173 << "void main (void)\n"
1174 << "{\n"
1175 << " highp uint ndx = gl_LocalInvocationID.x;\n"
1176 << " sb_out.result[ndx] = int(ndx);\n"
1177 << "}\n";
1178 programCollection.glslSources.add("compute_2") << glu::ComputeSource(src.str());
1179 }
1180 }
1181
createInstance(Context & context) const1182 TestInstance* createInstance (Context& context) const
1183 {
1184 vector<deUint32> shadersExecutions;
1185 shadersExecutions.push_back(16u); //compute_0
1186 shadersExecutions.push_back(1u); //compute_1
1187 shadersExecutions.push_back(1u); //compute_2
1188 return new PipelineCacheComputeTestInstance(context, shadersExecutions);
1189 }
1190 };
1191
1192 class PipelineCacheGraphicTest : public TestCase
1193 {
1194 public:
PipelineCacheGraphicTest(TestContext & testCtx,const string & name,const string & description)1195 PipelineCacheGraphicTest (TestContext& testCtx,
1196 const string& name,
1197 const string& description)
1198 :TestCase (testCtx, name, description)
1199 {
1200
1201 }
1202
initPrograms(SourceCollections & programCollection) const1203 void initPrograms (SourceCollections& programCollection) const
1204 {
1205 ostringstream buffer;
1206 buffer << "layout(set = 0, binding = 0, std430) buffer Output\n"
1207 << "{\n"
1208 << " int result[];\n"
1209 << "} sb_out;\n";
1210
1211 // Vertex
1212 {
1213 std::ostringstream src;
1214 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
1215 << "\n"
1216 << buffer.str()
1217 << "\n"
1218 << "void main (void)\n"
1219 << "{\n"
1220 << " sb_out.result[gl_VertexIndex] = int(gl_VertexIndex);\n"
1221 << " gl_PointSize = 1.0f;\n"
1222 << "}\n";
1223 programCollection.glslSources.add("vert_0") << glu::VertexSource(src.str());
1224 }
1225 // Vertex
1226 {
1227 std::ostringstream src;
1228 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
1229 << "\n"
1230 << buffer.str()
1231 << "\n"
1232 << "void main (void)\n"
1233 << "{\n"
1234 << " for (highp uint ndx = 0u; ndx < "<<BUFFER_ELEMENT_COUNT<<"u; ndx++)\n"
1235 << " {\n"
1236 << " sb_out.result[ndx] = int(ndx);\n"
1237 << " }\n"
1238 << " gl_PointSize = 1.0f;\n"
1239 << "}\n";
1240 programCollection.glslSources.add("vert_1") << glu::VertexSource(src.str());
1241 }
1242 // Vertex
1243 {
1244 std::ostringstream src;
1245 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
1246 << "\n"
1247 << buffer.str()
1248 << "\n"
1249 << "void main (void)\n"
1250 << "{\n"
1251 << " for (int ndx = "<<BUFFER_ELEMENT_COUNT-1<<"; ndx >= 0; ndx--)\n"
1252 << " {\n"
1253 << " sb_out.result[uint(ndx)] = ndx;\n"
1254 << " }\n"
1255 << " gl_PointSize = 1.0f;\n"
1256 << "}\n";
1257 programCollection.glslSources.add("vert_2") << glu::VertexSource(src.str());
1258 }
1259 // Fragment
1260 {
1261 std::ostringstream src;
1262 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
1263 << "\n"
1264 << "layout(location = 0) out vec4 o_color;\n"
1265 << "\n"
1266 << "void main (void)\n"
1267 << "{\n"
1268 << " o_color = vec4(1.0);\n"
1269 << "}\n";
1270 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1271 }
1272 }
1273
createInstance(Context & context) const1274 TestInstance* createInstance (Context& context) const
1275 {
1276 vector<deUint32> shadersExecutions;
1277 shadersExecutions.push_back(16u); //vert_0
1278 shadersExecutions.push_back(1u); //vert_1
1279 shadersExecutions.push_back(1u); //vert_2
1280 return new PipelineCacheGraphicTestInstance(context, shadersExecutions);
1281 }
1282 };
1283
1284
1285 } // anonymous
1286
createInternallySynchronizedObjects(tcu::TestContext & testCtx)1287 tcu::TestCaseGroup* createInternallySynchronizedObjects (tcu::TestContext& testCtx)
1288 {
1289 de::MovePtr<tcu::TestCaseGroup> tests(new tcu::TestCaseGroup(testCtx, "internally_synchronized_objects", "Internally synchronized objects"));
1290 tests->addChild(new PipelineCacheComputeTest(testCtx, "pipeline_cache_compute", "Internally synchronized object VkPipelineCache for compute pipeline is tested"));
1291 tests->addChild(new PipelineCacheGraphicTest(testCtx, "pipeline_cache_graphics", "Internally synchronized object VkPipelineCache for graphics pipeline is tested"));
1292 return tests.release();
1293 }
1294
1295 } // synchronization
1296 } // vkt
1297