1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 Google 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 Platform Synchronization tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktSynchronizationSmokeTests.hpp"
25 #include "vktSynchronizationUtil.hpp"
26 
27 #include "vktTestCaseUtil.hpp"
28 #include "vktCustomInstancesDevices.hpp"
29 
30 #include "vkPlatform.hpp"
31 #include "vkStrUtil.hpp"
32 #include "vkRef.hpp"
33 #include "vkRefUtil.hpp"
34 #include "vkDeviceUtil.hpp"
35 #include "vkSafetyCriticalUtil.hpp"
36 
37 #include "tcuTestLog.hpp"
38 #include "tcuFormatUtil.hpp"
39 #include "tcuCommandLine.hpp"
40 
41 #include "deUniquePtr.hpp"
42 #include "deThread.hpp"
43 #include "vkMemUtil.hpp"
44 #include "vkQueryUtil.hpp"
45 #include "vkPrograms.hpp"
46 #include "vkTypeUtil.hpp"
47 #include "vkCmdUtil.hpp"
48 
49 #include <limits>
50 
51 namespace vkt
52 {
53 namespace synchronization
54 {
55 
56 using namespace vk;
57 using namespace tcu;
58 
59 namespace
60 {
61 
62 using de::MovePtr;
63 using std::string;
64 using std::vector;
65 using tcu::TestLog;
66 
67 static const uint64_t DEFAULT_TIMEOUT = 2ull * 1000 * 1000 * 1000; //!< 2 seconds in nanoseconds
68 
69 struct SemaphoreTestConfig
70 {
71     SynchronizationType synchronizationType;
72     VkSemaphoreType semaphoreType;
73 };
74 
initShaders(SourceCollections & shaderCollection,SemaphoreTestConfig)75 void initShaders(SourceCollections &shaderCollection, SemaphoreTestConfig)
76 {
77     shaderCollection.glslSources.add("glslvert") << glu::VertexSource("#version 310 es\n"
78                                                                       "precision mediump float;\n"
79                                                                       "layout (location = 0) in vec4 vertexPosition;\n"
80                                                                       "void main()\n"
81                                                                       "{\n"
82                                                                       "    gl_Position = vertexPosition;\n"
83                                                                       "}\n");
84 
85     shaderCollection.glslSources.add("glslfrag") << glu::FragmentSource("#version 310 es\n"
86                                                                         "precision mediump float;\n"
87                                                                         "layout (location = 0) out vec4 outputColor;\n"
88                                                                         "void main()\n"
89                                                                         "{\n"
90                                                                         "    outputColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
91                                                                         "}\n");
92 }
93 
buildShaders(SourceCollections & shaderCollection)94 void buildShaders(SourceCollections &shaderCollection)
95 {
96     initShaders(shaderCollection, {SynchronizationType::LEGACY, VK_SEMAPHORE_TYPE_BINARY});
97 }
98 
createTestDevice(Context & context,SemaphoreTestConfig & config,const VkInstance & instance,const InstanceInterface & vki,uint32_t * outQueueFamilyIndex)99 Move<VkDevice> createTestDevice(Context &context, SemaphoreTestConfig &config, const VkInstance &instance,
100                                 const InstanceInterface &vki, uint32_t *outQueueFamilyIndex)
101 {
102     const PlatformInterface &vkp    = context.getPlatformInterface();
103     VkPhysicalDevice physicalDevice = chooseDevice(vki, instance, context.getTestContext().getCommandLine());
104     bool validationEnabled          = context.getTestContext().getCommandLine().isValidationEnabled();
105     VkDeviceQueueCreateInfo queueInfo;
106     VkDeviceCreateInfo deviceInfo;
107     size_t queueNdx;
108     const uint32_t queueCount             = 2u;
109     const float queuePriority[queueCount] = {1.0f, 1.0f};
110 
111     const vector<VkQueueFamilyProperties> queueProps      = getPhysicalDeviceQueueFamilyProperties(vki, physicalDevice);
112     const VkPhysicalDeviceFeatures physicalDeviceFeatures = getPhysicalDeviceFeatures(vki, physicalDevice);
113     VkPhysicalDeviceFeatures2 physicalDeviceFeatures2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, DE_NULL,
114                                                       physicalDeviceFeatures};
115     VkPhysicalDeviceSynchronization2FeaturesKHR synchronization2Features{
116         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES_KHR, DE_NULL, true};
117     VkPhysicalDeviceTimelineSemaphoreFeatures timelineSemaphoreFeatures{
118         VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES, DE_NULL, true};
119     void **nextPtr = &physicalDeviceFeatures2.pNext;
120 
121     for (queueNdx = 0; queueNdx < queueProps.size(); queueNdx++)
122     {
123         if ((queueProps[queueNdx].queueFlags & VK_QUEUE_GRAPHICS_BIT) == VK_QUEUE_GRAPHICS_BIT &&
124             (queueProps[queueNdx].queueCount >= queueCount))
125             break;
126     }
127 
128     if (queueNdx >= queueProps.size())
129     {
130         // No queue family index found
131         std::ostringstream msg;
132         msg << "Cannot create device with " << queueCount << " graphics queues";
133 
134         throw tcu::NotSupportedError(msg.str());
135     }
136 
137     deMemset(&queueInfo, 0, sizeof(queueInfo));
138     deMemset(&deviceInfo, 0, sizeof(deviceInfo));
139 
140     deMemset(&queueInfo, 0xcd, sizeof(queueInfo));
141     queueInfo.sType            = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
142     queueInfo.pNext            = DE_NULL;
143     queueInfo.flags            = (VkDeviceQueueCreateFlags)0u;
144     queueInfo.queueFamilyIndex = (uint32_t)queueNdx;
145     queueInfo.queueCount       = queueCount;
146     queueInfo.pQueuePriorities = queuePriority;
147 
148     vector<const char *> deviceExtensions;
149     bool useFeatures2 = false;
150     if (config.semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE)
151     {
152         if (!isCoreDeviceExtension(context.getUsedApiVersion(), "VK_KHR_timeline_semaphore"))
153             deviceExtensions.push_back("VK_KHR_timeline_semaphore");
154         addToChainVulkanStructure(&nextPtr, timelineSemaphoreFeatures);
155         useFeatures2 = true;
156     }
157     if (config.synchronizationType == SynchronizationType::SYNCHRONIZATION2)
158     {
159         deviceExtensions.push_back("VK_KHR_synchronization2");
160         addToChainVulkanStructure(&nextPtr, synchronization2Features);
161         useFeatures2 = true;
162     }
163 
164     void *pNext = !useFeatures2 ? DE_NULL : &physicalDeviceFeatures2;
165 #ifdef CTS_USES_VULKANSC
166     VkDeviceObjectReservationCreateInfo memReservationInfo = context.getTestContext().getCommandLine().isSubProcess() ?
167                                                                  context.getResourceInterface()->getStatMax() :
168                                                                  resetDeviceObjectReservationCreateInfo();
169     memReservationInfo.pNext                               = pNext;
170     pNext                                                  = &memReservationInfo;
171 
172     VkPhysicalDeviceVulkanSC10Features sc10Features = createDefaultSC10Features();
173     sc10Features.pNext                              = pNext;
174     pNext                                           = &sc10Features;
175 
176     VkPipelineCacheCreateInfo pcCI;
177     std::vector<VkPipelinePoolSize> poolSizes;
178     if (context.getTestContext().getCommandLine().isSubProcess())
179     {
180         if (context.getResourceInterface()->getCacheDataSize() > 0)
181         {
182             pcCI = {
183                 VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO, // VkStructureType sType;
184                 DE_NULL,                                      // const void* pNext;
185                 VK_PIPELINE_CACHE_CREATE_READ_ONLY_BIT |
186                     VK_PIPELINE_CACHE_CREATE_USE_APPLICATION_STORAGE_BIT, // VkPipelineCacheCreateFlags flags;
187                 context.getResourceInterface()->getCacheDataSize(),       // uintptr_t initialDataSize;
188                 context.getResourceInterface()->getCacheData()            // const void* pInitialData;
189             };
190             memReservationInfo.pipelineCacheCreateInfoCount = 1;
191             memReservationInfo.pPipelineCacheCreateInfos    = &pcCI;
192         }
193 
194         poolSizes = context.getResourceInterface()->getPipelinePoolSizes();
195         if (!poolSizes.empty())
196         {
197             memReservationInfo.pipelinePoolSizeCount = uint32_t(poolSizes.size());
198             memReservationInfo.pPipelinePoolSizes    = poolSizes.data();
199         }
200     }
201 #endif // CTS_USES_VULKANSC
202 
203     deMemset(&deviceInfo, 0xcd, sizeof(deviceInfo));
204     deviceInfo.sType                   = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
205     deviceInfo.pNext                   = pNext;
206     deviceInfo.flags                   = (VkDeviceCreateFlags)0u;
207     deviceInfo.queueCreateInfoCount    = 1u;
208     deviceInfo.pQueueCreateInfos       = &queueInfo;
209     deviceInfo.enabledExtensionCount   = static_cast<uint32_t>(deviceExtensions.size());
210     deviceInfo.ppEnabledExtensionNames = deviceExtensions.empty() ? DE_NULL : &deviceExtensions[0];
211     deviceInfo.enabledLayerCount       = 0u;
212     deviceInfo.ppEnabledLayerNames     = DE_NULL;
213     deviceInfo.pEnabledFeatures        = !useFeatures2 ? &physicalDeviceFeatures : DE_NULL;
214 
215     *outQueueFamilyIndex = queueInfo.queueFamilyIndex;
216 
217     return createCustomDevice(validationEnabled, vkp, instance, vki, physicalDevice, &deviceInfo);
218 }
219 
220 struct BufferParameters
221 {
222     const void *memory;
223     VkDeviceSize size;
224     VkBufferUsageFlags usage;
225     VkSharingMode sharingMode;
226     uint32_t queueFamilyCount;
227     const uint32_t *queueFamilyIndex;
228     VkAccessFlags inputBarrierFlags;
229 };
230 
231 struct Buffer
232 {
233     MovePtr<Allocation> allocation;
234     vector<VkMemoryBarrier> memoryBarrier;
235     vk::Move<VkBuffer> buffer;
236 };
237 
createVulkanBuffer(const DeviceInterface & vkd,VkDevice device,Allocator & allocator,const BufferParameters & bufferParameters,Buffer & buffer,MemoryRequirement visibility)238 void createVulkanBuffer(const DeviceInterface &vkd, VkDevice device, Allocator &allocator,
239                         const BufferParameters &bufferParameters, Buffer &buffer, MemoryRequirement visibility)
240 {
241     VkBufferCreateInfo bufferCreateParams;
242 
243     deMemset(&bufferCreateParams, 0xcd, sizeof(bufferCreateParams));
244     bufferCreateParams.sType                 = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
245     bufferCreateParams.pNext                 = DE_NULL;
246     bufferCreateParams.flags                 = 0;
247     bufferCreateParams.size                  = bufferParameters.size;
248     bufferCreateParams.usage                 = bufferParameters.usage;
249     bufferCreateParams.sharingMode           = bufferParameters.sharingMode;
250     bufferCreateParams.queueFamilyIndexCount = bufferParameters.queueFamilyCount;
251     bufferCreateParams.pQueueFamilyIndices   = bufferParameters.queueFamilyIndex;
252 
253     buffer.buffer     = createBuffer(vkd, device, &bufferCreateParams);
254     buffer.allocation = allocator.allocate(getBufferMemoryRequirements(vkd, device, *buffer.buffer), visibility);
255 
256     VK_CHECK(
257         vkd.bindBufferMemory(device, *buffer.buffer, buffer.allocation->getMemory(), buffer.allocation->getOffset()));
258 
259     // If caller provides a host memory buffer for the allocation, then go
260     // ahead and copy the provided data into the allocation and update the
261     // barrier list with the associated access
262     if (bufferParameters.memory != DE_NULL)
263     {
264         VkMemoryBarrier barrier;
265 
266         deMemcpy(buffer.allocation->getHostPtr(), bufferParameters.memory, (size_t)bufferParameters.size);
267         flushAlloc(vkd, device, *buffer.allocation);
268 
269         deMemset(&barrier, 0xcd, sizeof(barrier));
270         barrier.sType         = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
271         barrier.pNext         = DE_NULL;
272         barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;
273         barrier.dstAccessMask = bufferParameters.inputBarrierFlags;
274 
275         buffer.memoryBarrier.push_back(barrier);
276     }
277 }
278 
279 struct ImageParameters
280 {
281     VkImageType imageType;
282     VkFormat format;
283     VkExtent3D extent3D;
284     uint32_t mipLevels;
285     VkSampleCountFlagBits samples;
286     VkImageTiling tiling;
287     VkBufferUsageFlags usage;
288     VkSharingMode sharingMode;
289     uint32_t queueFamilyCount;
290     const uint32_t *queueFamilyNdxList;
291     VkImageLayout initialLayout;
292     VkImageLayout finalLayout;
293     VkAccessFlags barrierInputMask;
294 };
295 
296 struct Image
297 {
298     vk::Move<VkImage> image;
299     vk::Move<VkImageView> imageView;
300     MovePtr<Allocation> allocation;
301     vector<VkImageMemoryBarrier> imageMemoryBarrier;
302 };
303 
createVulkanImage(const DeviceInterface & vkd,VkDevice device,Allocator & allocator,const ImageParameters & imageParameters,Image & image,MemoryRequirement visibility)304 void createVulkanImage(const DeviceInterface &vkd, VkDevice device, Allocator &allocator,
305                        const ImageParameters &imageParameters, Image &image, MemoryRequirement visibility)
306 {
307     VkComponentMapping componentMap;
308     VkImageSubresourceRange subresourceRange;
309     VkImageViewCreateInfo imageViewCreateInfo;
310     VkImageCreateInfo imageCreateParams;
311     VkImageMemoryBarrier imageBarrier;
312 
313     deMemset(&imageCreateParams, 0xcd, sizeof(imageCreateParams));
314     imageCreateParams.sType                 = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
315     imageCreateParams.pNext                 = DE_NULL;
316     imageCreateParams.flags                 = 0;
317     imageCreateParams.imageType             = imageParameters.imageType;
318     imageCreateParams.format                = imageParameters.format;
319     imageCreateParams.extent                = imageParameters.extent3D;
320     imageCreateParams.mipLevels             = imageParameters.mipLevels;
321     imageCreateParams.arrayLayers           = 1;
322     imageCreateParams.samples               = imageParameters.samples;
323     imageCreateParams.tiling                = imageParameters.tiling;
324     imageCreateParams.usage                 = imageParameters.usage;
325     imageCreateParams.sharingMode           = imageParameters.sharingMode;
326     imageCreateParams.queueFamilyIndexCount = imageParameters.queueFamilyCount;
327     imageCreateParams.pQueueFamilyIndices   = imageParameters.queueFamilyNdxList;
328     imageCreateParams.initialLayout         = imageParameters.initialLayout;
329 
330     image.image      = createImage(vkd, device, &imageCreateParams);
331     image.allocation = allocator.allocate(getImageMemoryRequirements(vkd, device, *image.image), visibility);
332 
333     VK_CHECK(vkd.bindImageMemory(device, *image.image, image.allocation->getMemory(), image.allocation->getOffset()));
334 
335     componentMap.r = VK_COMPONENT_SWIZZLE_R;
336     componentMap.g = VK_COMPONENT_SWIZZLE_G;
337     componentMap.b = VK_COMPONENT_SWIZZLE_B;
338     componentMap.a = VK_COMPONENT_SWIZZLE_A;
339 
340     subresourceRange.aspectMask     = VK_IMAGE_ASPECT_COLOR_BIT;
341     subresourceRange.baseMipLevel   = 0;
342     subresourceRange.levelCount     = imageParameters.mipLevels;
343     subresourceRange.baseArrayLayer = 0;
344     subresourceRange.layerCount     = 1;
345 
346     deMemset(&imageViewCreateInfo, 0xcd, sizeof(imageViewCreateInfo));
347     imageViewCreateInfo.sType            = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
348     imageViewCreateInfo.pNext            = DE_NULL;
349     imageViewCreateInfo.flags            = 0;
350     imageViewCreateInfo.image            = image.image.get();
351     imageViewCreateInfo.viewType         = VK_IMAGE_VIEW_TYPE_2D;
352     imageViewCreateInfo.format           = imageParameters.format;
353     imageViewCreateInfo.components       = componentMap;
354     imageViewCreateInfo.subresourceRange = subresourceRange;
355 
356     image.imageView = createImageView(vkd, device, &imageViewCreateInfo);
357 
358     deMemset(&imageBarrier, 0xcd, sizeof(imageBarrier));
359     imageBarrier.sType               = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
360     imageBarrier.pNext               = DE_NULL;
361     imageBarrier.srcAccessMask       = 0;
362     imageBarrier.dstAccessMask       = imageParameters.barrierInputMask;
363     imageBarrier.oldLayout           = imageParameters.initialLayout;
364     imageBarrier.newLayout           = imageParameters.finalLayout;
365     imageBarrier.srcQueueFamilyIndex = imageParameters.queueFamilyNdxList[0];
366     imageBarrier.dstQueueFamilyIndex = imageParameters.queueFamilyNdxList[imageParameters.queueFamilyCount - 1];
367     imageBarrier.image               = image.image.get();
368     imageBarrier.subresourceRange    = subresourceRange;
369 
370     image.imageMemoryBarrier.push_back(imageBarrier);
371 }
372 
373 struct RenderPassParameters
374 {
375     VkFormat colorFormat;
376     VkSampleCountFlagBits colorSamples;
377 };
378 
createColorOnlyRenderPass(const DeviceInterface & vkd,VkDevice device,const RenderPassParameters & renderPassParameters,vk::Move<VkRenderPass> & renderPass)379 void createColorOnlyRenderPass(const DeviceInterface &vkd, VkDevice device,
380                                const RenderPassParameters &renderPassParameters, vk::Move<VkRenderPass> &renderPass)
381 {
382     VkAttachmentDescription colorAttachmentDesc;
383     VkAttachmentReference colorAttachmentRef;
384     VkAttachmentReference stencilAttachmentRef;
385     VkSubpassDescription subpassDesc;
386     VkRenderPassCreateInfo renderPassParams;
387     VkRenderPass newRenderPass;
388 
389     colorAttachmentDesc.flags          = 0;
390     colorAttachmentDesc.format         = renderPassParameters.colorFormat;
391     colorAttachmentDesc.samples        = renderPassParameters.colorSamples;
392     colorAttachmentDesc.loadOp         = VK_ATTACHMENT_LOAD_OP_CLEAR;
393     colorAttachmentDesc.storeOp        = VK_ATTACHMENT_STORE_OP_STORE;
394     colorAttachmentDesc.stencilLoadOp  = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
395     colorAttachmentDesc.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
396     colorAttachmentDesc.initialLayout  = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
397     colorAttachmentDesc.finalLayout    = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
398 
399     colorAttachmentRef.attachment = 0;
400     colorAttachmentRef.layout     = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
401 
402     stencilAttachmentRef.attachment = VK_ATTACHMENT_UNUSED;
403     stencilAttachmentRef.layout     = VK_IMAGE_LAYOUT_UNDEFINED;
404 
405     subpassDesc.flags                   = 0;
406     subpassDesc.pipelineBindPoint       = VK_PIPELINE_BIND_POINT_GRAPHICS;
407     subpassDesc.inputAttachmentCount    = 0;
408     subpassDesc.pInputAttachments       = DE_NULL;
409     subpassDesc.colorAttachmentCount    = 1;
410     subpassDesc.pColorAttachments       = &colorAttachmentRef;
411     subpassDesc.pResolveAttachments     = DE_NULL;
412     subpassDesc.pDepthStencilAttachment = &stencilAttachmentRef;
413     subpassDesc.preserveAttachmentCount = 0;
414     subpassDesc.pPreserveAttachments    = DE_NULL;
415 
416     deMemset(&renderPassParams, 0xcd, sizeof(renderPassParams));
417     renderPassParams.sType           = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
418     renderPassParams.pNext           = DE_NULL;
419     renderPassParams.flags           = 0;
420     renderPassParams.attachmentCount = 1;
421     renderPassParams.pAttachments    = &colorAttachmentDesc;
422     renderPassParams.subpassCount    = 1;
423     renderPassParams.pSubpasses      = &subpassDesc;
424     renderPassParams.dependencyCount = 0;
425     renderPassParams.pDependencies   = DE_NULL;
426 
427     renderPass = createRenderPass(vkd, device, &renderPassParams);
428 }
429 
430 struct ShaderDescParams
431 {
432     VkShaderModule shaderModule;
433     VkShaderStageFlagBits stage;
434 };
435 
436 struct VertexDesc
437 {
438     uint32_t location;
439     VkFormat format;
440     uint32_t stride;
441     uint32_t offset;
442 };
443 
createVertexInfo(const vector<VertexDesc> & vertexDesc,vector<VkVertexInputBindingDescription> & bindingList,vector<VkVertexInputAttributeDescription> & attrList,VkPipelineVertexInputStateCreateInfo & vertexInputState)444 void createVertexInfo(const vector<VertexDesc> &vertexDesc, vector<VkVertexInputBindingDescription> &bindingList,
445                       vector<VkVertexInputAttributeDescription> &attrList,
446                       VkPipelineVertexInputStateCreateInfo &vertexInputState)
447 {
448     for (vector<VertexDesc>::const_iterator vertDescIter = vertexDesc.begin(); vertDescIter != vertexDesc.end();
449          vertDescIter++)
450     {
451         uint32_t bindingId = 0;
452         VkVertexInputBindingDescription bindingDesc;
453         VkVertexInputAttributeDescription attrDesc;
454 
455         bindingDesc.binding   = bindingId;
456         bindingDesc.stride    = vertDescIter->stride;
457         bindingDesc.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
458         bindingList.push_back(bindingDesc);
459 
460         attrDesc.location = vertDescIter->location;
461         attrDesc.binding  = bindingId;
462         attrDesc.format   = vertDescIter->format;
463         attrDesc.offset   = vertDescIter->offset;
464         attrList.push_back(attrDesc);
465 
466         bindingId++;
467     }
468 
469     deMemset(&vertexInputState, 0xcd, sizeof(vertexInputState));
470     vertexInputState.sType                           = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
471     vertexInputState.pNext                           = DE_NULL;
472     vertexInputState.flags                           = 0u;
473     vertexInputState.vertexBindingDescriptionCount   = (uint32_t)bindingList.size();
474     vertexInputState.pVertexBindingDescriptions      = &bindingList[0];
475     vertexInputState.vertexAttributeDescriptionCount = (uint32_t)attrList.size();
476     vertexInputState.pVertexAttributeDescriptions    = &attrList[0];
477 }
478 
createCommandBuffer(const DeviceInterface & deviceInterface,const VkDevice device,const uint32_t queueFamilyNdx,vk::Move<VkCommandBuffer> * commandBufferRef,vk::Move<VkCommandPool> * commandPoolRef)479 void createCommandBuffer(const DeviceInterface &deviceInterface, const VkDevice device, const uint32_t queueFamilyNdx,
480                          vk::Move<VkCommandBuffer> *commandBufferRef, vk::Move<VkCommandPool> *commandPoolRef)
481 {
482     vk::Move<VkCommandPool> commandPool;
483     VkCommandBufferAllocateInfo commandBufferInfo;
484     VkCommandBuffer commandBuffer;
485 
486     commandPool = createCommandPool(deviceInterface, device, 0u, queueFamilyNdx);
487 
488     deMemset(&commandBufferInfo, 0xcd, sizeof(commandBufferInfo));
489     commandBufferInfo.sType              = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
490     commandBufferInfo.pNext              = DE_NULL;
491     commandBufferInfo.commandPool        = commandPool.get();
492     commandBufferInfo.level              = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
493     commandBufferInfo.commandBufferCount = 1;
494 
495     VK_CHECK(deviceInterface.allocateCommandBuffers(device, &commandBufferInfo, &commandBuffer));
496     *commandBufferRef = vk::Move<VkCommandBuffer>(vk::check<VkCommandBuffer>(commandBuffer),
497                                                   Deleter<VkCommandBuffer>(deviceInterface, device, commandPool.get()));
498     *commandPoolRef   = commandPool;
499 }
500 
createFences(const DeviceInterface & deviceInterface,VkDevice device,bool signaled,uint32_t numFences,VkFence * fence)501 void createFences(const DeviceInterface &deviceInterface, VkDevice device, bool signaled, uint32_t numFences,
502                   VkFence *fence)
503 {
504     VkFenceCreateInfo fenceState;
505     VkFenceCreateFlags signalFlag = signaled ? VK_FENCE_CREATE_SIGNALED_BIT : 0;
506 
507     deMemset(&fenceState, 0xcd, sizeof(fenceState));
508     fenceState.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
509     fenceState.pNext = DE_NULL;
510     fenceState.flags = signalFlag;
511 
512     for (uint32_t ndx = 0; ndx < numFences; ndx++)
513         VK_CHECK(deviceInterface.createFence(device, &fenceState, DE_NULL, &fence[ndx]));
514 }
515 
destroyFences(const DeviceInterface & deviceInterface,VkDevice device,uint32_t numFences,VkFence * fence)516 void destroyFences(const DeviceInterface &deviceInterface, VkDevice device, uint32_t numFences, VkFence *fence)
517 {
518     for (uint32_t ndx = 0; ndx < numFences; ndx++)
519         deviceInterface.destroyFence(device, fence[ndx], DE_NULL);
520 }
521 
522 struct RenderInfo
523 {
524     int32_t width;
525     int32_t height;
526     uint32_t vertexBufferSize;
527     VkBuffer vertexBuffer;
528     VkImage image;
529     VkCommandBuffer commandBuffer;
530     VkRenderPass renderPass;
531     VkFramebuffer framebuffer;
532     VkPipeline pipeline;
533     uint32_t mipLevels;
534     const uint32_t *queueFamilyNdxList;
535     uint32_t queueFamilyNdxCount;
536     bool waitEvent;
537     VkEvent event;
538     vector<VkImageMemoryBarrier> *barriers;
539 };
540 
recordRenderPass(const DeviceInterface & deviceInterface,const RenderInfo & renderInfo)541 void recordRenderPass(const DeviceInterface &deviceInterface, const RenderInfo &renderInfo)
542 {
543     const VkDeviceSize bindingOffset = 0;
544     VkImageMemoryBarrier renderBarrier;
545 
546     if (renderInfo.waitEvent)
547         deviceInterface.cmdWaitEvents(renderInfo.commandBuffer, 1, &renderInfo.event, VK_PIPELINE_STAGE_HOST_BIT,
548                                       VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, DE_NULL, 0, DE_NULL, 0, DE_NULL);
549 
550     beginRenderPass(deviceInterface, renderInfo.commandBuffer, renderInfo.renderPass, renderInfo.framebuffer,
551                     makeRect2D(0, 0, renderInfo.width, renderInfo.height), tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f));
552     deviceInterface.cmdBindPipeline(renderInfo.commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, renderInfo.pipeline);
553     deviceInterface.cmdBindVertexBuffers(renderInfo.commandBuffer, 0u, 1u, &renderInfo.vertexBuffer, &bindingOffset);
554     deviceInterface.cmdDraw(renderInfo.commandBuffer, renderInfo.vertexBufferSize, 1, 0, 0);
555     endRenderPass(deviceInterface, renderInfo.commandBuffer);
556 
557     deMemset(&renderBarrier, 0xcd, sizeof(renderBarrier));
558     renderBarrier.sType                           = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
559     renderBarrier.pNext                           = DE_NULL;
560     renderBarrier.srcAccessMask                   = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
561     renderBarrier.dstAccessMask                   = VK_ACCESS_TRANSFER_READ_BIT;
562     renderBarrier.oldLayout                       = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
563     renderBarrier.newLayout                       = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
564     renderBarrier.srcQueueFamilyIndex             = renderInfo.queueFamilyNdxList[0];
565     renderBarrier.dstQueueFamilyIndex             = renderInfo.queueFamilyNdxList[renderInfo.queueFamilyNdxCount - 1];
566     renderBarrier.image                           = renderInfo.image;
567     renderBarrier.subresourceRange.aspectMask     = VK_IMAGE_ASPECT_COLOR_BIT;
568     renderBarrier.subresourceRange.baseMipLevel   = 0;
569     renderBarrier.subresourceRange.levelCount     = renderInfo.mipLevels;
570     renderBarrier.subresourceRange.baseArrayLayer = 0;
571     renderBarrier.subresourceRange.layerCount     = 1;
572     renderInfo.barriers->push_back(renderBarrier);
573 }
574 
575 struct TransferInfo
576 {
577     VkCommandBuffer commandBuffer;
578     uint32_t width;
579     uint32_t height;
580     VkImage image;
581     VkBuffer buffer;
582     VkDeviceSize size;
583     uint32_t mipLevel;
584     VkOffset3D imageOffset;
585     vector<VkBufferMemoryBarrier> *barriers;
586 };
587 
copyToCPU(const DeviceInterface & vkd,TransferInfo * transferInfo)588 void copyToCPU(const DeviceInterface &vkd, TransferInfo *transferInfo)
589 {
590     VkBufferImageCopy copyState;
591 
592     copyState.bufferOffset                    = 0;
593     copyState.bufferRowLength                 = transferInfo->width;
594     copyState.bufferImageHeight               = transferInfo->height;
595     copyState.imageSubresource.aspectMask     = VK_IMAGE_ASPECT_COLOR_BIT;
596     copyState.imageSubresource.mipLevel       = transferInfo->mipLevel;
597     copyState.imageSubresource.baseArrayLayer = 0;
598     copyState.imageSubresource.layerCount     = 1;
599     copyState.imageOffset                     = transferInfo->imageOffset;
600     copyState.imageExtent.width               = (int32_t)(transferInfo->width);
601     copyState.imageExtent.height              = (int32_t)(transferInfo->height);
602     copyState.imageExtent.depth               = 1;
603 
604     vkd.cmdCopyImageToBuffer(transferInfo->commandBuffer, transferInfo->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
605                              transferInfo->buffer, 1, &copyState);
606 
607     {
608         VkBufferMemoryBarrier bufferBarrier;
609         deMemset(&bufferBarrier, 0xcd, sizeof(bufferBarrier));
610         bufferBarrier.sType               = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
611         bufferBarrier.pNext               = DE_NULL;
612         bufferBarrier.srcAccessMask       = VK_ACCESS_TRANSFER_WRITE_BIT;
613         bufferBarrier.dstAccessMask       = VK_ACCESS_HOST_READ_BIT;
614         bufferBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
615         bufferBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
616         bufferBarrier.buffer              = transferInfo->buffer;
617         bufferBarrier.offset              = 0;
618         bufferBarrier.size                = transferInfo->size;
619         transferInfo->barriers->push_back(bufferBarrier);
620     }
621 }
622 
623 struct TestContext
624 {
625     const DeviceInterface &vkd;
626     const VkDevice device;
627     const uint32_t queueFamilyIndex;
628     const BinaryCollection &binaryCollection;
629     Allocator &allocator;
630     de::SharedPtr<vk::ResourceInterface> resourceInterface;
631 
632     const tcu::Vec4 *vertices;
633     uint32_t numVertices;
634     tcu::IVec2 renderDimension;
635     VkFence fences[2];
636     VkDeviceSize renderSize;
637     MovePtr<Allocation> renderReadBuffer;
638     MovePtr<Allocation> vertexBufferAllocation;
639     vk::Move<VkBuffer> vertexBuffer;
640     vk::Move<VkBuffer> renderBuffer;
641     bool waitEvent;
642     VkEvent event;
643     vk::Move<VkImage> image;
644     vk::Move<VkImageView> imageView;
645     vk::Move<VkFramebuffer> framebuffer;
646     vk::Move<VkCommandPool> commandPool;
647     vk::Move<VkCommandBuffer> cmdBuffer;
648     vk::Move<VkRenderPass> renderPass;
649     vk::Move<VkPipelineCache> pipelineCache;
650     vk::Move<VkPipeline> pipeline;
651     MovePtr<Allocation> imageAllocation;
652 
TestContextvkt::synchronization::__anon00fc1daf0111::TestContext653     TestContext(const DeviceInterface &vkd_, const VkDevice device_, uint32_t queueFamilyIndex_,
654                 const BinaryCollection &binaryCollection_, Allocator &allocator_,
655                 de::SharedPtr<vk::ResourceInterface> resourceInterface_)
656         : vkd(vkd_)
657         , device(device_)
658         , queueFamilyIndex(queueFamilyIndex_)
659         , binaryCollection(binaryCollection_)
660         , allocator(allocator_)
661         , resourceInterface(resourceInterface_)
662         , vertices(0)
663         , numVertices(0)
664         , renderSize(0)
665         , waitEvent(false)
666     {
667         createFences(vkd, device, false, DE_LENGTH_OF_ARRAY(fences), fences);
668     }
669 
~TestContextvkt::synchronization::__anon00fc1daf0111::TestContext670     ~TestContext()
671     {
672         destroyFences(vkd, device, DE_LENGTH_OF_ARRAY(fences), fences);
673     }
674 };
675 
generateWork(TestContext & testContext)676 void generateWork(TestContext &testContext)
677 {
678     const DeviceInterface &deviceInterface = testContext.vkd;
679     const uint32_t queueFamilyNdx          = testContext.queueFamilyIndex;
680 
681     // \note VkShaderModule is consumed by vkCreate*Pipelines() so it can be deleted
682     //       as pipeline has been constructed.
683     const vk::Unique<VkShaderModule> vertShaderModule(createShaderModule(deviceInterface, testContext.device,
684                                                                          testContext.binaryCollection.get("glslvert"),
685                                                                          (VkShaderModuleCreateFlags)0));
686 
687     const vk::Unique<VkShaderModule> fragShaderModule(createShaderModule(deviceInterface, testContext.device,
688                                                                          testContext.binaryCollection.get("glslfrag"),
689                                                                          (VkShaderModuleCreateFlags)0));
690     const VkPipelineShaderStageCreateInfo shaderStageParams[] = {
691         {
692             VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
693             DE_NULL,
694             (VkPipelineShaderStageCreateFlags)0,
695             VK_SHADER_STAGE_VERTEX_BIT,
696             *vertShaderModule,
697             "main",
698             (const VkSpecializationInfo *)DE_NULL,
699         },
700         {
701             VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
702             DE_NULL,
703             (VkPipelineShaderStageCreateFlags)0,
704             VK_SHADER_STAGE_FRAGMENT_BIT,
705             *fragShaderModule,
706             "main",
707             (const VkSpecializationInfo *)DE_NULL,
708         }};
709 
710     vk::Move<VkPipelineLayout> layout;
711     vector<ShaderDescParams> shaderDescParams;
712     VertexDesc vertexDesc;
713     vector<VertexDesc> vertexDescList;
714     vector<VkVertexInputAttributeDescription> attrList;
715     vector<VkBufferMemoryBarrier> bufferMemoryBarrier;
716     uint32_t memoryBarrierNdx;
717     uint32_t bufferMemoryBarrierNdx;
718     uint32_t imageMemoryBarrierNdx;
719     vector<VkVertexInputBindingDescription> bindingList;
720     VkPipelineVertexInputStateCreateInfo vertexInputState;
721     VkPipelineInputAssemblyStateCreateInfo inputAssemblyState;
722     VkPipelineDepthStencilStateCreateInfo depthStencilState;
723     VkPipelineColorBlendAttachmentState blendAttachment;
724     VkPipelineColorBlendStateCreateInfo blendState;
725     VkPipelineLayoutCreateInfo pipelineLayoutState;
726     VkGraphicsPipelineCreateInfo pipelineState;
727     VkPipelineCacheCreateInfo cacheState;
728     VkViewport viewport;
729     VkPipelineViewportStateCreateInfo viewportInfo;
730     VkRect2D scissor;
731     BufferParameters bufferParameters;
732     Buffer buffer;
733     RenderInfo renderInfo;
734     ImageParameters imageParameters;
735     Image image;
736     VkPipelineRasterizationStateCreateInfo rasterState;
737     VkPipelineMultisampleStateCreateInfo multisampleState;
738     VkFramebufferCreateInfo fbState;
739     VkCommandBufferBeginInfo commandBufRecordState;
740     VkCommandBufferInheritanceInfo inheritanceInfo;
741     RenderPassParameters renderPassParameters;
742     TransferInfo transferInfo;
743     vector<void *> barrierList;
744     VkExtent3D extent;
745     vector<VkMemoryBarrier> memoryBarriers;
746     vector<VkBufferMemoryBarrier> bufferBarriers;
747     vector<VkImageMemoryBarrier> imageBarriers;
748 
749     memoryBarrierNdx       = 0;
750     bufferMemoryBarrierNdx = 0;
751     imageMemoryBarrierNdx  = 0;
752     buffer.memoryBarrier.resize(memoryBarrierNdx);
753     bufferMemoryBarrier.resize(bufferMemoryBarrierNdx);
754     image.imageMemoryBarrier.resize(imageMemoryBarrierNdx);
755 
756     memoryBarriers.resize(0);
757     bufferBarriers.resize(0);
758     imageBarriers.resize(0);
759 
760     bufferParameters.memory            = testContext.vertices;
761     bufferParameters.size              = testContext.numVertices * sizeof(tcu::Vec4);
762     bufferParameters.usage             = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
763     bufferParameters.sharingMode       = VK_SHARING_MODE_EXCLUSIVE;
764     bufferParameters.queueFamilyCount  = 1;
765     bufferParameters.queueFamilyIndex  = &queueFamilyNdx;
766     bufferParameters.inputBarrierFlags = VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
767     createVulkanBuffer(deviceInterface, testContext.device, testContext.allocator, bufferParameters, buffer,
768                        MemoryRequirement::HostVisible);
769     testContext.vertexBufferAllocation = buffer.allocation;
770     testContext.vertexBuffer           = buffer.buffer;
771 
772     bufferParameters.memory            = DE_NULL;
773     bufferParameters.size              = testContext.renderSize;
774     bufferParameters.usage             = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
775     bufferParameters.sharingMode       = VK_SHARING_MODE_EXCLUSIVE;
776     bufferParameters.queueFamilyCount  = 1;
777     bufferParameters.queueFamilyIndex  = &queueFamilyNdx;
778     bufferParameters.inputBarrierFlags = 0;
779     createVulkanBuffer(deviceInterface, testContext.device, testContext.allocator, bufferParameters, buffer,
780                        MemoryRequirement::HostVisible);
781     testContext.renderReadBuffer = buffer.allocation;
782     testContext.renderBuffer     = buffer.buffer;
783 
784     extent.width  = testContext.renderDimension.x();
785     extent.height = testContext.renderDimension.y();
786     extent.depth  = 1;
787 
788     imageParameters.imageType          = VK_IMAGE_TYPE_2D;
789     imageParameters.format             = VK_FORMAT_R8G8B8A8_UNORM;
790     imageParameters.extent3D           = extent;
791     imageParameters.mipLevels          = 1;
792     imageParameters.samples            = VK_SAMPLE_COUNT_1_BIT;
793     imageParameters.tiling             = VK_IMAGE_TILING_OPTIMAL;
794     imageParameters.usage              = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
795     imageParameters.sharingMode        = VK_SHARING_MODE_EXCLUSIVE;
796     imageParameters.queueFamilyCount   = 1;
797     imageParameters.queueFamilyNdxList = &queueFamilyNdx;
798     imageParameters.initialLayout      = VK_IMAGE_LAYOUT_UNDEFINED;
799     imageParameters.finalLayout        = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
800     imageParameters.barrierInputMask   = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
801     createVulkanImage(deviceInterface, testContext.device, testContext.allocator, imageParameters, image,
802                       MemoryRequirement::Any);
803     testContext.imageAllocation = image.allocation;
804     testContext.image           = image.image;
805 
806     for (size_t ndx = 0; ndx < image.imageMemoryBarrier.size(); ++ndx)
807         imageBarriers.push_back(image.imageMemoryBarrier[ndx]);
808 
809     renderPassParameters.colorFormat  = VK_FORMAT_R8G8B8A8_UNORM;
810     renderPassParameters.colorSamples = VK_SAMPLE_COUNT_1_BIT;
811     createColorOnlyRenderPass(deviceInterface, testContext.device, renderPassParameters, testContext.renderPass);
812 
813     vertexDesc.location = 0;
814     vertexDesc.format   = VK_FORMAT_R32G32B32A32_SFLOAT;
815     vertexDesc.stride   = sizeof(tcu::Vec4);
816     vertexDesc.offset   = 0;
817     vertexDescList.push_back(vertexDesc);
818 
819     createVertexInfo(vertexDescList, bindingList, attrList, vertexInputState);
820 
821     deMemset(&inputAssemblyState, 0xcd, sizeof(inputAssemblyState));
822     inputAssemblyState.sType                  = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
823     inputAssemblyState.pNext                  = DE_NULL;
824     inputAssemblyState.flags                  = 0u;
825     inputAssemblyState.topology               = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
826     inputAssemblyState.primitiveRestartEnable = false;
827 
828     viewport.x        = 0;
829     viewport.y        = 0;
830     viewport.width    = (float)testContext.renderDimension.x();
831     viewport.height   = (float)testContext.renderDimension.y();
832     viewport.minDepth = 0;
833     viewport.maxDepth = 1;
834 
835     scissor.offset.x      = 0;
836     scissor.offset.y      = 0;
837     scissor.extent.width  = testContext.renderDimension.x();
838     scissor.extent.height = testContext.renderDimension.y();
839 
840     deMemset(&viewportInfo, 0xcd, sizeof(viewportInfo));
841     viewportInfo.sType         = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
842     viewportInfo.pNext         = DE_NULL;
843     viewportInfo.flags         = 0;
844     viewportInfo.viewportCount = 1;
845     viewportInfo.pViewports    = &viewport;
846     viewportInfo.scissorCount  = 1;
847     viewportInfo.pScissors     = &scissor;
848 
849     deMemset(&rasterState, 0xcd, sizeof(rasterState));
850     rasterState.sType                   = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
851     rasterState.pNext                   = DE_NULL;
852     rasterState.flags                   = 0;
853     rasterState.depthClampEnable        = VK_FALSE;
854     rasterState.rasterizerDiscardEnable = VK_FALSE;
855     rasterState.polygonMode             = VK_POLYGON_MODE_FILL;
856     rasterState.cullMode                = VK_CULL_MODE_NONE;
857     rasterState.frontFace               = VK_FRONT_FACE_COUNTER_CLOCKWISE;
858     rasterState.depthBiasEnable         = VK_FALSE;
859     rasterState.lineWidth               = 1;
860 
861     deMemset(&multisampleState, 0xcd, sizeof(multisampleState));
862     multisampleState.sType                 = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
863     multisampleState.pNext                 = DE_NULL;
864     multisampleState.flags                 = 0;
865     multisampleState.rasterizationSamples  = VK_SAMPLE_COUNT_1_BIT;
866     multisampleState.sampleShadingEnable   = VK_FALSE;
867     multisampleState.pSampleMask           = DE_NULL;
868     multisampleState.alphaToCoverageEnable = VK_FALSE;
869     multisampleState.alphaToOneEnable      = VK_FALSE;
870 
871     deMemset(&depthStencilState, 0xcd, sizeof(depthStencilState));
872     depthStencilState.sType                 = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
873     depthStencilState.pNext                 = DE_NULL;
874     depthStencilState.flags                 = 0;
875     depthStencilState.depthTestEnable       = VK_FALSE;
876     depthStencilState.depthWriteEnable      = VK_FALSE;
877     depthStencilState.depthCompareOp        = VK_COMPARE_OP_ALWAYS;
878     depthStencilState.depthBoundsTestEnable = VK_FALSE;
879     depthStencilState.stencilTestEnable     = VK_FALSE;
880     depthStencilState.front.failOp          = VK_STENCIL_OP_KEEP;
881     depthStencilState.front.passOp          = VK_STENCIL_OP_KEEP;
882     depthStencilState.front.depthFailOp     = VK_STENCIL_OP_KEEP;
883     depthStencilState.front.compareOp       = VK_COMPARE_OP_ALWAYS;
884     depthStencilState.front.compareMask     = 0u;
885     depthStencilState.front.writeMask       = 0u;
886     depthStencilState.front.reference       = 0u;
887     depthStencilState.back                  = depthStencilState.front;
888 
889     deMemset(&blendAttachment, 0xcd, sizeof(blendAttachment));
890     blendAttachment.blendEnable         = VK_FALSE;
891     blendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_ZERO;
892     blendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
893     blendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO;
894     blendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
895     blendAttachment.colorBlendOp        = VK_BLEND_OP_ADD;
896     blendAttachment.alphaBlendOp        = VK_BLEND_OP_ADD;
897     blendAttachment.colorWriteMask =
898         VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
899 
900     deMemset(&blendState, 0xcd, sizeof(blendState));
901     blendState.sType           = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
902     blendState.pNext           = DE_NULL;
903     blendState.flags           = 0;
904     blendState.logicOpEnable   = VK_FALSE;
905     blendState.logicOp         = VK_LOGIC_OP_COPY;
906     blendState.attachmentCount = 1;
907     blendState.pAttachments    = &blendAttachment;
908 
909     deMemset(&pipelineLayoutState, 0xcd, sizeof(pipelineLayoutState));
910     pipelineLayoutState.sType                  = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
911     pipelineLayoutState.pNext                  = DE_NULL;
912     pipelineLayoutState.flags                  = 0;
913     pipelineLayoutState.setLayoutCount         = 0;
914     pipelineLayoutState.pSetLayouts            = DE_NULL;
915     pipelineLayoutState.pushConstantRangeCount = 0;
916     pipelineLayoutState.pPushConstantRanges    = DE_NULL;
917     layout = createPipelineLayout(deviceInterface, testContext.device, &pipelineLayoutState, DE_NULL);
918 
919     deMemset(&pipelineState, 0xcd, sizeof(pipelineState));
920     pipelineState.sType               = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
921     pipelineState.pNext               = DE_NULL;
922     pipelineState.flags               = 0;
923     pipelineState.stageCount          = DE_LENGTH_OF_ARRAY(shaderStageParams);
924     pipelineState.pStages             = &shaderStageParams[0];
925     pipelineState.pVertexInputState   = &vertexInputState;
926     pipelineState.pInputAssemblyState = &inputAssemblyState;
927     pipelineState.pTessellationState  = DE_NULL;
928     pipelineState.pViewportState      = &viewportInfo;
929     pipelineState.pRasterizationState = &rasterState;
930     pipelineState.pMultisampleState   = &multisampleState;
931     pipelineState.pDepthStencilState  = &depthStencilState;
932     pipelineState.pColorBlendState    = &blendState;
933     pipelineState.pDynamicState       = (const VkPipelineDynamicStateCreateInfo *)DE_NULL;
934     pipelineState.layout              = layout.get();
935     pipelineState.renderPass          = testContext.renderPass.get();
936     pipelineState.subpass             = 0;
937     pipelineState.basePipelineHandle  = DE_NULL;
938     pipelineState.basePipelineIndex   = 0;
939 
940     deMemset(&cacheState, 0xcd, sizeof(cacheState));
941     cacheState.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
942     cacheState.pNext = DE_NULL;
943 #ifndef CTS_USES_VULKANSC
944     cacheState.flags           = (VkPipelineCacheCreateFlags)0u;
945     cacheState.initialDataSize = 0;
946     cacheState.pInitialData    = DE_NULL;
947 #else
948     cacheState.flags = VK_PIPELINE_CACHE_CREATE_READ_ONLY_BIT | VK_PIPELINE_CACHE_CREATE_USE_APPLICATION_STORAGE_BIT;
949     cacheState.initialDataSize = testContext.resourceInterface->getCacheDataSize();
950     cacheState.pInitialData    = testContext.resourceInterface->getCacheData();
951 #endif
952 
953     testContext.pipelineCache = createPipelineCache(deviceInterface, testContext.device, &cacheState);
954     testContext.pipeline =
955         createGraphicsPipeline(deviceInterface, testContext.device, testContext.pipelineCache.get(), &pipelineState);
956 
957     deMemset(&fbState, 0xcd, sizeof(fbState));
958     fbState.sType           = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
959     fbState.pNext           = DE_NULL;
960     fbState.flags           = 0;
961     fbState.renderPass      = testContext.renderPass.get();
962     fbState.attachmentCount = 1;
963     fbState.pAttachments    = &image.imageView.get();
964     fbState.width           = (uint32_t)testContext.renderDimension.x();
965     fbState.height          = (uint32_t)testContext.renderDimension.y();
966     fbState.layers          = 1;
967 
968     testContext.framebuffer = createFramebuffer(deviceInterface, testContext.device, &fbState);
969     testContext.imageView   = image.imageView;
970 
971     deMemset(&inheritanceInfo, 0xcd, sizeof(inheritanceInfo));
972     inheritanceInfo.sType                = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
973     inheritanceInfo.pNext                = DE_NULL;
974     inheritanceInfo.renderPass           = testContext.renderPass.get();
975     inheritanceInfo.subpass              = 0;
976     inheritanceInfo.framebuffer          = *testContext.framebuffer;
977     inheritanceInfo.occlusionQueryEnable = VK_FALSE;
978     inheritanceInfo.queryFlags           = 0u;
979     inheritanceInfo.pipelineStatistics   = 0u;
980 
981     deMemset(&commandBufRecordState, 0xcd, sizeof(commandBufRecordState));
982     commandBufRecordState.sType            = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
983     commandBufRecordState.pNext            = DE_NULL;
984     commandBufRecordState.flags            = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
985     commandBufRecordState.pInheritanceInfo = &inheritanceInfo;
986     VK_CHECK(deviceInterface.beginCommandBuffer(testContext.cmdBuffer.get(), &commandBufRecordState));
987 
988     deviceInterface.cmdPipelineBarrier(
989         testContext.cmdBuffer.get(), VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, false,
990         (uint32_t)memoryBarriers.size(), (memoryBarriers.empty() ? DE_NULL : &memoryBarriers[0]),
991         (uint32_t)bufferBarriers.size(), (bufferBarriers.empty() ? DE_NULL : &bufferBarriers[0]),
992         (uint32_t)imageBarriers.size(), (imageBarriers.empty() ? DE_NULL : &imageBarriers[0]));
993 
994     memoryBarriers.resize(0);
995     bufferBarriers.resize(0);
996     imageBarriers.resize(0);
997 
998     renderInfo.width               = testContext.renderDimension.x();
999     renderInfo.height              = testContext.renderDimension.y();
1000     renderInfo.vertexBufferSize    = testContext.numVertices;
1001     renderInfo.vertexBuffer        = testContext.vertexBuffer.get();
1002     renderInfo.image               = testContext.image.get();
1003     renderInfo.commandBuffer       = testContext.cmdBuffer.get();
1004     renderInfo.renderPass          = testContext.renderPass.get();
1005     renderInfo.framebuffer         = *testContext.framebuffer;
1006     renderInfo.pipeline            = *testContext.pipeline;
1007     renderInfo.mipLevels           = 1;
1008     renderInfo.queueFamilyNdxList  = &queueFamilyNdx;
1009     renderInfo.queueFamilyNdxCount = 1;
1010     renderInfo.waitEvent           = testContext.waitEvent;
1011     renderInfo.event               = testContext.event;
1012     renderInfo.barriers            = &imageBarriers;
1013     recordRenderPass(deviceInterface, renderInfo);
1014 
1015     deviceInterface.cmdPipelineBarrier(
1016         renderInfo.commandBuffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, false,
1017         (uint32_t)memoryBarriers.size(), (memoryBarriers.empty() ? DE_NULL : &memoryBarriers[0]),
1018         (uint32_t)bufferBarriers.size(), (bufferBarriers.empty() ? DE_NULL : &bufferBarriers[0]),
1019         (uint32_t)imageBarriers.size(), (imageBarriers.empty() ? DE_NULL : &imageBarriers[0]));
1020 
1021     memoryBarriers.resize(0);
1022     bufferBarriers.resize(0);
1023     imageBarriers.resize(0);
1024 
1025     transferInfo.commandBuffer = renderInfo.commandBuffer;
1026     transferInfo.width         = testContext.renderDimension.x();
1027     transferInfo.height        = testContext.renderDimension.y();
1028     transferInfo.image         = renderInfo.image;
1029     transferInfo.buffer        = testContext.renderBuffer.get();
1030     transferInfo.size          = testContext.renderSize;
1031     transferInfo.mipLevel      = 0;
1032     transferInfo.imageOffset.x = 0;
1033     transferInfo.imageOffset.y = 0;
1034     transferInfo.imageOffset.z = 0;
1035     transferInfo.barriers      = &bufferBarriers;
1036     copyToCPU(deviceInterface, &transferInfo);
1037 
1038     deviceInterface.cmdPipelineBarrier(
1039         transferInfo.commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, false,
1040         (uint32_t)memoryBarriers.size(), (memoryBarriers.empty() ? DE_NULL : &memoryBarriers[0]),
1041         (uint32_t)bufferBarriers.size(), (bufferBarriers.empty() ? DE_NULL : &bufferBarriers[0]),
1042         (uint32_t)imageBarriers.size(), (imageBarriers.empty() ? DE_NULL : &imageBarriers[0]));
1043 
1044     memoryBarriers.resize(0);
1045     bufferBarriers.resize(0);
1046     imageBarriers.resize(0);
1047 
1048     endCommandBuffer(deviceInterface, transferInfo.commandBuffer);
1049 }
1050 
testFences(Context & context)1051 tcu::TestStatus testFences(Context &context)
1052 {
1053     TestLog &log                           = context.getTestContext().getLog();
1054     const DeviceInterface &deviceInterface = context.getDeviceInterface();
1055     const VkQueue queue                    = context.getUniversalQueue();
1056     const uint32_t queueFamilyIdx          = context.getUniversalQueueFamilyIndex();
1057     VkDevice device                        = context.getDevice();
1058     VkResult waitStatus;
1059     VkResult fenceStatus;
1060     TestContext testContext(deviceInterface, device, queueFamilyIdx, context.getBinaryCollection(),
1061                             context.getDefaultAllocator(), context.getResourceInterface());
1062     void *resultImage;
1063 
1064     const tcu::Vec4 vertices[] = {tcu::Vec4(0.5f, 0.5f, 0.0f, 1.0f), tcu::Vec4(-0.5f, 0.5f, 0.0f, 1.0f),
1065                                   tcu::Vec4(0.0f, -0.5f, 0.0f, 1.0f)};
1066 
1067     testContext.vertices        = vertices;
1068     testContext.numVertices     = DE_LENGTH_OF_ARRAY(vertices);
1069     testContext.renderDimension = tcu::IVec2(256, 256);
1070     testContext.renderSize      = sizeof(uint32_t) * testContext.renderDimension.x() * testContext.renderDimension.y();
1071 
1072     createCommandBuffer(deviceInterface, device, queueFamilyIdx, &testContext.cmdBuffer, &testContext.commandPool);
1073     generateWork(testContext);
1074 
1075     // Default status is unsignaled
1076     fenceStatus = deviceInterface.getFenceStatus(device, testContext.fences[0]);
1077     if (fenceStatus != VK_NOT_READY)
1078     {
1079         log << TestLog::Message << "testSynchronizationPrimitives fence 0 should be reset but status is "
1080             << getResultName(fenceStatus) << TestLog::EndMessage;
1081         return tcu::TestStatus::fail("Fence in incorrect state");
1082     }
1083     fenceStatus = deviceInterface.getFenceStatus(device, testContext.fences[1]);
1084     if (fenceStatus != VK_NOT_READY)
1085     {
1086         log << TestLog::Message << "testSynchronizationPrimitives fence 1 should be reset but status is "
1087             << getResultName(fenceStatus) << TestLog::EndMessage;
1088         return tcu::TestStatus::fail("Fence in incorrect state");
1089     }
1090 
1091     VkSubmitInfo submitInfo{VK_STRUCTURE_TYPE_SUBMIT_INFO, DE_NULL, 0u,     DE_NULL, DE_NULL, 1u,
1092                             &testContext.cmdBuffer.get(),  0,       DE_NULL};
1093     VK_CHECK(deviceInterface.queueSubmit(queue, 1, &submitInfo, testContext.fences[0]));
1094 
1095     // Wait with timeout = 0
1096     waitStatus = deviceInterface.waitForFences(device, 1, &testContext.fences[0], true, 0u);
1097     if (waitStatus != VK_SUCCESS && waitStatus != VK_TIMEOUT)
1098     {
1099         // Will most likely end with VK_TIMEOUT
1100         log << TestLog::Message << "testSynchPrimitives failed to wait for a single fence" << TestLog::EndMessage;
1101         return tcu::TestStatus::fail("Failed to wait for a single fence");
1102     }
1103 
1104     // Wait with a reasonable timeout
1105     waitStatus = deviceInterface.waitForFences(device, 1, &testContext.fences[0], true, DEFAULT_TIMEOUT);
1106     if (waitStatus != VK_SUCCESS && waitStatus != VK_TIMEOUT)
1107     {
1108         // \note Wait can end with a timeout if DEFAULT_TIMEOUT is not sufficient
1109         log << TestLog::Message << "testSynchPrimitives failed to wait for a single fence" << TestLog::EndMessage;
1110         return tcu::TestStatus::fail("Failed to wait for a single fence");
1111     }
1112 
1113     // Wait for work on fences[0] to actually complete
1114     waitStatus =
1115         deviceInterface.waitForFences(device, 1, &testContext.fences[0], true, std::numeric_limits<uint64_t>::max());
1116     if (waitStatus != VK_SUCCESS)
1117     {
1118         log << TestLog::Message << "testSynchPrimitives failed to wait for a fence" << TestLog::EndMessage;
1119         return tcu::TestStatus::fail("failed to wait for a fence");
1120     }
1121 
1122     // Wait until timeout on a fence that has not been submitted
1123     waitStatus = deviceInterface.waitForFences(device, 1, &testContext.fences[1], true, 1);
1124     if (waitStatus != VK_TIMEOUT)
1125     {
1126         log << TestLog::Message << "testSyncPrimitives failed to timeout on wait for single fence"
1127             << TestLog::EndMessage;
1128         return tcu::TestStatus::fail("failed to timeout on wait for single fence");
1129     }
1130 
1131     // Check that the fence is signaled after the wait
1132     fenceStatus = deviceInterface.getFenceStatus(device, testContext.fences[0]);
1133     if (fenceStatus != VK_SUCCESS)
1134     {
1135         log << TestLog::Message << "testSynchronizationPrimitives fence should be signaled but status is "
1136             << getResultName(fenceStatus) << TestLog::EndMessage;
1137         return tcu::TestStatus::fail("Fence in incorrect state");
1138     }
1139 
1140     invalidateAlloc(deviceInterface, device, *testContext.renderReadBuffer);
1141     resultImage = testContext.renderReadBuffer->getHostPtr();
1142 
1143     log << TestLog::Image(
1144         "result", "result",
1145         tcu::ConstPixelBufferAccess(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8),
1146                                     testContext.renderDimension.x(), testContext.renderDimension.y(), 1, resultImage));
1147 
1148     return TestStatus::pass("synchronization-fences passed");
1149 }
1150 
testSemaphores(Context & context,SemaphoreTestConfig config)1151 tcu::TestStatus testSemaphores(Context &context, SemaphoreTestConfig config)
1152 {
1153     if (config.semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE && !context.getTimelineSemaphoreFeatures().timelineSemaphore)
1154         TCU_THROW(NotSupportedError, "Timeline semaphore not supported");
1155 
1156     TestLog &log                               = context.getTestContext().getLog();
1157     const PlatformInterface &platformInterface = context.getPlatformInterface();
1158     const auto instance                        = context.getInstance();
1159     const auto &instanceDriver                 = context.getInstanceInterface();
1160     const VkPhysicalDevice physicalDevice =
1161         chooseDevice(instanceDriver, instance, context.getTestContext().getCommandLine());
1162     uint32_t queueFamilyIdx;
1163     bool isTimelineSemaphore(config.semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE);
1164     vk::Move<VkDevice> device(createTestDevice(context, config, instance, instanceDriver, &queueFamilyIdx));
1165 
1166 #ifndef CTS_USES_VULKANSC
1167     de::MovePtr<vk::DeviceDriver> deviceInterfacePtr = de::MovePtr<DeviceDriver>(new DeviceDriver(
1168         platformInterface, instance, *device, context.getUsedApiVersion(), context.getTestContext().getCommandLine()));
1169 #else
1170     de::MovePtr<vk::DeviceDriverSC, vk::DeinitDeviceDeleter> deviceInterfacePtr =
1171         de::MovePtr<DeviceDriverSC, DeinitDeviceDeleter>(
1172             new DeviceDriverSC(platformInterface, instance, *device, context.getTestContext().getCommandLine(),
1173                                context.getResourceInterface(), context.getDeviceVulkanSC10Properties(),
1174                                context.getDeviceProperties(), context.getUsedApiVersion()),
1175             vk::DeinitDeviceDeleter(context.getResourceInterface().get(), *device));
1176 #endif // CTS_USES_VULKANSC
1177     const DeviceDriver &deviceDriver = *deviceInterfacePtr;
1178     SimpleAllocator allocator(deviceDriver, *device, getPhysicalDeviceMemoryProperties(instanceDriver, physicalDevice));
1179     const VkQueue queue[2] = {getDeviceQueue(deviceDriver, *device, queueFamilyIdx, 0),
1180                               getDeviceQueue(deviceDriver, *device, queueFamilyIdx, 1)};
1181     VkResult testStatus;
1182     TestContext testContext1(deviceDriver, device.get(), queueFamilyIdx, context.getBinaryCollection(), allocator,
1183                              context.getResourceInterface());
1184     TestContext testContext2(deviceDriver, device.get(), queueFamilyIdx, context.getBinaryCollection(), allocator,
1185                              context.getResourceInterface());
1186     Unique<VkSemaphore> semaphore(createSemaphoreType(deviceDriver, *device, config.semaphoreType));
1187     VkSemaphoreSubmitInfoKHR waitSemaphoreSubmitInfo =
1188         makeCommonSemaphoreSubmitInfo(*semaphore, 1u, VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR);
1189     VkSemaphoreSubmitInfoKHR signalSemaphoreSubmitInfo =
1190         makeCommonSemaphoreSubmitInfo(*semaphore, 1u, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR);
1191 
1192     const tcu::Vec4 vertices1[] = {tcu::Vec4(0.5f, 0.5f, 0.0f, 1.0f), tcu::Vec4(-0.5f, 0.5f, 0.0f, 1.0f),
1193                                    tcu::Vec4(0.0f, -0.5f, 0.0f, 1.0f)};
1194 
1195     const tcu::Vec4 vertices2[] = {tcu::Vec4(-0.5f, -0.5f, 0.0f, 1.0f), tcu::Vec4(+0.5f, -0.5f, 0.0f, 1.0f),
1196                                    tcu::Vec4(0.0f, +0.5f, 0.0f, 1.0f)};
1197 
1198     testContext1.vertices        = vertices1;
1199     testContext1.numVertices     = DE_LENGTH_OF_ARRAY(vertices1);
1200     testContext1.renderDimension = tcu::IVec2(256, 256);
1201     testContext1.renderSize = sizeof(uint32_t) * testContext1.renderDimension.x() * testContext1.renderDimension.y();
1202 
1203     testContext2.vertices        = vertices2;
1204     testContext2.numVertices     = DE_LENGTH_OF_ARRAY(vertices2);
1205     testContext2.renderDimension = tcu::IVec2(256, 256);
1206     testContext2.renderSize = sizeof(uint32_t) * testContext2.renderDimension.x() * testContext2.renderDimension.y();
1207 
1208     createCommandBuffer(deviceDriver, device.get(), queueFamilyIdx, &testContext1.cmdBuffer, &testContext1.commandPool);
1209     generateWork(testContext1);
1210 
1211     createCommandBuffer(deviceDriver, device.get(), queueFamilyIdx, &testContext2.cmdBuffer, &testContext2.commandPool);
1212     generateWork(testContext2);
1213 
1214     {
1215         VkCommandBufferSubmitInfoKHR commandBufferSubmitInfo =
1216             makeCommonCommandBufferSubmitInfo(testContext1.cmdBuffer.get());
1217         SynchronizationWrapperPtr synchronizationWrapper =
1218             getSynchronizationWrapper(config.synchronizationType, deviceDriver, isTimelineSemaphore);
1219         synchronizationWrapper->addSubmitInfo(
1220             0u,                         // uint32_t                                waitSemaphoreInfoCount
1221             DE_NULL,                    // const VkSemaphoreSubmitInfoKHR*        pWaitSemaphoreInfos
1222             1u,                         // uint32_t                                commandBufferInfoCount
1223             &commandBufferSubmitInfo,   // const VkCommandBufferSubmitInfoKHR*    pCommandBufferInfos
1224             1u,                         // uint32_t                                signalSemaphoreInfoCount
1225             &signalSemaphoreSubmitInfo, // const VkSemaphoreSubmitInfoKHR*        pSignalSemaphoreInfos
1226             false, isTimelineSemaphore);
1227 
1228         VK_CHECK(synchronizationWrapper->queueSubmit(queue[0], testContext1.fences[0]));
1229     }
1230 
1231     testStatus = deviceDriver.waitForFences(device.get(), 1, &testContext1.fences[0], true,
1232                                             std::numeric_limits<uint64_t>::max());
1233     if (testStatus != VK_SUCCESS)
1234     {
1235         log << TestLog::Message << "testSynchPrimitives failed to wait for a set fence" << TestLog::EndMessage;
1236         return tcu::TestStatus::fail("failed to wait for a set fence");
1237     }
1238 
1239     invalidateAlloc(deviceDriver, device.get(), *testContext1.renderReadBuffer);
1240     void *resultImage = testContext1.renderReadBuffer->getHostPtr();
1241 
1242     log << TestLog::Image("result", "result",
1243                           tcu::ConstPixelBufferAccess(
1244                               tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8),
1245                               testContext1.renderDimension.x(), testContext1.renderDimension.y(), 1, resultImage));
1246 
1247     // The difference between the second submit info is that it will use a unique cmd buffer.
1248     // First submit signals a semaphore but not wait on a semaphore, the other waits on the
1249     // semaphore but not signal it.
1250     {
1251         VkCommandBufferSubmitInfoKHR commandBufferSubmitInfo =
1252             makeCommonCommandBufferSubmitInfo(testContext2.cmdBuffer.get());
1253         SynchronizationWrapperPtr synchronizationWrapper =
1254             getSynchronizationWrapper(config.synchronizationType, deviceDriver, isTimelineSemaphore);
1255         synchronizationWrapper->addSubmitInfo(
1256             1u,                       // uint32_t                                waitSemaphoreInfoCount
1257             &waitSemaphoreSubmitInfo, // const VkSemaphoreSubmitInfoKHR*        pWaitSemaphoreInfos
1258             1u,                       // uint32_t                                commandBufferInfoCount
1259             &commandBufferSubmitInfo, // const VkCommandBufferSubmitInfoKHR*    pCommandBufferInfos
1260             0u,                       // uint32_t                                signalSemaphoreInfoCount
1261             DE_NULL,                  // const VkSemaphoreSubmitInfoKHR*        pSignalSemaphoreInfos
1262             isTimelineSemaphore);
1263 
1264         VK_CHECK(synchronizationWrapper->queueSubmit(queue[1], testContext2.fences[0]));
1265     }
1266 
1267     testStatus = deviceDriver.waitForFences(device.get(), 1, &testContext2.fences[0], true,
1268                                             std::numeric_limits<uint64_t>::max());
1269     if (testStatus != VK_SUCCESS)
1270     {
1271         log << TestLog::Message << "testSynchPrimitives failed to wait for a set fence" << TestLog::EndMessage;
1272         return tcu::TestStatus::fail("failed to wait for a set fence");
1273     }
1274 
1275     invalidateAlloc(deviceDriver, device.get(), *testContext2.renderReadBuffer);
1276     resultImage = testContext2.renderReadBuffer->getHostPtr();
1277 
1278     log << TestLog::Image("result", "result",
1279                           tcu::ConstPixelBufferAccess(
1280                               tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8),
1281                               testContext2.renderDimension.x(), testContext2.renderDimension.y(), 1, resultImage));
1282 
1283     return tcu::TestStatus::pass("synchronization-semaphores passed");
1284 }
1285 
checkSupport(Context & context,SemaphoreTestConfig config)1286 void checkSupport(Context &context, SemaphoreTestConfig config)
1287 {
1288     if (config.semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE)
1289         context.requireDeviceFunctionality("VK_KHR_timeline_semaphore");
1290     if (config.synchronizationType == SynchronizationType::SYNCHRONIZATION2)
1291         context.requireDeviceFunctionality("VK_KHR_synchronization2");
1292 }
1293 
1294 } // namespace
1295 
createSmokeTests(tcu::TestContext & textCtx)1296 tcu::TestCaseGroup *createSmokeTests(tcu::TestContext &textCtx)
1297 {
1298     SynchronizationType type(SynchronizationType::LEGACY);
1299     de::MovePtr<tcu::TestCaseGroup> smokeTests(new tcu::TestCaseGroup(textCtx, "smoke"));
1300 
1301     addFunctionCaseWithPrograms(smokeTests.get(), "fences", buildShaders, testFences);
1302     addFunctionCaseWithPrograms(smokeTests.get(), "binary_semaphores", checkSupport, initShaders, testSemaphores,
1303                                 SemaphoreTestConfig{type, VK_SEMAPHORE_TYPE_BINARY});
1304     addFunctionCaseWithPrograms(smokeTests.get(), "timeline_semaphores", checkSupport, initShaders, testSemaphores,
1305                                 SemaphoreTestConfig{type, VK_SEMAPHORE_TYPE_TIMELINE});
1306 
1307     return smokeTests.release();
1308 }
1309 
createSynchronization2SmokeTests(tcu::TestContext & textCtx)1310 tcu::TestCaseGroup *createSynchronization2SmokeTests(tcu::TestContext &textCtx)
1311 {
1312     SynchronizationType type(SynchronizationType::SYNCHRONIZATION2);
1313     de::MovePtr<tcu::TestCaseGroup> smokeTests(new tcu::TestCaseGroup(textCtx, "smoke"));
1314 
1315     addFunctionCaseWithPrograms(smokeTests.get(), "binary_semaphores", checkSupport, initShaders, testSemaphores,
1316                                 SemaphoreTestConfig{type, VK_SEMAPHORE_TYPE_BINARY});
1317     addFunctionCaseWithPrograms(smokeTests.get(), "timeline_semaphores", checkSupport, initShaders, testSemaphores,
1318                                 SemaphoreTestConfig{type, VK_SEMAPHORE_TYPE_TIMELINE});
1319 
1320     return smokeTests.release();
1321 }
1322 
1323 } // namespace synchronization
1324 } // namespace vkt
1325