tcu::TestCaseGroup* createTests (tcu::TestContext& testCtx)
{
de::MovePtr<tcu::TestCaseGroup> apiTests (new tcu::TestCaseGroup(testCtx, "api", "API Tests"));
-
+
addFunctionCase(apiTests.get(), "create_sampler", "", createSamplerTest);
return apiTests.release();
VkCmdBufferResetFlags flags);
----
-Command pools
+[cols="1,4,8,8", options="header"]
+|===
+|No. | Tested area | Test Description | Relevant specification text
+|1 | Secondary buffers execution | Check if secondary command buffers are executed | Secondary command buffers may be called from primary command buffers, and are not directly submitted to queues.
+|2 | Order of execution | Check if commands that should be executed in-order are indeed done so. | Some command buffer commands are described as executing in-order with respect to other commands. This means that the effect of that one command must happen in the same order, relative to these other commands, as the order they were added to the command buffer.
+|3 | Synchronization | The commands may end in different order then they are being executed. Using semaphores for synchronization should prevent this | Unless otherwise specified, and without explicit synchronization, the various commands submitted to a queue via command buffers may execute in arbitrary order relative to each other, and/or concurrently. Also, the memory side-effects of those commands may not be directly visible to other commands without memory barriers. This is true within a command buffer, and across command buffers submitted to a given queue. See topic about synchronization primitives suitable to guarantee execution order and side-effect visibility between commands on a given queue.
+|4 | Independent state between buffers | Execute secondary command buffer, change state of primary, execute secondary again, and check if its state was changed | When secondary command buffer(s) are recorded to execute on a primary command buffer, the secondary command buffer inherits no state from the primary command buffer, and all state of the primary command buffer is undefined after an execute secondary command buffer command is recorded.
+|5 | Renderpass state independence | State inside a renderpass should not be changed by executing secondary command buffers | If the primary command buffer is inside a renderpass, then the renderpass and subpass state is not disturbed by executing secondary command buffers
+|===
+
+Command Buffer lifetime
+~~~~~~~~~~~~~~~~~~~~~~~
+
+[cols="1,4,8,8", options="header"]
+|===
+|No. | Tested area | Test Description | Relevant specification text
+|1 | Resetting command buffers - explicitly | Reset a command buffer using vkResetCommandBuffer | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT controls whether command buffers allocated from the pool can be individually reset. If this flag is set, individual command buffers allocated from the pool can be reset either explicitly, by calling vkResetCommandBuffer, or implicitly, by calling vkBeginCommandBuffer on a recorded command buffer. If this flag is not set, then the command buffers may only be reset in bulk by calling vkResetCommandPool.
+|2 | Resetting command buffers - implicitly | Reset a command buffer by calling vkBeginCommandBuffer on a buffer that has already been recorded |
+|3 | Resetting command buffers - bulk | Reset two command buffers that have already been recorded by calling vkResetCommandPool on the pool the command buffers were created from |
+|===
+
+Command Buffer recording
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+[cols="1,4,8,8", options="header"]
+|===
+|No. | Tested area | Test Description | Relevant specification text
+|1 | Recording to buffers | Check if all functions that should be recorded, are recorded |
+|2 | Render pass ignoring | if VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT flag is not set, the values of renderPass, framebuffer, and subpass members of the VkCommandBufferBeginInfo should be ignored | If flags has VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT set, the entire secondary command buffer is considered inside a render pass. In this case, the renderPass, framebuffer, and subpass members of the VkCommandBufferBeginInfo structure must be set as described below. Otherwise the renderPass, framebuffer, and subpass members of the VkCommandBufferBeginInfo structure are ignored, and the secondary command buffer may not contain commands that are only allowed inside a render pass.
+|3 | Simultaneous use – primary buffers | Set flag VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT and submit two times simultanously | If flags does not have VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT set, the command buffer must not be pending execution more than once at any given time. A primary command buffer is considered to be pending execution from the time it is submitted via vkQueueSubmit until that submission completes.
+|4 | Simultaneous use – secondary buffers | Set VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT on secondary buffer, and use the secondary buffer twice in primary buffer | If VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT is not set on a secondary command buffer, that command buffer cannot be used more than once in a given primary command buffer.
+|5 | Patch in place | Do not set VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT and check if buffer can be patched in-place | On some implementations, not using the VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT bit enables command buffers to be patched in-place if needed, rather than creating a copy of the command buffer.
+|6 | Improper recording | call vkBeginCommandBuffer on buffer currently recording – vkEndCommandBuffer should return error | It is invalid to begin a command buffer while it is being recorded
+|7 | | call vkEndCommandBuffer on buffer that is not recording – vkEndCommandBuffer should return error | It is invalid to end a command buffer if it is not being recorded.
+|8 | | call vkResetCommandBuffer on buffer currently recording – vkEndCommandBuffer should return error | It is invalid to reset a command buffer while it is being recorded.
+|9 | | vkBeginCommandBuffer on buffer already recorded, that has no VK_COMMAND_POOL_RESET_COMMAND_BUFFER_BIT flag set – vkEndCommandBuffer should return error | It is invalid to begin a command buffer that has already been recorded if the command buffer was allocated from a command pool that did not have the VK_COMMAND_POOL_RESET_COMMAND_BUFFER_BIT flag set until vkResetCommandPool is called on the pool
+|10 | | Make any of improper recording tests, reset the buffer and check if after the reset it starts recording correctly | If there was an error during recording, the application will by notified by an unsuccessful return code returned by vkEndCommandBuffer. If the application wishes to further use the command buffer, the command buffer must be reset.
+|===
+
+Command Buffer submission
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+[cols="1,4,8,8", options="header"]
+|===
+|No. | Tested area | Test Description | Relevant specification text
+|1 | Submission correctness | Call vkQueueSubmit with submitCount equal to the actual count of submits | pSubmits must be an array of submitCount valid VkSubmitInfo structures. If submitCount is 0 though, pSubmits is ignored
+|2 | | ... submitCount == 0 |
+|3 | queue and fence origin | Call vkQueueSubmit with queue and fence that were created from the same VkDevice | queue and fence must have been created, allocated or retrieved from the same VkDevice
+|4 | | Call vkQueueSubmit with queue and fence that were allocated from the same VkDevice |
+|5 | | Call vkQueueSubmit with queue and fence that were retrieved from the same VkDevice |
+|6 | Fence validity | Call vkQueueSubmit with VK_NULL_HANDLE passed as fence. | If fence is not VK_NULL_HANDLE, fence must be a valid VkFence handle
+|===
+
+Command Pools
~~~~~~~~~~~~~
TODO
VkCmdPoolResetFlags flags);
----
-2-level command buffers
-~~~~~~~~~~~~~~~~~~~~~~~
+[cols="1,4,8,8", options="header"]
+|===
+|No. | Tested area | Test Description | Relevant specification text
+|1 | Create, Reset and Destroy a Command Pool | Simple usage test. Create command pool, reset it, and destroy it. Check if result is success. |
+|===
+
+Secondary Command Buffers
+~~~~~~~~~~~~~~~~~~~~~~~~~
TODO
const VkCmdBuffer* pCmdBuffers);
----
+[cols="1,4,8,8", options="header"]
+|===
+|No. | Tested area | Test Description | Relevant specification text
+|1 | Buffers' origin | Call vkCmdExecuteCommands with commandBuffer and pCommandBuffers that created from the same VkDevice | commandBuffer and pCommandBuffers must have been created, allocated or retrieved from the same VkDevice
+|2 | | ... allocated from the same VkDevice |
+|3 | | ... retrieved from the same VkDevice |
+|4 | Simultaneous use | Call vkCmdExecuteCommands with pCommandBuffers such that its element is already pending execution in commandBuffer and was created with the VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT flag | Any given element of pCommandBuffers must not be already pending execution in commandBuffer, or appear twice in pCommandBuffers, unless it was created with the VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT flag
+|5 | | Call vkCmdExecuteCommands with pCommandBuffers such that its element appears twice in pCommandBuffers and was created with the VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT flag |
+|6 | Call from within a VkRenderPass | Call vkCmdExecuteCommands within a VkRenderPass with all elements of pCommandBuffers recorded with the VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT | If vkCmdExecuteCommands is being called within a VkRenderPass, any given element of pCommandBuffers must have been recorded with the VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT
+|===
+
+Render Pass
+~~~~~~~~~~~
+
+[cols="1,4,8,8", options="header"]
+|===
+|No. | Tested area | Test Description | Relevant specification text
+|1 | Attachment count in pCreateInfo | Call vkCreateRenderPass with pCreateInfo such that attachmentCount is equal to the number of attachments | pAttachments must be an array of attachmentCount valid VkSubpassDependency structures. If attachmentCount is 0 though, pAttachments is ignored
+|2 | | ... attachmentCount = 0 |
+|3 | Dependency count in pCreateInfo | Call vkCreateRenderPass with pCreateInfo such that dependencyCount is equal to the number of dependencies | pDependencies must be an array of dependencyCount valid VkSubpassDependency structures. If dependencyCount is 0 though, pDependencies is ignored
+|4 | | ... dependencyCount = 0 |
+|5 | Subpass dependency | Call vkCreateRenderPass with pCreateInfo pointing at a VkRenderPassCreateInfo structure with any two subpasses operating on attachments with overlapping ranges of the same VkDeviceMemory object and at least one of the writing to that area of VkDeviceMemory with a subpass dependency included directly | If any two subpasses operate on attachments with overlapping ranges of the same VkDeviceMemory object, and at least one subpass writes to that area of VkDeviceMemory, a subpass dependency must be included (either directly or via some intermediate subpasses) between them
+|6 | | ... with a subpass dependency included via intermediate subpasses |
+|7 | Attachments in subpasses | Call vkCreateRenderPass with pCreateInfo such that there is a subpass in pSubpasses where the attachment member of an element of pInputAttachments in an element of pSubpasses is bound to a range of a VkDeviceMemory object that overlaps with a different attachment in a subpass and the VkAttachmentReference structure describing said element includes VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS bit in flags | If the attachment member of any element of pInputAttachments, pColorAttachments, pResolveAttachments, pDepthStencilAttachment, or pPreserveAttachments in any given element of pSubpasses is bound to a range of a VkDeviceMemory object that overlaps with any other attachment in any subpass (including the same subpass), the VkAttachmentReference structures describing them must include VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT in flags
+|8 | | ... the attachment member of an element of pColorAttachments ... |
+|9 | | ... the attachment member of an element of pResolveAttachments ... |
+|10 | | ... the attachment member of an element of pDepthStencilAttachment ... |
+|11 | | ... the attachment member of an element of pPreserveAttachments ... |
+|12 | | ... the attachment member of an element of pInputAttachments in any given element of pSubpasses is not VK_ATTACHMENT_UNUSED and is less than the value of attachmentCount | If the attachment member of any element of pInputAttachments, pColorAttachments, pResolveAttachments, pDepthStencilAttachment, or pPreserveAttachments in any given element of pSubpasses is not VK_ATTACHMENT_UNUSED, it must be less than the value of attachmentCount
+|13 | | ... the attachment member of an element of pColorAttachments ... |
+|14 | | ... the attachment member of an element of pResolveAttachments ... |
+|15 | | ... the attachment member of an element of pDepthStencilAttachment ... |
+|16 | | ... the attachment member of an element of pPreserveAttachments ... |
+|17 | Subpass description | Call vkCreateRenderPass with pCreateInfo such that there is a subpass in pSubpasses where inputAttachmentCount is equal to the actual count of input attachments | pInputAttachments must be an array of inputAttachmentCount valid VkAttachmentReference structures. If inputAttachmentCount is 0 though, pInputAttachments is ignored
+|18 | | ... inputAttachmentCount == 0 |
+|19 | | Call vkCreateRenderPass with pCreateInfo such that there is a subpass in pSubpasses where colorAttachmentCount is equal to the actual count of color attachments | pColorAttachments must be an array of colorAttachmentCount valid VkAttachmentReference structures. If colorAttachmentCount is 0 though, pColorAttachments is ignored
+|20 | | ... colorAttachmentCount == 0 |
+|21 | | Call vkCreateRenderPass with pCreateInfo such that there is a subpass in pSubpasses where pResolveAttachments is not NULL and colorAttachmentCount is equal to the actual count of resolve attachments | If pResolveAttachments is not NULL, pResolveAttachments must be an array of colorAttachmentCount valid VkAttachmentReference structures. If colorAttachmentCount is 0 though, pResolveAttachments is ignored
+|22 | | ... pResolveAttachments is not NULL and colorAttachmentCount == 0 |
+|23 | | ... pResolveAttachments is NULL |
+|24 | | Call vkCreateRenderPass with pCreateInfo such that there is a subpass in pSubpasses where pDepthStencilAttachment points at a valid VkAttachmentReference structure | If pDepthStencilAttachment is not NULL, pDepthStencilAttachment must be a pointer to a valid VkAttachmentReference structure
+|25 | | ... pDepthStencilAttachment is NULL |
+|26 | | Call vkCreateRenderPass with pCreateInfo such that there is a subpass in pSubpasses where preserveAttachmentCount is equal to the actual count of preserveAttachments | pPreserveAttachments must be an array of preserveAttachmentCount valid VkAttachmentReference structures. If preserveAttachmentCount is 0 though, pPreserveAttachments is ignored
+|27 | | ... preserveAttachmentCount == 0 |
+|28 | | | he value of colorCount must be less than or equal to VkPhysicalDeviceLimits::maxColorAttachments
+|29 | | Call vkCreateRenderPass with pCreateInfo such that there is a subpass in pSubpasses where no depth nor stencil attachment is used and pDepthStencil == NULL | If no depth/stencil attachment is used in the subpass, pDepthStencil must be NULL, or the attachment member of a given element of pDepthStencil must be VK_ATTACHMENT_UNUSED
+|30 | | ... and pDepthStencil == VK_ATTACHMENT_UNUSED |
+|31 | | ... Call vkCreateRenderPass with pCreateInfo such that there is a subpass in pSubpasses where pResolveAttachments is not NULL and for each resolve attachment that does not have the value VK_ATTACHMENT_UNUSED, the corresponding color attachment does not have the value VK_ATTACHMENT_UNUSED either | If pResolveAttachments is not NULL, for each resolve attachment that does not have the value VK_ATTACHMENT_UNUSED, the corresponding color attachment must not have the value VK_ATTACHMENT_UNUSED
+|32 | | Call vkCreateRenderPass with pCreateInfo such that there is a subpass in pSubpasses where pResolveAttachments is not NULL and the sample count of each element of pColorAttachments is different than VK_SAMPLE_COUNT_1_BIT | If pResolveAttachments is not NULL, the sample count of each element of pColorAttachments must be anything other than VK_SAMPLE_COUNT_1_BIT
+|33 | | Call vkCreateRenderPass with pCreateInfo such that there is a subpass in pSubpasses where two attachments referenced by pColorAttachments and pDepthStencilAttachment are not VK_ATTACHMENT_UNUSED and have the same sample count | All attachments referenced by pColorAttachments and pDepthStencilAttachment that are not VK_ATTACHMENT_UNUSED, must have the same sample count
+|34 | | Call vkCreateRenderPass with pCreateInfo such that there is a subpass in pSubpasses where an input attachment is VK_ATTACHMENT_UNUSED and no pipelines bound during the subpass reference this input attachments | If any input attachments are VK_ATTACHMENT_UNUSED, then any pipelines bound during the subpass must not reference those input attachments
+|===
+
+Framebuffers
+~~~~~~~~~~~~~
+
+[cols="1,4,8,8", options="header"]
+|===
+|No. | Tested area | Test Description | Relevant specification text
+|1 | Attachment count in pCreateInfo | Call vkCreateFramebuffer with pCreateInfo such that attachmentCount is equal to the number of attachments | pAttachments must be an array of attachmentCount valid VkImageView handles. If attachmentCount is 0 though, pAttachments is ignored
+|2 | | ... where attachmentCount == 0 |
+|3 | Render Pass and Attachments origin | Call vkCreateFramebuffer with pCreateInfo such that renderPass and pAttachments were created using the same VkDevice | renderPass and pAttachments must have been created, allocated or retrieved from the same VkDevice
+|4 | | ... renderPass and pAttachments were allocated using the same VkDevice |
+|5 | | ... renderPass and pAttachments were retrieved from the same VkDevice |
+|6 | Dimensions | Call vkCreateFramebuffer with pCreateInfo such that width == 0 | The value of width must be less or equal to than VkPhysicalDeviceLimits::maxFramebufferWidth
+|7 | | ... width == VkPhysicalDeviceLimits::maxFramebufferWidth |
+|8 | | ... 0 < width < VkPhysicalDeviceLimits::maxFramebufferWidth |
+|9 | | ... height == 0 | The value of height must be less or equal to than VkPhysicalDeviceLimits::maxFramebufferHeight
+|10 | | ... height == VkPhysicalDeviceLimits::maxFramebufferHeight |
+|11 | | ... 0 < height < VkPhysicalDeviceLimits::maxFramebufferHeight |
+|===
+
Draw commands
-------------
--- /dev/null
+
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 The Khronos Group Inc.
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*--------------------------------------------------------------------*/
+
+
+
+#include "BufferComputeInstance.hpp"
+
+using namespace vk;
+using tcu::TestLog;
+using de::UniquePtr;
+
+
+vk::VkDescriptorInfo createDescriptorInfo (vk::VkBuffer buffer, vk::VkDeviceSize offset, vk::VkDeviceSize range)
+{
+ const vk::VkDescriptorInfo resultInfo =
+ {
+ 0, // bufferView
+ 0, // sampler
+ 0, // imageView
+ (vk::VkImageLayout)0, // imageLayout
+ { buffer, offset, range } // bufferInfo
+ };
+ return resultInfo;
+};
+
+vk::VkDescriptorInfo createDescriptorInfo (vk::VkBufferView bufferView)
+{
+ const vk::VkDescriptorInfo resultInfo =
+ {
+ bufferView, // bufferView
+ 0, // sampler
+ 0, // imageView
+ (vk::VkImageLayout)0, // imageLayout
+ { (vk::VkBuffer)0, 0, 0 } // bufferInfo
+ };
+ return resultInfo;
+};
+
+vk::VkDescriptorInfo createDescriptorInfo (vk::VkSampler sampler)
+{
+ const vk::VkDescriptorInfo resultInfo =
+ {
+ 0, // bufferView
+ sampler, // sampler
+ 0, // imageView
+ (vk::VkImageLayout)0, // imageLayout
+ { (vk::VkBuffer)0, 0, 0 } // bufferInfo
+ };
+ return resultInfo;
+};
+
+vk::VkDescriptorInfo createDescriptorInfo (vk::VkImageView imageView, vk::VkImageLayout layout)
+{
+ const vk::VkDescriptorInfo resultInfo =
+ {
+ 0, // bufferView
+ 0, // sampler
+ imageView, // imageView
+ layout, // imageLayout
+ { (vk::VkBuffer)0, 0, 0 } // bufferInfo
+ };
+ return resultInfo;
+};
+
+vk::VkDescriptorInfo createDescriptorInfo (vk::VkSampler sampler, vk::VkImageView imageView, vk::VkImageLayout layout)
+{
+ const vk::VkDescriptorInfo resultInfo =
+ {
+ 0, // bufferView
+ sampler, // sampler
+ imageView, // imageView
+ layout, // imageLayout
+ { (vk::VkBuffer)0, 0, 0 } // bufferInfo
+ };
+ return resultInfo;
+};
+
+vk::Move<vk::VkBuffer> createColorDataBuffer (deUint32 offset, deUint32 bufferSize, const tcu::Vec4& value1, const tcu::Vec4& value2, de::MovePtr<vk::Allocation>* outAllocation, vkt::Context& context)
+{
+ const vk::DeviceInterface& m_vki = context.getDeviceInterface();
+ const vk::VkDevice m_device = context.getDevice();
+ vk::Allocator& m_allocator = context.getDefaultAllocator();
+
+ DE_ASSERT(offset + sizeof(tcu::Vec4[2]) <= bufferSize);
+
+ const vk::VkBufferUsageFlags usageFlags = (vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) ;
+ const vk::VkBufferCreateInfo createInfo =
+ {
+ vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
+ DE_NULL,
+ (vk::VkDeviceSize)bufferSize, // size
+ usageFlags, // usage
+ 0u, // flags
+ vk::VK_SHARING_MODE_EXCLUSIVE, // sharingMode
+ 0u, // queueFamilyCount
+ DE_NULL, // pQueueFamilyIndices
+ };
+ vk::Move<vk::VkBuffer> buffer (vk::createBuffer(m_vki, m_device, &createInfo));
+ de::MovePtr<vk::Allocation> allocation (allocateAndBindObjectMemory(m_vki, m_device, m_allocator, *buffer, vk::MemoryRequirement::HostVisible));
+ void* mapPtr = allocation->getHostPtr();
+
+ if (offset)
+ deMemset(mapPtr, 0x5A, (size_t)offset);
+ deMemcpy((deUint8*)mapPtr + offset, value1.getPtr(), sizeof(tcu::Vec4));
+ deMemcpy((deUint8*)mapPtr + offset + sizeof(tcu::Vec4), value2.getPtr(), sizeof(tcu::Vec4));
+ deMemset((deUint8*)mapPtr + offset + 2 * sizeof(tcu::Vec4), 0x5A, (size_t)bufferSize - (size_t)offset - 2 * sizeof(tcu::Vec4));
+
+ flushMappedMemoryRange(m_vki, m_device, allocation->getMemory(), allocation->getOffset(), bufferSize);
+
+ *outAllocation = allocation;
+ return buffer;
+}
+
+vk::Move<vk::VkDescriptorSetLayout> createDescriptorSetLayout (vkt::Context& context)
+{
+
+ const vk::DeviceInterface& m_vki = context.getDeviceInterface();
+ const vk::VkDevice m_device = context.getDevice();
+
+ vk::DescriptorSetLayoutBuilder builder;
+
+ builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT);
+
+ builder.addSingleBinding( vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT);
+
+
+ return builder.build(m_vki, m_device);
+}
+
+vk::Move<vk::VkDescriptorPool> createDescriptorPool (vkt::Context& context)
+{
+ const vk::DeviceInterface& m_vki = context.getDeviceInterface();
+ const vk::VkDevice m_device = context.getDevice();
+
+ return vk::DescriptorPoolBuilder()
+ .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
+ .addType( vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u)
+ .build(m_vki, m_device, vk::VK_DESCRIPTOR_POOL_USAGE_ONE_SHOT, 1);
+}
+
+vk::Move<vk::VkDescriptorSet> createDescriptorSet (vk::VkDescriptorPool pool, vk::VkDescriptorSetLayout layout, vk::VkBuffer viewA, deUint32 offsetA, vk::VkBuffer viewB, deUint32 offsetB, vk::VkBuffer resBuf, vkt::Context& context)
+{
+ const vk::DeviceInterface& m_vki = context.getDeviceInterface();
+ const vk::VkDevice m_device = context.getDevice();
+
+ const vk::VkDescriptorInfo resultInfo = createDescriptorInfo(resBuf, 0u, (vk::VkDeviceSize)ComputeInstanceResultBuffer::DATA_SIZE);
+ const vk::VkDescriptorInfo bufferInfos[2] =
+ {
+ createDescriptorInfo(viewA, (vk::VkDeviceSize)offsetA, (vk::VkDeviceSize)sizeof(tcu::Vec4[2])),
+ createDescriptorInfo(viewB, (vk::VkDeviceSize)offsetB, (vk::VkDeviceSize)sizeof(tcu::Vec4[2])),
+ };
+
+ vk::Move<vk::VkDescriptorSet> descriptorSet = allocDescriptorSet(m_vki, m_device, pool, vk::VK_DESCRIPTOR_SET_USAGE_ONE_SHOT, layout);
+ vk::DescriptorSetUpdateBuilder builder;
+
+ // result
+ builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultInfo);
+
+ // buffers
+ builder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &bufferInfos[0]);
+
+ builder.update(m_vki, m_device);
+ return descriptorSet;
+}
--- /dev/null
+#include "vktApiCommandBuffersTests.hpp"
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 The Khronos Group Inc.
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and/or associated documentation files (the
+ * "Materials"), to deal in the Materials without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Materials, and to
+ * permit persons to whom the Materials are furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be
+ * included in all copies or substantial portions of the Materials.
+ *
+ * The Materials are Confidential Information as defined by the
+ * Khronos Membership Agreement until designated non-confidential by
+ * Khronos, at which point this condition clause shall be removed.
+ *
+ * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ *//*--------------------------------------------------------------------*/
+
+#include "vktApiTests.hpp"
+#include <vector>
+#include <sstream>
+
+#include "vktTestCaseUtil.hpp"
+#include "vkBuilderUtil.hpp"
+#include "vkDefs.hpp"
+#include "vkPlatform.hpp"
+#include "vkStrUtil.hpp"
+#include "vkRef.hpp"
+#include "vkRefUtil.hpp"
+#include "vkQueryUtil.hpp"
+#include "vkMemUtil.hpp"
+#include "vkDeviceUtil.hpp"
+#include "vkPrograms.hpp"
+#include "vkTypeUtil.hpp"
+#include "vkPlatform.hpp"
+#include "tcuTestLog.hpp"
+#include "tcuFormatUtil.hpp"
+#include "deUniquePtr.hpp"
+
+#include "BufferComputeInstance.hpp"
+#include "ComputeInstanceResultBuffer.hpp"
+
+namespace vkt
+{
+namespace api
+{
+namespace
+{
+
+
+using namespace vk;
+using tcu::TestLog;
+using de::UniquePtr;
+
+const deUint64 INFINITE_TIMEOUT = ~(deUint64)0u;
+
+tcu::TestStatus createBufferTest (Context& context)
+{
+ const VkDevice vkDevice = context.getDevice();
+ const DeviceInterface& vk = context.getDeviceInterface();
+ const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
+
+ const VkCmdPoolCreateInfo cmdPoolParams =
+ {
+ VK_STRUCTURE_TYPE_CMD_POOL_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ queueFamilyIndex, // deUint32 queueFamilyIndex;
+ VK_CMD_POOL_CREATE_RESET_COMMAND_BUFFER_BIT // VkCmdPoolCreateFlags flags;
+ };
+ const Unique<VkCmdPool> cmdPool (createCommandPool(vk, vkDevice, &cmdPoolParams));
+
+ // Command buffer
+ const VkCmdBufferCreateInfo cmdBufParams =
+ {
+ VK_STRUCTURE_TYPE_CMD_BUFFER_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ *cmdPool, // VkCmdPool pool;
+ VK_CMD_BUFFER_LEVEL_PRIMARY, // VkCmdBufferLevel level;
+ 0u, // VkCmdBufferCreateFlags flags;
+ };
+ const Unique<VkCmdBuffer> cmdBuf (createCommandBuffer(vk, vkDevice, &cmdBufParams));
+
+ return tcu::TestStatus::pass("create Command Buffer succeeded");
+}
+
+
+tcu::TestStatus executeSecondaryBufferTest (Context& context)
+{
+
+ const VkDevice vkDevice = context.getDevice();
+ const DeviceInterface& vk = context.getDeviceInterface();
+ const VkQueue queue = context.getUniversalQueue();
+ const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
+
+ const VkCmdPoolCreateInfo cmdPoolParams =
+ {
+ VK_STRUCTURE_TYPE_CMD_POOL_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ queueFamilyIndex, // deUint32 queueFamilyIndex;
+ VK_CMD_POOL_CREATE_RESET_COMMAND_BUFFER_BIT // VkCmdPoolCreateFlags flags;
+ };
+ const Unique<VkCmdPool> cmdPool (createCommandPool(vk, vkDevice, &cmdPoolParams));
+
+ // Command buffer
+ const VkCmdBufferCreateInfo cmdBufParams =
+ {
+ VK_STRUCTURE_TYPE_CMD_BUFFER_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ *cmdPool, // VkCmdPool pool;
+ VK_CMD_BUFFER_LEVEL_PRIMARY, // VkCmdBufferLevel level;
+ 0u, // VkCmdBufferCreateFlags flags;
+ };
+ const Unique<VkCmdBuffer> primCmdBuf (createCommandBuffer(vk, vkDevice, &cmdBufParams));
+
+ // Secondary Command buffer
+ const VkCmdBufferCreateInfo secCmdBufParams =
+ {
+ VK_STRUCTURE_TYPE_CMD_BUFFER_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ *cmdPool, // VkCmdPool pool;
+ VK_CMD_BUFFER_LEVEL_SECONDARY, // VkCmdBufferLevel level;
+ 0u, // VkCmdBufferCreateFlags flags;
+ };
+ const Unique<VkCmdBuffer> secCmdBuf (createCommandBuffer(vk, vkDevice, &secCmdBufParams));
+
+ const VkCmdBufferBeginInfo primCmdBufBeginInfo =
+ {
+ VK_STRUCTURE_TYPE_CMD_BUFFER_BEGIN_INFO,
+ DE_NULL,
+ 0,//VK_CMD_BUFFER_OPTIMIZE_SMALL_BATCH_BIT | VK_CMD_BUFFER_OPTIMIZE_ONE_TIME_SUBMIT_BIT, // flags
+ (VkRenderPass)0u, // renderPass
+ 0u, // subpass
+ (VkFramebuffer)0u, // framebuffer
+ };
+
+ const VkCmdBufferBeginInfo secCmdBufBeginInfo =
+ {
+ VK_STRUCTURE_TYPE_CMD_BUFFER_BEGIN_INFO,
+ DE_NULL,
+ 0u, //VK_CMD_BUFFER_OPTIMIZE_SMALL_BATCH_BIT | VK_CMD_BUFFER_OPTIMIZE_ONE_TIME_SUBMIT_BIT, // flags
+ (VkRenderPass)0u, // renderPass
+ 0u, // subpass
+ (VkFramebuffer)0u, // framebuffer
+ };
+
+
+ // Fill create info struct for event
+ const VkEventCreateInfo eventCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_EVENT_CREATE_INFO,
+ DE_NULL,
+ 0u,
+ };
+
+ // create event that will be used to check if secondary command buffer has been executed
+ const Unique<VkEvent> event ( createEvent(vk, vkDevice, &eventCreateInfo ) );
+
+ // reset event
+ vk.resetEvent(vkDevice, *event);
+
+ // record primary command buffer
+ vk.beginCommandBuffer( *primCmdBuf, &primCmdBufBeginInfo);
+ {
+ // record secondary command buffer
+ vk.beginCommandBuffer( *secCmdBuf, &secCmdBufBeginInfo);
+ {
+ // allow execution of event during every stage of pipeline
+ VkPipelineStageFlags stageMask = 0x0000FFFF;
+
+ // record setting event
+ vk.cmdSetEvent(*secCmdBuf, *event,stageMask);
+ }
+
+ // end recording of secondary buffers
+ vk.endCommandBuffer( *secCmdBuf );
+
+ // execute secondary buffer
+ vk.cmdExecuteCommands( *primCmdBuf, 1, &secCmdBuf.get());
+ }
+ vk.endCommandBuffer( *primCmdBuf );
+
+
+ vk.resetCommandBuffer(*primCmdBuf, 0u);
+
+ 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));
+
+ // submit primary buffer, the secondary should be executed too
+ vk.queueSubmit(queue,1, &primCmdBuf.get(), *fence);
+
+ // wait for end of execution of queue
+ const deUint64 infiniteTimeout = ~(deUint64)0u;
+ vk.waitForFences(vkDevice, 1, &fence.get(), 0u, infiniteTimeout);
+
+ // check if secondary buffer has been executed
+ VkResult result = vk.getEventStatus(vkDevice,*event);
+ if (result == VK_EVENT_SET) return tcu::TestStatus::pass("Execute Secondary Command Buffer succeeded");
+ else return tcu::TestStatus::pass("Execute Secondary Command Buffer FAILED");
+
+
+}
+
+tcu::TestStatus executeOrderTest (Context& context)
+{
+ const DeviceInterface& m_vki = context.getDeviceInterface();
+ const VkDevice m_device = context.getDevice();
+ const VkQueue m_queue = context.getUniversalQueue();
+ const deUint32 m_queueFamilyIndex = context.getUniversalQueueFamilyIndex();
+ Allocator& m_allocator = context.getDefaultAllocator();
+ const ComputeInstanceResultBuffer m_result(m_vki, m_device, m_allocator);
+
+ enum
+ {
+ ADDRESSABLE_SIZE = 256, // allocate a lot more than required
+ };
+
+ const tcu::Vec4 colorA1 = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
+ const tcu::Vec4 colorA2 = tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f);
+
+ const deUint32 dataOffsetA = (0u);
+ const deUint32 dataOffsetB = (0u);
+ const deUint32 viewOffsetA = (0u);
+ const deUint32 viewOffsetB = (0u);
+ const deUint32 bufferSizeA = dataOffsetA + ADDRESSABLE_SIZE;
+ const deUint32 bufferSizeB = dataOffsetB + ADDRESSABLE_SIZE;
+
+ de::MovePtr<Allocation> bufferMemA;
+ const Unique<VkBuffer> bufferA (createColorDataBuffer(dataOffsetA, bufferSizeA, colorA1, colorA2, &bufferMemA, context));
+
+ de::MovePtr<Allocation> bufferMemB;
+ const Unique<VkBuffer> bufferB ((Move<VkBuffer>()));
+
+ const Unique<VkDescriptorSetLayout> descriptorSetLayout (createDescriptorSetLayout(context));
+ const Unique<VkDescriptorPool> descriptorPool (createDescriptorPool(context));
+
+ const Unique<VkDescriptorSet> descriptorSet (createDescriptorSet(*descriptorPool, *descriptorSetLayout, *bufferA, viewOffsetA, *bufferB, viewOffsetB, m_result.getBuffer(), context));
+ const VkDescriptorSet descriptorSets[] = { *descriptorSet };
+ const int numDescriptorSets = DE_LENGTH_OF_ARRAY(descriptorSets);
+
+ const VkPipelineLayoutCreateInfo layoutCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
+ DE_NULL,
+ numDescriptorSets, // descriptorSetCount
+ &descriptorSetLayout.get(), // pSetLayouts
+ 0u, // pushConstantRangeCount
+ DE_NULL, // pPushConstantRanges
+ };
+ Unique<VkPipelineLayout> m_pipelineLayout (createPipelineLayout(m_vki, m_device, &layoutCreateInfo));
+
+
+ const Unique<VkShaderModule> computeModuleGood (createShaderModule(m_vki, m_device, context.getBinaryCollection().get("compute_good"), (VkShaderModuleCreateFlags)0u));
+ const Unique<VkShaderModule> computeModuleBad (createShaderModule(m_vki, m_device, context.getBinaryCollection().get("compute_bad"), (VkShaderModuleCreateFlags)0u));
+
+ const VkShaderCreateInfo shaderCreateInfoGood =
+ {
+ VK_STRUCTURE_TYPE_SHADER_CREATE_INFO,
+ DE_NULL,
+ *computeModuleGood, // module
+ "main", // pName
+ 0u, // flags
+ VK_SHADER_STAGE_COMPUTE
+ };
+ const VkShaderCreateInfo shaderCreateInfoBad =
+ {
+ VK_STRUCTURE_TYPE_SHADER_CREATE_INFO,
+ DE_NULL,
+ *computeModuleBad, // module
+ "main", // pName
+ 0u, // flags
+ VK_SHADER_STAGE_COMPUTE
+ };
+
+ const Unique<VkShader> computeShaderGood (createShader(m_vki, m_device, &shaderCreateInfoGood));
+ const Unique<VkShader> computeShaderBad (createShader(m_vki, m_device, &shaderCreateInfoBad));
+
+ const VkPipelineShaderStageCreateInfo csGood =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ DE_NULL,
+ VK_SHADER_STAGE_COMPUTE, // stage
+ *computeShaderGood, // shader
+ DE_NULL, // pSpecializationInfo
+ };
+
+ const VkPipelineShaderStageCreateInfo csBad =
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ DE_NULL,
+ VK_SHADER_STAGE_COMPUTE, // stage
+ *computeShaderBad, // shader
+ DE_NULL, // pSpecializationInfo
+ };
+
+
+ const VkComputePipelineCreateInfo createInfoGood =
+ {
+ VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
+ DE_NULL,
+ csGood, // cs
+ 0u, // flags
+ *m_pipelineLayout, // descriptorSetLayout.get()
+ (VkPipeline)0, // basePipelineHandle
+ 0u, // basePipelineIndex
+ };
+
+ const VkComputePipelineCreateInfo createInfoBad =
+ {
+ VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
+ DE_NULL,
+ csBad, // cs
+ 0u, // flags
+ *m_pipelineLayout, // descriptorSetLayout.get()
+ (VkPipeline)0, // basePipelineHandle
+ 0u, // basePipelineIndex
+ };
+
+ const Unique<VkPipeline> m_pipelineGood (createComputePipeline(m_vki, m_device, (VkPipelineCache)0u, &createInfoGood) );
+ const Unique<VkPipeline> m_pipelineBad (createComputePipeline(m_vki, m_device, (VkPipelineCache)0u, &createInfoBad) );
+
+ const VkMemoryInputFlags inputBit = (VK_MEMORY_INPUT_UNIFORM_READ_BIT) ;
+ const VkBufferMemoryBarrier bufferBarrierA =
+ {
+ VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
+ DE_NULL,
+ VK_MEMORY_OUTPUT_HOST_WRITE_BIT, // outputMask
+ inputBit, // inputMask
+ VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex
+ VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex
+ *bufferA, // buffer
+ (VkDeviceSize)0u, // offset
+ (VkDeviceSize)bufferSizeA, // size
+ };
+
+ const VkBufferMemoryBarrier bufferBarrierB =
+ {
+ VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
+ DE_NULL,
+ VK_MEMORY_OUTPUT_HOST_WRITE_BIT, // outputMask
+ inputBit, // inputMask
+ VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex
+ VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex
+ *bufferB, // buffer
+ (VkDeviceSize)0u, // offset
+ (VkDeviceSize)bufferSizeB, // size
+ };
+
+ const deUint32 numSrcBuffers = 1u;
+
+
+ const deUint32* const dynamicOffsets = (DE_NULL);
+ const deUint32 numDynamicOffsets = (0);
+ const void* const preBarriers[] = { &bufferBarrierA, &bufferBarrierB };
+ const int numPreBarriers = numSrcBuffers;
+ const void* const postBarriers[] = { m_result.getResultReadBarrier() };
+ const int numPostBarriers = DE_LENGTH_OF_ARRAY(postBarriers);
+ const tcu::Vec4 refQuadrantValue14 = (colorA2);
+ const tcu::Vec4 refQuadrantValue23 = (colorA1);
+ const tcu::Vec4 references[4] =
+ {
+ refQuadrantValue14,
+ refQuadrantValue23,
+ refQuadrantValue23,
+ refQuadrantValue14,
+ };
+ tcu::Vec4 results[4];
+
+ // submit and wait begin
+
+ const tcu::UVec3 m_numWorkGroups = tcu::UVec3(4, 1, 1);
+ const VkCmdPoolCreateInfo cmdPoolCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_CMD_POOL_CREATE_INFO,
+ DE_NULL,
+ m_queueFamilyIndex, // m_queueFamilyIndex
+ VK_CMD_POOL_CREATE_TRANSIENT_BIT, // flags
+ };
+ const Unique<VkCmdPool> cmdPool (createCommandPool(m_vki, m_device, &cmdPoolCreateInfo));
+
+ const VkFenceCreateInfo fenceCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
+ DE_NULL,
+ 0u, // flags
+ };
+
+ const VkCmdBufferCreateInfo cmdBufCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_CMD_BUFFER_CREATE_INFO,
+ DE_NULL,
+ *cmdPool, // cmdPool
+ VK_CMD_BUFFER_LEVEL_PRIMARY, // level
+ 0u, // flags
+ };
+ const VkCmdBufferBeginInfo cmdBufBeginInfo =
+ {
+ VK_STRUCTURE_TYPE_CMD_BUFFER_BEGIN_INFO,
+ DE_NULL,
+ VK_CMD_BUFFER_OPTIMIZE_SMALL_BATCH_BIT | VK_CMD_BUFFER_OPTIMIZE_ONE_TIME_SUBMIT_BIT, // flags
+ (VkRenderPass)0u, // renderPass
+ 0u, // subpass
+ (VkFramebuffer)0u, // framebuffer
+ };
+
+ const Unique<VkFence> cmdCompleteFence (createFence(m_vki, m_device, &fenceCreateInfo));
+ const Unique<VkCmdBuffer> cmd (createCommandBuffer(m_vki, m_device, &cmdBufCreateInfo));
+ const deUint64 infiniteTimeout = ~(deUint64)0u;
+
+ VK_CHECK(m_vki.beginCommandBuffer(*cmd, &cmdBufBeginInfo));
+
+ m_vki.cmdBindPipeline(*cmd, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineBad);
+ m_vki.cmdBindPipeline(*cmd, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineGood);
+ m_vki.cmdBindDescriptorSets(*cmd, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineLayout, 0, numDescriptorSets, descriptorSets, numDynamicOffsets, dynamicOffsets);
+
+ if (numPreBarriers)
+ m_vki.cmdPipelineBarrier(*cmd, 0u, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_FALSE, numPreBarriers, preBarriers);
+
+ m_vki.cmdDispatch(*cmd, m_numWorkGroups.x(), m_numWorkGroups.y(), m_numWorkGroups.z());
+ m_vki.cmdPipelineBarrier(*cmd, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_FALSE, numPostBarriers, postBarriers);
+ VK_CHECK(m_vki.endCommandBuffer(*cmd));
+
+ // run
+ VK_CHECK(m_vki.queueSubmit(m_queue, 1, &cmd.get(), *cmdCompleteFence));
+ VK_CHECK(m_vki.waitForFences(m_device, 1, &cmdCompleteFence.get(), 0u, infiniteTimeout)); // \note: timeout is failure
+
+ // submit and wait end
+ m_result.readResultContentsTo(&results);
+
+ // verify
+ if (results[0] == references[0] &&
+ results[1] == references[1] &&
+ results[2] == references[2] &&
+ results[3] == references[3])
+ {
+ return tcu::TestStatus::pass("Pass");
+ }
+ else if (results[0] == tcu::Vec4(-1.0f) &&
+ results[1] == tcu::Vec4(-1.0f) &&
+ results[2] == tcu::Vec4(-1.0f) &&
+ results[3] == tcu::Vec4(-1.0f))
+ {
+ context.getTestContext().getLog()
+ << tcu::TestLog::Message
+ << "Result buffer was not written to."
+ << tcu::TestLog::EndMessage;
+ return tcu::TestStatus::fail("Result buffer was not written to");
+ }
+ else
+ {
+ context.getTestContext().getLog()
+ << tcu::TestLog::Message
+ << "Error expected ["
+ << references[0] << ", "
+ << references[1] << ", "
+ << references[2] << ", "
+ << references[3] << "], got ["
+ << results[0] << ", "
+ << results[1] << ", "
+ << results[2] << ", "
+ << results[3] << "]"
+ << tcu::TestLog::EndMessage;
+ return tcu::TestStatus::fail("Invalid result values");
+ }
+};
+
+tcu::TestStatus explicitResetCmdBufferTest(Context& context)
+{
+ const VkDevice vkDevice = context.getDevice();
+ const DeviceInterface& vk = context.getDeviceInterface();
+ const VkQueue queue = context.getUniversalQueue();
+ const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
+
+ const VkCmdPoolCreateInfo cmdPoolParams =
+ {
+ VK_STRUCTURE_TYPE_CMD_POOL_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ queueFamilyIndex, // deUint32 queueFamilyIndex;
+ VK_CMD_POOL_CREATE_RESET_COMMAND_BUFFER_BIT // VkCmdPoolCreateFlags flags;
+ };
+ const Unique<VkCmdPool> cmdPool (createCommandPool(vk, vkDevice, &cmdPoolParams));
+
+ // Command buffer
+ const VkCmdBufferCreateInfo cmdBufParams =
+ {
+ VK_STRUCTURE_TYPE_CMD_BUFFER_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ *cmdPool, // VkCmdPool pool;
+ VK_CMD_BUFFER_LEVEL_PRIMARY, // VkCmdBufferLevel level;
+ 0u, // VkCmdBufferCreateFlags flags;
+ };
+ const Unique<VkCmdBuffer> cmdBuf (createCommandBuffer(vk, vkDevice, &cmdBufParams));
+
+ const VkCmdBufferBeginInfo cmdBufBeginInfo =
+ {
+ VK_STRUCTURE_TYPE_CMD_BUFFER_BEGIN_INFO,
+ DE_NULL,
+ VK_CMD_BUFFER_OPTIMIZE_ONE_TIME_SUBMIT_BIT,
+ DE_NULL,
+ 0u,
+ DE_NULL,
+ };
+
+ const VkEventCreateInfo eventCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_EVENT_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkEventCreateFlags flags;
+ };
+ const Unique<VkEvent> event (createEvent(vk, vkDevice, &eventCreateInfo));
+
+ // Put the command buffer in recording state.
+ VK_CHECK(vk.beginCommandBuffer(*cmdBuf, &cmdBufBeginInfo));
+ {
+ vk.cmdSetEvent(*cmdBuf, *event, VK_PIPELINE_STAGE_ALL_GPU_COMMANDS);
+ }
+ VK_CHECK(vk.endCommandBuffer(*cmdBuf));
+
+ // We'll use a fence to wait for the execution of the queue
+ const VkFenceCreateInfo fenceCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkFenceCreateFlags flags
+ };
+ const Unique<VkFence> fence (createFence(vk, vkDevice, &fenceCreateInfo));
+
+ // Submitting the command buffer that sets the event to the queue
+ VK_CHECK(vk.queueSubmit(queue, 1, &cmdBuf.get(), *fence));
+
+ // Waiting for the queue to finish executing
+ VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), 0u, INFINITE_TIMEOUT));
+
+ // Check if the buffer was executed
+ if (vk.getEventStatus(vkDevice, *event) != VK_EVENT_SET)
+ return tcu::TestStatus::fail("Failed to set the event.");
+
+ // Reset the event
+ VK_CHECK(vk.resetEvent(vkDevice, *event));
+ if(vk.getEventStatus(vkDevice, *event) != VK_EVENT_RESET)
+ return tcu::TestStatus::fail("Failed to reset the event.");
+
+ // Reset the command buffer.
+ VK_CHECK(vk.resetCommandBuffer(*cmdBuf, 0));
+ // Reset the fence so that we can reuse it
+ VK_CHECK(vk.resetFences(vkDevice, 1, &fence.get()));
+
+ // Submit the command buffer after resetting. It should have no commands
+ // recorded, so the event should remain unsignaled.
+ VK_CHECK(vk.queueSubmit(queue, 1, &cmdBuf.get(), *fence));
+ // Waiting for the queue to finish executing
+ VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), 0u, INFINITE_TIMEOUT));
+
+ // Check if the event remained unset.
+ if(vk.getEventStatus(vkDevice,*event) == VK_EVENT_RESET)
+ return tcu::TestStatus::pass("Buffer was reset properly.");
+ else
+ return tcu::TestStatus::fail("Buffer was not reset properly.");
+}
+
+tcu::TestStatus implicitResetCmdBufferTest(Context& context)
+{
+ const VkDevice vkDevice = context.getDevice();
+ const DeviceInterface& vk = context.getDeviceInterface();
+ const VkQueue queue = context.getUniversalQueue();
+ const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
+
+ const VkCmdPoolCreateInfo cmdPoolParams =
+ {
+ VK_STRUCTURE_TYPE_CMD_POOL_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ queueFamilyIndex, // deUint32 queueFamilyIndex;
+ VK_CMD_POOL_CREATE_RESET_COMMAND_BUFFER_BIT // VkCmdPoolCreateFlags flags;
+ };
+ const Unique<VkCmdPool> cmdPool (createCommandPool(vk, vkDevice, &cmdPoolParams));
+
+ // Command buffer
+ const VkCmdBufferCreateInfo cmdBufParams =
+ {
+ VK_STRUCTURE_TYPE_CMD_BUFFER_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ *cmdPool, // VkCmdPool pool;
+ VK_CMD_BUFFER_LEVEL_PRIMARY, // VkCmdBufferLevel level;
+ 0u, // VkCmdBufferCreateFlags flags;
+ };
+ const Unique<VkCmdBuffer> cmdBuf (createCommandBuffer(vk, vkDevice, &cmdBufParams));
+
+ const VkCmdBufferBeginInfo cmdBufBeginInfo =
+ {
+ VK_STRUCTURE_TYPE_CMD_BUFFER_BEGIN_INFO,
+ DE_NULL,
+ VK_CMD_BUFFER_OPTIMIZE_ONE_TIME_SUBMIT_BIT,
+ DE_NULL,
+ 0u,
+ DE_NULL,
+ };
+
+ const VkEventCreateInfo eventCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_EVENT_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkEventCreateFlags flags;
+ };
+ const Unique<VkEvent> event (createEvent(vk, vkDevice, &eventCreateInfo));
+
+ // Put the command buffer in recording state.
+ VK_CHECK(vk.beginCommandBuffer(*cmdBuf, &cmdBufBeginInfo));
+ {
+ // Set the event
+ vk.cmdSetEvent(*cmdBuf, *event, VK_PIPELINE_STAGE_ALL_GPU_COMMANDS);
+ }
+ VK_CHECK(vk.endCommandBuffer(*cmdBuf));
+
+ // We'll use a fence to wait for the execution of the queue
+ const VkFenceCreateInfo fenceCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkFenceCreateFlags flags
+ };
+ const Unique<VkFence> fence (createFence(vk, vkDevice, &fenceCreateInfo));
+
+ // Submitting the command buffer that sets the event to the queue
+ VK_CHECK(vk.queueSubmit(queue, 1, &cmdBuf.get(), *fence));
+
+ // Waiting for the queue to finish executing
+ VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), 0u, INFINITE_TIMEOUT));
+
+ // Check if the buffer was executed
+ if (vk.getEventStatus(vkDevice, *event) != VK_EVENT_SET)
+ return tcu::TestStatus::fail("Failed to set the event.");
+
+ // Reset the event
+ vk.resetEvent(vkDevice, *event);
+ if(vk.getEventStatus(vkDevice, *event) != VK_EVENT_RESET)
+ return tcu::TestStatus::fail("Failed to reset the event.");
+
+ // Reset the command buffer by putting it in recording state again. This
+ // should empty the command buffer.
+ VK_CHECK(vk.beginCommandBuffer(*cmdBuf, &cmdBufBeginInfo));
+ VK_CHECK(vk.endCommandBuffer(*cmdBuf));
+ // Reset the fence so that we can reuse it
+ VK_CHECK(vk.resetFences(vkDevice, 1, &fence.get()));
+
+ // Submit the command buffer after resetting. It should have no commands
+ // recorded, so the event should remain unsignaled.
+ VK_CHECK(vk.queueSubmit(queue, 1, &cmdBuf.get(), *fence));
+ // Waiting for the queue to finish executing
+ VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), 0u, INFINITE_TIMEOUT));
+
+ // Check if the event remained unset.
+ if(vk.getEventStatus(vkDevice, *event) == VK_EVENT_RESET)
+ return tcu::TestStatus::pass("Buffer was reset properly.");
+ else
+ return tcu::TestStatus::fail("Buffer was not reset properly.");
+}
+
+tcu::TestStatus bulkResetCmdBufferTest(Context& context)
+{
+ const VkDevice vkDevice = context.getDevice();
+ const DeviceInterface& vk = context.getDeviceInterface();
+ const VkQueue queue = context.getUniversalQueue();
+ const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
+
+ const short BUFFER_COUNT = 2;
+
+ const VkCmdPoolCreateInfo cmdPoolParams =
+ {
+ VK_STRUCTURE_TYPE_CMD_POOL_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ queueFamilyIndex, // deUint32 queueFamilyIndex;
+ 0u, // VkCmdPoolCreateFlags flags;
+ };
+ const Unique<VkCmdPool> cmdPool (createCommandPool(vk, vkDevice, &cmdPoolParams));
+
+ // Command buffer
+ const VkCmdBufferCreateInfo cmdBufParams =
+ {
+ VK_STRUCTURE_TYPE_CMD_BUFFER_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ *cmdPool, // VkCmdPool pool;
+ VK_CMD_BUFFER_LEVEL_PRIMARY, // VkCmdBufferLevel level;
+ 0u, // VkCmdBufferCreateFlags flags;
+ };
+ VkCmdBuffer cmdBuffers[BUFFER_COUNT];
+ for (short i = 0; i < BUFFER_COUNT; ++i)
+ VK_CHECK(vk.createCommandBuffer(vkDevice, &cmdBufParams, &cmdBuffers[i]));
+
+ const VkCmdBufferBeginInfo cmdBufBeginInfo =
+ {
+ VK_STRUCTURE_TYPE_CMD_BUFFER_BEGIN_INFO,
+ DE_NULL,
+ VK_CMD_BUFFER_OPTIMIZE_ONE_TIME_SUBMIT_BIT,
+ DE_NULL,
+ 0u,
+ DE_NULL,
+ };
+
+ const VkEventCreateInfo eventCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_EVENT_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkEventCreateFlags flags;
+ };
+ VkEvent events[BUFFER_COUNT];
+ for (short i = 0; i < BUFFER_COUNT; ++i)
+ VK_CHECK(vk.createEvent(vkDevice, &eventCreateInfo, &events[i]));
+
+ // Record the command buffers
+ for (short i = 0; i < BUFFER_COUNT; ++i)
+ {
+ VK_CHECK(vk.beginCommandBuffer(cmdBuffers[i], &cmdBufBeginInfo));
+ {
+ vk.cmdSetEvent(cmdBuffers[i], events[i], VK_PIPELINE_STAGE_ALL_GPU_COMMANDS);
+ }
+ VK_CHECK(vk.endCommandBuffer(cmdBuffers[i]));
+ }
+
+ // We'll use a fence to wait for the execution of the queue
+ const VkFenceCreateInfo fenceCreateInfo =
+ {
+ VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkFenceCreateFlags flags
+ };
+ const Unique<VkFence> fence (createFence(vk, vkDevice, &fenceCreateInfo));
+
+ // Submit the alpha command buffer to the queue
+ VK_CHECK(vk.queueSubmit(queue, BUFFER_COUNT, cmdBuffers, *fence));
+ // Wait for the queue
+ VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), VK_TRUE, INFINITE_TIMEOUT));
+ // Reset the fence so that we can use it again
+ VK_CHECK(vk.resetFences(vkDevice, 1, &fence.get()));
+
+ // Check if the buffers were executed
+ for (short i = 0; i < BUFFER_COUNT; ++i)
+ if (vk.getEventStatus(vkDevice, events[i]) != VK_EVENT_SET)
+ return tcu::TestStatus::fail("Failed to set the event.");
+
+ // Reset the events
+ for (short i = 0; i < BUFFER_COUNT; ++i)
+ {
+ VK_CHECK(vk.resetEvent(vkDevice, events[i]));
+ // Check if the event was reset properly
+ if (vk.getEventStatus(vkDevice, events[0]) != VK_EVENT_RESET)
+ return tcu::TestStatus::fail("Failed to reset the event.");
+ }
+
+ // Reset the command buffers by resetting the command pool
+ VK_CHECK(vk.resetCommandPool(vkDevice, *cmdPool, 0u));
+
+ // Submit the command buffers to the queue
+ VK_CHECK(vk.queueSubmit(queue, BUFFER_COUNT, cmdBuffers, *fence));
+ // Wait for the queue
+ VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), VK_TRUE, INFINITE_TIMEOUT));
+
+ // Check if the event remained unset.
+ for (short i = 0; i < BUFFER_COUNT; ++i)
+ if (vk.getEventStatus(vkDevice, events[i]) != VK_EVENT_RESET)
+ return tcu::TestStatus::fail("Buffers were not reset properly.");
+
+ return tcu::TestStatus::pass("All buffers were reset properly.");
+}
+
+} // anonymous
+
+ void genComputeSource (SourceCollections& programCollection)
+ {
+ const char* const versionDecl = glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
+ std::ostringstream buf_good;
+
+ buf_good << versionDecl << "\n"
+ << ""
+ << "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
+ << "layout(set = 0, binding = 1, std140) uniform BufferName\n"
+ << "{\n"
+ << " highp vec4 colorA;\n"
+ << " highp vec4 colorB;\n"
+ << "} b_instance;\n"
+ << "layout(set = 0, binding = 0, std140) writeonly buffer OutBuf\n"
+ << "{\n"
+ << " highp vec4 read_colors[4];\n"
+ << "} b_out;\n"
+ << "void main(void)\n"
+ << "{\n"
+ << " highp int quadrant_id = int(gl_WorkGroupID.x);\n"
+ << " highp vec4 result_color;\n"
+ << " if (quadrant_id == 1 || quadrant_id == 2)\n"
+ << " result_color = b_instance.colorA;\n"
+ << " else\n"
+ << " result_color = b_instance.colorB;\n"
+ << " b_out.read_colors[gl_WorkGroupID.x] = result_color;\n"
+ << "}\n";
+
+ programCollection.glslSources.add("compute_good") << glu::ComputeSource(buf_good.str());
+
+
+ std::ostringstream buf_bad;
+
+ buf_bad << versionDecl << "\n"
+ << ""
+ << "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
+ << "layout(set = 0, binding = 1, std140) uniform BufferName\n"
+ << "{\n"
+ << " highp vec4 colorA;\n"
+ << " highp vec4 colorB;\n"
+ << "} b_instance;\n"
+ << "layout(set = 0, binding = 0, std140) writeonly buffer OutBuf\n"
+ << "{\n"
+ << " highp vec4 read_colors[4];\n"
+ << "} b_out;\n"
+ << "void main(void)\n"
+ << "{\n"
+ << " highp int quadrant_id = int(gl_WorkGroupID.x);\n"
+ << " highp vec4 result_color;\n"
+ << " if (quadrant_id == 1 || quadrant_id == 2)\n"
+ << " result_color = b_instance.colorA;\n"
+ << " else\n"
+ << " result_color = b_instance.colorB;\n"
+ << " 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());
+ }
+
+
+tcu::TestCaseGroup* createCommandBuffersTests (tcu::TestContext& testCtx)
+{
+ de::MovePtr<tcu::TestCaseGroup> commandBuffersTests (new tcu::TestCaseGroup(testCtx, "command_buffers", "Command Buffers Tests"));
+
+ addFunctionCase (commandBuffersTests.get(), "create_buffers", "", createBufferTest);
+ addFunctionCase (commandBuffersTests.get(), "execute_secondary_buffers", "", executeSecondaryBufferTest);
+ addFunctionCaseWithPrograms (commandBuffersTests.get(), "order_of_execution", "", genComputeSource, executeOrderTest );
+ addFunctionCase (commandBuffersTests.get(), "explicit_reset", "", explicitResetCmdBufferTest);
+ addFunctionCase (commandBuffersTests.get(), "implicit_reset", "", implicitResetCmdBufferTest);
+ addFunctionCase (commandBuffersTests.get(), "bulk_reset", "", bulkResetCmdBufferTest);
+
+ return commandBuffersTests.release();
+}
+
+} // api
+} // vkt