Add test for concurrent draw and compute
authorJari Komppa <jari.komppa@siru.fi>
Wed, 3 Apr 2019 11:59:23 +0000 (14:59 +0300)
committerAlexander Galazin <Alexander.Galazin@arm.com>
Thu, 27 Jun 2019 07:37:45 +0000 (03:37 -0400)
Added test that performs compute and drawing at the same time.

New tests:

dEQP-VK.draw.concurrent.compute_and_triangle_list

Components: Vulkan

VK-GL-CTS issue: 1661

Change-Id: I956ceafa705c6648df887f0cd1866ce7c9d902ce

AndroidGen.mk
android/cts/master/vk-master.txt
external/vulkancts/data/vulkan/draw/ConcurrentPayload.comp [new file with mode: 0644]
external/vulkancts/modules/vulkan/draw/CMakeLists.txt
external/vulkancts/modules/vulkan/draw/vktDrawConcurrentTests.cpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/draw/vktDrawConcurrentTests.hpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/draw/vktDrawTests.cpp
external/vulkancts/mustpass/master/vk-default-no-waivers.txt
external/vulkancts/mustpass/master/vk-default.txt

index e7b40b0..642e332 100644 (file)
@@ -115,6 +115,7 @@ LOCAL_SRC_FILES := \
        external/vulkancts/modules/vulkan/draw/vktBasicDrawTests.cpp \
        external/vulkancts/modules/vulkan/draw/vktDrawBaseClass.cpp \
        external/vulkancts/modules/vulkan/draw/vktDrawBufferObjectUtil.cpp \
+       external/vulkancts/modules/vulkan/draw/vktDrawConcurrentTests.cpp \
        external/vulkancts/modules/vulkan/draw/vktDrawCreateInfoUtil.cpp \
        external/vulkancts/modules/vulkan/draw/vktDrawDifferingInterpolationTests.cpp \
        external/vulkancts/modules/vulkan/draw/vktDrawDiscardRectanglesTests.cpp \
index efeb90c..d82f362 100644 (file)
@@ -331637,6 +331637,7 @@ dEQP-VK.query_pool.statistics_query.reset_before_copy.tes_control_patches.tes_co
 dEQP-VK.query_pool.statistics_query.reset_before_copy.tes_evaluation_shader_invocations.tes_evaluation_shader_invocations
 dEQP-VK.query_pool.statistics_query.reset_before_copy.tes_evaluation_shader_invocations.tes_evaluation_shader_invocations_secondary
 dEQP-VK.query_pool.statistics_query.reset_before_copy.tes_evaluation_shader_invocations.tes_evaluation_shader_invocations_secondary_inherited
+dEQP-VK.draw.concurrent.compute_and_triangle_list
 dEQP-VK.draw.simple_draw.simple_draw_triangle_list
 dEQP-VK.draw.simple_draw.simple_draw_triangle_strip
 dEQP-VK.draw.simple_draw.simple_draw_instanced_triangle_list
diff --git a/external/vulkancts/data/vulkan/draw/ConcurrentPayload.comp b/external/vulkancts/data/vulkan/draw/ConcurrentPayload.comp
new file mode 100644 (file)
index 0000000..c633292
--- /dev/null
@@ -0,0 +1,16 @@
+#version 310 es
+
+layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+layout(binding = 0) buffer InOut {
+    uint values[1024];
+} sb_inout;
+
+void main (void) {
+    uvec3 size           = gl_NumWorkGroups * gl_WorkGroupSize;
+    uint numValuesPerInv = uint(sb_inout.values.length()) / (size.x*size.y*size.z);
+    uint groupNdx        = size.x*size.y*gl_GlobalInvocationID.z + size.x*gl_GlobalInvocationID.y + gl_GlobalInvocationID.x;
+    uint offset          = numValuesPerInv*groupNdx;
+
+    for (uint ndx = 0u; ndx < numValuesPerInv; ndx++)
+        sb_inout.values[offset + ndx] = ~sb_inout.values[offset + ndx];
+}
index f212e8e..33578a9 100644 (file)
@@ -19,6 +19,8 @@ set(DEQP_VK_DRAW_SRCS
        vktDrawShaderViewportIndexTests.cpp
        vktDrawSimpleTest.hpp
        vktDrawSimpleTest.cpp
+       vktDrawConcurrentTests.hpp
+       vktDrawConcurrentTests.cpp
        vktDrawNegativeViewportHeightTests.hpp
        vktDrawNegativeViewportHeightTests.cpp
        vktDrawBaseClass.hpp
diff --git a/external/vulkancts/modules/vulkan/draw/vktDrawConcurrentTests.cpp b/external/vulkancts/modules/vulkan/draw/vktDrawConcurrentTests.cpp
new file mode 100644 (file)
index 0000000..7abd8a0
--- /dev/null
@@ -0,0 +1,402 @@
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2019 The Khronos Group Inc.
+ * Copyright (c) 2019 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Concurrent draw tests
+ * Tests that create queue for rendering as well as queue for
+ * compute, and trigger work on both pipelines at the same time,
+ * and finally verify that the results are as expected.
+ *//*--------------------------------------------------------------------*/
+
+#include "vktDrawConcurrentTests.hpp"
+
+#include "vktTestCaseUtil.hpp"
+#include "vktDrawTestCaseUtil.hpp"
+#include "../compute/vktComputeTestsUtil.hpp"
+
+#include "vktDrawBaseClass.hpp"
+
+#include "tcuTestLog.hpp"
+#include "tcuResource.hpp"
+#include "tcuImageCompare.hpp"
+#include "tcuTextureUtil.hpp"
+#include "tcuRGBA.hpp"
+
+#include "vkDefs.hpp"
+#include "vkCmdUtil.hpp"
+#include "vkQueryUtil.hpp"
+#include "vkBuilderUtil.hpp"
+#include "vkBarrierUtil.hpp"
+
+#include "deRandom.hpp"
+
+using namespace vk;
+
+namespace vkt
+{
+namespace Draw
+{
+namespace
+{
+
+class ConcurrentDraw : public DrawTestsBaseClass
+{
+public:
+       typedef TestSpecBase    TestSpec;
+                                                       ConcurrentDraw                  (Context &context, TestSpec testSpec);
+       virtual tcu::TestStatus iterate                                 (void);
+};
+
+ConcurrentDraw::ConcurrentDraw (Context &context, TestSpec testSpec)
+       : DrawTestsBaseClass(context, testSpec.shaders[glu::SHADERTYPE_VERTEX], testSpec.shaders[glu::SHADERTYPE_FRAGMENT], testSpec.topology)
+{
+       m_data.push_back(VertexElementData(tcu::Vec4(1.0f, -1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), -1));
+       m_data.push_back(VertexElementData(tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), -1));
+
+       int refVertexIndex = 2;
+
+       for (int i = 0; i < 1000; i++)
+       {
+               m_data.push_back(VertexElementData(tcu::Vec4(-0.3f, -0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
+               m_data.push_back(VertexElementData(tcu::Vec4(-0.3f, 0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
+               m_data.push_back(VertexElementData(tcu::Vec4(0.3f, -0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
+               m_data.push_back(VertexElementData(tcu::Vec4(0.3f, -0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
+               m_data.push_back(VertexElementData(tcu::Vec4(0.3f, 0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
+               m_data.push_back(VertexElementData(tcu::Vec4(-0.3f, 0.3f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), refVertexIndex++));
+       }
+       m_data.push_back(VertexElementData(tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f), tcu::RGBA::blue().toVec(), -1));
+
+       initialize();
+}
+
+tcu::TestStatus ConcurrentDraw::iterate (void)
+{
+       enum
+       {
+               NO_MATCH_FOUND          = ~((deUint32)0),
+               ERROR_NONE                      = 0,
+               ERROR_WAIT_COMPUTE      = 1,
+               ERROR_WAIT_DRAW         = 2
+       };
+
+       struct Queue
+       {
+               VkQueue         queue;
+               deUint32        queueFamilyIndex;
+       };
+
+       const DeviceInterface&                                  vk                              = m_context.getDeviceInterface();
+       const deUint32                                                  numValues               = 1024;
+       const InstanceInterface&                                instance                = m_context.getInstanceInterface();
+       const VkPhysicalDevice                                  physicalDevice  = m_context.getPhysicalDevice();
+       tcu::TestLog&                                                   log                             = m_context.getTestContext().getLog();
+       Move<VkDevice>                                                  computeDevice;
+       std::vector<VkQueueFamilyProperties>    queueFamilyProperties;
+       VkDeviceCreateInfo                                              deviceInfo;
+       VkPhysicalDeviceFeatures                                deviceFeatures;
+       const float                                                             queuePriority   = 1.0f;
+       VkDeviceQueueCreateInfo                                 queueInfos;
+       Queue                                                                   computeQueue    = { DE_NULL, (deUint32)NO_MATCH_FOUND };
+
+       // Set up compute
+
+       queueFamilyProperties = getPhysicalDeviceQueueFamilyProperties(instance, physicalDevice);
+
+       for (deUint32 queueNdx = 0; queueNdx < queueFamilyProperties.size(); ++queueNdx)
+       {
+               if (queueFamilyProperties[queueNdx].queueFlags & VK_QUEUE_COMPUTE_BIT)
+               {
+                       if (computeQueue.queueFamilyIndex == NO_MATCH_FOUND)
+                               computeQueue.queueFamilyIndex = queueNdx;
+               }
+       }
+
+       if (computeQueue.queueFamilyIndex == NO_MATCH_FOUND)
+               TCU_THROW(NotSupportedError, "Compute queue couldn't be created");
+
+       VkDeviceQueueCreateInfo queueInfo;
+       deMemset(&queueInfo, 0, sizeof(queueInfo));
+
+       queueInfo.sType                         = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
+       queueInfo.pNext                         = DE_NULL;
+       queueInfo.flags                         = (VkDeviceQueueCreateFlags)0u;
+       queueInfo.queueFamilyIndex      = computeQueue.queueFamilyIndex;
+       queueInfo.queueCount            = 1;
+       queueInfo.pQueuePriorities      = &queuePriority;
+
+       queueInfos = queueInfo;
+
+       deMemset(&deviceInfo, 0, sizeof(deviceInfo));
+       instance.getPhysicalDeviceFeatures(physicalDevice, &deviceFeatures);
+
+       deviceInfo.sType                                        = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
+       deviceInfo.pNext                                        = DE_NULL;
+       deviceInfo.enabledExtensionCount        = 0u;
+       deviceInfo.ppEnabledExtensionNames      = DE_NULL;
+       deviceInfo.enabledLayerCount            = 0u;
+       deviceInfo.ppEnabledLayerNames          = DE_NULL;
+       deviceInfo.pEnabledFeatures                     = &deviceFeatures;
+       deviceInfo.queueCreateInfoCount         = 1;
+       deviceInfo.pQueueCreateInfos            = &queueInfos;
+
+       computeDevice = createDevice(m_context.getPlatformInterface(), m_context.getInstance(), instance, physicalDevice, &deviceInfo);
+
+       vk.getDeviceQueue(*computeDevice, computeQueue.queueFamilyIndex, 0, &computeQueue.queue);
+
+       // Create an input/output buffer
+       const VkPhysicalDeviceMemoryProperties memoryProperties = getPhysicalDeviceMemoryProperties(instance, physicalDevice);
+
+       SimpleAllocator *                       allocator                       = new SimpleAllocator(vk, *computeDevice, memoryProperties);
+       const VkDeviceSize                      bufferSizeBytes         = sizeof(deUint32) * numValues;
+       const vkt::compute::Buffer      buffer(vk, *computeDevice, *allocator, makeBufferCreateInfo(bufferSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), MemoryRequirement::HostVisible);
+
+       // Fill the buffer with data
+
+       typedef std::vector<deUint32> data_vector_t;
+       data_vector_t inputData(numValues);
+
+       {
+               de::Random                      rnd(0x82ce7f);
+               const Allocation&       bufferAllocation        = buffer.getAllocation();
+               deUint32*                       bufferPtr                       = static_cast<deUint32*>(bufferAllocation.getHostPtr());
+
+               for (deUint32 i = 0; i < numValues; ++i)
+               {
+                       deUint32 val = rnd.getUint32();
+                       inputData[i] = val;
+                       *bufferPtr++ = val;
+               }
+
+               flushAlloc(vk, *computeDevice, bufferAllocation);
+       }
+
+       // Create descriptor set
+
+       const Unique<VkDescriptorSetLayout>     descriptorSetLayout(
+               DescriptorSetLayoutBuilder()
+               .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
+               .build(vk, *computeDevice));
+
+       const Unique<VkDescriptorPool>          descriptorPool(
+               DescriptorPoolBuilder()
+               .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
+               .build(vk, *computeDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
+
+       const Unique<VkDescriptorSet>           descriptorSet(makeDescriptorSet(vk, *computeDevice, *descriptorPool, *descriptorSetLayout));
+
+       const VkDescriptorBufferInfo            bufferDescriptorInfo = makeDescriptorBufferInfo(*buffer, 0ull, bufferSizeBytes);
+       DescriptorSetUpdateBuilder()
+               .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &bufferDescriptorInfo)
+               .update(vk, *computeDevice);
+
+       // Perform the computation
+
+       const Unique<VkShaderModule>            shaderModule(createShaderModule(vk, *computeDevice, m_context.getBinaryCollection().get("vulkan/draw/ConcurrentPayload.comp"), 0u));
+
+       const Unique<VkPipelineLayout>          pipelineLayout(vkt::compute::makePipelineLayout(vk, *computeDevice, *descriptorSetLayout));
+       const Unique<VkPipeline>                        pipeline(vkt::compute::makeComputePipeline(vk, *computeDevice, *pipelineLayout, *shaderModule));
+       const VkBufferMemoryBarrier                     hostWriteBarrier        = makeBufferMemoryBarrier(VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, *buffer, 0ull, bufferSizeBytes);
+       const VkBufferMemoryBarrier                     shaderWriteBarrier      = makeBufferMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *buffer, 0ull, bufferSizeBytes);
+       const Unique<VkCommandPool>                     cmdPool(vkt::compute::makeCommandPool(vk, *computeDevice, computeQueue.queueFamilyIndex));
+       const Unique<VkCommandBuffer>           computeCommandBuffer(allocateCommandBuffer(vk, *computeDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
+
+       // Compute command buffer
+
+       beginCommandBuffer(vk, *computeCommandBuffer);
+       vk.cmdBindPipeline(*computeCommandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
+       vk.cmdBindDescriptorSets(*computeCommandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
+       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);
+       vk.cmdDispatch(*computeCommandBuffer, 1, 1, 1);
+       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);
+       endCommandBuffer(vk, *computeCommandBuffer);
+
+       const VkSubmitInfo      submitInfo =
+       {
+               VK_STRUCTURE_TYPE_SUBMIT_INFO,                  // sType
+               DE_NULL,                                                                // pNext
+               0u,                                                                             // waitSemaphoreCount
+               DE_NULL,                                                                // pWaitSemaphores
+               (const VkPipelineStageFlags*)DE_NULL,   // pWaitDstStageMask
+               1u,                                                                             // commandBufferCount
+               &computeCommandBuffer.get(),                    // pCommandBuffers
+               0u,                                                                             // signalSemaphoreCount
+               DE_NULL                                                                 // pSignalSemaphores
+       };
+
+       // Set up draw
+
+       const VkQueue           drawQueue                       = m_context.getUniversalQueue();
+       const VkDevice          drawDevice                      = m_context.getDevice();
+
+       beginRenderPass();
+
+       const VkDeviceSize      vertexBufferOffset      = 0;
+       const VkBuffer          vertexBuffer            = m_vertexBuffer->object();
+
+       m_vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
+       m_vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
+
+       m_vk.cmdDraw(*m_cmdBuffer, 6, 1, 2, 0);
+
+       endRenderPass(m_vk, *m_cmdBuffer);
+       endCommandBuffer(m_vk, *m_cmdBuffer);
+
+       const VkCommandBuffer   drawCommandBuffer       = m_cmdBuffer.get();
+       const bool                              useDeviceGroups         = false;
+       const deUint32                  deviceMask                      = 1u;
+       const Unique<VkFence>   drawFence(createFence(vk, drawDevice));
+
+       VkDeviceGroupSubmitInfo deviceGroupSubmitInfo =
+       {
+               VK_STRUCTURE_TYPE_DEVICE_GROUP_SUBMIT_INFO_KHR, //      VkStructureType         sType;
+               DE_NULL,                                                                                //      const void*                     pNext;
+               0u,                                                                                             //      deUint32                        waitSemaphoreCount;
+               DE_NULL,                                                                                //      const deUint32*         pWaitSemaphoreDeviceIndices;
+               1u,                                                                                             //      deUint32                        commandBufferCount;
+               &deviceMask,                                                                    //      const deUint32*         pCommandBufferDeviceMasks;
+               0u,                                                                                             //      deUint32                        signalSemaphoreCount;
+               DE_NULL,                                                                                //      const deUint32*         pSignalSemaphoreDeviceIndices;
+       };
+
+       const VkSubmitInfo              drawSubmitInfo =
+       {
+               VK_STRUCTURE_TYPE_SUBMIT_INFO,                                          // VkStructureType                              sType;
+               useDeviceGroups ? &deviceGroupSubmitInfo : DE_NULL,     // const void*                                  pNext;
+               0u,                                                                                                     // deUint32                                             waitSemaphoreCount;
+               DE_NULL,                                                                                        // const VkSemaphore*                   pWaitSemaphores;
+               (const VkPipelineStageFlags*)DE_NULL,                           // const VkPipelineStageFlags*  pWaitDstStageMask;
+               1u,                                                                                                     // deUint32                                             commandBufferCount;
+               &drawCommandBuffer,                                                                     // const VkCommandBuffer*               pCommandBuffers;
+               0u,                                                                                                     // deUint32                                             signalSemaphoreCount;
+               DE_NULL,                                                                                        // const VkSemaphore*                   pSignalSemaphores;
+       };
+
+       const Unique<VkFence>   computeFence(createFence(vk, *computeDevice));
+
+       // Submit both compute and draw queues
+       VK_CHECK(vk.queueSubmit(computeQueue.queue, 1u, &submitInfo, *computeFence));
+       VK_CHECK(vk.queueSubmit(drawQueue, 1u, &drawSubmitInfo, *drawFence));
+
+       int err = ERROR_NONE;
+
+       if (VK_SUCCESS != vk.waitForFences(*computeDevice, 1u, &computeFence.get(), DE_TRUE, ~0ull))
+               err = ERROR_WAIT_COMPUTE;
+
+       if (VK_SUCCESS != vk.waitForFences(drawDevice, 1u, &drawFence.get(), DE_TRUE, ~0ull))
+               err = ERROR_WAIT_DRAW;
+
+       // Have to wait for all fences before calling fail, or some fence may be left hanging.
+
+       if (err == ERROR_WAIT_COMPUTE)
+               return tcu::TestStatus::fail("Failed waiting for compute queue fence.");
+
+       if (err == ERROR_WAIT_DRAW)
+               return tcu::TestStatus::fail("Failed waiting for draw queue fence.");
+
+       // Validation - compute
+
+       const Allocation&       bufferAllocation        = buffer.getAllocation();
+       invalidateAlloc(vk, *computeDevice, bufferAllocation);
+       const deUint32*         bufferPtr                       = static_cast<deUint32*>(bufferAllocation.getHostPtr());
+
+       for (deUint32 ndx = 0; ndx < numValues; ++ndx)
+       {
+               const deUint32 res = bufferPtr[ndx];
+               const deUint32 inp = inputData[ndx];
+               const deUint32 ref = ~inp;
+
+               if (res != ref)
+               {
+                       std::ostringstream msg;
+                       msg << "Comparison failed (compute) for InOut.values[" << ndx << "] ref:" << ref << " res:" << res << " inp:" << inp;
+                       return tcu::TestStatus::fail(msg.str());
+               }
+       }
+
+       // Validation - draw
+
+       tcu::Texture2D referenceFrame(mapVkFormat(m_colorAttachmentFormat), (int)(0.5 + WIDTH), (int)(0.5 + HEIGHT));
+
+       referenceFrame.allocLevel(0);
+
+       const deInt32 frameWidth        = referenceFrame.getWidth();
+       const deInt32 frameHeight       = referenceFrame.getHeight();
+
+       tcu::clear(referenceFrame.getLevel(0), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
+
+       ReferenceImageCoordinates refCoords;
+
+       for (int y = 0; y < frameHeight; y++)
+       {
+               const float yCoord = (float)(y / (0.5 * frameHeight)) - 1.0f;
+
+               for (int x = 0; x < frameWidth; x++)
+               {
+                       const float xCoord = (float)(x / (0.5 * frameWidth)) - 1.0f;
+
+                       if ((yCoord >= refCoords.bottom &&
+                                yCoord <= refCoords.top        &&
+                                xCoord >= refCoords.left       &&
+                                xCoord <= refCoords.right))
+                               referenceFrame.getLevel(0).setPixel(tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), x, y);
+               }
+       }
+
+       const VkOffset3D                                        zeroOffset              = { 0, 0, 0 };
+       const tcu::ConstPixelBufferAccess       renderedFrame   = m_colorTargetImage->readSurface(
+               drawQueue, m_context.getDefaultAllocator(), VK_IMAGE_LAYOUT_GENERAL, zeroOffset, WIDTH, HEIGHT, VK_IMAGE_ASPECT_COLOR_BIT);
+
+       qpTestResult res = QP_TEST_RESULT_PASS;
+
+       if (!tcu::fuzzyCompare(log, "Result", "Image comparison result",
+               referenceFrame.getLevel(0), renderedFrame, 0.05f,
+               tcu::COMPARE_LOG_RESULT))
+       {
+               res = QP_TEST_RESULT_FAIL;
+       }
+
+       return tcu::TestStatus(res, qpGetTestResultName(res));
+}
+
+}      // anonymous
+
+ConcurrentDrawTests::ConcurrentDrawTests (tcu::TestContext &testCtx)
+: TestCaseGroup        (testCtx, "concurrent", "concurrent drawing")
+{
+       /* Left blank on purpose */
+}
+
+ConcurrentDrawTests::~ConcurrentDrawTests (void) {}
+
+void ConcurrentDrawTests::init (void)
+{
+       {
+               ConcurrentDraw::TestSpec testSpec;
+               testSpec.shaders[glu::SHADERTYPE_VERTEX]        = "vulkan/draw/VertexFetch.vert";
+               testSpec.shaders[glu::SHADERTYPE_FRAGMENT]      = "vulkan/draw/VertexFetch.frag";
+               testSpec.shaders[glu::SHADERTYPE_COMPUTE]       = "vulkan/draw/ConcurrentPayload.comp";
+
+               testSpec.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+               addChild(new InstanceFactory<ConcurrentDraw>(m_testCtx, "compute_and_triangle_list", "Draws triangle list while running a compute shader", testSpec));
+       }
+}
+
+}      // DrawTests
+}      // vkt
diff --git a/external/vulkancts/modules/vulkan/draw/vktDrawConcurrentTests.hpp b/external/vulkancts/modules/vulkan/draw/vktDrawConcurrentTests.hpp
new file mode 100644 (file)
index 0000000..8145905
--- /dev/null
@@ -0,0 +1,48 @@
+#ifndef _VKTDRAWCONCURRENTTESTS_HPP
+#define _VKTDRAWCONCURRENTTESTS_HPP
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2019 The Khronos Group Inc.
+ * Copyright (c) 2019 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Concurrent draw tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vktTestCase.hpp"
+
+namespace vkt
+{
+namespace Draw
+{
+class ConcurrentDrawTests : public tcu::TestCaseGroup
+{
+public:
+                                               ConcurrentDrawTests             (tcu::TestContext &testCtx);
+                                               ~ConcurrentDrawTests    (void);
+       void                            init                                    (void);
+
+private:
+       ConcurrentDrawTests                                                     (const ConcurrentDrawTests &other);
+       ConcurrentDrawTests&    operator=                       (const ConcurrentDrawTests &other);
+
+};
+} // Draw
+} // vkt
+
+#endif // _VKTDRAWCONCURRENTTESTS_HPP
index 1b9d8fc..eb80924 100644 (file)
@@ -25,6 +25,7 @@
 #include "vktDrawTests.hpp"
 
 #include "vktDrawSimpleTest.hpp"
+#include "vktDrawConcurrentTests.hpp"
 #include "vktDrawIndexedTest.hpp"
 #include "vktDrawIndirectTest.hpp"
 #include "vktDrawInstancedTests.hpp"
@@ -52,6 +53,7 @@ void createChildren (tcu::TestCaseGroup* group)
 {
        tcu::TestContext&       testCtx         = group->getTestContext();
 
+       group->addChild(new ConcurrentDrawTests                         (testCtx));
        group->addChild(new SimpleDrawTests                                     (testCtx));
        group->addChild(new DrawIndexedTests                            (testCtx));
        group->addChild(new IndirectDrawTests                           (testCtx));
index b94401c..44aeac3 100644 (file)
@@ -331770,6 +331770,7 @@ dEQP-VK.query_pool.statistics_query.reset_before_copy.tes_control_patches.tes_co
 dEQP-VK.query_pool.statistics_query.reset_before_copy.tes_evaluation_shader_invocations.tes_evaluation_shader_invocations
 dEQP-VK.query_pool.statistics_query.reset_before_copy.tes_evaluation_shader_invocations.tes_evaluation_shader_invocations_secondary
 dEQP-VK.query_pool.statistics_query.reset_before_copy.tes_evaluation_shader_invocations.tes_evaluation_shader_invocations_secondary_inherited
+dEQP-VK.draw.concurrent.compute_and_triangle_list
 dEQP-VK.draw.simple_draw.simple_draw_triangle_list
 dEQP-VK.draw.simple_draw.simple_draw_triangle_strip
 dEQP-VK.draw.simple_draw.simple_draw_instanced_triangle_list
index c539c88..51e2f91 100644 (file)
@@ -331732,6 +331732,7 @@ dEQP-VK.query_pool.statistics_query.reset_before_copy.tes_control_patches.tes_co
 dEQP-VK.query_pool.statistics_query.reset_before_copy.tes_evaluation_shader_invocations.tes_evaluation_shader_invocations
 dEQP-VK.query_pool.statistics_query.reset_before_copy.tes_evaluation_shader_invocations.tes_evaluation_shader_invocations_secondary
 dEQP-VK.query_pool.statistics_query.reset_before_copy.tes_evaluation_shader_invocations.tes_evaluation_shader_invocations_secondary_inherited
+dEQP-VK.draw.concurrent.compute_and_triangle_list
 dEQP-VK.draw.simple_draw.simple_draw_triangle_list
 dEQP-VK.draw.simple_draw.simple_draw_triangle_strip
 dEQP-VK.draw.simple_draw.simple_draw_instanced_triangle_list