blob: adeefd13517bce634ea10df84db99a568eae4eba [file] [log] [blame]
/*-------------------------------------------------------------------------
* Vulkan Conformance Tests
* ------------------------
*
* Copyright (c) 2015 The Khronos Group Inc.
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
* Copyright (c) 2015 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*//*--------------------------------------------------------------------*/
#include "vkDefs.hpp"
#include "vktTestCaseUtil.hpp"
#include "vkBuilderUtil.hpp"
#include "vkPlatform.hpp"
#include "vkRefUtil.hpp"
#include "vkQueryUtil.hpp"
#include "vkMemUtil.hpp"
#include "vkDeviceUtil.hpp"
#include "vkCmdUtil.hpp"
#include "vkObjUtil.hpp"
#include "vkImageUtil.hpp"
#include "vkPrograms.hpp"
#include "vkTypeUtil.hpp"
#include "vkAllocationCallbackUtil.hpp"
#include "vkCmdUtil.hpp"
#include "vkBarrierUtil.hpp"
#include "vkBufferWithMemory.hpp"
#include "vkImageWithMemory.hpp"
#include "tcuTextureUtil.hpp"
#include "tcuCommandLine.hpp"
#include "vktApiCommandBuffersTests.hpp"
#include "vktApiBufferComputeInstance.hpp"
#include "vktApiComputeInstanceResultBuffer.hpp"
#include "deSharedPtr.hpp"
#include "deRandom.hpp"
#include <sstream>
#include <limits>
namespace vkt
{
namespace api
{
namespace
{
using namespace vk;
typedef de::SharedPtr<vk::Unique<vk::VkEvent> > VkEventSp;
// Global variables
const deUint64 INFINITE_TIMEOUT = ~(deUint64)0u;
template <deUint32 NumBuffers>
class CommandBufferBareTestEnvironment
{
public:
CommandBufferBareTestEnvironment (Context& context,
VkCommandPoolCreateFlags commandPoolCreateFlags);
VkCommandPool getCommandPool (void) const { return *m_commandPool; }
VkCommandBuffer getCommandBuffer (deUint32 bufferIndex) const;
protected:
Context& m_context;
const VkDevice m_device;
const DeviceInterface& m_vkd;
const VkQueue m_queue;
const deUint32 m_queueFamilyIndex;
Allocator& m_allocator;
// \note All VkCommandBuffers are allocated from m_commandPool so there is no need
// to free them separately as the auto-generated dtor will do that through
// destroying the pool.
Move<VkCommandPool> m_commandPool;
VkCommandBuffer m_primaryCommandBuffers[NumBuffers];
};
template <deUint32 NumBuffers>
CommandBufferBareTestEnvironment<NumBuffers>::CommandBufferBareTestEnvironment(Context& context, VkCommandPoolCreateFlags commandPoolCreateFlags)
: m_context (context)
, m_device (context.getDevice())
, m_vkd (context.getDeviceInterface())
, m_queue (context.getUniversalQueue())
, m_queueFamilyIndex (context.getUniversalQueueFamilyIndex())
, m_allocator (context.getDefaultAllocator())
{
m_commandPool = createCommandPool(m_vkd, m_device, commandPoolCreateFlags, m_queueFamilyIndex);
const VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
*m_commandPool, // VkCommandPool commandPool;
VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level;
NumBuffers // deUint32 commandBufferCount;
};
VK_CHECK(m_vkd.allocateCommandBuffers(m_device, &cmdBufferAllocateInfo, m_primaryCommandBuffers));
}
template <deUint32 NumBuffers>
VkCommandBuffer CommandBufferBareTestEnvironment<NumBuffers>::getCommandBuffer(deUint32 bufferIndex) const
{
DE_ASSERT(bufferIndex < NumBuffers);
return m_primaryCommandBuffers[bufferIndex];
}
class CommandBufferRenderPassTestEnvironment : public CommandBufferBareTestEnvironment<1>
{
public:
CommandBufferRenderPassTestEnvironment (Context& context,
VkCommandPoolCreateFlags commandPoolCreateFlags);
VkRenderPass getRenderPass (void) const { return *m_renderPass; }
VkFramebuffer getFrameBuffer (void) const { return *m_frameBuffer; }
VkCommandBuffer getPrimaryCommandBuffer (void) const { return getCommandBuffer(0); }
VkCommandBuffer getSecondaryCommandBuffer (void) const { return *m_secondaryCommandBuffer; }
void beginPrimaryCommandBuffer (VkCommandBufferUsageFlags usageFlags);
void beginSecondaryCommandBuffer (VkCommandBufferUsageFlags usageFlags, bool framebufferHint);
void beginRenderPass (VkSubpassContents content);
void submitPrimaryCommandBuffer (void);
de::MovePtr<tcu::TextureLevel> readColorAttachment (void);
static const VkImageType DEFAULT_IMAGE_TYPE;
static const VkFormat DEFAULT_IMAGE_FORMAT;
static const VkExtent3D DEFAULT_IMAGE_SIZE;
static const VkRect2D DEFAULT_IMAGE_AREA;
protected:
Move<VkImage> m_colorImage;
Move<VkImageView> m_colorImageView;
Move<VkRenderPass> m_renderPass;
Move<VkFramebuffer> m_frameBuffer;
de::MovePtr<Allocation> m_colorImageMemory;
Move<VkCommandPool> m_secCommandPool;
Move<VkCommandBuffer> m_secondaryCommandBuffer;
};
const VkImageType CommandBufferRenderPassTestEnvironment::DEFAULT_IMAGE_TYPE = VK_IMAGE_TYPE_2D;
const VkFormat CommandBufferRenderPassTestEnvironment::DEFAULT_IMAGE_FORMAT = VK_FORMAT_R8G8B8A8_UINT;
const VkExtent3D CommandBufferRenderPassTestEnvironment::DEFAULT_IMAGE_SIZE = {255, 255, 1};
const VkRect2D CommandBufferRenderPassTestEnvironment::DEFAULT_IMAGE_AREA =
{
{ 0u, 0u, }, // VkOffset2D offset;
{ DEFAULT_IMAGE_SIZE.width, DEFAULT_IMAGE_SIZE.height }, // VkExtent2D extent;
};
CommandBufferRenderPassTestEnvironment::CommandBufferRenderPassTestEnvironment(Context& context, VkCommandPoolCreateFlags commandPoolCreateFlags)
: CommandBufferBareTestEnvironment<1> (context, commandPoolCreateFlags)
{
m_renderPass = makeRenderPass(m_vkd, m_device, DEFAULT_IMAGE_FORMAT);
{
const VkImageCreateInfo imageCreateInfo =
{
VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkImageCreateFlags flags;
DEFAULT_IMAGE_TYPE, // VkImageType imageType;
DEFAULT_IMAGE_FORMAT, // VkFormat format;
DEFAULT_IMAGE_SIZE, // VkExtent3D extent;
1, // deUint32 mipLevels;
1, // deUint32 arrayLayers;
VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage;
VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1, // deUint32 queueFamilyIndexCount;
&m_queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
};
m_colorImage = createImage(m_vkd, m_device, &imageCreateInfo, DE_NULL);
}
m_colorImageMemory = m_allocator.allocate(getImageMemoryRequirements(m_vkd, m_device, *m_colorImage), MemoryRequirement::Any);
VK_CHECK(m_vkd.bindImageMemory(m_device, *m_colorImage, m_colorImageMemory->getMemory(), m_colorImageMemory->getOffset()));
{
const VkImageViewCreateInfo imageViewCreateInfo =
{
VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkImageViewCreateFlags flags;
*m_colorImage, // VkImage image;
VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
DEFAULT_IMAGE_FORMAT, // VkFormat format;
{
VK_COMPONENT_SWIZZLE_R,
VK_COMPONENT_SWIZZLE_G,
VK_COMPONENT_SWIZZLE_B,
VK_COMPONENT_SWIZZLE_A
}, // VkComponentMapping components;
{
VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
0u, // deUint32 baseMipLevel;
1u, // deUint32 mipLevels;
0u, // deUint32 baseArrayLayer;
1u, // deUint32 arraySize;
}, // VkImageSubresourceRange subresourceRange;
};
m_colorImageView = createImageView(m_vkd, m_device, &imageViewCreateInfo, DE_NULL);
}
{
const VkImageView attachmentViews[1] =
{
*m_colorImageView
};
const VkFramebufferCreateInfo framebufferCreateInfo =
{
VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkFramebufferCreateFlags flags;
*m_renderPass, // VkRenderPass renderPass;
1, // deUint32 attachmentCount;
attachmentViews, // const VkImageView* pAttachments;
DEFAULT_IMAGE_SIZE.width, // deUint32 width;
DEFAULT_IMAGE_SIZE.height, // deUint32 height;
1u, // deUint32 layers;
};
m_frameBuffer = createFramebuffer(m_vkd, m_device, &framebufferCreateInfo, DE_NULL);
}
m_secCommandPool = createCommandPool(m_vkd, m_device, commandPoolCreateFlags, m_queueFamilyIndex);
{
const VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
*m_secCommandPool, // VkCommandPool commandPool;
VK_COMMAND_BUFFER_LEVEL_SECONDARY, // VkCommandBufferLevel level;
1u // deUint32 commandBufferCount;
};
m_secondaryCommandBuffer = allocateCommandBuffer(m_vkd, m_device, &cmdBufferAllocateInfo);
}
}
void CommandBufferRenderPassTestEnvironment::beginRenderPass(VkSubpassContents content)
{
vk::beginRenderPass(m_vkd, m_primaryCommandBuffers[0], *m_renderPass, *m_frameBuffer, DEFAULT_IMAGE_AREA, tcu::UVec4(17, 59, 163, 251), content);
}
void CommandBufferRenderPassTestEnvironment::beginPrimaryCommandBuffer(VkCommandBufferUsageFlags usageFlags)
{
beginCommandBuffer(m_vkd, m_primaryCommandBuffers[0], usageFlags);
}
void CommandBufferRenderPassTestEnvironment::beginSecondaryCommandBuffer(VkCommandBufferUsageFlags usageFlags, bool framebufferHint)
{
const VkCommandBufferInheritanceInfo commandBufferInheritanceInfo =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
*m_renderPass, // VkRenderPass renderPass;
0u, // deUint32 subpass;
(framebufferHint ? *m_frameBuffer : DE_NULL), // VkFramebuffer framebuffer;
VK_FALSE, // VkBool32 occlusionQueryEnable;
0u, // VkQueryControlFlags queryFlags;
0u // VkQueryPipelineStatisticFlags pipelineStatistics;
};
const VkCommandBufferBeginInfo commandBufferBeginInfo =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
usageFlags, // VkCommandBufferUsageFlags flags;
&commandBufferInheritanceInfo // const VkCommandBufferInheritanceInfo* pInheritanceInfo;
};
VK_CHECK(m_vkd.beginCommandBuffer(*m_secondaryCommandBuffer, &commandBufferBeginInfo));
}
void CommandBufferRenderPassTestEnvironment::submitPrimaryCommandBuffer(void)
{
submitCommandsAndWait(m_vkd, m_device, m_queue, *m_primaryCommandBuffers);
}
de::MovePtr<tcu::TextureLevel> CommandBufferRenderPassTestEnvironment::readColorAttachment ()
{
Move<VkBuffer> buffer;
de::MovePtr<Allocation> bufferAlloc;
const tcu::TextureFormat tcuFormat = mapVkFormat(DEFAULT_IMAGE_FORMAT);
const VkDeviceSize pixelDataSize = DEFAULT_IMAGE_SIZE.height * DEFAULT_IMAGE_SIZE.height * tcuFormat.getPixelSize();
de::MovePtr<tcu::TextureLevel> resultLevel (new tcu::TextureLevel(tcuFormat, DEFAULT_IMAGE_SIZE.width, DEFAULT_IMAGE_SIZE.height));
// Create destination buffer
{
const VkBufferCreateInfo bufferParams =
{
VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkBufferCreateFlags flags;
pixelDataSize, // VkDeviceSize size;
VK_BUFFER_USAGE_TRANSFER_DST_BIT, // VkBufferUsageFlags usage;
VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
0u, // deUint32 queueFamilyIndexCount;
DE_NULL // const deUint32* pQueueFamilyIndices;
};
buffer = createBuffer(m_vkd, m_device, &bufferParams);
bufferAlloc = m_allocator.allocate(getBufferMemoryRequirements(m_vkd, m_device, *buffer), MemoryRequirement::HostVisible);
VK_CHECK(m_vkd.bindBufferMemory(m_device, *buffer, bufferAlloc->getMemory(), bufferAlloc->getOffset()));
}
// Copy image to buffer
beginPrimaryCommandBuffer(0);
copyImageToBuffer(m_vkd, m_primaryCommandBuffers[0], *m_colorImage, *buffer, tcu::IVec2(DEFAULT_IMAGE_SIZE.width, DEFAULT_IMAGE_SIZE.height));
endCommandBuffer(m_vkd, m_primaryCommandBuffers[0]);
submitPrimaryCommandBuffer();
// Read buffer data
invalidateAlloc(m_vkd, m_device, *bufferAlloc);
tcu::copy(*resultLevel, tcu::ConstPixelBufferAccess(resultLevel->getFormat(), resultLevel->getSize(), bufferAlloc->getHostPtr()));
return resultLevel;
}
// Testcases
/********* 19.1. Command Pools (5.1 in VK 1.0 Spec) ***************************/
tcu::TestStatus createPoolNullParamsTest(Context& context)
{
const VkDevice vkDevice = context.getDevice();
const DeviceInterface& vk = context.getDeviceInterface();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
createCommandPool(vk, vkDevice, 0u, queueFamilyIndex);
return tcu::TestStatus::pass("Command Pool allocated correctly.");
}
#ifndef CTS_USES_VULKANSC
tcu::TestStatus createPoolNonNullAllocatorTest(Context& context)
{
const VkDevice vkDevice = context.getDevice();
const DeviceInterface& vk = context.getDeviceInterface();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
const VkAllocationCallbacks* allocationCallbacks = getSystemAllocator();
const VkCommandPoolCreateInfo cmdPoolParams =
{
VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType;
DE_NULL, // pNext;
0u, // flags;
queueFamilyIndex, // queueFamilyIndex;
};
createCommandPool(vk, vkDevice, &cmdPoolParams, allocationCallbacks);
return tcu::TestStatus::pass("Command Pool allocated correctly.");
}
#endif // CTS_USES_VULKANSC
tcu::TestStatus createPoolTransientBitTest(Context& context)
{
const VkDevice vkDevice = context.getDevice();
const DeviceInterface& vk = context.getDeviceInterface();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
const VkCommandPoolCreateInfo cmdPoolParams =
{
VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType;
DE_NULL, // pNext;
VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // flags;
queueFamilyIndex, // queueFamilyIndex;
};
createCommandPool(vk, vkDevice, &cmdPoolParams, DE_NULL);
return tcu::TestStatus::pass("Command Pool allocated correctly.");
}
tcu::TestStatus createPoolResetBitTest(Context& context)
{
const VkDevice vkDevice = context.getDevice();
const DeviceInterface& vk = context.getDeviceInterface();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
const VkCommandPoolCreateInfo cmdPoolParams =
{
VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType;
DE_NULL, // pNext;
VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // flags;
queueFamilyIndex, // queueFamilyIndex;
};
createCommandPool(vk, vkDevice, &cmdPoolParams, DE_NULL);
return tcu::TestStatus::pass("Command Pool allocated correctly.");
}
#ifndef CTS_USES_VULKANSC
tcu::TestStatus resetPoolReleaseResourcesBitTest(Context& context)
{
const VkDevice vkDevice = context.getDevice();
const DeviceInterface& vk = context.getDeviceInterface();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
const VkCommandPoolCreateInfo cmdPoolParams =
{
VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType;
DE_NULL, // pNext;
0u, // flags;
queueFamilyIndex, // queueFamilyIndex;
};
const Unique<VkCommandPool> cmdPool (createCommandPool(vk, vkDevice, &cmdPoolParams, DE_NULL));
VK_CHECK(vk.resetCommandPool(vkDevice, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT));
return tcu::TestStatus::pass("Command Pool allocated correctly.");
}
#endif // CTS_USES_VULKANSC
tcu::TestStatus resetPoolNoFlagsTest(Context& context)
{
const VkDevice vkDevice = context.getDevice();
const DeviceInterface& vk = context.getDeviceInterface();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
const VkCommandPoolCreateInfo cmdPoolParams =
{
VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType;
DE_NULL, // pNext;
0u, // flags;
queueFamilyIndex, // queueFamilyIndex;
};
const Unique<VkCommandPool> cmdPool (createCommandPool(vk, vkDevice, &cmdPoolParams, DE_NULL));
VK_CHECK(vk.resetCommandPool(vkDevice, *cmdPool, 0u));
return tcu::TestStatus::pass("Command Pool allocated correctly.");
}
bool executeCommandBuffer (const VkDevice device,
const DeviceInterface& vk,
const VkQueue queue,
const VkCommandBuffer commandBuffer,
const bool exitBeforeEndCommandBuffer = false)
{
const Unique<VkEvent> event (createEvent(vk, device));
beginCommandBuffer(vk, commandBuffer, 0u);
{
const VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
vk.cmdSetEvent(commandBuffer, *event, stageMask);
if (exitBeforeEndCommandBuffer)
return exitBeforeEndCommandBuffer;
}
endCommandBuffer(vk, commandBuffer);
submitCommandsAndWait(vk, device, queue, commandBuffer);
// check if buffer has been executed
const VkResult result = vk.getEventStatus(device, *event);
return result == VK_EVENT_SET;
}
#ifndef CTS_USES_VULKANSC
tcu::TestStatus resetPoolReuseTest (Context& context)
{
const VkDevice vkDevice = context.getDevice();
const DeviceInterface& vk = context.getDeviceInterface();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
const VkQueue queue = context.getUniversalQueue();
const VkCommandPoolCreateInfo cmdPoolParams =
{
VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType;
DE_NULL, // pNext;
0u, // flags;
queueFamilyIndex // queueFamilyIndex;
};
const Unique<VkCommandPool> cmdPool (createCommandPool(vk, vkDevice, &cmdPoolParams, DE_NULL));
const VkCommandBufferAllocateInfo cmdBufParams =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
DE_NULL, // pNext;
*cmdPool, // commandPool;
VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level;
1u // bufferCount;
};
const Move<VkCommandBuffer> commandBuffers[] =
{
allocateCommandBuffer(vk, vkDevice, &cmdBufParams),
allocateCommandBuffer(vk, vkDevice, &cmdBufParams)
};
#ifdef CTS_USES_VULKANSC
bool canFinishEarlier = context.getTestContext().getCommandLine().isSubProcess();
#else
bool canFinishEarlier = true;
#endif // CTS_USES_VULKANSC
if (!executeCommandBuffer(vkDevice, vk, queue, *(commandBuffers[0])) && canFinishEarlier)
return tcu::TestStatus::fail("Failed");
if (!executeCommandBuffer(vkDevice, vk, queue, *(commandBuffers[1]), true) && canFinishEarlier)
return tcu::TestStatus::fail("Failed");
VK_CHECK(vk.resetCommandPool(vkDevice, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT));
if (!executeCommandBuffer(vkDevice, vk, queue, *(commandBuffers[0])) && canFinishEarlier)
return tcu::TestStatus::fail("Failed");
if (!executeCommandBuffer(vkDevice, vk, queue, *(commandBuffers[1])) && canFinishEarlier)
return tcu::TestStatus::fail("Failed");
{
const Unique<VkCommandBuffer> afterResetCommandBuffers(allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
if (!executeCommandBuffer(vkDevice, vk, queue, *afterResetCommandBuffers) && canFinishEarlier)
return tcu::TestStatus::fail("Failed");
}
return tcu::TestStatus::pass("Passed");
}
#endif // CTS_USES_VULKANSC
/******** 19.2. Command Buffer Lifetime (5.2 in VK 1.0 Spec) ******************/
tcu::TestStatus allocatePrimaryBufferTest(Context& context)
{
const VkDevice vkDevice = context.getDevice();
const DeviceInterface& vk = context.getDeviceInterface();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
const VkCommandPoolCreateInfo cmdPoolParams =
{
VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType;
DE_NULL, // pNext;
VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // flags;
queueFamilyIndex, // queueFamilyIndex;
};
const Unique<VkCommandPool> cmdPool (createCommandPool(vk, vkDevice, &cmdPoolParams));
// Command buffer
const VkCommandBufferAllocateInfo cmdBufParams =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
DE_NULL, // pNext;
*cmdPool, // commandPool;
VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level;
1u, // bufferCount;
};
const Unique<VkCommandBuffer> cmdBuf (allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
return tcu::TestStatus::pass("Buffer was created correctly.");
}
tcu::TestStatus allocateManyPrimaryBuffersTest(Context& context)
{
const VkDevice vkDevice = context.getDevice();
const DeviceInterface& vk = context.getDeviceInterface();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
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));
// \todo Determining the minimum number of command buffers should be a function of available system memory and driver capabilities.
#ifndef CTS_USES_VULKANSC
#if (DE_PTR_SIZE == 4)
const unsigned minCommandBuffer = 1024;
#else
const unsigned minCommandBuffer = 10000;
#endif
#else
const unsigned minCommandBuffer = 100;
#endif // CTS_USES_VULKANSC
// 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;
minCommandBuffer, // uint32_t bufferCount;
};
// do not keep the handles to buffers, as they will be freed with command pool
// allocate the minimum required amount of buffers
VkCommandBuffer cmdBuffers[minCommandBuffer];
VK_CHECK(vk.allocateCommandBuffers(vkDevice, &cmdBufParams, cmdBuffers));
std::ostringstream out;
out << "allocateManyPrimaryBuffersTest succeded: created " << minCommandBuffer << " command buffers";
return tcu::TestStatus::pass(out.str());
}
tcu::TestStatus allocateSecondaryBufferTest(Context& context)
{
const VkDevice vkDevice = context.getDevice();
const DeviceInterface& vk = context.getDeviceInterface();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
const VkCommandPoolCreateInfo cmdPoolParams =
{
VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType;
DE_NULL, // pNext;
VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // flags;
queueFamilyIndex, // queueFamilyIndex;
};
const Unique<VkCommandPool> cmdPool (createCommandPool(vk, vkDevice, &cmdPoolParams));
// Command buffer
const VkCommandBufferAllocateInfo cmdBufParams =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
DE_NULL, // pNext;
*cmdPool, // commandPool;
VK_COMMAND_BUFFER_LEVEL_SECONDARY, // level;
1u, // bufferCount;
};
const Unique<VkCommandBuffer> cmdBuf (allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
return tcu::TestStatus::pass("Buffer was created correctly.");
}
tcu::TestStatus allocateManySecondaryBuffersTest(Context& context)
{
const VkDevice vkDevice = context.getDevice();
const DeviceInterface& vk = context.getDeviceInterface();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
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));
// \todo Determining the minimum number of command buffers should be a function of available system memory and driver capabilities.
#ifndef CTS_USES_VULKANSC
#if (DE_PTR_SIZE == 4)
const unsigned minCommandBuffer = 1024;
#else
const unsigned minCommandBuffer = 10000;
#endif
#else
const unsigned minCommandBuffer = 100;
#endif // CTS_USES_VULKANSC
// 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_SECONDARY, // VkCommandBufferLevel level;
minCommandBuffer, // uint32_t bufferCount;
};
// do not keep the handles to buffers, as they will be freed with command pool
// allocate the minimum required amount of buffers
VkCommandBuffer cmdBuffers[minCommandBuffer];
VK_CHECK(vk.allocateCommandBuffers(vkDevice, &cmdBufParams, cmdBuffers));
std::ostringstream out;
out << "allocateManySecondaryBuffersTest succeded: created " << minCommandBuffer << " command buffers";
return tcu::TestStatus::pass(out.str());
}
tcu::TestStatus executePrimaryBufferTest(Context& context)
{
const VkDevice vkDevice = context.getDevice();
const DeviceInterface& vk = context.getDeviceInterface();
const VkQueue queue = context.getUniversalQueue();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
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));
// create event that will be used to check if secondary command buffer has been executed
const Unique<VkEvent> event (createEvent(vk, vkDevice));
// reset event
VK_CHECK(vk.resetEvent(vkDevice, *event));
// record primary command buffer
beginCommandBuffer(vk, *primCmdBuf, 0u);
{
// allow execution of event during every stage of pipeline
VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
// record setting event
vk.cmdSetEvent(*primCmdBuf, *event,stageMask);
}
endCommandBuffer(vk, *primCmdBuf);
submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf.get());
// check if buffer has been executed
VkResult result = vk.getEventStatus(vkDevice,*event);
if (result == VK_EVENT_SET)
return tcu::TestStatus::pass("Execute Primary Command Buffer succeeded");
return tcu::TestStatus::fail("Execute Primary Command Buffer FAILED");
}
tcu::TestStatus executeLargePrimaryBufferTest(Context& context)
{
const VkDevice vkDevice = context.getDevice();
const DeviceInterface& vk = context.getDeviceInterface();
const VkQueue queue = context.getUniversalQueue();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
#ifndef CTS_USES_VULKANSC
const deUint32 LARGE_BUFFER_SIZE = 10000;
#else
const deUint32 LARGE_BUFFER_SIZE = 100;
#endif // CTS_USES_VULKANSC
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));
std::vector<VkEventSp> events;
for (deUint32 ndx = 0; ndx < LARGE_BUFFER_SIZE; ++ndx)
events.push_back(VkEventSp(new vk::Unique<VkEvent>(createEvent(vk, vkDevice))));
// record primary command buffer
beginCommandBuffer(vk, *primCmdBuf, 0u);
{
// set all the events
for (deUint32 ndx = 0; ndx < LARGE_BUFFER_SIZE; ++ndx)
{
vk.cmdSetEvent(*primCmdBuf, events[ndx]->get(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
}
}
endCommandBuffer(vk, *primCmdBuf);
submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf.get());
// check if the buffer was executed correctly - all events had their status
// changed
tcu::TestStatus testResult = tcu::TestStatus::incomplete();
for (deUint32 ndx = 0; ndx < LARGE_BUFFER_SIZE; ++ndx)
{
if (vk.getEventStatus(vkDevice, events[ndx]->get()) != VK_EVENT_SET)
{
testResult = tcu::TestStatus::fail("An event was not set.");
break;
}
}
if (!testResult.isComplete())
testResult = tcu::TestStatus::pass("All events set correctly.");
return testResult;
}
tcu::TestStatus resetBufferImplicitlyTest(Context& context)
{
const VkDevice vkDevice = context.getDevice();
const DeviceInterface& vk = context.getDeviceInterface();
const VkQueue queue = context.getUniversalQueue();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
const VkCommandPoolCreateInfo cmdPoolParams =
{
VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType;
DE_NULL, // pNext;
VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // flags;
queueFamilyIndex, // queueFamilyIndex;
};
const Unique<VkCommandPool> cmdPool (createCommandPool(vk, vkDevice, &cmdPoolParams));
// Command buffer
const VkCommandBufferAllocateInfo cmdBufParams =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
DE_NULL, // pNext;
*cmdPool, // pool;
VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level;
1u, // bufferCount;
};
const Unique<VkCommandBuffer> cmdBuf (allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
const Unique<VkEvent> event (createEvent(vk, vkDevice));
// Put the command buffer in recording state.
beginCommandBuffer(vk, *cmdBuf, 0u);
{
// Set the event
vk.cmdSetEvent(*cmdBuf, *event, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
}
endCommandBuffer(vk, *cmdBuf);
submitCommandsAndWait(vk, vkDevice, queue, cmdBuf.get());
// 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.
beginCommandBuffer(vk, *cmdBuf, 0u);
endCommandBuffer(vk, *cmdBuf);
// Submit the command buffer after resetting. It should have no commands
// recorded, so the event should remain unsignaled.
submitCommandsAndWait(vk, vkDevice, queue, cmdBuf.get());
// Check if the event remained unset.
if(vk.getEventStatus(vkDevice, *event) == VK_EVENT_RESET)
return tcu::TestStatus::pass("Buffer was reset correctly.");
else
return tcu::TestStatus::fail("Buffer was not reset correctly.");
}
#ifndef CTS_USES_VULKANSC
using de::SharedPtr;
typedef SharedPtr<Unique<VkEvent> > VkEventShared;
template<typename T>
inline SharedPtr<Unique<T> > makeSharedPtr (Move<T> move)
{
return SharedPtr<Unique<T> >(new Unique<T>(move));
}
bool submitAndCheck (Context& context, std::vector<VkCommandBuffer>& cmdBuffers, std::vector <VkEventShared>& events)
{
const VkDevice vkDevice = context.getDevice();
const DeviceInterface& vk = context.getDeviceInterface();
const VkQueue queue = context.getUniversalQueue();
const Unique<VkFence> fence (createFence(vk, vkDevice));
const VkSubmitInfo submitInfo =
{
VK_STRUCTURE_TYPE_SUBMIT_INFO, // sType
DE_NULL, // pNext
0u, // waitSemaphoreCount
DE_NULL, // pWaitSemaphores
(const VkPipelineStageFlags*)DE_NULL, // pWaitDstStageMask
static_cast<deUint32>(cmdBuffers.size()), // commandBufferCount
&cmdBuffers[0], // pCommandBuffers
0u, // signalSemaphoreCount
DE_NULL, // pSignalSemaphores
};
VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, fence.get()));
VK_CHECK(vk.waitForFences(vkDevice, 1u, &fence.get(), 0u, INFINITE_TIMEOUT));
for(int eventNdx = 0; eventNdx < static_cast<int>(events.size()); ++eventNdx)
{
if (vk.getEventStatus(vkDevice, **events[eventNdx]) != VK_EVENT_SET)
return false;
vk.resetEvent(vkDevice, **events[eventNdx]);
}
return true;
}
void createCommadBuffers (const DeviceInterface& vk,
const VkDevice vkDevice,
deUint32 bufferCount,
VkCommandPool pool,
const VkCommandBufferLevel cmdBufferLevel,
VkCommandBuffer* pCommandBuffers)
{
const VkCommandBufferAllocateInfo cmdBufParams =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
pool, // VkCommandPool pool;
cmdBufferLevel, // VkCommandBufferLevel level;
bufferCount, // uint32_t bufferCount;
};
VK_CHECK(vk.allocateCommandBuffers(vkDevice, &cmdBufParams, pCommandBuffers));
}
void addCommandsToBuffer (const DeviceInterface& vk, std::vector<VkCommandBuffer>& cmdBuffers, std::vector <VkEventShared>& events)
{
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 cmdBufBeginInfo =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
DE_NULL, // pNext
0u, // flags
&secCmdBufInheritInfo, // pInheritanceInfo;
};
for(int bufferNdx = 0; bufferNdx < static_cast<int>(cmdBuffers.size()); ++bufferNdx)
{
VK_CHECK(vk.beginCommandBuffer(cmdBuffers[bufferNdx], &cmdBufBeginInfo));
vk.cmdSetEvent(cmdBuffers[bufferNdx], **events[bufferNdx % events.size()], VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
endCommandBuffer(vk, cmdBuffers[bufferNdx]);
}
}
bool executeSecondaryCmdBuffer (Context& context,
VkCommandPool pool,
std::vector<VkCommandBuffer>& cmdBuffersSecondary,
std::vector <VkEventShared>& events)
{
const VkDevice vkDevice = context.getDevice();
const DeviceInterface& vk = context.getDeviceInterface();
std::vector<VkCommandBuffer> cmdBuffer (1);
createCommadBuffers(vk, vkDevice, 1u, pool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, &cmdBuffer[0]);
beginCommandBuffer(vk, cmdBuffer[0], 0u);
vk.cmdExecuteCommands(cmdBuffer[0], static_cast<deUint32>(cmdBuffersSecondary.size()), &cmdBuffersSecondary[0]);
endCommandBuffer(vk, cmdBuffer[0]);
bool returnValue = submitAndCheck(context, cmdBuffer, events);
vk.freeCommandBuffers(vkDevice, pool, 1u, &cmdBuffer[0]);
return returnValue;
}
tcu::TestStatus trimCommandPoolTest (Context& context, const VkCommandBufferLevel cmdBufferLevel)
{
if (!context.isDeviceFunctionalitySupported("VK_KHR_maintenance1"))
TCU_THROW(NotSupportedError, "Extension VK_KHR_maintenance1 not supported");
const VkDevice vkDevice = context.getDevice();
const DeviceInterface& vk = context.getDeviceInterface();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
//test parameters
const deUint32 cmdBufferIterationCount = 300u;
const deUint32 cmdBufferCount = 10u;
const VkCommandPoolCreateInfo cmdPoolParams =
{
VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType;
DE_NULL, // pNext;
VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // flags;
queueFamilyIndex, // queueFamilyIndex;
};
const Unique<VkCommandPool> cmdPool (createCommandPool(vk, vkDevice, &cmdPoolParams));
std::vector <VkEventShared> events;
for (deUint32 ndx = 0u; ndx < cmdBufferCount; ++ndx)
events.push_back(makeSharedPtr(createEvent(vk, vkDevice)));
{
std::vector<VkCommandBuffer> cmdBuffers(cmdBufferCount);
createCommadBuffers(vk, vkDevice, cmdBufferCount, *cmdPool, cmdBufferLevel, &cmdBuffers[0]);
for (deUint32 cmdBufferIterationrNdx = 0; cmdBufferIterationrNdx < cmdBufferIterationCount; ++cmdBufferIterationrNdx)
{
addCommandsToBuffer(vk, cmdBuffers, events);
//Peak, situation when we use a lot more command buffers
if (cmdBufferIterationrNdx % 10u == 0)
{
std::vector<VkCommandBuffer> cmdBuffersPeak(cmdBufferCount * 10u);
createCommadBuffers(vk, vkDevice, static_cast<deUint32>(cmdBuffersPeak.size()), *cmdPool, cmdBufferLevel, &cmdBuffersPeak[0]);
addCommandsToBuffer(vk, cmdBuffersPeak, events);
switch(cmdBufferLevel)
{
case VK_COMMAND_BUFFER_LEVEL_PRIMARY:
if (!submitAndCheck(context, cmdBuffersPeak, events))
return tcu::TestStatus::fail("Fail");
break;
case VK_COMMAND_BUFFER_LEVEL_SECONDARY:
if (!executeSecondaryCmdBuffer(context, *cmdPool, cmdBuffersPeak, events))
return tcu::TestStatus::fail("Fail");
break;
default:
DE_ASSERT(0);
}
vk.freeCommandBuffers(vkDevice, *cmdPool, static_cast<deUint32>(cmdBuffersPeak.size()), &cmdBuffersPeak[0]);
}
vk.trimCommandPool(vkDevice, *cmdPool, (VkCommandPoolTrimFlags)0);
switch(cmdBufferLevel)
{
case VK_COMMAND_BUFFER_LEVEL_PRIMARY:
if (!submitAndCheck(context, cmdBuffers, events))
return tcu::TestStatus::fail("Fail");
break;
case VK_COMMAND_BUFFER_LEVEL_SECONDARY:
if (!executeSecondaryCmdBuffer(context, *cmdPool, cmdBuffers, events))
return tcu::TestStatus::fail("Fail");
break;
default:
DE_ASSERT(0);
}
for (deUint32 bufferNdx = cmdBufferIterationrNdx % 3u; bufferNdx < cmdBufferCount; bufferNdx+=2u)
{
vk.freeCommandBuffers(vkDevice, *cmdPool, 1u, &cmdBuffers[bufferNdx]);
createCommadBuffers(vk, vkDevice, 1u, *cmdPool, cmdBufferLevel, &cmdBuffers[bufferNdx]);
}
}
}
return tcu::TestStatus::pass("Pass");
}
#endif // CTS_USES_VULKANSC
/******** 19.3. Command Buffer Recording (5.3 in VK 1.0 Spec) *****************/
tcu::TestStatus recordSinglePrimaryBufferTest(Context& context)
{
const VkDevice vkDevice = context.getDevice();
const DeviceInterface& vk = context.getDeviceInterface();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
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));
// create event that will be used to check if secondary command buffer has been executed
const Unique<VkEvent> event (createEvent(vk, vkDevice));
// record primary command buffer
beginCommandBuffer(vk, *primCmdBuf, 0u);
{
// record setting event
vk.cmdSetEvent(*primCmdBuf, *event, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
}
endCommandBuffer(vk, *primCmdBuf);
return tcu::TestStatus::pass("Primary buffer recorded successfully.");
}
tcu::TestStatus recordLargePrimaryBufferTest(Context &context)
{
const VkDevice vkDevice = context.getDevice();
const DeviceInterface& vk = context.getDeviceInterface();
const VkQueue queue = context.getUniversalQueue();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
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));
// create event that will be used to check if secondary command buffer has been executed
const Unique<VkEvent> event (createEvent(vk, vkDevice));
// reset event
VK_CHECK(vk.resetEvent(vkDevice, *event));
// record primary command buffer
beginCommandBuffer(vk, *primCmdBuf, 0u);
{
// allow execution of event during every stage of pipeline
VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
// define minimal amount of commands to accept
#ifndef CTS_USES_VULKANSC
const long long unsigned minNumCommands = 10000llu;
#else
const long long unsigned minNumCommands = 1000llu;
#endif // CTS_USES_VULKANSC
for ( long long unsigned currentCommands = 0; currentCommands < minNumCommands / 2; ++currentCommands )
{
// record setting event
vk.cmdSetEvent(*primCmdBuf, *event,stageMask);
// record resetting event
vk.cmdResetEvent(*primCmdBuf, *event,stageMask);
}
}
endCommandBuffer(vk, *primCmdBuf);
submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf.get());
return tcu::TestStatus::pass("hugeTest succeeded");
}
tcu::TestStatus recordSingleSecondaryBufferTest(Context& context)
{
const VkDevice vkDevice = context.getDevice();
const DeviceInterface& vk = context.getDeviceInterface();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
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_SECONDARY, // VkCommandBufferLevel level;
1u, // uint32_t bufferCount;
};
const Unique<VkCommandBuffer> secCmdBuf (allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
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,
0, // flags
&secCmdBufInheritInfo,
};
// create event that will be used to check if secondary command buffer has been executed
const Unique<VkEvent> event (createEvent(vk, vkDevice));
// record primary command buffer
VK_CHECK(vk.beginCommandBuffer(*secCmdBuf, &secCmdBufBeginInfo));
{
// record setting event
vk.cmdSetEvent(*secCmdBuf, *event, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
}
endCommandBuffer(vk, *secCmdBuf);
return tcu::TestStatus::pass("Secondary buffer recorded successfully.");
}
tcu::TestStatus recordLargeSecondaryBufferTest(Context &context)
{
const VkDevice vkDevice = context.getDevice();
const DeviceInterface& vk = context.getDeviceInterface();
const VkQueue queue = context.getUniversalQueue();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
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));
const Unique<VkCommandPool> secCmdPool (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));
const VkCommandBufferAllocateInfo secCmdBufParams =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
*secCmdPool, // VkCommandPool pool;
VK_COMMAND_BUFFER_LEVEL_SECONDARY, // VkCommandBufferLevel level;
1u, // uint32_t bufferCount;
};
const Unique<VkCommandBuffer> secCmdBuf (allocateCommandBuffer(vk, vkDevice, &secCmdBufParams));
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,
0, // flags
&secCmdBufInheritInfo,
};
// create event that will be used to check if secondary command buffer has been executed
const Unique<VkEvent> event (createEvent(vk, vkDevice));
// reset event
VK_CHECK(vk.resetEvent(vkDevice, *event));
// record primary command buffer
beginCommandBuffer(vk, *primCmdBuf, 0u);
{
// record secondary command buffer
VK_CHECK(vk.beginCommandBuffer(*secCmdBuf, &secCmdBufBeginInfo));
{
// allow execution of event during every stage of pipeline
VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
// define minimal amount of commands to accept
#ifndef CTS_USES_VULKANSC
const long long unsigned minNumCommands = 10000llu;
#else
const long long unsigned minNumCommands = 1000llu;
#endif // CTS_USES_VULKANSC
for ( long long unsigned currentCommands = 0; currentCommands < minNumCommands / 2; ++currentCommands )
{
// record setting event
vk.cmdSetEvent(*secCmdBuf, *event,stageMask);
// record resetting event
vk.cmdResetEvent(*secCmdBuf, *event,stageMask);
}
}
// end recording of secondary buffers
endCommandBuffer(vk, *secCmdBuf);
// execute secondary buffer
vk.cmdExecuteCommands(*primCmdBuf, 1, &secCmdBuf.get());
}
endCommandBuffer(vk, *primCmdBuf);
submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf.get());
return tcu::TestStatus::pass("hugeTest succeeded");
}
tcu::TestStatus submitPrimaryBufferTwiceTest(Context& context)
{
const VkDevice vkDevice = context.getDevice();
const DeviceInterface& vk = context.getDeviceInterface();
const VkQueue queue = context.getUniversalQueue();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
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));
// create event that will be used to check if secondary command buffer has been executed
const Unique<VkEvent> event (createEvent(vk, vkDevice));
// reset event
VK_CHECK(vk.resetEvent(vkDevice, *event));
// record primary command buffer
beginCommandBuffer(vk, *primCmdBuf, 0u);
{
// allow execution of event during every stage of pipeline
VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
// record setting event
vk.cmdSetEvent(*primCmdBuf, *event,stageMask);
}
endCommandBuffer(vk, *primCmdBuf);
submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf.get());
// check if buffer has been executed
VkResult result = vk.getEventStatus(vkDevice,*event);
if (result != VK_EVENT_SET)
return tcu::TestStatus::fail("Submit Twice Test FAILED");
// reset event
VK_CHECK(vk.resetEvent(vkDevice, *event));
submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf.get());
// check if buffer has been executed
result = vk.getEventStatus(vkDevice,*event);
if (result != VK_EVENT_SET)
return tcu::TestStatus::fail("Submit Twice Test FAILED");
else
return tcu::TestStatus::pass("Submit Twice Test succeeded");
}
tcu::TestStatus submitSecondaryBufferTwiceTest(Context& context)
{
const VkDevice vkDevice = context.getDevice();
const DeviceInterface& vk = context.getDeviceInterface();
const VkQueue queue = context.getUniversalQueue();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
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));
const Unique<VkCommandPool> secCmdPool (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> primCmdBuf1 (allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
const Unique<VkCommandBuffer> primCmdBuf2 (allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
// Secondary Command buffer
const VkCommandBufferAllocateInfo secCmdBufParams =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
*secCmdPool, // VkCommandPool pool;
VK_COMMAND_BUFFER_LEVEL_SECONDARY, // VkCommandBufferLevel level;
1u, // uint32_t bufferCount;
};
const Unique<VkCommandBuffer> secCmdBuf (allocateCommandBuffer(vk, vkDevice, &secCmdBufParams));
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,
0u, // flags
&secCmdBufInheritInfo,
};
// create event that will be used to check if secondary command buffer has been executed
const Unique<VkEvent> event (createEvent(vk, vkDevice));
// reset event
VK_CHECK(vk.resetEvent(vkDevice, *event));
// record first primary command buffer
beginCommandBuffer(vk, *primCmdBuf1, 0u);
{
// record secondary command buffer
VK_CHECK(vk.beginCommandBuffer(*secCmdBuf, &secCmdBufBeginInfo));
{
// allow execution of event during every stage of pipeline
VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
// record setting event
vk.cmdSetEvent(*secCmdBuf, *event,stageMask);
}
// end recording of secondary buffers
endCommandBuffer(vk, *secCmdBuf);
// execute secondary buffer
vk.cmdExecuteCommands(*primCmdBuf1, 1, &secCmdBuf.get());
}
endCommandBuffer(vk, *primCmdBuf1);
submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf1.get());
// check if secondary buffer has been executed
VkResult result = vk.getEventStatus(vkDevice,*event);
if (result != VK_EVENT_SET)
return tcu::TestStatus::fail("Submit Twice Secondary Command Buffer FAILED");
// reset first primary buffer
vk.resetCommandBuffer( *primCmdBuf1, 0u);
// reset event to allow receiving it again
VK_CHECK(vk.resetEvent(vkDevice, *event));
// record second primary command buffer
beginCommandBuffer(vk, *primCmdBuf2, 0u);
{
// execute secondary buffer
vk.cmdExecuteCommands(*primCmdBuf2, 1, &secCmdBuf.get());
}
// end recording
endCommandBuffer(vk, *primCmdBuf2);
submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf2.get());
// check if secondary buffer has been executed
result = vk.getEventStatus(vkDevice,*event);
if (result != VK_EVENT_SET)
return tcu::TestStatus::fail("Submit Twice Secondary Command Buffer FAILED");
else
return tcu::TestStatus::pass("Submit Twice Secondary Command Buffer succeeded");
}
tcu::TestStatus oneTimeSubmitFlagPrimaryBufferTest(Context& context)
{
const VkDevice vkDevice = context.getDevice();
const DeviceInterface& vk = context.getDeviceInterface();
const VkQueue queue = context.getUniversalQueue();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
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));
// create event that will be used to check if secondary command buffer has been executed
const Unique<VkEvent> event (createEvent(vk, vkDevice));
// reset event
VK_CHECK(vk.resetEvent(vkDevice, *event));
// record primary command buffer
beginCommandBuffer(vk, *primCmdBuf);
{
// allow execution of event during every stage of pipeline
VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
// record setting event
vk.cmdSetEvent(*primCmdBuf, *event,stageMask);
}
endCommandBuffer(vk, *primCmdBuf);
submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf.get());
// check if buffer has been executed
VkResult result = vk.getEventStatus(vkDevice,*event);
if (result != VK_EVENT_SET)
return tcu::TestStatus::fail("oneTimeSubmitFlagPrimaryBufferTest FAILED");
// record primary command buffer again - implicit reset because of VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT
beginCommandBuffer(vk, *primCmdBuf);
{
// allow execution of event during every stage of pipeline
VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
// record setting event
vk.cmdSetEvent(*primCmdBuf, *event,stageMask);
}
endCommandBuffer(vk, *primCmdBuf);
submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf.get());
// check if buffer has been executed
result = vk.getEventStatus(vkDevice,*event);
if (result != VK_EVENT_SET)
return tcu::TestStatus::fail("oneTimeSubmitFlagPrimaryBufferTest FAILED");
else
return tcu::TestStatus::pass("oneTimeSubmitFlagPrimaryBufferTest succeeded");
}
tcu::TestStatus oneTimeSubmitFlagSecondaryBufferTest(Context& context)
{
const VkDevice vkDevice = context.getDevice();
const DeviceInterface& vk = context.getDeviceInterface();
const VkQueue queue = context.getUniversalQueue();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
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));
const Unique<VkCommandPool> secCmdPool (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> primCmdBuf1 (allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
const Unique<VkCommandBuffer> primCmdBuf2 (allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
// Secondary Command buffer
const VkCommandBufferAllocateInfo secCmdBufParams =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
*secCmdPool, // VkCommandPool pool;
VK_COMMAND_BUFFER_LEVEL_SECONDARY, // VkCommandBufferLevel level;
1u, // uint32_t bufferCount;
};
const Unique<VkCommandBuffer> secCmdBuf (allocateCommandBuffer(vk, vkDevice, &secCmdBufParams));
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_ONE_TIME_SUBMIT_BIT, // flags
&secCmdBufInheritInfo,
};
// create event that will be used to check if secondary command buffer has been executed
const Unique<VkEvent> event (createEvent(vk, vkDevice));
// reset event
VK_CHECK(vk.resetEvent(vkDevice, *event));
// record first primary command buffer
beginCommandBuffer(vk, *primCmdBuf1, 0u);
{
// record secondary command buffer
VK_CHECK(vk.beginCommandBuffer(*secCmdBuf, &secCmdBufBeginInfo));
{
// allow execution of event during every stage of pipeline
VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
// record setting event
vk.cmdSetEvent(*secCmdBuf, *event,stageMask);
}
// end recording of secondary buffers
endCommandBuffer(vk, *secCmdBuf);
// execute secondary buffer
vk.cmdExecuteCommands(*primCmdBuf1, 1, &secCmdBuf.get());
}
endCommandBuffer(vk, *primCmdBuf1);
submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf1.get());
// check if secondary buffer has been executed
VkResult result = vk.getEventStatus(vkDevice,*event);
if (result != VK_EVENT_SET)
return tcu::TestStatus::fail("Submit Twice Secondary Command Buffer FAILED");
// reset first primary buffer
vk.resetCommandBuffer( *primCmdBuf1, 0u);
// reset event to allow receiving it again
VK_CHECK(vk.resetEvent(vkDevice, *event));
// record secondary command buffer again
VK_CHECK(vk.beginCommandBuffer(*secCmdBuf, &secCmdBufBeginInfo));
{
// allow execution of event during every stage of pipeline
VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
// record setting event
vk.cmdSetEvent(*secCmdBuf, *event,stageMask);
}
// end recording of secondary buffers
endCommandBuffer(vk, *secCmdBuf);
// record second primary command buffer
beginCommandBuffer(vk, *primCmdBuf2, 0u);
{
// execute secondary buffer
vk.cmdExecuteCommands(*primCmdBuf2, 1, &secCmdBuf.get());
}
// end recording
endCommandBuffer(vk, *primCmdBuf2);
submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf2.get());
// check if secondary buffer has been executed
result = vk.getEventStatus(vkDevice,*event);
if (result != VK_EVENT_SET)
return tcu::TestStatus::fail("oneTimeSubmitFlagSecondaryBufferTest FAILED");
else
return tcu::TestStatus::pass("oneTimeSubmitFlagSecondaryBufferTest succeeded");
}
tcu::TestStatus renderPassContinueTest(Context& context, bool framebufferHint)
{
const DeviceInterface& vkd = context.getDeviceInterface();
CommandBufferRenderPassTestEnvironment env (context, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT);
VkCommandBuffer primaryCommandBuffer = env.getPrimaryCommandBuffer();
VkCommandBuffer secondaryCommandBuffer = env.getSecondaryCommandBuffer();
const deUint32 clearColor[4] = { 2, 47, 131, 211 };
const VkClearAttachment clearAttachment =
{
VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
0, // deUint32 colorAttachment;
makeClearValueColorU32(clearColor[0],
clearColor[1],
clearColor[2],
clearColor[3]) // VkClearValue clearValue;
};
const VkClearRect clearRect =
{
CommandBufferRenderPassTestEnvironment::DEFAULT_IMAGE_AREA, // VkRect2D rect;
0u, // deUint32 baseArrayLayer;
1u // deUint32 layerCount;
};
env.beginSecondaryCommandBuffer(VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, framebufferHint);
vkd.cmdClearAttachments(secondaryCommandBuffer, 1, &clearAttachment, 1, &clearRect);
endCommandBuffer(vkd, secondaryCommandBuffer);
env.beginPrimaryCommandBuffer(0);
env.beginRenderPass(VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
vkd.cmdExecuteCommands(primaryCommandBuffer, 1, &secondaryCommandBuffer);
endRenderPass(vkd, primaryCommandBuffer);
endCommandBuffer(vkd, primaryCommandBuffer);
env.submitPrimaryCommandBuffer();
de::MovePtr<tcu::TextureLevel> result = env.readColorAttachment();
tcu::PixelBufferAccess pixelBufferAccess = result->getAccess();
for (deUint32 i = 0; i < (CommandBufferRenderPassTestEnvironment::DEFAULT_IMAGE_SIZE.width * CommandBufferRenderPassTestEnvironment::DEFAULT_IMAGE_SIZE.height); ++i)
{
deUint8* colorData = reinterpret_cast<deUint8*>(pixelBufferAccess.getDataPtr());
for (int colorComponent = 0; colorComponent < 4; ++colorComponent)
if (colorData[i * 4 + colorComponent] != clearColor[colorComponent])
return tcu::TestStatus::fail("clear value mismatch");
}
return tcu::TestStatus::pass("render pass continue test passed");
}
tcu::TestStatus simultaneousUsePrimaryBufferTest(Context& context)
{
const VkDevice vkDevice = context.getDevice();
const DeviceInterface& vk = context.getDeviceInterface();
const VkQueue queue = context.getUniversalQueue();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
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));
// create event that will be used to check if secondary command buffer has been executed
const Unique<VkEvent> eventOne (createEvent(vk, vkDevice));
const Unique<VkEvent> eventTwo (createEvent(vk, vkDevice));
// reset event
VK_CHECK(vk.resetEvent(vkDevice, *eventOne));
// record primary command buffer
beginCommandBuffer(vk, *primCmdBuf, VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT);
{
// wait for event
vk.cmdWaitEvents(*primCmdBuf, 1u, &eventOne.get(), VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0u, DE_NULL, 0u, DE_NULL, 0u, DE_NULL);
// Set the second event
vk.cmdSetEvent(*primCmdBuf, eventTwo.get(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
}
endCommandBuffer(vk, *primCmdBuf);
// create fence to wait for execution of queue
const Unique<VkFence> fence1 (createFence(vk, vkDevice));
const Unique<VkFence> fence2 (createFence(vk, vkDevice));
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 first buffer
VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence1));
// submit second buffer
VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence2));
// wait for both buffer to stop at event for 100 microseconds
vk.waitForFences(vkDevice, 1, &fence1.get(), 0u, 100000);
vk.waitForFences(vkDevice, 1, &fence2.get(), 0u, 100000);
// set event
VK_CHECK(vk.setEvent(vkDevice, *eventOne));
// wait for end of execution of the first buffer
VK_CHECK(vk.waitForFences(vkDevice, 1, &fence1.get(), 0u, INFINITE_TIMEOUT));
// wait for end of execution of the second buffer
VK_CHECK(vk.waitForFences(vkDevice, 1, &fence2.get(), 0u, INFINITE_TIMEOUT));
// TODO: this will be true if the command buffer was executed only once
// TODO: add some test that will say if it was executed twice
// check if buffer has been executed
VkResult result = vk.getEventStatus(vkDevice, *eventTwo);
if (result == VK_EVENT_SET)
return tcu::TestStatus::pass("simultaneous use - primary buffers test succeeded");
else
return tcu::TestStatus::fail("simultaneous use - primary buffers test FAILED");
}
tcu::TestStatus simultaneousUseSecondaryBufferTest(Context& context)
{
const VkDevice vkDevice = context.getDevice();
const DeviceInterface& vk = context.getDeviceInterface();
const VkQueue queue = context.getUniversalQueue();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
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 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,
};
// create event that will be used to check if secondary command buffer has been executed
const Unique<VkEvent> eventOne (createEvent(vk, vkDevice));
const Unique<VkEvent> eventTwo (createEvent(vk, vkDevice));
// reset event
VK_CHECK(vk.resetEvent(vkDevice, *eventOne));
VK_CHECK(vk.resetEvent(vkDevice, *eventTwo));
// record secondary command buffer
VK_CHECK(vk.beginCommandBuffer(*secCmdBuf, &secCmdBufBeginInfo));
{
// allow execution of event during every stage of pipeline
VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
// wait for event
vk.cmdWaitEvents(*secCmdBuf, 1, &eventOne.get(), stageMask, stageMask, 0, DE_NULL, 0u, DE_NULL, 0u, DE_NULL);
// reset event
vk.cmdSetEvent(*secCmdBuf, *eventTwo, stageMask);
}
// end recording of secondary buffers
endCommandBuffer(vk, *secCmdBuf);
// record primary command buffer
beginCommandBuffer(vk, *primCmdBuf, 0u);
{
// execute secondary buffer
vk.cmdExecuteCommands(*primCmdBuf, 1, &secCmdBuf.get());
}
endCommandBuffer(vk, *primCmdBuf);
// create fence to wait for execution of queue
const Unique<VkFence> fence (createFence(vk, vkDevice));
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 both buffers to stop at event for 100 microseconds
vk.waitForFences(vkDevice, 1, &fence.get(), 0u, 100000);
// set event
VK_CHECK(vk.setEvent(vkDevice, *eventOne));
// wait for end of execution of queue
VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), 0u, INFINITE_TIMEOUT));
// TODO: this will be true if the command buffer was executed only once
// TODO: add some test that will say if it was executed twice
// check if secondary buffer has been executed
VkResult result = vk.getEventStatus(vkDevice,*eventTwo);
if (result == VK_EVENT_SET)
return tcu::TestStatus::pass("Simultaneous Secondary Command Buffer Execution succeeded");
else
return tcu::TestStatus::fail("Simultaneous 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 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 VkBufferMemoryBarrier bufferBarrier =
{
VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // sType
DE_NULL, // pNext
VK_ACCESS_SHADER_WRITE_BIT, // srcAccessMask
VK_ACCESS_HOST_READ_BIT, // dstAccessMask
VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex
VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex
*buffer, // buffer
(VkDeviceSize)0u, // offset
(VkDeviceSize)VK_WHOLE_SIZE, // size
};
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);
vk.cmdPipelineBarrier(*secCmdBuf, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0,
0, (const VkMemoryBarrier*)DE_NULL,
1, &bufferBarrier,
0, (const VkImageMemoryBarrier*)DE_NULL);
}
// end recording of secondary buffer
endCommandBuffer(vk, *secCmdBuf);
// record primary command buffer
beginCommandBuffer(vk, *primCmdBuf, 0u);
{
// execute secondary buffer twice in same primary
vk.cmdExecuteCommands(*primCmdBuf, 1, &secCmdBuf.get());
vk.cmdExecuteCommands(*primCmdBuf, 1, &secCmdBuf.get());
}
endCommandBuffer(vk, *primCmdBuf);
submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf.get());
deUint32 resultCount;
result.readResultContentsTo(&resultCount);
// check if secondary buffer has been executed
if (resultCount == 2)
return tcu::TestStatus::pass("Simultaneous Secondary Command Buffer Execution succeeded");
else
return tcu::TestStatus::fail("Simultaneous Secondary Command Buffer Execution FAILED");
}
enum class BadInheritanceInfoCase
{
RANDOM_PTR = 0,
RANDOM_PTR_CONTINUATION,
RANDOM_DATA_PTR,
INVALID_STRUCTURE_TYPE,
VALID_NONSENSE_TYPE,
};
tcu::TestStatus badInheritanceInfoTest (Context& context, BadInheritanceInfoCase testCase)
{
const auto& vkd = context.getDeviceInterface();
const auto device = context.getDevice();
const auto queue = context.getUniversalQueue();
const auto queueFamilyIndex = context.getUniversalQueueFamilyIndex();
auto& allocator = context.getDefaultAllocator();
const ComputeInstanceResultBuffer result (vkd, device, allocator, 0.0f);
// Command pool and command buffer.
const auto cmdPool = makeCommandPool(vkd, device, queueFamilyIndex);
const auto cmdBufferPtr = allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
const auto cmdBuffer = cmdBufferPtr.get();
// Buffers, descriptor set layouts and descriptor sets.
const deUint32 offset = 0u;
const deUint32 addressableSize = 256u;
const deUint32 dataSize = 8u;
// The uniform buffer will not be used by the shader but is needed by auxiliar functions here.
de::MovePtr<Allocation> bufferMem;
const Unique<VkBuffer> buffer(createDataBuffer(context, offset, addressableSize, 0x00, dataSize, 0x5A, &bufferMem));
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);
// Pipeline layout.
const auto pipelineLayout = makePipelineLayout(vkd, device, descriptorSetLayout.get());
// Compute shader module.
const Unique<VkShaderModule> computeModule (createShaderModule(vkd, device, 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(vkd, device, (VkPipelineCache)0u, &pipelineCreateInfo));
// Compute to host barrier to read result.
const VkBufferMemoryBarrier bufferBarrier =
{
VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // sType
DE_NULL, // pNext
VK_ACCESS_SHADER_WRITE_BIT, // srcAccessMask
VK_ACCESS_HOST_READ_BIT, // dstAccessMask
VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex
VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex
*buffer, // buffer
(VkDeviceSize)0u, // offset
(VkDeviceSize)VK_WHOLE_SIZE, // size
};
// Record command buffer and submit it.
VkCommandBufferBeginInfo beginInfo =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
nullptr, // const void* pNext;
0u, // VkCommandBufferUsageFlags flags;
nullptr, // const VkCommandBufferInheritanceInfo* pInheritanceInfo;
};
// Structures used in different test types.
VkCommandBufferInheritanceInfo inheritanceInfo;
VkBufferCreateInfo validNonsenseStructure;
struct
{
VkStructureType sType;
void* pNext;
} invalidStructure;
if (testCase == BadInheritanceInfoCase::RANDOM_PTR || testCase == BadInheritanceInfoCase::RANDOM_PTR_CONTINUATION)
{
de::Random rnd (1602600778u);
VkCommandBufferInheritanceInfo* info;
auto ptrData = reinterpret_cast<deUint8*>(&info);
// Fill pointer value with pseudorandom garbage.
for (size_t i = 0; i < sizeof(info); ++i)
*ptrData++ = rnd.getUint8();
beginInfo.pInheritanceInfo = info;
// Try to trick the implementation into reading pInheritanceInfo one more way.
if (testCase == BadInheritanceInfoCase::RANDOM_PTR_CONTINUATION)
beginInfo.flags |= VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
}
else if (testCase == BadInheritanceInfoCase::RANDOM_DATA_PTR)
{
de::Random rnd (1602601141u);
auto itr = reinterpret_cast<deUint8*>(&inheritanceInfo);
// Fill inheritance info data structure with random data.
for (size_t i = 0; i < sizeof(inheritanceInfo); ++i)
*itr++ = rnd.getUint8();
beginInfo.pInheritanceInfo = &inheritanceInfo;
}
else if (testCase == BadInheritanceInfoCase::INVALID_STRUCTURE_TYPE)
{
de::Random rnd (1602658515u);
auto ptrData = reinterpret_cast<deUint8*>(&(invalidStructure.pNext));
invalidStructure.sType = VK_STRUCTURE_TYPE_MAX_ENUM;
// Fill pNext pointer with random data.
for (size_t i = 0; i < sizeof(invalidStructure.pNext); ++i)
*ptrData++ = rnd.getUint8();
beginInfo.pInheritanceInfo = reinterpret_cast<VkCommandBufferInheritanceInfo*>(&invalidStructure);
}
else if (testCase == BadInheritanceInfoCase::VALID_NONSENSE_TYPE)
{
validNonsenseStructure.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
validNonsenseStructure.pNext = nullptr;
validNonsenseStructure.flags = 0u;
validNonsenseStructure.size = 1024u;
validNonsenseStructure.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
validNonsenseStructure.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
validNonsenseStructure.queueFamilyIndexCount = 0u;
validNonsenseStructure.pQueueFamilyIndices = nullptr;
beginInfo.pInheritanceInfo = reinterpret_cast<VkCommandBufferInheritanceInfo*>(&validNonsenseStructure);
}
else
{
DE_ASSERT(false);
}
VK_CHECK(vkd.beginCommandBuffer(cmdBuffer, &beginInfo));
{
vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0, numDescriptorSets, descriptorSets, 0, 0);
vkd.cmdDispatch(cmdBuffer, 1u, 1u, 1u);
vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0,
0, (const VkMemoryBarrier*)DE_NULL,
1, &bufferBarrier,
0, (const VkImageMemoryBarrier*)DE_NULL);
}
endCommandBuffer(vkd, cmdBuffer);
submitCommandsAndWait(vkd, device, queue, cmdBuffer);
deUint32 resultCount;
result.readResultContentsTo(&resultCount);
// Make sure the command buffer was run.
if (resultCount != 1u)
{
std::ostringstream msg;
msg << "Invalid value found in results buffer (expected value 1u but found " << resultCount << ")";
return tcu::TestStatus::fail(msg.str());
}
return tcu::TestStatus::pass("Pass");
}
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
endCommandBuffer(vk, *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());
}
endCommandBuffer(vk, *primCmdBufOne);
VK_CHECK(vk.beginCommandBuffer(*primCmdBufTwo, &primCmdBufBeginInfo));
{
vk.cmdExecuteCommands(*primCmdBufTwo, 1, &secCmdBuf.get());
}
endCommandBuffer(vk, *primCmdBufTwo);
// create fence to wait for execution of queue
const Unique<VkFence> fence(createFence(vk, vkDevice));
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("Simultaneous Secondary Command Buffer Execution succeeded");
else
return tcu::TestStatus::fail("Simultaneous Secondary Command Buffer Execution FAILED");
}
tcu::TestStatus recordBufferQueryPreciseWithFlagTest(Context& context)
{
const VkDevice vkDevice = context.getDevice();
const DeviceInterface& vk = context.getDeviceInterface();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
if (!context.getDeviceFeatures().inheritedQueries)
TCU_THROW(NotSupportedError, "Inherited queries feature is not supported");
const VkCommandPoolCreateInfo cmdPoolParams =
{
VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType;
DE_NULL, // pNext;
VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // flags;
queueFamilyIndex, // queueFamilyIndex;
};
const Unique<VkCommandPool> cmdPool (createCommandPool(vk, vkDevice, &cmdPoolParams));
// Command buffer
const VkCommandBufferAllocateInfo primCmdBufParams =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
DE_NULL, // pNext;
*cmdPool, // pool;
VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level;
1u, // flags;
};
const Unique<VkCommandBuffer> primCmdBuf (allocateCommandBuffer(vk, vkDevice, &primCmdBufParams));
// Secondary Command buffer params
const VkCommandBufferAllocateInfo secCmdBufParams =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
DE_NULL, // pNext;
*cmdPool, // pool;
VK_COMMAND_BUFFER_LEVEL_SECONDARY, // level;
1u, // flags;
};
const Unique<VkCommandBuffer> secCmdBuf (allocateCommandBuffer(vk, vkDevice, &secCmdBufParams));
const VkCommandBufferBeginInfo primBufferBeginInfo =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
DE_NULL, // pNext
0u, // flags
(const VkCommandBufferInheritanceInfo*)DE_NULL,
};
const VkCommandBufferInheritanceInfo secBufferInheritInfo =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
DE_NULL,
0u, // renderPass
0u, // subpass
0u, // framebuffer
VK_TRUE, // occlusionQueryEnable
VK_QUERY_CONTROL_PRECISE_BIT, // queryFlags
(VkQueryPipelineStatisticFlags)0u, // pipelineStatistics
};
const VkCommandBufferBeginInfo secBufferBeginInfo =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
DE_NULL, // pNext
0u, // flags
&secBufferInheritInfo,
};
const VkQueryPoolCreateInfo queryPoolCreateInfo =
{
VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // sType
DE_NULL, // pNext
(VkQueryPoolCreateFlags)0, // flags
VK_QUERY_TYPE_OCCLUSION, // queryType
1u, // entryCount
0u, // pipelineStatistics
};
Unique<VkQueryPool> queryPool (createQueryPool(vk, vkDevice, &queryPoolCreateInfo));
VK_CHECK(vk.beginCommandBuffer(secCmdBuf.get(), &secBufferBeginInfo));
endCommandBuffer(vk, secCmdBuf.get());
VK_CHECK(vk.beginCommandBuffer(primCmdBuf.get(), &primBufferBeginInfo));
{
vk.cmdResetQueryPool(primCmdBuf.get(), queryPool.get(), 0u, 1u);
vk.cmdBeginQuery(primCmdBuf.get(), queryPool.get(), 0u, VK_QUERY_CONTROL_PRECISE_BIT);
{
vk.cmdExecuteCommands(primCmdBuf.get(), 1u, &secCmdBuf.get());
}
vk.cmdEndQuery(primCmdBuf.get(), queryPool.get(), 0u);
}
endCommandBuffer(vk, primCmdBuf.get());
return tcu::TestStatus::pass("Successfully recorded a secondary command buffer allowing a precise occlusion query.");
}
tcu::TestStatus recordBufferQueryImpreciseWithFlagTest(Context& context)
{
const VkDevice vkDevice = context.getDevice();
const DeviceInterface& vk = context.getDeviceInterface();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
if (!context.getDeviceFeatures().inheritedQueries)
TCU_THROW(NotSupportedError, "Inherited queries feature is not supported");
const VkCommandPoolCreateInfo cmdPoolParams =
{
VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType;
DE_NULL, // pNext;
VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // flags;
queueFamilyIndex, // queueFamilyIndex;
};
const Unique<VkCommandPool> cmdPool (createCommandPool(vk, vkDevice, &cmdPoolParams));
// Command buffer
const VkCommandBufferAllocateInfo primCmdBufParams =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
DE_NULL, // pNext;
*cmdPool, // pool;
VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level;
1u, // flags;
};
const Unique<VkCommandBuffer> primCmdBuf (allocateCommandBuffer(vk, vkDevice, &primCmdBufParams));
// Secondary Command buffer params
const VkCommandBufferAllocateInfo secCmdBufParams =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
DE_NULL, // pNext;
*cmdPool, // pool;
VK_COMMAND_BUFFER_LEVEL_SECONDARY, // level;
1u, // flags;
};
const Unique<VkCommandBuffer> secCmdBuf (allocateCommandBuffer(vk, vkDevice, &secCmdBufParams));
const VkCommandBufferBeginInfo primBufferBeginInfo =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
DE_NULL, // pNext
0u, // flags
(const VkCommandBufferInheritanceInfo*)DE_NULL,
};
const VkCommandBufferInheritanceInfo secBufferInheritInfo =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
DE_NULL,
0u, // renderPass
0u, // subpass
0u, // framebuffer
VK_TRUE, // occlusionQueryEnable
VK_QUERY_CONTROL_PRECISE_BIT, // queryFlags
(VkQueryPipelineStatisticFlags)0u, // pipelineStatistics
};
const VkCommandBufferBeginInfo secBufferBeginInfo =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
DE_NULL, // pNext
0u, // flags
&secBufferInheritInfo,
};
// Create an occlusion query with VK_QUERY_CONTROL_PRECISE_BIT set
const VkQueryPoolCreateInfo queryPoolCreateInfo =
{
VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // sType
DE_NULL, // pNext
0u, // flags
VK_QUERY_TYPE_OCCLUSION, // queryType
1u, // entryCount
0u, // pipelineStatistics
};
Unique<VkQueryPool> queryPool (createQueryPool(vk, vkDevice, &queryPoolCreateInfo));
VK_CHECK(vk.beginCommandBuffer(secCmdBuf.get(), &secBufferBeginInfo));
endCommandBuffer(vk, secCmdBuf.get());
VK_CHECK(vk.beginCommandBuffer(primCmdBuf.get(), &primBufferBeginInfo));
{
vk.cmdResetQueryPool(primCmdBuf.get(), queryPool.get(), 0u, 1u);
vk.cmdBeginQuery(primCmdBuf.get(), queryPool.get(), 0u, VK_QUERY_CONTROL_PRECISE_BIT);
{
vk.cmdExecuteCommands(primCmdBuf.get(), 1u, &secCmdBuf.get());
}
vk.cmdEndQuery(primCmdBuf.get(), queryPool.get(), 0u);
}
endCommandBuffer(vk, primCmdBuf.get());
return tcu::TestStatus::pass("Successfully recorded a secondary command buffer allowing a precise occlusion query.");
}
tcu::TestStatus recordBufferQueryImpreciseWithoutFlagTest(Context& context)
{
const VkDevice vkDevice = context.getDevice();
const DeviceInterface& vk = context.getDeviceInterface();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
if (!context.getDeviceFeatures().inheritedQueries)
TCU_THROW(NotSupportedError, "Inherited queries feature is not supported");
const VkCommandPoolCreateInfo cmdPoolParams =
{
VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType;
DE_NULL, // pNext;
VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // flags;
queueFamilyIndex, // queueFamilyIndex;
};
const Unique<VkCommandPool> cmdPool (createCommandPool(vk, vkDevice, &cmdPoolParams));
// Command buffer
const VkCommandBufferAllocateInfo primCmdBufParams =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
DE_NULL, // pNext;
*cmdPool, // pool;
VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level;
1u, // flags;
};
const Unique<VkCommandBuffer> primCmdBuf (allocateCommandBuffer(vk, vkDevice, &primCmdBufParams));
// Secondary Command buffer params
const VkCommandBufferAllocateInfo secCmdBufParams =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
DE_NULL, // pNext;
*cmdPool, // pool;
VK_COMMAND_BUFFER_LEVEL_SECONDARY, // level;
1u, // flags;
};
const Unique<VkCommandBuffer> secCmdBuf (allocateCommandBuffer(vk, vkDevice, &secCmdBufParams));
const VkCommandBufferBeginInfo primBufferBeginInfo =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
DE_NULL, // pNext
0u, // flags
(const VkCommandBufferInheritanceInfo*)DE_NULL,
};
const VkCommandBufferInheritanceInfo secBufferInheritInfo =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
DE_NULL,
0u, // renderPass
0u, // subpass
0u, // framebuffer
VK_TRUE, // occlusionQueryEnable
0u, // queryFlags
(VkQueryPipelineStatisticFlags)0u, // pipelineStatistics
};
const VkCommandBufferBeginInfo secBufferBeginInfo =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
DE_NULL, // pNext
0u, // flags
&secBufferInheritInfo,
};
// Create an occlusion query with VK_QUERY_CONTROL_PRECISE_BIT set
const VkQueryPoolCreateInfo queryPoolCreateInfo =
{
VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // sType
DE_NULL, // pNext
(VkQueryPoolCreateFlags)0,
VK_QUERY_TYPE_OCCLUSION,
1u,
0u,
};
Unique<VkQueryPool> queryPool (createQueryPool(vk, vkDevice, &queryPoolCreateInfo));
VK_CHECK(vk.beginCommandBuffer(secCmdBuf.get(), &secBufferBeginInfo));
endCommandBuffer(vk, secCmdBuf.get());
VK_CHECK(vk.beginCommandBuffer(primCmdBuf.get(), &primBufferBeginInfo));
{
vk.cmdResetQueryPool(primCmdBuf.get(), queryPool.get(), 0u, 1u);
vk.cmdBeginQuery(primCmdBuf.get(), queryPool.get(), 0u, VK_QUERY_CONTROL_PRECISE_BIT);
{
vk.cmdExecuteCommands(primCmdBuf.get(), 1u, &secCmdBuf.get());
}
vk.cmdEndQuery(primCmdBuf.get(), queryPool.get(), 0u);
}
endCommandBuffer(vk, primCmdBuf.get());
return tcu::TestStatus::pass("Successfully recorded a secondary command buffer allowing a precise occlusion query.");
}
/******** 19.4. Command Buffer Submission (5.4 in VK 1.0 Spec) ****************/
tcu::TestStatus submitBufferCountNonZero(Context& context)
{
const VkDevice vkDevice = context.getDevice();
const DeviceInterface& vk = context.getDeviceInterface();
const VkQueue queue = context.getUniversalQueue();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
const deUint32 BUFFER_COUNT = 5u;
const VkCommandPoolCreateInfo cmdPoolParams =
{
VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType;
DE_NULL, // pNext;
0u, // flags;
queueFamilyIndex, // queueFamilyIndex;
};
const Unique<VkCommandPool> cmdPool (createCommandPool(vk, vkDevice, &cmdPoolParams));
// Command buffer
const VkCommandBufferAllocateInfo cmdBufParams =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
DE_NULL, // pNext;
*cmdPool, // pool;
VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level;
BUFFER_COUNT, // bufferCount;
};
VkCommandBuffer cmdBuffers[BUFFER_COUNT];
VK_CHECK(vk.allocateCommandBuffers(vkDevice, &cmdBufParams, cmdBuffers));
const VkCommandBufferBeginInfo cmdBufBeginInfo =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
DE_NULL, // pNext
0u, // flags
(const VkCommandBufferInheritanceInfo*)DE_NULL,
};
std::vector<VkEventSp> events;
for (deUint32 ndx = 0; ndx < BUFFER_COUNT; ++ndx)
{
events.push_back(VkEventSp(new vk::Unique<VkEvent>(createEvent(vk, vkDevice))));
}
// Record the command buffers
for (deUint32 ndx = 0; ndx < BUFFER_COUNT; ++ndx)
{
VK_CHECK(vk.beginCommandBuffer(cmdBuffers[ndx], &cmdBufBeginInfo));
{
vk.cmdSetEvent(cmdBuffers[ndx], events[ndx]->get(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
}
endCommandBuffer(vk, cmdBuffers[ndx]);
}
// We'll use a fence to wait for the execution of the queue
const Unique<VkFence> fence (createFence(vk, vkDevice));
const VkSubmitInfo submitInfo =
{
VK_STRUCTURE_TYPE_SUBMIT_INFO, // sType
DE_NULL, // pNext
0u, // waitSemaphoreCount
DE_NULL, // pWaitSemaphores
(const VkPipelineStageFlags*)DE_NULL, // pWaitDstStageMask
BUFFER_COUNT, // commandBufferCount
cmdBuffers, // pCommandBuffers
0u, // signalSemaphoreCount
DE_NULL, // pSignalSemaphores
};
// Submit the alpha command buffer to the queue
VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, fence.get()));
// Wait for the queue
VK_CHECK(vk.waitForFences(vkDevice, 1u, &fence.get(), VK_TRUE, INFINITE_TIMEOUT));
// Check if the buffers were executed
tcu::TestStatus testResult = tcu::TestStatus::incomplete();
for (deUint32 ndx = 0; ndx < BUFFER_COUNT; ++ndx)
{
if (vk.getEventStatus(vkDevice, events[ndx]->get()) != VK_EVENT_SET)
{
testResult = tcu::TestStatus::fail("Failed to set the event.");
break;
}
}
if (!testResult.isComplete())
testResult = tcu::TestStatus::pass("All buffers were submitted and executed correctly.");
return testResult;
}
tcu::TestStatus submitBufferCountEqualZero(Context& context)
{
const VkDevice vkDevice = context.getDevice();
const DeviceInterface& vk = context.getDeviceInterface();
const VkQueue queue = context.getUniversalQueue();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
const deUint32 BUFFER_COUNT = 2u;
const VkCommandPoolCreateInfo cmdPoolParams =
{
VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType;
DE_NULL, // pNext;
0u, // flags;
queueFamilyIndex, // queueFamilyIndex;
};
const Unique<VkCommandPool> cmdPool (createCommandPool(vk, vkDevice, &cmdPoolParams));
// Command buffer
const VkCommandBufferAllocateInfo cmdBufParams =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
DE_NULL, // pNext;
*cmdPool, // pool;
VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level;
BUFFER_COUNT, // bufferCount;
};
VkCommandBuffer cmdBuffers[BUFFER_COUNT];
VK_CHECK(vk.allocateCommandBuffers(vkDevice, &cmdBufParams, cmdBuffers));
const VkCommandBufferBeginInfo cmdBufBeginInfo =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
DE_NULL, // pNext
0u, // flags
(const VkCommandBufferInheritanceInfo*)DE_NULL,
};
std::vector<VkEventSp> events;
for (deUint32 ndx = 0; ndx < BUFFER_COUNT; ++ndx)
events.push_back(VkEventSp(new vk::Unique<VkEvent>(createEvent(vk, vkDevice))));
// Record the command buffers
for (deUint32 ndx = 0; ndx < BUFFER_COUNT; ++ndx)
{
VK_CHECK(vk.beginCommandBuffer(cmdBuffers[ndx], &cmdBufBeginInfo));
{
vk.cmdSetEvent(cmdBuffers[ndx], events[ndx]->get(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
}
endCommandBuffer(vk, cmdBuffers[ndx]);
}
// We'll use a fence to wait for the execution of the queue
const Unique<VkFence> fenceZero (createFence(vk, vkDevice));
const Unique<VkFence> fenceOne (createFence(vk, vkDevice));
const VkSubmitInfo submitInfoCountZero =
{
VK_STRUCTURE_TYPE_SUBMIT_INFO, // sType
DE_NULL, // pNext
0u, // waitSemaphoreCount
DE_NULL, // pWaitSemaphores
(const VkPipelineStageFlags*)DE_NULL, // pWaitDstStageMask
1u, // commandBufferCount
&cmdBuffers[0], // pCommandBuffers
0u, // signalSemaphoreCount
DE_NULL, // pSignalSemaphores
};
const VkSubmitInfo submitInfoCountOne =
{
VK_STRUCTURE_TYPE_SUBMIT_INFO, // sType
DE_NULL, // pNext
0u, // waitSemaphoreCount
DE_NULL, // pWaitSemaphores
(const VkPipelineStageFlags*)DE_NULL, // pWaitDstStageMask
1u, // commandBufferCount
&cmdBuffers[1], // pCommandBuffers
0u, // signalSemaphoreCount
DE_NULL, // pSignalSemaphores
};
// Submit the command buffers to the queue
// We're performing two submits to make sure that the first one has
// a chance to be processed before we check the event's status
VK_CHECK(vk.queueSubmit(queue, 0, &submitInfoCountZero, fenceZero.get()));
VK_CHECK(vk.queueSubmit(queue, 1, &submitInfoCountOne, fenceOne.get()));
const VkFence fences[] =
{
fenceZero.get(),
fenceOne.get(),
};
// Wait for the queue
VK_CHECK(vk.waitForFences(vkDevice, (deUint32)DE_LENGTH_OF_ARRAY(fences), fences, VK_TRUE, INFINITE_TIMEOUT));
// Check if the first buffer was executed
tcu::TestStatus testResult = tcu::TestStatus::incomplete();
if (vk.getEventStatus(vkDevice, events[0]->get()) == VK_EVENT_SET)
testResult = tcu::TestStatus::fail("The first event was signaled.");
else
testResult = tcu::TestStatus::pass("The first submission was ignored.");
return testResult;
}
tcu::TestStatus submitBufferWaitSingleSemaphore(Context& context)
{
const VkDevice vkDevice = context.getDevice();
const DeviceInterface& vk = context.getDeviceInterface();
const VkQueue queue = context.getUniversalQueue();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
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;
};
// Create two command buffers
const Unique<VkCommandBuffer> primCmdBuf1 (allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
const Unique<VkCommandBuffer> primCmdBuf2 (allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
const VkCommandBufferBeginInfo primCmdBufBeginInfo =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
DE_NULL, // pNext
0, // flags
DE_NULL // const VkCommandBufferInheritanceInfo* pInheritanceInfo;
};
// create two events that will be used to check if command buffers has been executed
const Unique<VkEvent> event1 (createEvent(vk, vkDevice));
const Unique<VkEvent> event2 (createEvent(vk, vkDevice));
// reset events
VK_CHECK(vk.resetEvent(vkDevice, *event1));
VK_CHECK(vk.resetEvent(vkDevice, *event2));
// record first command buffer
VK_CHECK(vk.beginCommandBuffer(*primCmdBuf1, &primCmdBufBeginInfo));
{
// allow execution of event during every stage of pipeline
VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
// record setting event
vk.cmdSetEvent(*primCmdBuf1, *event1,stageMask);
}
endCommandBuffer(vk, *primCmdBuf1);
// record second command buffer
VK_CHECK(vk.beginCommandBuffer(*primCmdBuf2, &primCmdBufBeginInfo));
{
// allow execution of event during every stage of pipeline
VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
// record setting event
vk.cmdSetEvent(*primCmdBuf2, *event2,stageMask);
}
endCommandBuffer(vk, *primCmdBuf2);
// create fence to wait for execution of queue
const Unique<VkFence> fence (createFence(vk, vkDevice));
// create semaphore for use in this test
const Unique <VkSemaphore> semaphore (createSemaphore(vk, vkDevice));
// create submit info for first buffer - signalling semaphore
const VkSubmitInfo submitInfo1 =
{
VK_STRUCTURE_TYPE_SUBMIT_INFO, // sType
DE_NULL, // pNext
0u, // waitSemaphoreCount
DE_NULL, // pWaitSemaphores
DE_NULL, // pWaitDstStageMask
1, // commandBufferCount
&primCmdBuf1.get(), // pCommandBuffers
1u, // signalSemaphoreCount
&semaphore.get(), // pSignalSemaphores
};
// Submit the command buffer to the queue
VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo1, *fence));
// wait for end of execution of queue
VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), 0u, INFINITE_TIMEOUT));
// check if buffer has been executed
VkResult result = vk.getEventStatus(vkDevice,*event1);
if (result != VK_EVENT_SET)
return tcu::TestStatus::fail("Submit Buffer and Wait for Single Semaphore Test FAILED");
const VkPipelineStageFlags waitDstStageFlags = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
// create submit info for second buffer - waiting for semaphore
const VkSubmitInfo submitInfo2 =
{
VK_STRUCTURE_TYPE_SUBMIT_INFO, // sType
DE_NULL, // pNext
1u, // waitSemaphoreCount
&semaphore.get(), // pWaitSemaphores
&waitDstStageFlags, // pWaitDstStageMask
1, // commandBufferCount
&primCmdBuf2.get(), // pCommandBuffers
0u, // signalSemaphoreCount
DE_NULL, // pSignalSemaphores
};
// reset fence, so it can be used again
VK_CHECK(vk.resetFences(vkDevice, 1u, &fence.get()));
// Submit the second command buffer to the queue
VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo2, *fence));
// wait for end of execution of queue
VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), 0u, INFINITE_TIMEOUT));
// check if second buffer has been executed
// if it has been executed, it means that the semaphore was signalled - so test if passed
result = vk.getEventStatus(vkDevice,*event1);
if (result != VK_EVENT_SET)
return tcu::TestStatus::fail("Submit Buffer and Wait for Single Semaphore Test FAILED");
return tcu::TestStatus::pass("Submit Buffer and Wait for Single Semaphore Test succeeded");
}
tcu::TestStatus submitBufferWaitManySemaphores(Context& context)
{
// This test will create numSemaphores semaphores, and signal them in NUM_SEMAPHORES submits to queue
// After that the numSubmissions queue submissions will wait for each semaphore
const deUint32 numSemaphores = 10u; // it must be multiply of numSubmission
const deUint32 numSubmissions = 2u;
const VkDevice vkDevice = context.getDevice();
const DeviceInterface& vk = context.getDeviceInterface();
const VkQueue queue = context.getUniversalQueue();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
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;
};
// Create command buffer
const Unique<VkCommandBuffer> primCmdBuf (allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
const VkCommandBufferBeginInfo primCmdBufBeginInfo =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
DE_NULL, // pNext
0, // flags
DE_NULL // const VkCommandBufferInheritanceInfo* pInheritanceInfo;
};
// create event that will be used to check if command buffers has been executed
const Unique<VkEvent> event (createEvent(vk, vkDevice));
// reset event - at creation state is undefined
VK_CHECK(vk.resetEvent(vkDevice, *event));
// record command buffer
VK_CHECK(vk.beginCommandBuffer(*primCmdBuf, &primCmdBufBeginInfo));
{
// allow execution of event during every stage of pipeline
VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
// record setting event
vk.cmdSetEvent(*primCmdBuf, *event,stageMask);
}
endCommandBuffer(vk, *primCmdBuf);
// create fence to wait for execution of queue
const Unique<VkFence> fence (createFence(vk, vkDevice));
// numSemaphores is declared const, so this array can be static
// the semaphores will be destroyed automatically at end of scope
Move <VkSemaphore> semaphoreArray[numSemaphores];
VkSemaphore semaphores[numSemaphores];
for (deUint32 idx = 0; idx < numSemaphores; ++idx) {
// create semaphores for use in this test
semaphoreArray[idx] = createSemaphore(vk, vkDevice);
semaphores[idx] = semaphoreArray[idx].get();
}
{
// create submit info for buffer - signal semaphores
const VkSubmitInfo submitInfo1 =
{
VK_STRUCTURE_TYPE_SUBMIT_INFO, // sType
DE_NULL, // pNext
0u, // waitSemaphoreCount
DE_NULL, // pWaitSemaphores
DE_NULL, // pWaitDstStageMask
1, // commandBufferCount
&primCmdBuf.get(), // pCommandBuffers
numSemaphores, // signalSemaphoreCount
semaphores // pSignalSemaphores
};
// Submit the command buffer to the queue
VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo1, *fence));
// wait for end of execution of queue
VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), 0u, INFINITE_TIMEOUT));
// check if buffer has been executed
VkResult result = vk.getEventStatus(vkDevice,*event);
if (result != VK_EVENT_SET)
return tcu::TestStatus::fail("Submit Buffer and Wait for Many Semaphores Test FAILED");
// reset event, so next buffers can set it again
VK_CHECK(vk.resetEvent(vkDevice, *event));
// reset fence, so it can be used again
VK_CHECK(vk.resetFences(vkDevice, 1u, &fence.get()));
}
const deUint32 numberOfSemaphoresToBeWaitedByOneSubmission = numSemaphores / numSubmissions;
const std::vector<VkPipelineStageFlags> waitDstStageFlags (numberOfSemaphoresToBeWaitedByOneSubmission, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
// the following code waits for the semaphores set above - numSubmissions queues will wait for each semaphore from above
for (deUint32 idxSubmission = 0; idxSubmission < numSubmissions; ++idxSubmission) {
// create submit info for buffer - waiting for semaphore
const VkSubmitInfo submitInfo2 =
{
VK_STRUCTURE_TYPE_SUBMIT_INFO, // sType
DE_NULL, // pNext
numberOfSemaphoresToBeWaitedByOneSubmission, // waitSemaphoreCount
semaphores + (numberOfSemaphoresToBeWaitedByOneSubmission * idxSubmission), // pWaitSemaphores
waitDstStageFlags.data(), // pWaitDstStageMask
1, // commandBufferCount
&primCmdBuf.get(), // pCommandBuffers
0u, // signalSemaphoreCount
DE_NULL, // pSignalSemaphores
};
// Submit the second command buffer to the queue
VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo2, *fence));
// wait for 1 second.
VK_CHECK(vk.waitForFences(vkDevice, 1, &fence.get(), 0u, 1000 * 1000 * 1000));
// check if second buffer has been executed
// if it has been executed, it means that the semaphore was signalled - so test if passed
VkResult result = vk.getEventStatus(vkDevice,*event);
if (result != VK_EVENT_SET)
return tcu::TestStatus::fail("Submit Buffer and Wait for Many Semaphores Test FAILED");
// reset fence, so it can be used again
VK_CHECK(vk.resetFences(vkDevice, 1u, &fence.get()));
// reset event, so next buffers can set it again
VK_CHECK(vk.resetEvent(vkDevice, *event));
}
return tcu::TestStatus::pass("Submit Buffer and Wait for Many Semaphores Test succeeded");
}
tcu::TestStatus submitBufferNullFence(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 VkCommandPoolCreateInfo cmdPoolParams =
{
VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType;
DE_NULL, // pNext;
0u, // flags;
queueFamilyIndex, // queueFamilyIndex;
};
const Unique<VkCommandPool> cmdPool (createCommandPool(vk, vkDevice, &cmdPoolParams));
// Command buffer
const VkCommandBufferAllocateInfo cmdBufParams =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
DE_NULL, // pNext;
*cmdPool, // pool;
VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level;
1u, // bufferCount;
};
VkCommandBuffer cmdBuffers[BUFFER_COUNT];
for (deUint32 ndx = 0; ndx < BUFFER_COUNT; ++ndx)
VK_CHECK(vk.allocateCommandBuffers(vkDevice, &cmdBufParams, &cmdBuffers[ndx]));
const VkCommandBufferBeginInfo cmdBufBeginInfo =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
DE_NULL, // pNext
0u, // flags
(const VkCommandBufferInheritanceInfo*)DE_NULL,
};
std::vector<VkEventSp> events;
for (deUint32 ndx = 0; ndx < BUFFER_COUNT; ++ndx)
events.push_back(VkEventSp(new vk::Unique<VkEvent>(createEvent(vk, vkDevice))));
// Record the command buffers
for (deUint32 ndx = 0; ndx < BUFFER_COUNT; ++ndx)
{
VK_CHECK(vk.beginCommandBuffer(cmdBuffers[ndx], &cmdBufBeginInfo));
{
vk.cmdSetEvent(cmdBuffers[ndx], events[ndx]->get(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
}
endCommandBuffer(vk, cmdBuffers[ndx]);
}
// We'll use a fence to wait for the execution of the queue
const Unique<VkFence> fence (createFence(vk, vkDevice));
const VkSubmitInfo submitInfoNullFence =
{
VK_STRUCTURE_TYPE_SUBMIT_INFO, // sType
DE_NULL, // pNext
0u, // waitSemaphoreCount
DE_NULL, // pWaitSemaphores
(const VkPipelineStageFlags*)DE_NULL, // pWaitDstStageMask
1u, // commandBufferCount
&cmdBuffers[0], // pCommandBuffers
0u, // signalSemaphoreCount
DE_NULL, // pSignalSemaphores
};
const VkSubmitInfo submitInfoNonNullFence =
{
VK_STRUCTURE_TYPE_SUBMIT_INFO, // sType
DE_NULL, // pNext
0u, // waitSemaphoreCount
DE_NULL, // pWaitSemaphores
(const VkPipelineStageFlags*)DE_NULL, // pWaitDstStageMask
1u, // commandBufferCount
&cmdBuffers[1], // pCommandBuffers
0u, // signalSemaphoreCount
DE_NULL, // pSignalSemaphores
};
// Perform two submissions - one with no fence, the other one with a valid
// fence Hoping submitting the other buffer will give the first one time to
// execute
VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfoNullFence, DE_NULL));
VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfoNonNullFence, fence.get()));
// Wait for the queue
VK_CHECK(vk.waitForFences(vkDevice, 1u, &fence.get(), VK_TRUE, INFINITE_TIMEOUT));
tcu::TestStatus testResult = tcu::TestStatus::incomplete();
//Fence guaranteed that all buffers submited before fence were executed
if (vk.getEventStatus(vkDevice, events[0]->get()) != VK_EVENT_SET || vk.getEventStatus(vkDevice, events[1]->get()) != VK_EVENT_SET)
{
testResult = tcu::TestStatus::fail("One of the buffers was not executed.");
}
else
{
testResult = tcu::TestStatus::pass("Buffers have been submitted and executed correctly.");
}
vk.queueWaitIdle(queue);
return testResult;
}
tcu::TestStatus submitTwoBuffersOneBufferNullWithFence(Context& context)
{
const VkDevice vkDevice = context.getDevice();
const DeviceInterface& vk = context.getDeviceInterface();
const VkQueue queue = context.getUniversalQueue();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
const deUint32 BUFFER_COUNT = 2u;
const VkCommandPoolCreateInfo cmdPoolParams =
{
VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType;
DE_NULL, // pNext;
VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // flags;
queueFamilyIndex, // queueFamilyIndex;
};
const Unique<VkCommandPool> cmdPool (createCommandPool(vk, vkDevice, &cmdPoolParams));
const VkCommandBufferAllocateInfo cmdBufParams =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
DE_NULL, // pNext;
*cmdPool, // pool;
VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level;
BUFFER_COUNT, // bufferCount;
};
VkCommandBuffer cmdBuffers[BUFFER_COUNT];
VK_CHECK(vk.allocateCommandBuffers(vkDevice, &cmdBufParams, cmdBuffers));
const VkCommandBufferBeginInfo cmdBufBeginInfo =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
DE_NULL, // pNext
0u, // flags
(const VkCommandBufferInheritanceInfo*)DE_NULL, // pInheritanceInfo
};
std::vector<VkEventSp> events;
for (deUint32 ndx = 0; ndx < BUFFER_COUNT; ++ndx)
events.push_back(VkEventSp(new vk::Unique<VkEvent>(createEvent(vk, vkDevice))));
// Record the command buffers
for (deUint32 ndx = 0; ndx < BUFFER_COUNT; ++ndx)
{
VK_CHECK(vk.beginCommandBuffer(cmdBuffers[ndx], &cmdBufBeginInfo));
{
vk.cmdSetEvent(cmdBuffers[ndx], events[ndx]->get(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
}
VK_CHECK(vk.endCommandBuffer(cmdBuffers[ndx]));
}
// First command buffer
const VkSubmitInfo submitInfoNonNullFirst =
{
VK_STRUCTURE_TYPE_SUBMIT_INFO, // sType
DE_NULL, // pNext
0u, // waitSemaphoreCount
DE_NULL, // pWaitSemaphores
(const VkPipelineStageFlags*)DE_NULL, // pWaitDstStageMask
1u, // commandBufferCount
&cmdBuffers[0], // pCommandBuffers
0u, // signalSemaphoreCount
DE_NULL, // pSignalSemaphores
};
// Second command buffer
const VkSubmitInfo submitInfoNonNullSecond =
{
VK_STRUCTURE_TYPE_SUBMIT_INFO, // sType
DE_NULL, // pNext
0u, // waitSemaphoreCount
DE_NULL, // pWaitSemaphores
(const VkPipelineStageFlags*)DE_NULL, // pWaitDstStageMask
1u, // commandBufferCount
&cmdBuffers[1], // pCommandBuffers
0u, // signalSemaphoreCount
DE_NULL, // pSignalSemaphores
};
// Fence will be submitted with the null queue
const Unique<VkFence> fence (createFence(vk, vkDevice));
// Perform two separate queueSubmit calls on the same queue followed
// by a third call with no submitInfos and with a valid fence
VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfoNonNullFirst, DE_NULL));
VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfoNonNullSecond, DE_NULL));
VK_CHECK(vk.queueSubmit(queue, 0u, DE_NULL, fence.get()));
// Wait for the queue
VK_CHECK(vk.waitForFences(vkDevice, 1u, &fence.get(), VK_TRUE, INFINITE_TIMEOUT));
return tcu::TestStatus::pass("Buffers have been submitted correctly");
}
/******** 19.5. Secondary Command Buffer Execution (5.6 in VK 1.0 Spec) *******/
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 VkCommandPoolCreateInfo cmdPoolParams =
{
VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType;
DE_NULL, // pNext;
VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // flags;
queueFamilyIndex, // queueFamilyIndex;
};
const Unique<VkCommandPool> cmdPool (createCommandPool(vk, vkDevice, &cmdPoolParams));
// Command buffer
const VkCommandBufferAllocateInfo cmdBufParams =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
DE_NULL, // pNext;
*cmdPool, // commandPool;
VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level;
1u, // bufferCount;
};
const Unique<VkCommandBuffer> primCmdBuf (allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
// Secondary Command buffer
const VkCommandBufferAllocateInfo secCmdBufParams =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType;
DE_NULL, // pNext;
*cmdPool, // commandPool;
VK_COMMAND_BUFFER_LEVEL_SECONDARY, // level;
1u, // bufferCount;
};
const Unique<VkCommandBuffer> secCmdBuf (allocateCommandBuffer(vk, vkDevice, &secCmdBufParams));
const VkCommandBufferBeginInfo primCmdBufBeginInfo =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
DE_NULL, // pNext
0u, // flags
(const VkCommandBufferInheritanceInfo*)DE_NULL,
};
const VkCommandBufferInheritanceInfo secCmdBufInheritInfo =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
DE_NULL,
DE_NULL, // renderPass
0u, // subpass
DE_NULL, // framebuffer
VK_FALSE, // occlusionQueryEnable
(VkQueryControlFlags)0u, // queryFlags
(VkQueryPipelineStatisticFlags)0u, // pipelineStatistics
};
const VkCommandBufferBeginInfo secCmdBufBeginInfo =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
DE_NULL, // pNext
0u, // flags
&secCmdBufInheritInfo,
};
// create event that will be used to check if secondary command buffer has been executed
const Unique<VkEvent> event (createEvent(vk, vkDevice));
// reset event
VK_CHECK(vk.resetEvent(vkDevice, *event));
// record secondary command buffer
VK_CHECK(vk.beginCommandBuffer(*secCmdBuf, &secCmdBufBeginInfo));
{
// allow execution of event during every stage of pipeline
VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
// record setting event
vk.cmdSetEvent(*secCmdBuf, *event, stageMask);
}
// end recording of the secondary buffer
endCommandBuffer(vk, *secCmdBuf);
// record primary command buffer
VK_CHECK(vk.beginCommandBuffer(*primCmdBuf, &primCmdBufBeginInfo));
{
// execute secondary buffer
vk.cmdExecuteCommands(*primCmdBuf, 1u, &secCmdBuf.get());
}
endCommandBuffer(vk, *primCmdBuf);
submitCommandsAndWait(vk, vkDevice, queue, primCmdBuf.get());
// check if secondary buffer has been executed
VkResult result = vk.getEventStatus(vkDevice, *event);
if (result == VK_EVENT_SET)
return tcu::TestStatus::pass("executeSecondaryBufferTest succeeded");
return tcu::TestStatus::fail("executeSecondaryBufferTest FAILED");
}
tcu::TestStatus executeSecondaryBufferTwiceTest(Context& context)
{
const deUint32 BUFFER_COUNT = 10u;
const VkDevice vkDevice = context.getDevice();
const DeviceInterface& vk = context.getDeviceInterface();
const VkQueue queue = context.getUniversalQueue();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
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> primCmdBufOne (allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
const Unique<VkCommandBuffer> primCmdBufTwo (allocateCommandBuffer(vk, vkDevice, &cmdBufParams));
// Secondary Command buffers 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;
BUFFER_COUNT, // uint32_t bufferCount;
};
VkCommandBuffer cmdBuffers[BUFFER_COUNT];
VK_CHECK(vk.allocateCommandBuffers(vkDevice, &secCmdBufParams, cmdBuffers));
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,
};
// create event that will be used to check if secondary command buffer has been executed
const Unique<VkEvent> eventOne (createEvent(vk, vkDevice));
// reset event
VK_CHECK(vk.resetEvent(vkDevice, *eventOne));
for (deUint32 ndx = 0; ndx < BUFFER_COUNT; ++ndx)
{
// record secondary command buffer
VK_CHECK(vk.beginCommandBuffer(cmdBuffers[ndx], &secCmdBufBeginInfo));
{
// allow execution of event during every stage of pipeline
VkPipelineStageFlags stageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
// wait for event
vk.cmdWaitEvents(cmdBuffers[ndx], 1, &eventOne.get(), stageMask, stageMask, 0, DE_NULL, 0u, DE_NULL, 0u, DE_NULL);
}
// end recording of secondary buffers
endCommandBuffer(vk, cmdBuffers[ndx]);
}
// record primary command buffer one
VK_CHECK(vk.beginCommandBuffer(*primCmdBufOne, &primCmdBufBeginInfo));
{
// execute one secondary buffer
vk.cmdExecuteCommands(*primCmdBufOne, 1, cmdBuffers );
}
endCommandBuffer(vk, *primCmdBufOne);
// record primary command buffer two
VK_CHECK(vk.beginCommandBuffer(*primCmdBufTwo, &primCmdBufBeginInfo));
{
// execute one secondary buffer with all buffers
vk.cmdExecuteCommands(*primCmdBufTwo, BUFFER_COUNT, cmdBuffers );
}
endCommandBuffer(vk, *primCmdBufTwo);
// create fence to wait for execution of queue
const Unique<VkFence> fenceOne (createFence(vk, vkDevice));
const Unique<VkFence> fenceTwo (createFence(vk, vkDevice));
const VkSubmitInfo submitInfoOne =
{
VK_STRUCTURE_TYPE_SUBMIT_INFO, // sType
DE_NULL, // pNext
0u, // waitSemaphoreCount
DE_NULL, // pWaitSemaphores
(const VkPipelineStageFlags*)DE_NULL, // pWaitDstStageMask
1, // commandBufferCount
&primCmdBufOne.get(), // pCommandBuffers
0u, // signalSemaphoreCount
DE_NULL, // pSignalSemaphores
};
// submit primary buffer, the secondary should be executed too
VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfoOne, *fenceOne));
// wait for buffer to stop at event for 100 microseconds
vk.waitForFences(vkDevice, 1, &fenceOne.get(), 0u, 100000);
const VkSubmitInfo submitInfoTwo =
{
VK_STRUCTURE_TYPE_SUBMIT_INFO, // sType
DE_NULL, // pNext
0u, // waitSemaphoreCount
DE_NULL, // pWaitSemaphores
(const VkPipelineStageFlags*)DE_NULL, // pWaitDstStageMask
1, // commandBufferCount
&primCmdBufTwo.get(), // pCommandBuffers
0u, // signalSemaphoreCount
DE_NULL, // pSignalSemaphores
};
// submit second primary buffer, the secondary should be executed too
VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfoTwo, *fenceTwo));
// wait for all buffers to stop at event for 100 microseconds
vk.waitForFences(vkDevice, 1, &fenceOne.get(), 0u, 100000);
// now all buffers are waiting at eventOne
// set event eventOne
VK_CHECK(vk.setEvent(vkDevice, *eventOne));
// wait for end of execution of fenceOne
VK_CHECK(vk.waitForFences(vkDevice, 1, &fenceOne.get(), 0u, INFINITE_TIMEOUT));
// wait for end of execution of second queue
VK_CHECK(vk.waitForFences(vkDevice, 1, &fenceTwo.get(), 0u, INFINITE_TIMEOUT));
return tcu::TestStatus::pass("executeSecondaryBufferTwiceTest succeeded");
}
/******** 19.6. Commands Allowed Inside Command Buffers (? in VK 1.0 Spec) **/
tcu::TestStatus orderBindPipelineTest(Context& context)
{
const DeviceInterface& vk = context.getDeviceInterface();
const VkDevice device = context.getDevice();
const VkQueue queue = context.getUniversalQueue();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
Allocator& allocator = context.getDefaultAllocator();
const ComputeInstanceResultBuffer result (vk, device, 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 tcu::Vec4 colorB1 = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
const tcu::Vec4 colorB2 = tcu::Vec4(0.0f, 0.0f, 1.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 (createColorDataBuffer(dataOffsetB, bufferSizeB, colorB1, colorB2, &bufferMemB, context));
const Unique<VkDescriptorSetLayout> descriptorSetLayout (createDescriptorSetLayout(context));
const Unique<VkDescriptorPool> descriptorPool (createDescriptorPool(context));
const Unique<VkDescriptorSet> descriptorSet (createDescriptorSet(*descriptorPool, *descriptorSetLayout, *bufferA, viewOffsetA, *bufferB, viewOffsetB, 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, // sType
DE_NULL, // pNext
(VkPipelineLayoutCreateFlags)0,
numDescriptorSets, // setLayoutCount
&descriptorSetLayout.get(), // pSetLayouts
0u, // pushConstantRangeCount
DE_NULL, // pPushConstantRanges
};
Unique<VkPipelineLayout> pipelineLayout (createPipelineLayout(vk, device, &layoutCreateInfo));
const Unique<VkShaderModule> computeModuleGood (createShaderModule(vk, device, context.getBinaryCollection().get("compute_good"), (VkShaderModuleCreateFlags)0u));
const Unique<VkShaderModule> computeModuleBad (createShaderModule(vk, device, context.getBinaryCollection().get("compute_bad"), (VkShaderModuleCreateFlags)0u));
const VkPipelineShaderStageCreateInfo shaderCreateInfoGood =
{
VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
DE_NULL,
(VkPipelineShaderStageCreateFlags)0,
VK_SHADER_STAGE_COMPUTE_BIT, // stage
*computeModuleGood, // shader
"main",
DE_NULL, // pSpecializationInfo
};
const VkPipelineShaderStageCreateInfo shaderCreateInfoBad =
{
VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
DE_NULL,
(vk::VkPipelineShaderStageCreateFlags)0,
vk::VK_SHADER_STAGE_COMPUTE_BIT, // stage
*computeModuleBad, // shader
"main",
DE_NULL, // pSpecializationInfo
};
const VkComputePipelineCreateInfo createInfoGood =
{
VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
DE_NULL,
0u, // flags
shaderCreateInfoGood, // cs
*pipelineLayout, // layout
(vk::VkPipeline)0, // basePipelineHandle
0u, // basePipelineIndex
};
const VkComputePipelineCreateInfo createInfoBad =
{
VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
DE_NULL,
0u, // flags
shaderCreateInfoBad, // cs
*pipelineLayout, // descriptorSetLayout.get()
(VkPipeline)0, // basePipelineHandle
0u, // basePipelineIndex
};
const Unique<VkPipeline> pipelineGood (createComputePipeline(vk, device, (VkPipelineCache)0u, &createInfoGood));
const Unique<VkPipeline> pipelineBad (createComputePipeline(vk, device, (VkPipelineCache)0u, &createInfoBad));
const VkAccessFlags inputBit = (VK_ACCESS_UNIFORM_READ_BIT);
const VkBufferMemoryBarrier bufferBarriers[] =
{
{
VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
DE_NULL,
VK_ACCESS_HOST_WRITE_BIT, // srcAccessMask
inputBit, // dstAccessMask
VK_QUEUE_FAMILY_IGNORED, // srcQueueFamilyIndex
VK_QUEUE_FAMILY_IGNORED, // destQueueFamilyIndex
*bufferA, // buffer
(VkDeviceSize)0u, // offset
(VkDeviceSize)bufferSizeA, // size
},
{
VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
DE_NULL,
VK_ACCESS_HOST_WRITE_BIT, // srcAccessMask
inputBit, // dstAccessMask
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 int numPreBarriers = numSrcBuffers;
const vk::VkBufferMemoryBarrier* const postBarriers = result.getResultReadBarrier();
const int numPostBarriers = 1;
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 numWorkGroups = tcu::UVec3(4, 1u, 1);
const VkCommandPoolCreateInfo cmdPoolCreateInfo =
{
VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType;
DE_NULL, // pNext
VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // flags
queueFamilyIndex, // queueFamilyIndex
};
const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, &cmdPoolCreateInfo));
const VkCommandBufferAllocateInfo cmdBufCreateInfo =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType
DE_NULL, // pNext
*cmdPool, // commandPool
VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level
1u, // bufferCount;
};
const VkCommandBufferBeginInfo cmdBufBeginInfo =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // sType
DE_NULL, // pNext
0u, // flags
(const VkCommandBufferInheritanceInfo*)DE_NULL,
};
const Unique<VkCommandBuffer> cmd (allocateCommandBuffer(vk, device, &cmdBufCreateInfo));
VK_CHECK(vk.beginCommandBuffer(*cmd, &cmdBufBeginInfo));
vk.cmdBindPipeline(*cmd, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineBad);
vk.cmdBindPipeline(*cmd, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineGood);
vk.cmdBindDescriptorSets(*cmd, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0, numDescriptorSets, descriptorSets, numDynamicOffsets, dynamicOffsets);
if (numPreBarriers)
vk.cmdPipelineBarrier(*cmd, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0,
0, (const VkMemoryBarrier*)DE_NULL,
numPreBarriers, bufferBarriers,
0, (const VkImageMemoryBarrier*)DE_NULL);
vk.cmdDispatch(*cmd, numWorkGroups.x(), numWorkGroups.y(), numWorkGroups.z());
vk.cmdPipelineBarrier(*cmd, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0,
0, (const VkMemoryBarrier*)DE_NULL,
numPostBarriers, postBarriers,
0, (const VkImageMemoryBarrier*)DE_NULL);
endCommandBuffer(vk, *cmd);
// run
// submit second primary buffer, the secondary should be executed too
submitCommandsAndWait(vk, device, queue, cmd.get());
// submit and wait end
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");
}
}
enum StateTransitionTest
{
STT_RECORDING_TO_INITIAL = 0,
STT_EXECUTABLE_TO_INITIAL,
STT_RECORDING_TO_INVALID,
STT_EXECUTABLE_TO_INVALID,
};
tcu::TestStatus executeStateTransitionTest(Context& context, StateTransitionTest type)
{
const VkDevice vkDevice = context.getDevice();
const DeviceInterface& vk = context.getDeviceInterface();
const VkQueue queue = context.getUniversalQueue();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
const Unique<VkCommandPool> cmdPool (createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer(vk, vkDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
const Unique<VkEvent> globalEvent (createEvent(vk, vkDevice));
VK_CHECK(vk.resetEvent(vkDevice, *globalEvent));
switch (type)
{
case STT_RECORDING_TO_INITIAL:
{
beginCommandBuffer(vk, *cmdBuffer, 0u);
vk.cmdSetEvent(*cmdBuffer, *globalEvent, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
break;
// command buffer is still in recording state
}
case STT_EXECUTABLE_TO_INITIAL:
{
beginCommandBuffer(vk, *cmdBuffer, 0u);
vk.cmdSetEvent(*cmdBuffer, *globalEvent, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
endCommandBuffer(vk, *cmdBuffer);
break;
// command buffer is still in executable state
}
case STT_RECORDING_TO_INVALID:
{
VkSubpassDescription subpassDescription;
deMemset(&subpassDescription, 0, sizeof(VkSubpassDescription));
subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
VkRenderPassCreateInfo renderPassCreateInfo
{
VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
DE_NULL, 0, 0, DE_NULL,
1, &subpassDescription, 0, DE_NULL
};
// Error here - renderpass and framebuffer were created localy
Move <VkRenderPass> renderPass = createRenderPass(vk, vkDevice, &renderPassCreateInfo);
VkFramebufferCreateInfo framebufferCreateInfo
{
VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, DE_NULL,
0, *renderPass, 0, DE_NULL, 16, 16, 1
};
Move <VkFramebuffer> framebuffer = createFramebuffer(vk, vkDevice, &framebufferCreateInfo);
VkRenderPassBeginInfo renderPassBeginInfo =
{
VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
DE_NULL, *renderPass, *framebuffer, { { 0, 0 }, { 16, 16 } },
0, DE_NULL
};
beginCommandBuffer(vk, *cmdBuffer, 0u);
vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
vk.cmdEndRenderPass(*cmdBuffer);
// not executing endCommandBuffer(vk, *cmdBuffer);
// command buffer is still in recording state
break;
// renderpass and framebuffer are destroyed; command buffer should be now in invalid state
}
case STT_EXECUTABLE_TO_INVALID:
{
// create event that will be used to check if command buffer has been executed
const Unique<VkEvent> localEvent(createEvent(vk, vkDevice));
VK_CHECK(vk.resetEvent(vkDevice, *localEvent));
beginCommandBuffer(vk, *cmdBuffer, 0u);
vk.cmdSetEvent(*cmdBuffer, *localEvent, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
endCommandBuffer(vk, *cmdBuffer);
// command buffer is in executable state
break;
// localEvent is destroyed; command buffer should be now in invalid state
}
}
VK_CHECK(vk.resetEvent(vkDevice, *globalEvent));
vk.resetCommandBuffer(*cmdBuffer, 0u);
// command buffer should now be back in initial state
// verify commandBuffer
beginCommandBuffer(vk, *cmdBuffer, 0u);
vk.cmdSetEvent(*cmdBuffer, *globalEvent, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
endCommandBuffer(vk, *cmdBuffer);
submitCommandsAndWait(vk, vkDevice, queue, *cmdBuffer);
// check if buffer has been executed
VkResult result = vk.getEventStatus(vkDevice, *globalEvent);
if (result != VK_EVENT_SET)
return tcu::TestStatus::fail("Submit failed");
return tcu::TestStatus::pass("Pass");
}
// Shaders
void genComputeSource (SourceCollections& programCollection)
{
const char* const versionDecl = glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
std::ostringstream bufGood;
bufGood << versionDecl << "\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"
<< " 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(bufGood.str());
std::ostringstream bufBad;
bufBad << versionDecl << "\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"
<< " 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(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());
}
void genComputeIncrementSourceBadInheritance(SourceCollections& programCollection, BadInheritanceInfoCase testCase)
{
DE_UNREF(testCase);
return genComputeIncrementSource(programCollection);
}
void checkEventSupport (Context& context)
{
#ifndef CTS_USES_VULKANSC
if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") && !context.getPortabilitySubsetFeatures().events)
TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Events are not supported by this implementation");
#else
DE_UNREF(context);
#endif // CTS_USES_VULKANSC
}
void checkCommandBufferSimultaneousUseSupport(Context& context)
{
#ifdef CTS_USES_VULKANSC
if(context.getDeviceVulkanSC10Properties().commandBufferSimultaneousUse == VK_FALSE)
TCU_THROW(NotSupportedError, "commandBufferSimultaneousUse is not supported");
#else
DE_UNREF(context);
#endif // CTS_USES_VULKANSC
}
void checkSecondaryCommandBufferNullOrImagelessFramebufferSupport(Context& context)
{
#ifdef CTS_USES_VULKANSC
if (context.getDeviceVulkanSC10Properties().secondaryCommandBufferNullOrImagelessFramebuffer == VK_FALSE)
TCU_THROW(NotSupportedError, "secondaryCommandBufferNullFramebuffer is not supported");
#else
DE_UNREF(context);
#endif // CTS_USES_VULKANSC
}
void checkSecondaryCommandBufferNullOrImagelessFramebufferSupport1(Context& context, bool value)
{
DE_UNREF(value);
#ifdef CTS_USES_VULKANSC
if (context.getDeviceVulkanSC10Properties().secondaryCommandBufferNullOrImagelessFramebuffer == VK_FALSE)
TCU_THROW(NotSupportedError, "secondaryCommandBufferNullFramebuffer is not supported");
#else
DE_UNREF(context);
#endif // CTS_USES_VULKANSC
}
void checkEventAndCommandBufferSimultaneousUseSupport(Context& context)
{
checkEventSupport(context);
checkCommandBufferSimultaneousUseSupport(context);
}
void checkEventAndSecondaryCommandBufferNullFramebufferSupport(Context& context)
{
checkEventSupport(context);
checkSecondaryCommandBufferNullOrImagelessFramebufferSupport(context);
}
void checkSimultaneousUseAndSecondaryCommandBufferNullFramebufferSupport(Context& context)
{
checkCommandBufferSimultaneousUseSupport(context);
checkSecondaryCommandBufferNullOrImagelessFramebufferSupport(context);
}
void checkEventAndSimultaneousUseAndSecondaryCommandBufferNullFramebufferSupport(Context& context)
{
checkEventSupport(context);
checkCommandBufferSimultaneousUseSupport(context);
checkSecondaryCommandBufferNullOrImagelessFramebufferSupport(context);
}
#ifndef CTS_USES_VULKANSC
void checkEventSupport (Context& context, const VkCommandBufferLevel)
{
checkEventSupport(context);
}
#endif // CTS_USES_VULKANSC
struct ManyDrawsParams
{
VkCommandBufferLevel level;
VkExtent3D imageExtent;
deUint32 seed;
ManyDrawsParams(VkCommandBufferLevel level_, const VkExtent3D& extent_, deUint32 seed_)
: level (level_)
, imageExtent (extent_)
, seed (seed_)
{}
};
struct ManyDrawsVertex
{
using Color = tcu::Vector<deUint8, 4>;
tcu::Vec2 coords;
Color color;
ManyDrawsVertex (const tcu::Vec2& coords_, const Color& color_) : coords(coords_), color(color_) {}
};
VkFormat getSupportedDepthStencilFormat (const InstanceInterface& vki, VkPhysicalDevice physDev)
{
const VkFormat formatList[] = { VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT };
const VkFormatFeatureFlags requirements = (VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_FORMAT_FEATURE_TRANSFER_SRC_BIT);
for (int i = 0; i < DE_LENGTH_OF_ARRAY(formatList); ++i)
{
const auto properties = getPhysicalDeviceFormatProperties(vki, physDev, formatList[i]);
if ((properties.optimalTilingFeatures & requirements) == requirements)
return formatList[i];
}
TCU_THROW(NotSupportedError, "No suitable depth/stencil format support");
return VK_FORMAT_UNDEFINED;
}
class ManyDrawsCase : public TestCase
{
public:
ManyDrawsCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const ManyDrawsParams& params);
virtual ~ManyDrawsCase (void) {}
virtual void checkSupport (Context& context) const;
virtual void initPrograms (vk::SourceCollections& programCollection) const;
virtual TestInstance* createInstance (Context& context) const;
static VkFormat getColorFormat (void) { return VK_FORMAT_R8G8B8A8_UINT; }
protected:
ManyDrawsParams m_params;
};
class ManyDrawsInstance : public TestInstance
{
public:
ManyDrawsInstance (Context& context, const ManyDrawsParams& params);
virtual ~ManyDrawsInstance (void) {}
virtual tcu::TestStatus iterate (void);
protected:
ManyDrawsParams m_params;
};
using BufferPtr = de::MovePtr<BufferWithMemory>;
using ImagePtr = de::MovePtr<ImageWithMemory>;
struct ManyDrawsVertexBuffers
{
BufferPtr stagingBuffer;
BufferPtr vertexBuffer;
};
struct ManyDrawsAllocatedData
{
ManyDrawsVertexBuffers frontBuffers;
ManyDrawsVertexBuffers backBuffers;
ImagePtr colorAttachment;
ImagePtr dsAttachment;
BufferPtr colorCheckBuffer;
BufferPtr stencilCheckBuffer;
static deUint32 calcNumPixels (const VkExtent3D& extent)
{
DE_ASSERT(extent.depth == 1u);
return (extent.width * extent.height);
}
static deUint32 calcNumVertices (const VkExtent3D& extent)
{
// One triangle (3 vertices) per output image pixel.
return (calcNumPixels(extent) * 3u);
}
static VkDeviceSize calcVertexBufferSize (const VkExtent3D& extent)
{
return calcNumVertices(extent) * sizeof(ManyDrawsVertex);
}
static void makeVertexBuffers (const DeviceInterface& vkd, VkDevice device, Allocator& alloc, VkDeviceSize size, ManyDrawsVertexBuffers& buffers)
{
const auto stagingBufferInfo = makeBufferCreateInfo(size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
const auto vertexBufferInfo = makeBufferCreateInfo(size, (VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
buffers.stagingBuffer = BufferPtr(new BufferWithMemory(vkd, device, alloc, stagingBufferInfo, MemoryRequirement::HostVisible));
buffers.vertexBuffer = BufferPtr(new BufferWithMemory(vkd, device, alloc, vertexBufferInfo, MemoryRequirement::Any));
}
ManyDrawsAllocatedData (const DeviceInterface &vkd, VkDevice device, Allocator &alloc, const VkExtent3D& imageExtent, VkFormat colorFormat, VkFormat dsFormat)
{
const auto numPixels = calcNumPixels(imageExtent);
const auto vertexBufferSize = calcVertexBufferSize(imageExtent);
makeVertexBuffers(vkd, device, alloc, vertexBufferSize, frontBuffers);
makeVertexBuffers(vkd, device, alloc, vertexBufferSize, backBuffers);
const auto colorUsage = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
const auto dsUsage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
const VkImageCreateInfo colorAttachmentInfo =
{
VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
nullptr, // const void* pNext;
0u, // VkImageCreateFlags flags;
VK_IMAGE_TYPE_2D, // VkImageType imageType;
colorFormat, // VkFormat format;
imageExtent, // VkExtent3D extent;
1u, // deUint32 mipLevels;
1u, // deUint32 arrayLayers;
VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
colorUsage, // VkImageUsageFlags usage;
VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
0u, // deUint32 queueFamilyIndexCount;
nullptr, // const deUint32* pQueueFamilyIndices;
VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
};
colorAttachment = ImagePtr(new ImageWithMemory(vkd, device, alloc, colorAttachmentInfo, MemoryRequirement::Any));
const VkImageCreateInfo dsAttachmentInfo =
{
VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
nullptr, // const void* pNext;
0u, // VkImageCreateFlags flags;
VK_IMAGE_TYPE_2D, // VkImageType imageType;
dsFormat, // VkFormat format;
imageExtent, // VkExtent3D extent;
1u, // deUint32 mipLevels;
1u, // deUint32 arrayLayers;
VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
dsUsage, // VkImageUsageFlags usage;
VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
0u, // deUint32 queueFamilyIndexCount;
nullptr, // const deUint32* pQueueFamilyIndices;
VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
};
dsAttachment = ImagePtr(new ImageWithMemory(vkd, device, alloc, dsAttachmentInfo, MemoryRequirement::Any));
const auto colorCheckBufferSize = static_cast<VkDeviceSize>(numPixels * tcu::getPixelSize(mapVkFormat(colorFormat)));
const auto colorCheckBufferInfo = makeBufferCreateInfo(colorCheckBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
colorCheckBuffer = BufferPtr(new BufferWithMemory(vkd, device, alloc, colorCheckBufferInfo, MemoryRequirement::HostVisible));
const auto stencilFormat = tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT8);
const auto stencilCheckBufferSize = static_cast<VkDeviceSize>(numPixels * tcu::getPixelSize(stencilFormat));
const auto stencilCheckBufferInfo = makeBufferCreateInfo(stencilCheckBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
stencilCheckBuffer = BufferPtr(new BufferWithMemory(vkd, device, alloc, stencilCheckBufferInfo, MemoryRequirement::HostVisible));
}
};
ManyDrawsCase::ManyDrawsCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description, const ManyDrawsParams& params)
: TestCase (testCtx, name, description)
, m_params (params)
{}
void ManyDrawsCase::checkSupport (Context& context) const
{
const auto& vki = context.getInstanceInterface();
const auto physDev = context.getPhysicalDevice();
const auto& vkd = context.getDeviceInterface();
const auto device = context.getDevice();
auto& alloc = context.getDefaultAllocator();
const auto dsFormat = getSupportedDepthStencilFormat(vki, physDev);
try
{
ManyDrawsAllocatedData allocatedData(vkd, device, alloc, m_params.imageExtent, getColorFormat(), dsFormat);
}
catch (const vk::Error& err)
{
const auto result = err.getError();
if (result == VK_ERROR_OUT_OF_HOST_MEMORY || result == VK_ERROR_OUT_OF_DEVICE_MEMORY)
TCU_THROW(NotSupportedError, "Not enough memory to run this test");
throw;
}
}
void ManyDrawsCase::initPrograms (vk::SourceCollections& programCollection) const
{
std::ostringstream vert;
vert
<< "#version 450\n"
<< "\n"
<< "layout(location=0) in vec2 inCoords;\n"
<< "layout(location=1) in uvec4 inColor;\n"
<< "\n"
<< "layout(location=0) out flat uvec4 outColor;\n"
<< "\n"
<< "void main()\n"
<< "{\n"
<< " gl_Position = vec4(inCoords, 0.0, 1.0);\n"
<< " outColor = inColor;\n"
<< "}\n"
;
std::ostringstream frag;
frag
<< "#version 450\n"
<< "\n"
<< "layout(location=0) in flat uvec4 inColor;\n"
<< "layout(location=0) out uvec4 outColor;\n"
<< "\n"
<< "void main()\n"
<< "{\n"
<< " outColor = inColor;\n"
<< "}\n"
;
programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
}
TestInstance* ManyDrawsCase::createInstance (Context& context) const
{
return new ManyDrawsInstance(context, m_params);
}
ManyDrawsInstance::ManyDrawsInstance (Context& context, const ManyDrawsParams& params)
: TestInstance (context)
, m_params (params)
{}
void copyAndFlush (const DeviceInterface& vkd, VkDevice device, BufferWithMemory& buffer, const std::vector<ManyDrawsVertex>& vertices)
{
auto& alloc = buffer.getAllocation();
void* hostPtr = alloc.getHostPtr();
deMemcpy(hostPtr, vertices.data(), de::dataSize(vertices));
flushAlloc(vkd, device, alloc);
}
tcu::TestStatus ManyDrawsInstance::iterate (void)
{
const auto& vki = m_context.getInstanceInterface();
const auto physDev = m_context.getPhysicalDevice();
const auto& vkd = m_context.getDeviceInterface();
const auto device = m_context.getDevice();
auto& alloc = m_context.getDefaultAllocator();
const auto qIndex = m_context.getUniversalQueueFamilyIndex();
const auto queue = m_context.getUniversalQueue();
const auto colorFormat = ManyDrawsCase::getColorFormat();
const auto dsFormat = getSupportedDepthStencilFormat(vki, physDev);
const auto vertexBufferSize = ManyDrawsAllocatedData::calcVertexBufferSize(m_params.imageExtent);
const auto vertexBufferOffset = static_cast<VkDeviceSize>(0);
const auto numPixels = ManyDrawsAllocatedData::calcNumPixels(m_params.imageExtent);
const auto numVertices = ManyDrawsAllocatedData::calcNumVertices(m_params.imageExtent);
const auto alphaValue = std::numeric_limits<deUint8>::max();
const auto pixelWidth = 2.0f / static_cast<float>(m_params.imageExtent.width); // Normalized size.
const auto pixelWidthHalf = pixelWidth / 2.0f; // Normalized size.
const auto pixelHeight = 2.0f / static_cast<float>(m_params.imageExtent.height); // Normalized size.
const auto useSecondary = (m_params.level == VK_COMMAND_BUFFER_LEVEL_SECONDARY);
// Allocate all needed data up front.
ManyDrawsAllocatedData testData(vkd, device, alloc, m_params.imageExtent, colorFormat, dsFormat);
// Generate random colors.
de::Random rnd(m_params.seed);
std::vector<ManyDrawsVertex::Color> colors;
colors.reserve(numPixels);
for (deUint32 i = 0; i < numPixels; ++i)
{
#if 0
const deUint8 red = ((i ) & 0xFFu);
const deUint8 green = ((i >> 8) & 0xFFu);
const deUint8 blue = ((i >> 16) & 0xFFu);
colors.push_back(ManyDrawsVertex::Color(red, green, blue, alphaValue));
#else
colors.push_back(ManyDrawsVertex::Color(rnd.getUint8(), rnd.getUint8(), rnd.getUint8(), alphaValue));
#endif
}
// Fill vertex data. One triangle per pixel, front and back.
std::vector<ManyDrawsVertex> frontVector;
std::vector<ManyDrawsVertex> backVector;
frontVector.reserve(numVertices);
backVector.reserve(numVertices);
for (deUint32 y = 0; y < m_params.imageExtent.height; ++y)
for (deUint32 x = 0; x < m_params.imageExtent.width; ++x)
{
float x_left = static_cast<float>(x) * pixelWidth - 1.0f;
float x_mid = x_left + pixelWidthHalf;
float x_right = x_left + pixelWidth;
float y_top = static_cast<float>(y) * pixelHeight - 1.0f;
float y_bottom = y_top + pixelHeight;
// Triangles in the "back" mesh will have different colors.
const auto colorIdx = y * m_params.imageExtent.width + x;
const auto& frontColor = colors[colorIdx];
const auto& backColor = colors[colors.size() - 1u - colorIdx];
const tcu::Vec2 triangle[3u] =
{
tcu::Vec2(x_left, y_top),
tcu::Vec2(x_right, y_top),
tcu::Vec2(x_mid, y_bottom),
};
frontVector.emplace_back(triangle[0], frontColor);
frontVector.emplace_back(triangle[1], frontColor);
frontVector.emplace_back(triangle[2], frontColor);
backVector.emplace_back(triangle[0], backColor);
backVector.emplace_back(triangle[1], backColor);
backVector.emplace_back(triangle[2], backColor);
}
// Copy vertex data to staging buffers.
copyAndFlush(vkd, device, *testData.frontBuffers.stagingBuffer, frontVector);
copyAndFlush(vkd, device, *testData.backBuffers.stagingBuffer, backVector);
// Color attachment view.
const auto colorResourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
const auto colorAttachmentView = makeImageView(vkd, device, testData.colorAttachment->get(), VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorResourceRange);
// Depth/stencil attachment view.
const auto dsResourceRange = makeImageSubresourceRange((VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT), 0u, 1u, 0u, 1u);
const auto dsAttachmentView = makeImageView(vkd, device, testData.dsAttachment->get(), VK_IMAGE_VIEW_TYPE_2D, dsFormat, dsResourceRange);
const VkImageView attachmentArray[] = { colorAttachmentView.get(), dsAttachmentView.get() };
const auto numAttachments = static_cast<deUint32>(DE_LENGTH_OF_ARRAY(attachmentArray));
const auto renderPass = makeRenderPass(vkd, device, colorFormat, dsFormat);
const auto framebuffer = makeFramebuffer(vkd, device, renderPass.get(), numAttachments, attachmentArray, m_params.imageExtent.width, m_params.imageExtent.height);
const auto vertModule = createShaderModule(vkd, device, m_context.getBinaryCollection().get("vert"), 0u);
const auto fragModule = createShaderModule(vkd, device, m_context.getBinaryCollection().get("frag"), 0u);
const std::vector<VkViewport> viewports (1u, makeViewport(m_params.imageExtent));
const std::vector<VkRect2D> scissors (1u, makeRect2D(m_params.imageExtent));
const auto descriptorSetLayout = DescriptorSetLayoutBuilder().build(vkd, device);
const auto pipelineLayout = makePipelineLayout(vkd, device, descriptorSetLayout.get());
const VkVertexInputBindingDescription bindings[] =
{
makeVertexInputBindingDescription(0u, static_cast<deUint32>(sizeof(ManyDrawsVertex)), VK_VERTEX_INPUT_RATE_VERTEX),
};
const VkVertexInputAttributeDescription attributes[] =
{
makeVertexInputAttributeDescription(0u, 0u, VK_FORMAT_R32G32_SFLOAT, static_cast<deUint32>(offsetof(ManyDrawsVertex, coords))),
makeVertexInputAttributeDescription(1u, 0u, VK_FORMAT_R8G8B8A8_UINT, static_cast<deUint32>(offsetof(ManyDrawsVertex, color))),
};
const VkPipelineVertexInputStateCreateInfo inputState =
{
VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
nullptr, // const void* pNext;
0u, // VkPipelineVertexInputStateCreateFlags flags;
static_cast<deUint32>(DE_LENGTH_OF_ARRAY(bindings)), // deUint32 vertexBindingDescriptionCount;
bindings, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
static_cast<deUint32>(DE_LENGTH_OF_ARRAY(attributes)), // deUint32 vertexAttributeDescriptionCount;
attributes, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
};
// Stencil state: this is key for checking and obtaining the right results. The stencil buffer will be cleared to 0. The first
// set of draws ("front" set of triangles) will pass the test and increment the stencil value to 1. The second set of draws
// ("back" set of triangles, not really in the back because all of them have depth 0.0) will not pass the stencil test then, but
// still increment the stencil value to 2.
//
// At the end of the test, if every draw command was executed correctly in the expected order, the color buffer will have the
// colors of the front set, and the stencil buffer will be full of 2s.
const auto stencilOpState = makeStencilOpState(VK_STENCIL_OP_INCREMENT_AND_CLAMP, VK_STENCIL_OP_INCREMENT_AND_CLAMP, VK_STENCIL_OP_KEEP,
VK_COMPARE_OP_EQUAL, 0xFFu, 0xFFu, 0u);
const VkPipelineDepthStencilStateCreateInfo dsState =
{
VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType
nullptr, // const void* pNext
0u, // VkPipelineDepthStencilStateCreateFlags flags
VK_FALSE, // VkBool32 depthTestEnable
VK_FALSE, // VkBool32 depthWriteEnable
VK_COMPARE_OP_NEVER, // VkCompareOp depthCompareOp
VK_FALSE, // VkBool32 depthBoundsTestEnable
VK_TRUE, // VkBool32 stencilTestEnable
stencilOpState, // VkStencilOpState front
stencilOpState, // VkStencilOpState back
0.0f, // float minDepthBounds
1.0f, // float maxDepthBounds
};
const auto pipeline = makeGraphicsPipeline(vkd, device, pipelineLayout.get(),
vertModule.get(), DE_NULL, DE_NULL, DE_NULL, fragModule.get(),
renderPass.get(), viewports, scissors, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0u, 0u,
&inputState, nullptr, nullptr, &dsState);
// Command pool and buffers.
using CmdBufferPtr = Move<VkCommandBuffer>;
const auto cmdPool = makeCommandPool(vkd, device, qIndex);
const auto secCmdPool = makeCommandPool(vkd, device, qIndex);
CmdBufferPtr primaryCmdBufferPtr;
CmdBufferPtr secondaryCmdBufferPtr;
VkCommandBuffer primaryCmdBuffer;
VkCommandBuffer secondaryCmdBuffer;
VkCommandBuffer drawsCmdBuffer;
primaryCmdBufferPtr = allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
primaryCmdBuffer = primaryCmdBufferPtr.get();
drawsCmdBuffer = primaryCmdBuffer;
beginCommandBuffer(vkd, primaryCmdBuffer);
// Clear values.
std::vector<VkClearValue> clearValues(2u);
clearValues[0] = makeClearValueColorU32(0u, 0u, 0u, 0u);
clearValues[1] = makeClearValueDepthStencil(1.0f, 0u);
// Copy staging buffers to vertex buffers.
const auto copyRegion = makeBufferCopy(0ull, 0ull, vertexBufferSize);
vkd.cmdCopyBuffer(primaryCmdBuffer, testData.frontBuffers.stagingBuffer->get(), testData.frontBuffers.vertexBuffer->get(), 1u, &copyRegion);
vkd.cmdCopyBuffer(primaryCmdBuffer, testData.backBuffers.stagingBuffer->get(), testData.backBuffers.vertexBuffer->get(), 1u, &copyRegion);
// Use barrier for vertex reads.
const auto vertexBarier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT);
vkd.cmdPipelineBarrier(primaryCmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0u, 1u, &vertexBarier, 0u, nullptr, 0u, nullptr);
// Change depth/stencil attachment layout.
const auto dsBarrier = makeImageMemoryBarrier(0, (VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, testData.dsAttachment->get(), dsResourceRange);
vkd.cmdPipelineBarrier(primaryCmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, (VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT), 0u, 0u, nullptr, 0u, nullptr, 1u, &dsBarrier);
beginRenderPass(vkd, primaryCmdBuffer, renderPass.get(), framebuffer.get(),
scissors[0], static_cast<deUint32>(clearValues.size()), clearValues.data(),
(useSecondary ? VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS : VK_SUBPASS_CONTENTS_INLINE));
if (useSecondary)
{
secondaryCmdBufferPtr = allocateCommandBuffer(vkd, device, secCmdPool.get(), VK_COMMAND_BUFFER_LEVEL_SECONDARY);
secondaryCmdBuffer = secondaryCmdBufferPtr.get();
drawsCmdBuffer = secondaryCmdBuffer;
const VkCommandBufferInheritanceInfo inheritanceInfo =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, // VkStructureType sType;
nullptr, // const void* pNext;
renderPass.get(), // VkRenderPass renderPass;
0u, // deUint32 subpass;
framebuffer.get(), // VkFramebuffer framebuffer;
0u, // VkBool32 occlusionQueryEnable;
0u, // VkQueryControlFlags queryFlags;
0u, // VkQueryPipelineStatisticFlags pipelineStatistics;
};
const VkCommandBufferUsageFlags usageFlags = (VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT | VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
const VkCommandBufferBeginInfo beginInfo =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
nullptr,
usageFlags, // VkCommandBufferUsageFlags flags;
&inheritanceInfo, // const VkCommandBufferInheritanceInfo* pInheritanceInfo;
};
VK_CHECK(vkd.beginCommandBuffer(secondaryCmdBuffer, &beginInfo));
}
// Bind pipeline.
vkd.cmdBindPipeline(drawsCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
// Draw triangles in front.
vkd.cmdBindVertexBuffers(drawsCmdBuffer, 0u, 1u, &testData.frontBuffers.vertexBuffer->get(), &vertexBufferOffset);
for (deUint32 i = 0; i < numPixels; ++i)
vkd.cmdDraw(drawsCmdBuffer, 3u, 1u, i*3u, 0u);
// Draw triangles in the "back". This should have no effect due to the stencil test.
vkd.cmdBindVertexBuffers(drawsCmdBuffer, 0u, 1u, &testData.backBuffers.vertexBuffer->get(), &vertexBufferOffset);
for (deUint32 i = 0; i < numPixels; ++i)
vkd.cmdDraw(drawsCmdBuffer, 3u, 1u, i*3u, 0u);
if (useSecondary)
{
endCommandBuffer(vkd, secondaryCmdBuffer);
vkd.cmdExecuteCommands(primaryCmdBuffer, 1u, &secondaryCmdBuffer);
}
endRenderPass(vkd, primaryCmdBuffer);
// Copy color and depth/stencil attachments to verification buffers.
const auto colorAttachmentBarrier = makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, testData.colorAttachment->get(), colorResourceRange);
vkd.cmdPipelineBarrier(primaryCmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &colorAttachmentBarrier);
const auto colorResourceLayers = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
const auto colorCopyRegion = makeBufferImageCopy(m_params.imageExtent, colorResourceLayers);
vkd.cmdCopyImageToBuffer(primaryCmdBuffer, testData.colorAttachment->get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, testData.colorCheckBuffer->get(), 1u, &colorCopyRegion);
const auto stencilAttachmentBarrier = makeImageMemoryBarrier(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, testData.dsAttachment->get(), dsResourceRange);
vkd.cmdPipelineBarrier(primaryCmdBuffer, (VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT), VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &stencilAttachmentBarrier);
const auto stencilResourceLayers = makeImageSubresourceLayers(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 0u, 1u);
const auto stencilCopyRegion = makeBufferImageCopy(m_params.imageExtent, stencilResourceLayers);
vkd.cmdCopyImageToBuffer(primaryCmdBuffer, testData.dsAttachment->get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, testData.stencilCheckBuffer->get(), 1u, &stencilCopyRegion);
const auto verificationBuffersBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
vkd.cmdPipelineBarrier(primaryCmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &verificationBuffersBarrier, 0u, nullptr, 0u, nullptr);
endCommandBuffer(vkd, primaryCmdBuffer);
submitCommandsAndWait(vkd, device, queue, primaryCmdBuffer);
// Check buffer contents.
auto& colorCheckBufferAlloc = testData.colorCheckBuffer->getAllocation();
void* colorCheckBufferData = colorCheckBufferAlloc.getHostPtr();
invalidateAlloc(vkd, device, colorCheckBufferAlloc);
auto& stencilCheckBufferAlloc = testData.stencilCheckBuffer->getAllocation();
void* stencilCheckBufferData = stencilCheckBufferAlloc.getHostPtr();
invalidateAlloc(vkd, device, stencilCheckBufferAlloc);
const auto iWidth = static_cast<int>(m_params.imageExtent.width);
const auto iHeight = static_cast<int>(m_params.imageExtent.height);
const auto colorTcuFormat = mapVkFormat(colorFormat);
const auto stencilTcuFormat = tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT8);
tcu::TextureLevel referenceLevel (colorTcuFormat, iWidth, iHeight);
tcu::PixelBufferAccess referenceAccess = referenceLevel.getAccess();
tcu::TextureLevel colorErrorLevel (mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM), iWidth, iHeight);
tcu::PixelBufferAccess colorErrorAccess = colorErrorLevel.getAccess();
tcu::TextureLevel stencilErrorLevel (mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM), iWidth, iHeight);
tcu::PixelBufferAccess stencilErrorAccess = stencilErrorLevel.getAccess();
tcu::ConstPixelBufferAccess colorAccess (colorTcuFormat, iWidth, iHeight, 1, colorCheckBufferData);
tcu::ConstPixelBufferAccess stencilAccess (stencilTcuFormat, iWidth, iHeight, 1, stencilCheckBufferData);
const tcu::Vec4 green (0.0f, 1.0f, 0.0f, 1.0f);
const tcu::Vec4 red (1.0f, 0.0f, 0.0f, 1.0f);
const int expectedStencil = 2;
bool colorFail = false;
bool stencilFail = false;
for (int y = 0; y < iHeight; ++y)
for (int x = 0; x < iWidth; ++x)
{
const tcu::UVec4 colorValue = colorAccess.getPixelUint(x, y);
const auto expectedPixel = colors[y * iWidth + x];
const tcu::UVec4 expectedValue (expectedPixel.x(), expectedPixel.y(), expectedPixel.z(), expectedPixel.w());
const bool colorMismatch = (colorValue != expectedValue);
const auto stencilValue = stencilAccess.getPixStencil(x, y);
const bool stencilMismatch = (stencilValue != expectedStencil);
referenceAccess.setPixel(expectedValue, x, y);
colorErrorAccess.setPixel((colorMismatch ? red : green), x, y);
stencilErrorAccess.setPixel((stencilMismatch ? red : green), x, y);
if (stencilMismatch)
stencilFail = true;
if (colorMismatch)
colorFail = true;
}
if (colorFail || stencilFail)
{
auto& log = m_context.getTestContext().getLog();
log
<< tcu::TestLog::ImageSet("Result", "")
<< tcu::TestLog::Image("ColorOutput", "", colorAccess)
<< tcu::TestLog::Image("ColorReference", "", referenceAccess)
<< tcu::TestLog::Image("ColorError", "", colorErrorAccess)
<< tcu::TestLog::Image("StencilError", "", stencilErrorAccess)
<< tcu::TestLog::EndImageSet
;
TCU_FAIL("Mismatched output and reference color or stencil; please check test log --");
}
return tcu::TestStatus::pass("Pass");
}
} // anonymous
tcu::TestCaseGroup* createCommandBuffersTests (tcu::TestContext& testCtx)
{
de::MovePtr<tcu::TestCaseGroup> commandBuffersTests (new tcu::TestCaseGroup(testCtx, "command_buffers", "Command Buffers Tests"));
/* 19.1. Command Pools (5.1 in VK 1.0 Spec) */
addFunctionCase (commandBuffersTests.get(), "pool_create_null_params", "", createPoolNullParamsTest);
#ifndef CTS_USES_VULKANSC
// VkAllocationCallbacks must be NULL in Vulkan SC
addFunctionCase (commandBuffersTests.get(), "pool_create_non_null_allocator", "", createPoolNonNullAllocatorTest);
#endif // CTS_USES_VULKANSC
addFunctionCase (commandBuffersTests.get(), "pool_create_transient_bit", "", createPoolTransientBitTest);
addFunctionCase (commandBuffersTests.get(), "pool_create_reset_bit", "", createPoolResetBitTest);
#ifndef CTS_USES_VULKANSC
addFunctionCase (commandBuffersTests.get(), "pool_reset_release_res", "", resetPoolReleaseResourcesBitTest);
#endif // CTS_USES_VULKANSC
addFunctionCase (commandBuffersTests.get(), "pool_reset_no_flags_res", "", resetPoolNoFlagsTest);
#ifndef CTS_USES_VULKANSC
addFunctionCase (commandBuffersTests.get(), "pool_reset_reuse", "", checkEventSupport, resetPoolReuseTest);
#endif // CTS_USES_VULKANSC
/* 19.2. Command Buffer Lifetime (5.2 in VK 1.0 Spec) */
addFunctionCase (commandBuffersTests.get(), "allocate_single_primary", "", allocatePrimaryBufferTest);
addFunctionCase (commandBuffersTests.get(), "allocate_many_primary", "", allocateManyPrimaryBuffersTest);
addFunctionCase (commandBuffersTests.get(), "allocate_single_secondary", "", allocateSecondaryBufferTest);
addFunctionCase (commandBuffersTests.get(), "allocate_many_secondary", "", allocateManySecondaryBuffersTest);
addFunctionCase (commandBuffersTests.get(), "execute_small_primary", "", checkEventSupport, executePrimaryBufferTest);
addFunctionCase (commandBuffersTests.get(), "execute_large_primary", "", checkEventSupport, executeLargePrimaryBufferTest);
addFunctionCase (commandBuffersTests.get(), "reset_implicit", "", checkEventSupport, resetBufferImplicitlyTest);
#ifndef CTS_USES_VULKANSC
addFunctionCase (commandBuffersTests.get(), "trim_command_pool", "", checkEventSupport, trimCommandPoolTest, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
addFunctionCase (commandBuffersTests.get(), "trim_command_pool_secondary", "", checkEventSupport, trimCommandPoolTest, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
#endif // CTS_USES_VULKANSC
/* 19.3. Command Buffer Recording (5.3 in VK 1.0 Spec) */
addFunctionCase (commandBuffersTests.get(), "record_single_primary", "", checkEventSupport, recordSinglePrimaryBufferTest);
addFunctionCase (commandBuffersTests.get(), "record_many_primary", "", checkEventSupport, recordLargePrimaryBufferTest);
addFunctionCase (commandBuffersTests.get(), "record_single_secondary", "", checkEventAndSecondaryCommandBufferNullFramebufferSupport, recordSingleSecondaryBufferTest);
addFunctionCase (commandBuffersTests.get(), "record_many_secondary", "", checkEventAndSecondaryCommandBufferNullFramebufferSupport, recordLargeSecondaryBufferTest);
{
deUint32 seed = 1614182419u;
const auto smallExtent = makeExtent3D(128u, 128u, 1u);
const auto largeExtent = makeExtent3D(512u, 512u, 1u);
commandBuffersTests->addChild(new ManyDrawsCase(testCtx, "record_many_draws_primary_1", "", ManyDrawsParams(VK_COMMAND_BUFFER_LEVEL_PRIMARY, smallExtent, seed++)));
commandBuffersTests->addChild(new ManyDrawsCase(testCtx, "record_many_draws_primary_2", "", ManyDrawsParams(VK_COMMAND_BUFFER_LEVEL_PRIMARY, largeExtent, seed++)));
commandBuffersTests->addChild(new ManyDrawsCase(testCtx, "record_many_draws_secondary_1", "", ManyDrawsParams(VK_COMMAND_BUFFER_LEVEL_SECONDARY, smallExtent, seed++)));
commandBuffersTests->addChild(new ManyDrawsCase(testCtx, "record_many_draws_secondary_2", "", ManyDrawsParams(VK_COMMAND_BUFFER_LEVEL_SECONDARY, largeExtent, seed++)));
}
addFunctionCase (commandBuffersTests.get(), "submit_twice_primary", "", checkEventSupport, submitPrimaryBufferTwiceTest);
addFunctionCase (commandBuffersTests.get(), "submit_twice_secondary", "", checkEventAndSecondaryCommandBufferNullFramebufferSupport, submitSecondaryBufferTwiceTest);
addFunctionCase (commandBuffersTests.get(), "record_one_time_submit_primary", "", checkEventSupport, oneTimeSubmitFlagPrimaryBufferTest);
addFunctionCase (commandBuffersTests.get(), "record_one_time_submit_secondary", "", checkEventAndSecondaryCommandBufferNullFramebufferSupport, oneTimeSubmitFlagSecondaryBufferTest);
addFunctionCase (commandBuffersTests.get(), "render_pass_continue", "", renderPassContinueTest, true);
addFunctionCase (commandBuffersTests.get(), "render_pass_continue_no_fb", "", checkSecondaryCommandBufferNullOrImagelessFramebufferSupport1, renderPassContinueTest, false);
addFunctionCase (commandBuffersTests.get(), "record_simul_use_primary", "", checkEventAndCommandBufferSimultaneousUseSupport, simultaneousUsePrimaryBufferTest);
addFunctionCase (commandBuffersTests.get(), "record_simul_use_secondary", "", checkEventAndSimultaneousUseAndSecondaryCommandBufferNullFramebufferSupport, simultaneousUseSecondaryBufferTest);
addFunctionCaseWithPrograms (commandBuffersTests.get(), "record_simul_use_secondary_one_primary", "", checkSimultaneousUseAndSecondaryCommandBufferNullFramebufferSupport, genComputeIncrementSource, simultaneousUseSecondaryBufferOnePrimaryBufferTest);
addFunctionCaseWithPrograms (commandBuffersTests.get(), "record_simul_use_secondary_two_primary", "", checkSimultaneousUseAndSecondaryCommandBufferNullFramebufferSupport, genComputeIncrementSource, simultaneousUseSecondaryBufferTwoPrimaryBuffersTest);
addFunctionCase (commandBuffersTests.get(), "record_query_precise_w_flag", "", checkSecondaryCommandBufferNullOrImagelessFramebufferSupport, recordBufferQueryPreciseWithFlagTest);
addFunctionCase (commandBuffersTests.get(), "record_query_imprecise_w_flag", "", checkSecondaryCommandBufferNullOrImagelessFramebufferSupport, recordBufferQueryImpreciseWithFlagTest);
addFunctionCase (commandBuffersTests.get(), "record_query_imprecise_wo_flag", "", checkSecondaryCommandBufferNullOrImagelessFramebufferSupport, recordBufferQueryImpreciseWithoutFlagTest);
addFunctionCaseWithPrograms (commandBuffersTests.get(), "bad_inheritance_info_random", "", genComputeIncrementSourceBadInheritance, badInheritanceInfoTest, BadInheritanceInfoCase::RANDOM_PTR);
addFunctionCaseWithPrograms (commandBuffersTests.get(), "bad_inheritance_info_random_cont", "", genComputeIncrementSourceBadInheritance, badInheritanceInfoTest, BadInheritanceInfoCase::RANDOM_PTR_CONTINUATION);
addFunctionCaseWithPrograms (commandBuffersTests.get(), "bad_inheritance_info_random_data", "", genComputeIncrementSourceBadInheritance, badInheritanceInfoTest, BadInheritanceInfoCase::RANDOM_DATA_PTR);
addFunctionCaseWithPrograms (commandBuffersTests.get(), "bad_inheritance_info_invalid_type", "", genComputeIncrementSourceBadInheritance, badInheritanceInfoTest, BadInheritanceInfoCase::INVALID_STRUCTURE_TYPE);
addFunctionCaseWithPrograms (commandBuffersTests.get(), "bad_inheritance_info_valid_nonsense_type", "", genComputeIncrementSourceBadInheritance, badInheritanceInfoTest, BadInheritanceInfoCase::VALID_NONSENSE_TYPE);
/* 19.4. Command Buffer Submission (5.4 in VK 1.0 Spec) */
addFunctionCase (commandBuffersTests.get(), "submit_count_non_zero", "", checkEventSupport, submitBufferCountNonZero);
addFunctionCase (commandBuffersTests.get(), "submit_count_equal_zero", "", checkEventSupport, submitBufferCountEqualZero);
addFunctionCase (commandBuffersTests.get(), "submit_wait_single_semaphore", "", checkEventSupport, submitBufferWaitSingleSemaphore);
addFunctionCase (commandBuffersTests.get(), "submit_wait_many_semaphores", "", checkEventSupport, submitBufferWaitManySemaphores);
addFunctionCase (commandBuffersTests.get(), "submit_null_fence", "", checkEventSupport, submitBufferNullFence);
addFunctionCase (commandBuffersTests.get(), "submit_two_buffers_one_buffer_null_with_fence", "", checkEventSupport, submitTwoBuffersOneBufferNullWithFence);
/* 19.5. Secondary Command Buffer Execution (5.6 in VK 1.0 Spec) */
addFunctionCase (commandBuffersTests.get(), "secondary_execute", "", checkEventAndSecondaryCommandBufferNullFramebufferSupport, executeSecondaryBufferTest);
addFunctionCase (commandBuffersTests.get(), "secondary_execute_twice", "", checkEventAndSimultaneousUseAndSecondaryCommandBufferNullFramebufferSupport, executeSecondaryBufferTwiceTest);
/* 19.6. Commands Allowed Inside Command Buffers (? in VK 1.0 Spec) */
addFunctionCaseWithPrograms (commandBuffersTests.get(), "order_bind_pipeline", "", genComputeSource, orderBindPipelineTest);
/* Verify untested transitions between command buffer states */
addFunctionCase (commandBuffersTests.get(), "recording_to_ininitial", "", executeStateTransitionTest, STT_RECORDING_TO_INITIAL);
addFunctionCase (commandBuffersTests.get(), "executable_to_ininitial", "", executeStateTransitionTest, STT_EXECUTABLE_TO_INITIAL);
addFunctionCase (commandBuffersTests.get(), "recording_to_invalid", "", executeStateTransitionTest, STT_RECORDING_TO_INVALID);
addFunctionCase (commandBuffersTests.get(), "executable_to_invalid", "", executeStateTransitionTest, STT_EXECUTABLE_TO_INVALID);
return commandBuffersTests.release();
}
} // api
} // vkt