Fix missing dependency on sparse binds
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / draw / vktDrawConcurrentTests.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2019 The Khronos Group Inc.
6  * Copyright (c) 2019 Google Inc.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Concurrent draw tests
23  * Tests that create queue for rendering as well as queue for
24  * compute, and trigger work on both pipelines at the same time,
25  * and finally verify that the results are as expected.
26  *//*--------------------------------------------------------------------*/
27
28 #include "vktDrawConcurrentTests.hpp"
29
30 #include "vktCustomInstancesDevices.hpp"
31 #include "vktTestCaseUtil.hpp"
32 #include "vktDrawTestCaseUtil.hpp"
33 #include "../compute/vktComputeTestsUtil.hpp"
34
35 #include "vktDrawBaseClass.hpp"
36
37 #include "tcuTestLog.hpp"
38 #include "tcuResource.hpp"
39 #include "tcuImageCompare.hpp"
40 #include "tcuTextureUtil.hpp"
41 #include "tcuRGBA.hpp"
42
43 #include "vkDefs.hpp"
44 #include "vkCmdUtil.hpp"
45 #include "vkQueryUtil.hpp"
46 #include "vkBuilderUtil.hpp"
47 #include "vkBarrierUtil.hpp"
48 #include "vkObjUtil.hpp"
49 #include "vkDeviceUtil.hpp"
50 #include "vkSafetyCriticalUtil.hpp"
51 #include "vkBufferWithMemory.hpp"
52
53 #include "deRandom.hpp"
54
55 using namespace vk;
56
57 namespace vkt
58 {
59 namespace Draw
60 {
61 namespace
62 {
63
64 class ConcurrentDraw : public DrawTestsBaseClass
65 {
66 public:
67         typedef TestSpecBase    TestSpec;
68                                                         ConcurrentDraw                  (Context &context, TestSpec testSpec);
69         virtual tcu::TestStatus iterate                                 (void);
70 };
71
72 ConcurrentDraw::ConcurrentDraw (Context &context, TestSpec testSpec)
73         : DrawTestsBaseClass(context, testSpec.shaders[glu::SHADERTYPE_VERTEX], testSpec.shaders[glu::SHADERTYPE_FRAGMENT], testSpec.groupParams, testSpec.topology)
74 {
75         m_data.push_back(VertexElementData(tcu::Vec4(1.0f, -1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), -1));
76         m_data.push_back(VertexElementData(tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), -1));
77
78         int refVertexIndex = 2;
79
80         for (int i = 0; i < 1000; i++)
81         {
82                 m_data.push_back(VertexElementData(tcu::Vec4(-0.3f, -0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
83                 m_data.push_back(VertexElementData(tcu::Vec4(-0.3f, 0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
84                 m_data.push_back(VertexElementData(tcu::Vec4(0.3f, -0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
85                 m_data.push_back(VertexElementData(tcu::Vec4(0.3f, -0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
86                 m_data.push_back(VertexElementData(tcu::Vec4(0.3f, 0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
87                 m_data.push_back(VertexElementData(tcu::Vec4(-0.3f, 0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
88         }
89         m_data.push_back(VertexElementData(tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), -1));
90
91         initialize();
92 }
93
94 tcu::TestStatus ConcurrentDraw::iterate (void)
95 {
96         enum
97         {
98                 NO_MATCH_FOUND          = ~((deUint32)0),
99                 ERROR_NONE                      = 0,
100                 ERROR_WAIT_COMPUTE      = 1,
101                 ERROR_WAIT_DRAW         = 2
102         };
103
104         struct Queue
105         {
106                 VkQueue         queue;
107                 deUint32        queueFamilyIndex;
108         };
109
110         const deUint32                                                  numValues               = 1024;
111         const CustomInstance                                    instance                (createCustomInstanceFromContext(m_context));
112         const InstanceDriver&                                   instanceDriver  (instance.getDriver());
113         const VkPhysicalDevice                                  physicalDevice  = chooseDevice(instanceDriver, instance, m_context.getTestContext().getCommandLine());
114 //
115 //      const InstanceInterface&                                instance                = m_context.getInstanceInterface();
116 //      const VkPhysicalDevice                                  physicalDevice  = m_context.getPhysicalDevice();
117         const auto                                                              validation              = m_context.getTestContext().getCommandLine().isValidationEnabled();
118         tcu::TestLog&                                                   log                             = m_context.getTestContext().getLog();
119         Move<VkDevice>                                                  computeDevice;
120         std::vector<VkQueueFamilyProperties>    queueFamilyProperties;
121         VkDeviceCreateInfo                                              deviceInfo;
122         VkPhysicalDeviceFeatures                                deviceFeatures;
123         const float                                                             queuePriority   = 1.0f;
124         VkDeviceQueueCreateInfo                                 queueInfos;
125         Queue                                                                   computeQueue    = { DE_NULL, (deUint32)NO_MATCH_FOUND };
126
127         // Set up compute
128
129         queueFamilyProperties = getPhysicalDeviceQueueFamilyProperties(instanceDriver, physicalDevice);
130
131         for (deUint32 queueNdx = 0; queueNdx < queueFamilyProperties.size(); ++queueNdx)
132         {
133                 if (queueFamilyProperties[queueNdx].queueFlags & VK_QUEUE_COMPUTE_BIT)
134                 {
135                         if (computeQueue.queueFamilyIndex == NO_MATCH_FOUND)
136                                 computeQueue.queueFamilyIndex = queueNdx;
137                 }
138         }
139
140         if (computeQueue.queueFamilyIndex == NO_MATCH_FOUND)
141                 TCU_THROW(NotSupportedError, "Compute queue couldn't be created");
142
143         VkDeviceQueueCreateInfo queueInfo;
144         deMemset(&queueInfo, 0, sizeof(queueInfo));
145
146         queueInfo.sType                         = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
147         queueInfo.pNext                         = DE_NULL;
148         queueInfo.flags                         = (VkDeviceQueueCreateFlags)0u;
149         queueInfo.queueFamilyIndex      = computeQueue.queueFamilyIndex;
150         queueInfo.queueCount            = 1;
151         queueInfo.pQueuePriorities      = &queuePriority;
152
153         queueInfos = queueInfo;
154
155         deMemset(&deviceInfo, 0, sizeof(deviceInfo));
156         instanceDriver.getPhysicalDeviceFeatures(physicalDevice, &deviceFeatures);
157
158         void* pNext                                                                                             = DE_NULL;
159 #ifdef CTS_USES_VULKANSC
160         VkDeviceObjectReservationCreateInfo memReservationInfo  = m_context.getTestContext().getCommandLine().isSubProcess() ? m_context.getResourceInterface()->getStatMax() : resetDeviceObjectReservationCreateInfo();
161         memReservationInfo.pNext                                                                = pNext;
162         pNext                                                                                                   = &memReservationInfo;
163
164         VkPhysicalDeviceVulkanSC10Features sc10Features                 = createDefaultSC10Features();
165         sc10Features.pNext                                                                              = pNext;
166         pNext                                                                                                   = &sc10Features;
167
168         VkPipelineCacheCreateInfo                       pcCI;
169         std::vector<VkPipelinePoolSize>         poolSizes;
170         if (m_context.getTestContext().getCommandLine().isSubProcess())
171         {
172                 if (m_context.getResourceInterface()->getCacheDataSize() > 0)
173                 {
174                         pcCI =
175                         {
176                                 VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO,                   // VkStructureType                              sType;
177                                 DE_NULL,                                                                                                // const void*                                  pNext;
178                                 VK_PIPELINE_CACHE_CREATE_READ_ONLY_BIT |
179                                         VK_PIPELINE_CACHE_CREATE_USE_APPLICATION_STORAGE_BIT,   // VkPipelineCacheCreateFlags   flags;
180                                 m_context.getResourceInterface()->getCacheDataSize(),   // deUintptr                                    initialDataSize;
181                                 m_context.getResourceInterface()->getCacheData()                // const void*                                  pInitialData;
182                         };
183                         memReservationInfo.pipelineCacheCreateInfoCount         = 1;
184                         memReservationInfo.pPipelineCacheCreateInfos            = &pcCI;
185                 }
186
187                 poolSizes                                                       = m_context.getResourceInterface()->getPipelinePoolSizes();
188                 if (!poolSizes.empty())
189                 {
190                         memReservationInfo.pipelinePoolSizeCount                        = deUint32(poolSizes.size());
191                         memReservationInfo.pPipelinePoolSizes                           = poolSizes.data();
192                 }
193         }
194 #endif // CTS_USES_VULKANSC
195
196         deviceInfo.sType                                        = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
197         deviceInfo.pNext                                        = pNext;
198         deviceInfo.enabledExtensionCount        = 0u;
199         deviceInfo.ppEnabledExtensionNames      = DE_NULL;
200         deviceInfo.enabledLayerCount            = 0u;
201         deviceInfo.ppEnabledLayerNames          = DE_NULL;
202         deviceInfo.pEnabledFeatures                     = &deviceFeatures;
203         deviceInfo.queueCreateInfoCount         = 1;
204         deviceInfo.pQueueCreateInfos            = &queueInfos;
205
206         computeDevice = createCustomDevice(validation, m_context.getPlatformInterface(), instance, instanceDriver, physicalDevice, &deviceInfo);
207
208 #ifndef CTS_USES_VULKANSC
209         de::MovePtr<vk::DeviceDriver>   deviceDriver = de::MovePtr<vk::DeviceDriver>(new vk::DeviceDriver(m_context.getPlatformInterface(), instance, *computeDevice));
210 #else
211         de::MovePtr<vk::DeviceDriverSC, vk::DeinitDeviceDeleter>        deviceDriver = de::MovePtr<DeviceDriverSC, DeinitDeviceDeleter>(new DeviceDriverSC(m_context.getPlatformInterface(), instance, *computeDevice, m_context.getTestContext().getCommandLine(), m_context.getResourceInterface(), m_context.getDeviceVulkanSC10Properties(), m_context.getDeviceProperties()), vk::DeinitDeviceDeleter(m_context.getResourceInterface().get(), *computeDevice));
212 #endif // CTS_USES_VULKANSC
213         vk::DeviceInterface& vk = *deviceDriver;
214
215         vk.getDeviceQueue(*computeDevice, computeQueue.queueFamilyIndex, 0, &computeQueue.queue);
216
217         // Create an input/output buffer
218         const VkPhysicalDeviceMemoryProperties memoryProperties = getPhysicalDeviceMemoryProperties(instanceDriver, physicalDevice);
219
220         de::MovePtr<SimpleAllocator> allocator                  = de::MovePtr<SimpleAllocator>(new SimpleAllocator(vk, *computeDevice, memoryProperties));
221         const VkDeviceSize                       bufferSizeBytes        = sizeof(deUint32) * numValues;
222         const vk::BufferWithMemory       buffer(vk, *computeDevice, *allocator, makeBufferCreateInfo(bufferSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), MemoryRequirement::HostVisible);
223
224         // Fill the buffer with data
225
226         typedef std::vector<deUint32> data_vector_t;
227         data_vector_t inputData(numValues);
228
229         {
230                 de::Random                      rnd(0x82ce7f);
231                 const Allocation&       bufferAllocation        = buffer.getAllocation();
232                 deUint32*                       bufferPtr                       = static_cast<deUint32*>(bufferAllocation.getHostPtr());
233
234                 for (deUint32 i = 0; i < numValues; ++i)
235                 {
236                         deUint32 val = rnd.getUint32();
237                         inputData[i] = val;
238                         *bufferPtr++ = val;
239                 }
240
241                 flushAlloc(vk, *computeDevice, bufferAllocation);
242         }
243
244         // Create descriptor set
245
246         const Unique<VkDescriptorSetLayout>     descriptorSetLayout(
247                 DescriptorSetLayoutBuilder()
248                 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
249                 .build(vk, *computeDevice));
250
251         const Unique<VkDescriptorPool>          descriptorPool(
252                 DescriptorPoolBuilder()
253                 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
254                 .build(vk, *computeDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
255
256         const Unique<VkDescriptorSet>           descriptorSet(makeDescriptorSet(vk, *computeDevice, *descriptorPool, *descriptorSetLayout));
257
258         const VkDescriptorBufferInfo            bufferDescriptorInfo = makeDescriptorBufferInfo(*buffer, 0ull, bufferSizeBytes);
259         DescriptorSetUpdateBuilder()
260                 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &bufferDescriptorInfo)
261                 .update(vk, *computeDevice);
262
263         // Perform the computation
264
265         const Unique<VkShaderModule>            shaderModule(createShaderModule(vk, *computeDevice, m_context.getBinaryCollection().get("vulkan/draw/ConcurrentPayload.comp"), 0u));
266
267         const Unique<VkPipelineLayout>          pipelineLayout(makePipelineLayout(vk, *computeDevice, *descriptorSetLayout));
268         const Unique<VkPipeline>                        pipeline(makeComputePipeline(vk, *computeDevice, *pipelineLayout, *shaderModule));
269         const VkBufferMemoryBarrier                     hostWriteBarrier        = makeBufferMemoryBarrier(VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, *buffer, 0ull, bufferSizeBytes);
270         const VkBufferMemoryBarrier                     shaderWriteBarrier      = makeBufferMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *buffer, 0ull, bufferSizeBytes);
271         const Unique<VkCommandPool>                     cmdPool(makeCommandPool(vk, *computeDevice, computeQueue.queueFamilyIndex));
272         const Unique<VkCommandBuffer>           computeCommandBuffer(allocateCommandBuffer(vk, *computeDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
273
274         // Compute command buffer
275
276         beginCommandBuffer(vk, *computeCommandBuffer);
277         vk.cmdBindPipeline(*computeCommandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
278         vk.cmdBindDescriptorSets(*computeCommandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
279         vk.cmdPipelineBarrier(*computeCommandBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &hostWriteBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
280         vk.cmdDispatch(*computeCommandBuffer, 1, 1, 1);
281         vk.cmdPipelineBarrier(*computeCommandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &shaderWriteBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
282         endCommandBuffer(vk, *computeCommandBuffer);
283
284         const VkSubmitInfo      submitInfo =
285         {
286                 VK_STRUCTURE_TYPE_SUBMIT_INFO,                  // sType
287                 DE_NULL,                                                                // pNext
288                 0u,                                                                             // waitSemaphoreCount
289                 DE_NULL,                                                                // pWaitSemaphores
290                 (const VkPipelineStageFlags*)DE_NULL,   // pWaitDstStageMask
291                 1u,                                                                             // commandBufferCount
292                 &computeCommandBuffer.get(),                    // pCommandBuffers
293                 0u,                                                                             // signalSemaphoreCount
294                 DE_NULL                                                                 // pSignalSemaphores
295         };
296
297         // Set up draw
298
299         const VkQueue           drawQueue                       = m_context.getUniversalQueue();
300         const VkDevice          drawDevice                      = m_context.getDevice();
301         const VkDeviceSize      vertexBufferOffset      = 0;
302         const VkBuffer          vertexBuffer            = m_vertexBuffer->object();
303
304 #ifndef CTS_USES_VULKANSC
305         if (m_groupParams->useSecondaryCmdBuffer)
306         {
307                 // record secondary command buffer
308                 if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
309                 {
310                         beginSecondaryCmdBuffer(m_vk, VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
311                         beginDynamicRender(*m_secCmdBuffer);
312                 }
313                 else
314                         beginSecondaryCmdBuffer(m_vk);
315
316                 m_vk.cmdBindVertexBuffers(*m_secCmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
317                 m_vk.cmdBindPipeline(*m_secCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
318                 m_vk.cmdDraw(*m_secCmdBuffer, 6, 1, 2, 0);
319
320                 if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
321                         endDynamicRender(*m_secCmdBuffer);
322
323                 endCommandBuffer(m_vk, *m_secCmdBuffer);
324
325                 // record primary command buffer
326                 beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
327                 preRenderBarriers();
328
329                 if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
330                         beginDynamicRender(*m_cmdBuffer, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
331
332                 m_vk.cmdExecuteCommands(*m_cmdBuffer, 1u, &*m_secCmdBuffer);
333
334                 if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
335                         endDynamicRender(*m_cmdBuffer);
336
337                 endCommandBuffer(m_vk, *m_cmdBuffer);
338         }
339         else if (m_groupParams->useDynamicRendering)
340         {
341                 beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
342                 preRenderBarriers();
343                 beginDynamicRender(*m_cmdBuffer);
344
345                 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
346                 m_vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
347                 m_vk.cmdDraw(*m_cmdBuffer, 6, 1, 2, 0);
348
349                 endDynamicRender(*m_cmdBuffer);
350                 endCommandBuffer(m_vk, *m_cmdBuffer);
351         }
352 #endif // CTS_USES_VULKANSC
353
354         if (!m_groupParams->useDynamicRendering)
355         {
356                 beginCommandBuffer(m_vk, *m_cmdBuffer, 0u);
357                 preRenderBarriers();
358                 beginLegacyRender(*m_cmdBuffer);
359
360                 m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
361                 m_vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
362                 m_vk.cmdDraw(*m_cmdBuffer, 6, 1, 2, 0);
363
364                 endLegacyRender(*m_cmdBuffer);
365                 endCommandBuffer(m_vk, *m_cmdBuffer);
366         }
367
368         const VkCommandBuffer   drawCommandBuffer       = m_cmdBuffer.get();
369         const bool                              useDeviceGroups         = false;
370         const deUint32                  deviceMask                      = 1u;
371         const Unique<VkFence>   drawFence(createFence(vk, drawDevice));
372
373         VkDeviceGroupSubmitInfo deviceGroupSubmitInfo =
374         {
375                 VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO,             //      VkStructureType         sType;
376                 DE_NULL,                                                                                //      const void*                     pNext;
377                 0u,                                                                                             //      deUint32                        waitSemaphoreCount;
378                 DE_NULL,                                                                                //      const deUint32*         pWaitSemaphoreDeviceIndices;
379                 1u,                                                                                             //      deUint32                        commandBufferCount;
380                 &deviceMask,                                                                    //      const deUint32*         pCommandBufferDeviceMasks;
381                 0u,                                                                                             //      deUint32                        signalSemaphoreCount;
382                 DE_NULL,                                                                                //      const deUint32*         pSignalSemaphoreDeviceIndices;
383         };
384
385         const VkSubmitInfo              drawSubmitInfo =
386         {
387                 VK_STRUCTURE_TYPE_SUBMIT_INFO,                                          // VkStructureType                              sType;
388                 useDeviceGroups ? &deviceGroupSubmitInfo : DE_NULL,     // const void*                                  pNext;
389                 0u,                                                                                                     // deUint32                                             waitSemaphoreCount;
390                 DE_NULL,                                                                                        // const VkSemaphore*                   pWaitSemaphores;
391                 (const VkPipelineStageFlags*)DE_NULL,                           // const VkPipelineStageFlags*  pWaitDstStageMask;
392                 1u,                                                                                                     // deUint32                                             commandBufferCount;
393                 &drawCommandBuffer,                                                                     // const VkCommandBuffer*               pCommandBuffers;
394                 0u,                                                                                                     // deUint32                                             signalSemaphoreCount;
395                 DE_NULL,                                                                                        // const VkSemaphore*                   pSignalSemaphores;
396         };
397
398         const Unique<VkFence>   computeFence(createFence(vk, *computeDevice));
399
400         // Submit both compute and draw queues
401         VK_CHECK(vk.queueSubmit(computeQueue.queue, 1u, &submitInfo, *computeFence));
402         VK_CHECK(vk.queueSubmit(drawQueue, 1u, &drawSubmitInfo, *drawFence));
403
404         int err = ERROR_NONE;
405
406         if (VK_SUCCESS != vk.waitForFences(*computeDevice, 1u, &computeFence.get(), DE_TRUE, ~0ull))
407                 err = ERROR_WAIT_COMPUTE;
408
409         if (VK_SUCCESS != vk.waitForFences(drawDevice, 1u, &drawFence.get(), DE_TRUE, ~0ull))
410                 err = ERROR_WAIT_DRAW;
411
412         // Have to wait for all fences before calling fail, or some fence may be left hanging.
413
414
415 #ifdef CTS_USES_VULKANSC
416         if (m_context.getTestContext().getCommandLine().isSubProcess())
417 #endif // CTS_USES_VULKANSC
418         {
419                 if (err == ERROR_WAIT_COMPUTE)
420                 {
421                         return tcu::TestStatus::fail("Failed waiting for compute queue fence.");
422                 }
423
424                 if (err == ERROR_WAIT_DRAW)
425                 {
426                         return tcu::TestStatus::fail("Failed waiting for draw queue fence.");
427                 }
428
429                 // Validation - compute
430
431                 const Allocation&       bufferAllocation        = buffer.getAllocation();
432                 invalidateAlloc(vk, *computeDevice, bufferAllocation);
433                 const deUint32*         bufferPtr                       = static_cast<deUint32*>(bufferAllocation.getHostPtr());
434
435                 for (deUint32 ndx = 0; ndx < numValues; ++ndx)
436                 {
437                         const deUint32 res = bufferPtr[ndx];
438                         const deUint32 inp = inputData[ndx];
439                         const deUint32 ref = ~inp;
440
441                         if (res != ref)
442                         {
443                                 std::ostringstream msg;
444                                 msg << "Comparison failed (compute) for InOut.values[" << ndx << "] ref:" << ref << " res:" << res << " inp:" << inp;
445                                 return tcu::TestStatus::fail(msg.str());
446                         }
447                 }
448         }
449
450         // Validation - draw
451
452         tcu::Texture2D referenceFrame(mapVkFormat(m_colorAttachmentFormat), (int)(0.5f + static_cast<float>(WIDTH)), (int)(0.5f + static_cast<float>(HEIGHT)));
453
454         referenceFrame.allocLevel(0);
455
456         const deInt32 frameWidth        = referenceFrame.getWidth();
457         const deInt32 frameHeight       = referenceFrame.getHeight();
458
459         tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
460
461         ReferenceImageCoordinates refCoords;
462
463         for (int y = 0; y < frameHeight; y++)
464         {
465                 const float yCoord = (float)(y / (0.5 * frameHeight)) - 1.0f;
466
467                 for (int x = 0; x < frameWidth; x++)
468                 {
469                         const float xCoord = (float)(x / (0.5 * frameWidth)) - 1.0f;
470
471                         if ((yCoord >= refCoords.bottom &&
472                                  yCoord <= refCoords.top        &&
473                                  xCoord >= refCoords.left       &&
474                                  xCoord <= refCoords.right))
475                                 referenceFrame.getLevel(0).setPixel(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), x, y);
476                 }
477         }
478
479         const VkOffset3D                                        zeroOffset              = { 0, 0, 0 };
480         const tcu::ConstPixelBufferAccess       renderedFrame   = m_colorTargetImage->readSurface(
481                 drawQueue, m_context.getDefaultAllocator(), VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, VK_IMAGE_ASPECT_COLOR_BIT);
482
483         qpTestResult res = QP_TEST_RESULT_PASS;
484
485         if (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
486                 referenceFrame.getLevel(0), renderedFrame, 0.05f,
487                 tcu::COMPARE_LOG_RESULT))
488         {
489                 res = QP_TEST_RESULT_FAIL;
490         }
491         return tcu::TestStatus(res, qpGetTestResultName(res));
492 }
493
494 void checkSupport(Context& context, ConcurrentDraw::TestSpec testSpec)
495 {
496         if (testSpec.groupParams->useDynamicRendering)
497                 context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
498 }
499
500 }       // anonymous
501
502 ConcurrentDrawTests::ConcurrentDrawTests (tcu::TestContext &testCtx, const SharedGroupParams groupParams)
503         : TestCaseGroup                 (testCtx, "concurrent", "concurrent drawing")
504         , m_groupParams                 (groupParams)
505 {
506         /* Left blank on purpose */
507 }
508
509 void ConcurrentDrawTests::init (void)
510 {
511         ConcurrentDraw::TestSpec testSpec
512         {
513                 {
514                         { glu::SHADERTYPE_VERTEX,       "vulkan/draw/VertexFetch.vert" },
515                         { glu::SHADERTYPE_FRAGMENT,     "vulkan/draw/VertexFetch.frag" },
516                         { glu::SHADERTYPE_COMPUTE,      "vulkan/draw/ConcurrentPayload.comp" }
517                 },
518                 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
519                 m_groupParams
520         };
521
522         addChild(new InstanceFactory<ConcurrentDraw, FunctionSupport1<ConcurrentDraw::TestSpec>>(m_testCtx, "compute_and_triangle_list", "Draws triangle list while running a compute shader", testSpec, FunctionSupport1<ConcurrentDraw::TestSpec>::Args(checkSupport, testSpec)));
523 }
524
525 }       // DrawTests
526 }       // vkt