Add tests for simultaneous use of secondary command buffer
authorTobin Ehlis <tobine@google.com>
Wed, 31 Aug 2016 18:49:07 +0000 (12:49 -0600)
committerTobin Ehlis <tobine@google.com>
Tue, 6 Sep 2016 22:53:35 +0000 (16:53 -0600)
Fixes #335

Add simultaneousUseSecondaryBufferOnePrimaryBufferTest() test. This test
creates a single secondary command with SIMULTANEOUS_USE flag set and add
two instances of it to the same primary command buffer. Then verify that
each instance executes correctly.
Also add simultaneousUseSecondaryBufferTwoPrimaryBuffersTest(). Similar to
above test but same secondary command buffer is bound into two different
primary comman buffers that are then executed simultaneously.
In both cases the secondary command buffers are each atomically
incrementing a count from within a compute shader.

Update the mustpass lists.

Also made a few minor infrastructure additions:
Add a generic createDataBuffer() function to create a single buffer that
isn't built around a vec4 of color data.
Add a simpler createDescriptorSet() function that binds a results buffer
to binding 0 and an input uniform to binding 1.
Provide the compute result buffer initialization value in a parameter
which defaults to -1.0f. This allows flexibility for other tests that may
want a different default value, such as the new test mentioned above.

Change-Id: Icf6ebbac0e1975e1cf49f60e5aa8afb32f9885de

android/cts/master/com.drawelements.deqp.vk.xml
android/cts/master/vk-master.txt
external/vulkancts/modules/vulkan/api/vktApiBufferComputeInstance.cpp
external/vulkancts/modules/vulkan/api/vktApiBufferComputeInstance.hpp
external/vulkancts/modules/vulkan/api/vktApiCommandBuffersTests.cpp
external/vulkancts/modules/vulkan/api/vktApiComputeInstanceResultBuffer.cpp
external/vulkancts/modules/vulkan/api/vktApiComputeInstanceResultBuffer.hpp
external/vulkancts/mustpass/1.0.1/vk-default.txt

index 4c203f2d98ef7e67053beee4c4e7922154fdaf6a..7b4559fa056ae3e57b770d7ae0cb32c0664a3be3 100644 (file)
                                <Test name="record_simul_use_secondary">
                                        <TestInstance/>
                                </Test>
+                               <Test name="record_simul_use_secondary_one_primary">
+                                       <TestInstance/>
+                               </Test>
+                               <Test name="record_simul_use_secondary_two_primary">
+                                       <TestInstance/>
+                               </Test>
                                <Test name="record_query_precise_w_flag">
                                        <TestInstance/>
                                </Test>
index 8c5c0fc0ac7aa18e519d938eaac1d9b34b9b5c99..a8f53d39364650e805a0513b9bae483b238ae26f 100644 (file)
@@ -3866,6 +3866,8 @@ dEQP-VK.api.command_buffers.record_one_time_submit_secondary
 dEQP-VK.api.command_buffers.render_pass_continue
 dEQP-VK.api.command_buffers.record_simul_use_primary
 dEQP-VK.api.command_buffers.record_simul_use_secondary
+dEQP-VK.api.command_buffers.record_simul_use_secondary_one_primary
+dEQP-VK.api.command_buffers.record_simul_use_secondary_two_primary
 dEQP-VK.api.command_buffers.record_query_precise_w_flag
 dEQP-VK.api.command_buffers.record_query_imprecise_w_flag
 dEQP-VK.api.command_buffers.record_query_imprecise_wo_flag
index 4de3bd3d3a85f80d441d76659eb482cdb7c4b9e2..6ef677faee909bdd26650ef025825526f152e929 100644 (file)
@@ -33,6 +33,54 @@ namespace api
 
 using namespace vk;
 
+Move<VkBuffer> createDataBuffer (vkt::Context&                         context,
+                                                                deUint32                                       offset,
+                                                                deUint32                                       bufferSize,
+                                                                deUint32                                       initData,
+                                                                deUint32                                       initDataSize,
+                                                                deUint32                                       uninitData,
+                                                                de::MovePtr<Allocation>*       outAllocation)
+{
+       const DeviceInterface&                                  vki             = context.getDeviceInterface();
+       const VkDevice                                                  device          = context.getDevice();
+       Allocator&                                                              allocator       = context.getDefaultAllocator();
+
+       DE_ASSERT(offset + initDataSize <= bufferSize);
+
+       const VkBufferUsageFlags                                usageFlags      = (VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
+       const VkBufferCreateInfo                                createInfo      =
+       {
+               VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
+               DE_NULL,
+               0u,                                                                                                                     // flags
+               (VkDeviceSize)bufferSize,                                                                       // size
+               usageFlags,                                                                                                     // usage
+               VK_SHARING_MODE_EXCLUSIVE,                                                                      // sharingMode
+               0u,                                                                                                                     // queueFamilyCount
+               DE_NULL,                                                                                                        // pQueueFamilyIndices
+       };
+       Move<VkBuffer>                                                  buffer(createBuffer(vki, device, &createInfo));
+
+       const VkMemoryRequirements                              requirements    = getBufferMemoryRequirements(vki, device, *buffer);
+       de::MovePtr<Allocation>                                 allocation      = allocator.allocate(requirements, MemoryRequirement::HostVisible);
+
+       VK_CHECK(vki.bindBufferMemory(device, *buffer, allocation->getMemory(), allocation->getOffset()));
+
+       void* const                                                             mapPtr          = allocation->getHostPtr();
+
+       if (offset)
+               deMemset(mapPtr, uninitData, (size_t)offset);
+
+       deMemset((deUint8 *)mapPtr + offset, initData, initDataSize);
+       deMemset((deUint8 *)mapPtr + offset + initDataSize, uninitData,
+               (size_t)bufferSize - (size_t)offset - initDataSize);
+
+       flushMappedMemoryRange(vki, device, allocation->getMemory(), allocation->getOffset(), bufferSize);
+
+       *outAllocation = allocation;
+       return buffer;
+}
+
 Move<VkBuffer> createColorDataBuffer (deUint32 offset,
                                                                          deUint32 bufferSize,
                                                                          const tcu::Vec4& color1,
@@ -65,7 +113,6 @@ Move<VkBuffer> createColorDataBuffer (deUint32 offset,
 
        VK_CHECK(vki.bindBufferMemory(device, *buffer, allocation->getMemory(), allocation->getOffset()));
 
-
        void*                                                                   mapPtr                                  = allocation->getHostPtr();
 
        if (offset)
@@ -107,6 +154,41 @@ Move<VkDescriptorPool> createDescriptorPool (vkt::Context& context)
                .build(vki, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
 }
 
+Move<VkDescriptorSet> createDescriptorSet (vkt::Context& context,
+                                                                                       VkDescriptorPool pool,
+                                                                                       VkDescriptorSetLayout layout,
+                                                                                       VkBuffer buffer,
+                                                                                       deUint32 offset,
+                                                                                       VkBuffer resBuf)
+{
+       const DeviceInterface&                                  vki             = context.getDeviceInterface();
+       const VkDevice                                                  device          = context.getDevice();
+
+       const vk::VkDescriptorBufferInfo                resultInfo      = makeDescriptorBufferInfo(resBuf, 0u, (vk::VkDeviceSize) ComputeInstanceResultBuffer::DATA_SIZE);
+       const vk::VkDescriptorBufferInfo                bufferInfo      = makeDescriptorBufferInfo(buffer, (vk::VkDeviceSize)offset, (vk::VkDeviceSize)sizeof(tcu::Vec4[2]));
+
+       const vk::VkDescriptorSetAllocateInfo   allocInfo       =
+       {
+               vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
+               DE_NULL,
+               pool,
+               1u,
+               &layout
+       };
+       vk::Move<vk::VkDescriptorSet>                   descriptorSet   = allocateDescriptorSet(vki, device, &allocInfo);
+
+       DescriptorSetUpdateBuilder builder;
+
+       // result
+       builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo);
+
+       // buffer
+       builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &bufferInfo);
+
+       builder.update(vki, device);
+       return descriptorSet;
+}
+
 Move<VkDescriptorSet> createDescriptorSet (VkDescriptorPool pool,
                                                                                   VkDescriptorSetLayout layout,
                                                                                   VkBuffer viewA,
index f742fec4cc36ea6888605234996819bce2d4db4b..968c0d4b6902525cf74f6d7c703a65691fe3ee3a 100644 (file)
@@ -33,6 +33,14 @@ namespace vkt
 namespace api
 {
 
+vk::Move<vk::VkBuffer>                                 createDataBuffer                (vkt::Context&                                  context,
+                                                                                                                                deUint32                                               offset,
+                                                                                                                                deUint32                                               bufferSize,
+                                                                                                                                deUint32                                               initData,
+                                                                                                                                deUint32                                               initDataSize,
+                                                                                                                                deUint32                                               uninitData,
+                                                                                                                                de::MovePtr<vk::Allocation>*   outAllocation);
+
 vk::Move<vk::VkBuffer>                                 createColorDataBuffer ( deUint32 offset,
                                                                                                                                deUint32 bufferSize,
                                                                                                                                const tcu::Vec4& color1,
@@ -44,6 +52,13 @@ vk::Move<vk::VkDescriptorSetLayout>          createDescriptorSetLayout (vkt::Context& co
 
 vk::Move<vk::VkDescriptorPool>                 createDescriptorPool (vkt::Context& context);
 
+vk::Move<vk::VkDescriptorSet>                  createDescriptorSet             (vkt::Context&                          context,
+                                                                                                                                vk::VkDescriptorPool           pool,
+                                                                                                                                vk::VkDescriptorSetLayout      layout,
+                                                                                                                                vk::VkBuffer                           buffer,
+                                                                                                                                deUint32                                       offset,
+                                                                                                                                vk::VkBuffer                           resBuf);
+
 vk::Move<vk::VkDescriptorSet>                  createDescriptorSet (vk::VkDescriptorPool pool,
                                                                                                                          vk::VkDescriptorSetLayout layout,
                                                                                                                          vk::VkBuffer viewA, deUint32 offsetA,
index 1bc8947279b69470832a833e8085cbb0a00ba73c..7ce31196fd9b62a3fd3f47a1cff682f80ad4ae18 100644 (file)
@@ -2325,6 +2325,365 @@ tcu::TestStatus simultaneousUseSecondaryBufferTest(Context& context)
                return tcu::TestStatus::fail("Simulatous Secondary Command Buffer Execution FAILED");
 }
 
+tcu::TestStatus simultaneousUseSecondaryBufferOnePrimaryBufferTest(Context& context)
+{
+       const VkDevice                                                  vkDevice = context.getDevice();
+       const DeviceInterface&                                  vk = context.getDeviceInterface();
+       const VkQueue                                                   queue = context.getUniversalQueue();
+       const deUint32                                                  queueFamilyIndex = context.getUniversalQueueFamilyIndex();
+       Allocator&                                                              allocator = context.getDefaultAllocator();
+       const ComputeInstanceResultBuffer               result(vk, vkDevice, allocator, 0.0f);
+
+       const VkCommandPoolCreateInfo                   cmdPoolParams =
+       {
+               VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,                                     //      VkStructureType                         sType;
+               DE_NULL,                                                                                                        //      const void*                                     pNext;
+               VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,                        //      VkCommandPoolCreateFlags        flags;
+               queueFamilyIndex,                                                                                       //      deUint32                                        queueFamilyIndex;
+       };
+       const Unique<VkCommandPool>                             cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
+
+       // Command buffer
+       const VkCommandBufferAllocateInfo               cmdBufParams =
+       {
+               VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,                         //      VkStructureType                 sType;
+               DE_NULL,                                                                                                        //      const void*                             pNext;
+               *cmdPool,                                                                                                       //      VkCommandPool                           pool;
+               VK_COMMAND_BUFFER_LEVEL_PRIMARY,                                                        //      VkCommandBufferLevel            level;
+               1u,                                                                                                                     //      uint32_t                                        bufferCount;
+       };
+       const Unique<VkCommandBuffer>                   primCmdBuf(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
+
+       // Secondary Command buffer params
+       const VkCommandBufferAllocateInfo               secCmdBufParams =
+       {
+               VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,                         //      VkStructureType                 sType;
+               DE_NULL,                                                                                                        //      const void*                             pNext;
+               *cmdPool,                                                                                                       //      VkCommandPool                           pool;
+               VK_COMMAND_BUFFER_LEVEL_SECONDARY,                                                      //      VkCommandBufferLevel            level;
+               1u,                                                                                                                     //      uint32_t                                        bufferCount;
+       };
+       const Unique<VkCommandBuffer>                   secCmdBuf(allocateCommandBuffer(vk, vkDevice, &secCmdBufParams));
+
+       const VkCommandBufferBeginInfo                  primCmdBufBeginInfo =
+       {
+               VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
+               DE_NULL,
+               0,                                                                                                                      // flags
+               (const VkCommandBufferInheritanceInfo*)DE_NULL,
+       };
+
+       const VkCommandBufferInheritanceInfo    secCmdBufInheritInfo =
+       {
+               VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
+               DE_NULL,
+               (VkRenderPass)0u,
+               0u,                                                                                                                     // subpass
+               (VkFramebuffer)0u,
+               VK_FALSE,                                                                                                       // occlusionQueryEnable
+               (VkQueryControlFlags)0u,
+               (VkQueryPipelineStatisticFlags)0u,
+       };
+       const VkCommandBufferBeginInfo                  secCmdBufBeginInfo =
+       {
+               VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
+               DE_NULL,
+               VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT,                           // flags
+               &secCmdBufInheritInfo,
+       };
+
+       const deUint32                                                  offset = (0u);
+       const deUint32                                                  addressableSize = 256;
+       const deUint32                                                  dataSize = 8;
+       de::MovePtr<Allocation>                                 bufferMem;
+       const Unique<VkBuffer>                                  buffer(createDataBuffer(context, offset, addressableSize, 0x00, dataSize, 0x5A, &bufferMem));
+       // Secondary command buffer will have a compute shader that does an atomic increment to make sure that all instances of secondary buffers execute
+       const Unique<VkDescriptorSetLayout>             descriptorSetLayout(createDescriptorSetLayout(context));
+       const Unique<VkDescriptorPool>                  descriptorPool(createDescriptorPool(context));
+       const Unique<VkDescriptorSet>                   descriptorSet(createDescriptorSet(context, *descriptorPool, *descriptorSetLayout, *buffer, offset, result.getBuffer()));
+       const VkDescriptorSet                                   descriptorSets[] = { *descriptorSet };
+       const int                                                               numDescriptorSets = DE_LENGTH_OF_ARRAY(descriptorSets);
+
+       const VkPipelineLayoutCreateInfo layoutCreateInfo =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,                          // sType
+               DE_NULL,                                                                                                        // pNext
+               (VkPipelineLayoutCreateFlags)0,
+               numDescriptorSets,                                                                                      // setLayoutCount
+               &descriptorSetLayout.get(),                                                                     // pSetLayouts
+               0u,                                                                                                                     // pushConstantRangeCount
+               DE_NULL,                                                                                                        // pPushConstantRanges
+       };
+       Unique<VkPipelineLayout>                                pipelineLayout(createPipelineLayout(vk, vkDevice, &layoutCreateInfo));
+
+       const Unique<VkShaderModule>                    computeModule(createShaderModule(vk, vkDevice, context.getBinaryCollection().get("compute_increment"), (VkShaderModuleCreateFlags)0u));
+
+       const VkPipelineShaderStageCreateInfo   shaderCreateInfo =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+               DE_NULL,
+               (VkPipelineShaderStageCreateFlags)0,
+               VK_SHADER_STAGE_COMPUTE_BIT,                                                            // stage
+               *computeModule,                                                                                         // shader
+               "main",
+               DE_NULL,                                                                                                        // pSpecializationInfo
+       };
+
+       const VkComputePipelineCreateInfo               pipelineCreateInfo =
+       {
+               VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
+               DE_NULL,
+               0u,                                                                                                                     // flags
+               shaderCreateInfo,                                                                                       // cs
+               *pipelineLayout,                                                                                        // layout
+               (vk::VkPipeline)0,                                                                                      // basePipelineHandle
+               0u,                                                                                                                     // basePipelineIndex
+       };
+
+       const Unique<VkPipeline>                                pipeline(createComputePipeline(vk, vkDevice, (VkPipelineCache)0u, &pipelineCreateInfo));
+
+       // record secondary command buffer
+       VK_CHECK(vk.beginCommandBuffer(*secCmdBuf, &secCmdBufBeginInfo));
+       {
+               vk.cmdBindPipeline(*secCmdBuf, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
+               vk.cmdBindDescriptorSets(*secCmdBuf, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0, numDescriptorSets, descriptorSets, 0, 0);
+               vk.cmdDispatch(*secCmdBuf, 1u, 1u, 1u);
+       }
+       // end recording of secondary buffer
+       VK_CHECK(vk.endCommandBuffer(*secCmdBuf));
+
+       // record primary command buffer
+       VK_CHECK(vk.beginCommandBuffer(*primCmdBuf, &primCmdBufBeginInfo));
+       {
+               // execute secondary buffer twice in same primary
+               vk.cmdExecuteCommands(*primCmdBuf, 1, &secCmdBuf.get());
+               vk.cmdExecuteCommands(*primCmdBuf, 1, &secCmdBuf.get());
+       }
+       VK_CHECK(vk.endCommandBuffer(*primCmdBuf));
+
+       const VkFenceCreateInfo                                 fenceCreateInfo =
+       {
+               VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
+               DE_NULL,
+               0u,                                                                                                                     // flags
+       };
+
+       // create fence to wait for execution of queue
+       const Unique<VkFence>                                   fence(createFence(vk, vkDevice, &fenceCreateInfo));
+
+       const VkSubmitInfo                                              submitInfo =
+       {
+               VK_STRUCTURE_TYPE_SUBMIT_INFO,                                                          // sType
+               DE_NULL,                                                                                                        // pNext
+               0u,                                                                                                                     // waitSemaphoreCount
+               DE_NULL,                                                                                                        // pWaitSemaphores
+               (const VkPipelineStageFlags*)DE_NULL,                                           // pWaitDstStageMask
+               1,                                                                                                                      // commandBufferCount
+               &primCmdBuf.get(),                                                                                      // pCommandBuffers
+               0u,                                                                                                                     // signalSemaphoreCount
+               DE_NULL,                                                                                                        // pSignalSemaphores
+       };
+
+       // submit primary buffer, the secondary should be executed too
+       VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence));
+
+       // wait for end of execution of queue
+       VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), 0u, INFINITE_TIMEOUT));
+
+       deUint32 resultCount;
+       result.readResultContentsTo(&resultCount);
+       // check if secondary buffer has been executed
+       if (resultCount == 2)
+               return tcu::TestStatus::pass("Simulatous Secondary Command Buffer Execution succeeded");
+       else
+               return tcu::TestStatus::fail("Simulatous Secondary Command Buffer Execution FAILED");
+}
+
+tcu::TestStatus simultaneousUseSecondaryBufferTwoPrimaryBuffersTest(Context& context)
+{
+       const VkDevice                                                  vkDevice = context.getDevice();
+       const DeviceInterface&                                  vk = context.getDeviceInterface();
+       const VkQueue                                                   queue = context.getUniversalQueue();
+       const deUint32                                                  queueFamilyIndex = context.getUniversalQueueFamilyIndex();
+       Allocator&                                                              allocator = context.getDefaultAllocator();
+       const ComputeInstanceResultBuffer               result(vk, vkDevice, allocator, 0.0f);
+
+       const VkCommandPoolCreateInfo                   cmdPoolParams =
+       {
+               VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,                                     //      VkStructureType                         sType;
+               DE_NULL,                                                                                                        //      const void*                                     pNext;
+               VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,                        //      VkCommandPoolCreateFlags        flags;
+               queueFamilyIndex,                                                                                       //      deUint32                                        queueFamilyIndex;
+       };
+       const Unique<VkCommandPool>                             cmdPool(createCommandPool(vk, vkDevice, &cmdPoolParams));
+
+       // Command buffer
+       const VkCommandBufferAllocateInfo               cmdBufParams =
+       {
+               VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,                         //      VkStructureType                 sType;
+               DE_NULL,                                                                                                        //      const void*                             pNext;
+               *cmdPool,                                                                                                       //      VkCommandPool                           pool;
+               VK_COMMAND_BUFFER_LEVEL_PRIMARY,                                                        //      VkCommandBufferLevel            level;
+               1u,                                                                                                                     //      uint32_t                                        bufferCount;
+       };
+       // Two separate primary cmd buffers that will be executed with the same secondary cmd buffer
+       const deUint32 numPrimCmdBufs = 2;
+       const Unique<VkCommandBuffer>                   primCmdBufOne(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
+       const Unique<VkCommandBuffer>                   primCmdBufTwo(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
+       VkCommandBuffer primCmdBufs[numPrimCmdBufs];
+       primCmdBufs[0] = primCmdBufOne.get();
+       primCmdBufs[1] = primCmdBufTwo.get();
+
+       // Secondary Command buffer params
+       const VkCommandBufferAllocateInfo               secCmdBufParams =
+       {
+               VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,                         //      VkStructureType                 sType;
+               DE_NULL,                                                                                                        //      const void*                             pNext;
+               *cmdPool,                                                                                                       //      VkCommandPool                           pool;
+               VK_COMMAND_BUFFER_LEVEL_SECONDARY,                                                      //      VkCommandBufferLevel            level;
+               1u,                                                                                                                     //      uint32_t                                        bufferCount;
+       };
+       const Unique<VkCommandBuffer>                   secCmdBuf(allocateCommandBuffer(vk, vkDevice, &secCmdBufParams));
+
+       const VkCommandBufferBeginInfo                  primCmdBufBeginInfo =
+       {
+               VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
+               DE_NULL,
+               0,                                                                                                                      // flags
+               (const VkCommandBufferInheritanceInfo*)DE_NULL,
+       };
+
+       const VkCommandBufferInheritanceInfo    secCmdBufInheritInfo =
+       {
+               VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
+               DE_NULL,
+               (VkRenderPass)0u,                                                                                       // renderPass
+               0u,                                                                                                                     // subpass
+               (VkFramebuffer)0u,                                                                                      // framebuffer
+               VK_FALSE,                                                                                                       // occlusionQueryEnable
+               (VkQueryControlFlags)0u,                                                                        // queryFlags
+               (VkQueryPipelineStatisticFlags)0u,                                                      // pipelineStatistics
+       };
+       const VkCommandBufferBeginInfo                  secCmdBufBeginInfo =
+       {
+               VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
+               DE_NULL,
+               VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT,                           // flags
+               &secCmdBufInheritInfo,
+       };
+
+       const deUint32                                                  offset = (0u);
+       const deUint32                                                  addressableSize = 256;
+       const deUint32                                                  dataSize = 8;
+       de::MovePtr<Allocation>                                 bufferMem;
+       const Unique<VkBuffer>                                  buffer(createDataBuffer(context, offset, addressableSize, 0x00, dataSize, 0x5A, &bufferMem));
+       // Secondary command buffer will have a compute shader that does an atomic increment to make sure that all instances of secondary buffers execute
+       const Unique<VkDescriptorSetLayout>             descriptorSetLayout(createDescriptorSetLayout(context));
+       const Unique<VkDescriptorPool>                  descriptorPool(createDescriptorPool(context));
+       const Unique<VkDescriptorSet>                   descriptorSet(createDescriptorSet(context, *descriptorPool, *descriptorSetLayout, *buffer, offset, result.getBuffer()));
+       const VkDescriptorSet                                   descriptorSets[] = { *descriptorSet };
+       const int                                                               numDescriptorSets = DE_LENGTH_OF_ARRAY(descriptorSets);
+
+       const VkPipelineLayoutCreateInfo layoutCreateInfo =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,                          // sType
+               DE_NULL,                                                                                                        // pNext
+               (VkPipelineLayoutCreateFlags)0,
+               numDescriptorSets,                                                                                      // setLayoutCount
+               &descriptorSetLayout.get(),                                                                     // pSetLayouts
+               0u,                                                                                                                     // pushConstantRangeCount
+               DE_NULL,                                                                                                        // pPushConstantRanges
+       };
+       Unique<VkPipelineLayout>                                pipelineLayout(createPipelineLayout(vk, vkDevice, &layoutCreateInfo));
+
+       const Unique<VkShaderModule>                    computeModule(createShaderModule(vk, vkDevice, context.getBinaryCollection().get("compute_increment"), (VkShaderModuleCreateFlags)0u));
+
+       const VkPipelineShaderStageCreateInfo   shaderCreateInfo =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+               DE_NULL,
+               (VkPipelineShaderStageCreateFlags)0,
+               VK_SHADER_STAGE_COMPUTE_BIT,                                                            // stage
+               *computeModule,                                                                                         // shader
+               "main",
+               DE_NULL,                                                                                                        // pSpecializationInfo
+       };
+
+       const VkComputePipelineCreateInfo               pipelineCreateInfo =
+       {
+               VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
+               DE_NULL,
+               0u,                                                                                                                     // flags
+               shaderCreateInfo,                                                                                       // cs
+               *pipelineLayout,                                                                                        // layout
+               (vk::VkPipeline)0,                                                                                      // basePipelineHandle
+               0u,                                                                                                                     // basePipelineIndex
+       };
+
+       const Unique<VkPipeline>                                pipeline(createComputePipeline(vk, vkDevice, (VkPipelineCache)0u, &pipelineCreateInfo));
+
+       // record secondary command buffer
+       VK_CHECK(vk.beginCommandBuffer(*secCmdBuf, &secCmdBufBeginInfo));
+       {
+               vk.cmdBindPipeline(*secCmdBuf, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
+               vk.cmdBindDescriptorSets(*secCmdBuf, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0, numDescriptorSets, descriptorSets, 0, 0);
+               vk.cmdDispatch(*secCmdBuf, 1u, 1u, 1u);
+       }
+       // end recording of secondary buffer
+       VK_CHECK(vk.endCommandBuffer(*secCmdBuf));
+
+       // record primary command buffers
+       // Insert one instance of same secondary command buffer into two separate primary command buffers
+       VK_CHECK(vk.beginCommandBuffer(*primCmdBufOne, &primCmdBufBeginInfo));
+       {
+               vk.cmdExecuteCommands(*primCmdBufOne, 1, &secCmdBuf.get());
+       }
+       VK_CHECK(vk.endCommandBuffer(*primCmdBufOne));
+
+       VK_CHECK(vk.beginCommandBuffer(*primCmdBufTwo, &primCmdBufBeginInfo));
+       {
+               vk.cmdExecuteCommands(*primCmdBufTwo, 1, &secCmdBuf.get());
+       }
+       VK_CHECK(vk.endCommandBuffer(*primCmdBufTwo));
+
+       const VkFenceCreateInfo                                 fenceCreateInfo =
+       {
+               VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
+               DE_NULL,
+               0u,                                                                                                                     // flags
+       };
+
+       // create fence to wait for execution of queue
+       const Unique<VkFence>                                   fence(createFence(vk, vkDevice, &fenceCreateInfo));
+
+       const VkSubmitInfo                                              submitInfo =
+       {
+               VK_STRUCTURE_TYPE_SUBMIT_INFO,                                                          // sType
+               DE_NULL,                                                                                                        // pNext
+               0u,                                                                                                                     // waitSemaphoreCount
+               DE_NULL,                                                                                                        // pWaitSemaphores
+               (const VkPipelineStageFlags*)DE_NULL,                                           // pWaitDstStageMask
+               numPrimCmdBufs,                                                                                         // commandBufferCount
+               primCmdBufs,                                                                                            // pCommandBuffers
+               0u,                                                                                                                     // signalSemaphoreCount
+               DE_NULL,                                                                                                        // pSignalSemaphores
+       };
+
+       // submit primary buffers, the secondary should be executed too
+       VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence));
+
+       // wait for end of execution of queue
+       VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), 0u, INFINITE_TIMEOUT));
+
+       deUint32 resultCount;
+       result.readResultContentsTo(&resultCount);
+       // check if secondary buffer has been executed
+       if (resultCount == 2)
+               return tcu::TestStatus::pass("Simulatous Secondary Command Buffer Execution succeeded");
+       else
+               return tcu::TestStatus::fail("Simulatous Secondary Command Buffer Execution FAILED");
+}
+
 tcu::TestStatus recordBufferQueryPreciseWithFlagTest(Context& context)
 {
        const VkDevice                                                  vkDevice                                = context.getDevice();
@@ -3864,11 +4223,11 @@ tcu::TestStatus orderBindPipelineTest(Context& context)
 void genComputeSource (SourceCollections& programCollection)
 {
        const char* const                                               versionDecl                             = glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
-       std::ostringstream                                              buf_good;
+       std::ostringstream                                              bufGood;
 
-       buf_good << versionDecl << "\n"
+       bufGood << versionDecl << "\n"
        << ""
-       << "layout(local_size_x = 1u, local_size_y = 1u, local_size_z = 1) in;\n"
+       << "layout(local_size_x = 1u, local_size_y = 1u, local_size_z = 1u) in;\n"
        << "layout(set = 0, binding = 1u, std140) uniform BufferName\n"
        << "{\n"
        << "    highp vec4 colorA;\n"
@@ -3889,13 +4248,13 @@ void genComputeSource (SourceCollections& programCollection)
        << "    b_out.read_colors[gl_WorkGroupID.x] = result_color;\n"
        << "}\n";
 
-       programCollection.glslSources.add("compute_good") << glu::ComputeSource(buf_good.str());
+       programCollection.glslSources.add("compute_good") << glu::ComputeSource(bufGood.str());
 
-       std::ostringstream      buf_bad;
+       std::ostringstream      bufBad;
 
-       buf_bad << versionDecl << "\n"
+       bufBad  << versionDecl << "\n"
        << ""
-       << "layout(local_size_x = 1u, local_size_y = 1u, local_size_z = 1) in;\n"
+       << "layout(local_size_x = 1u, local_size_y = 1u, local_size_z = 1u) in;\n"
        << "layout(set = 0, binding = 1u, std140) uniform BufferName\n"
        << "{\n"
        << "    highp vec4 colorA;\n"
@@ -3916,7 +4275,27 @@ void genComputeSource (SourceCollections& programCollection)
        << "    b_out.read_colors[gl_WorkGroupID.x] = vec4(0.0, 0.0, 0.0, 0.0);\n"
        << "}\n";
 
-       programCollection.glslSources.add("compute_bad") << glu::ComputeSource(buf_bad.str());
+       programCollection.glslSources.add("compute_bad") << glu::ComputeSource(bufBad.str());
+}
+
+void genComputeIncrementSource (SourceCollections& programCollection)
+{
+       const char* const                                               versionDecl = glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
+       std::ostringstream                                              bufIncrement;
+
+       bufIncrement << versionDecl << "\n"
+               << ""
+               << "layout(local_size_x = 1u, local_size_y = 1u, local_size_z = 1u) in;\n"
+               << "layout(set = 0, binding = 0, std140) buffer InOutBuf\n"
+               << "{\n"
+               << "    coherent uint count;\n"
+               << "} b_in_out;\n"
+               << "void main(void)\n"
+               << "{\n"
+               << "    atomicAdd(b_in_out.count, 1u);\n"
+               << "}\n";
+
+       programCollection.glslSources.add("compute_increment") << glu::ComputeSource(bufIncrement.str());
 }
 
 } // anonymous
@@ -3952,6 +4331,8 @@ tcu::TestCaseGroup* createCommandBuffersTests (tcu::TestContext& testCtx)
        addFunctionCase                         (commandBuffersTests.get(), "render_pass_continue",                             "",     renderPassContinueTest);
        addFunctionCase                         (commandBuffersTests.get(), "record_simul_use_primary",                 "",     simultaneousUsePrimaryBufferTest);
        addFunctionCase                         (commandBuffersTests.get(), "record_simul_use_secondary",               "",     simultaneousUseSecondaryBufferTest);
+       addFunctionCaseWithPrograms (commandBuffersTests.get(), "record_simul_use_secondary_one_primary", "", genComputeIncrementSource, simultaneousUseSecondaryBufferOnePrimaryBufferTest);
+       addFunctionCaseWithPrograms (commandBuffersTests.get(), "record_simul_use_secondary_two_primary", "", genComputeIncrementSource, simultaneousUseSecondaryBufferTwoPrimaryBuffersTest);
        addFunctionCase                         (commandBuffersTests.get(), "record_query_precise_w_flag",              "",     recordBufferQueryPreciseWithFlagTest);
        addFunctionCase                         (commandBuffersTests.get(), "record_query_imprecise_w_flag",    "",     recordBufferQueryImpreciseWithFlagTest);
        addFunctionCase                         (commandBuffersTests.get(), "record_query_imprecise_wo_flag",   "",     recordBufferQueryImpreciseWithoutFlagTest);
index 902663cbf384e4e28da7abec15dd569b4a03d173..6157f77d40f87cf3159dda5d7ff14750d5e6ddc2 100644 (file)
@@ -33,11 +33,12 @@ using namespace vk;
 
 ComputeInstanceResultBuffer::ComputeInstanceResultBuffer (const DeviceInterface &vki,
                                                                                                                                          VkDevice device,
-                                                                                                                                         Allocator &allocator)
+                                                                                                                                         Allocator &allocator,
+                                                                                                                                         float initValue)
                : m_vki(vki),
                m_device(device),
                m_bufferMem(DE_NULL),
-               m_buffer(createResultBuffer(m_vki, m_device, allocator, &m_bufferMem)),
+               m_buffer(createResultBuffer(m_vki, m_device, allocator, &m_bufferMem, initValue)),
                m_bufferBarrier(createResultBufferBarrier(*m_buffer))
 {
 }
@@ -48,10 +49,17 @@ void ComputeInstanceResultBuffer::readResultContentsTo(tcu::Vec4 (*results)[4])
        deMemcpy(*results, m_bufferMem->getHostPtr(), sizeof(*results));
 }
 
+void ComputeInstanceResultBuffer::readResultContentsTo(deUint32 *result) const
+{
+       invalidateMappedMemoryRange(m_vki, m_device, m_bufferMem->getMemory(), m_bufferMem->getOffset(), sizeof(*result));
+       deMemcpy(result, m_bufferMem->getHostPtr(), sizeof(*result));
+}
+
 Move<VkBuffer> ComputeInstanceResultBuffer::createResultBuffer(const DeviceInterface &vki,
                                                                                                                                         VkDevice device,
                                                                                                                                         Allocator &allocator,
-                                                                                                                                        de::MovePtr<Allocation> *outAllocation)
+                                                                                                                                        de::MovePtr<Allocation> *outAllocation,
+                                                                                                                                        float initValue)
 {
        const VkBufferCreateInfo createInfo =
        {
@@ -72,7 +80,7 @@ Move<VkBuffer> ComputeInstanceResultBuffer::createResultBuffer(const DeviceInter
 
        VK_CHECK(vki.bindBufferMemory(device, *buffer, allocation->getMemory(), allocation->getOffset()));
 
-       const float                                                             clearValue                              = -1.0f;
+       const float                                                             clearValue                              = initValue;
        void*                                                                   mapPtr                                  = allocation->getHostPtr();
 
        for (size_t offset = 0; offset < DATA_SIZE; offset += sizeof(float))
index feb7eb9601cfc6aeb96f712bc436003b0b5b29c7..6537a0b8bcc9670936b8205a2a6565cfb77bf4c4 100644 (file)
@@ -45,10 +45,13 @@ public:
 
                                                                                        ComputeInstanceResultBuffer (const vk::DeviceInterface &vki,
                                                                                                                                                                vk::VkDevice device,
-                                                                                                                                                               vk::Allocator &allocator);
+                                                                                                                                                               vk::Allocator &allocator,
+                                                                                                                                                               float initValue = -1.0f);
 
        void                                                                    readResultContentsTo(tcu::Vec4 (* results)[4]) const;
 
+       void                                                                    readResultContentsTo(deUint32* result) const;
+
        inline vk::VkBuffer                                             getBuffer(void) const { return *m_buffer; }
 
        inline const vk::VkBufferMemoryBarrier* getResultReadBarrier(void) const { return &m_bufferBarrier; }
@@ -57,7 +60,8 @@ private:
        static vk::Move<vk::VkBuffer>                   createResultBuffer(const vk::DeviceInterface &vki,
                                                                                                                vk::VkDevice device,
                                                                                                                vk::Allocator &allocator,
-                                                                                                               de::MovePtr<vk::Allocation>* outAllocation);
+                                                                                                               de::MovePtr<vk::Allocation>* outAllocation,
+                                                                                                               float initValue = -1.0f);
 
        static vk::VkBufferMemoryBarrier                createResultBufferBarrier(vk::VkBuffer buffer);
 
index b0bb1c62949beb301329c182b97319afca2654c9..cfcb3399de7a4e863db7eafc96a201abc07967c3 100644 (file)
@@ -3866,6 +3866,8 @@ dEQP-VK.api.command_buffers.record_one_time_submit_secondary
 dEQP-VK.api.command_buffers.render_pass_continue
 dEQP-VK.api.command_buffers.record_simul_use_primary
 dEQP-VK.api.command_buffers.record_simul_use_secondary
+dEQP-VK.api.command_buffers.record_simul_use_secondary_one_primary
+dEQP-VK.api.command_buffers.record_simul_use_secondary_two_primary
 dEQP-VK.api.command_buffers.record_query_precise_w_flag
 dEQP-VK.api.command_buffers.record_query_imprecise_w_flag
 dEQP-VK.api.command_buffers.record_query_imprecise_wo_flag