blob: 108cd8dc6c8ff24d46280487e27fd944c021a598 [file] [log] [blame]
/*------------------------------------------------------------------------
* Vulkan Conformance Tests
* ------------------------
*
* Copyright (c) 2016 The Khronos Group Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*//*!
* \file
* \brief Synchronization event basic tests
*//*--------------------------------------------------------------------*/
#include "vktSynchronizationBasicEventTests.hpp"
#include "vktTestCaseUtil.hpp"
#include "vktSynchronizationUtil.hpp"
#include "vkDefs.hpp"
#include "vkPlatform.hpp"
#include "vkRef.hpp"
#include "vkCmdUtil.hpp"
namespace vkt
{
namespace synchronization
{
namespace
{
using namespace vk;
#define SHORT_FENCE_WAIT 1000ull
#define LONG_FENCE_WAIT ~0ull
struct TestConfig
{
SynchronizationType type;
VkEventCreateFlags flags;
};
tcu::TestStatus hostResetSetEventCase (Context& context, TestConfig config)
{
const DeviceInterface& vk = context.getDeviceInterface();
const VkDevice device = context.getDevice();
const VkEventCreateInfo eventInfo =
{
VK_STRUCTURE_TYPE_EVENT_CREATE_INFO,
DE_NULL,
0
};
VkEvent event;
Move<VkEvent> ptrEvent;
DE_UNREF(config);
if (VK_SUCCESS != vk.createEvent(device, &eventInfo, DE_NULL, &event))
return tcu::TestStatus::fail("Couldn't create event");
ptrEvent = Move<VkEvent>(check<VkEvent>(event), Deleter<VkEvent>(vk, device, DE_NULL));
if (VK_EVENT_RESET != vk.getEventStatus(device, event))
return tcu::TestStatus::fail("Created event should be in unsignaled state");
if (VK_SUCCESS != vk.setEvent(device, event))
return tcu::TestStatus::fail("Couldn't set event");
if (VK_EVENT_SET != vk.getEventStatus(device, event))
return tcu::TestStatus::fail("Event should be in signaled state after set");
if (VK_SUCCESS != vk.resetEvent(device, event))
return tcu::TestStatus::fail("Couldn't reset event");
if (VK_EVENT_RESET != vk.getEventStatus(device, event))
return tcu::TestStatus::fail("Event should be in unsignaled state after reset");
return tcu::TestStatus::pass("Tests set and reset event on host pass");
}
tcu::TestStatus deviceResetSetEventCase (Context& context, TestConfig config)
{
const DeviceInterface& vk = context.getDeviceInterface();
const VkDevice device = context.getDevice();
const VkQueue queue = context.getUniversalQueue();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool));
const Unique<VkEvent> event (createEvent(vk, device));
const VkCommandBufferSubmitInfoKHR commandBufferSubmitInfo = makeCommonCommandBufferSubmitInfo(cmdBuffer.get());
const VkMemoryBarrier2KHR memoryBarrier2 =
{
VK_STRUCTURE_TYPE_MEMORY_BARRIER_2_KHR, // VkStructureType sType
DE_NULL, // const void* pNext
VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR, // VkPipelineStageFlags2KHR srcStageMask
VK_ACCESS_2_NONE_KHR, // VkAccessFlags2KHR srcAccessMask
VK_PIPELINE_STAGE_2_HOST_BIT_KHR, // VkPipelineStageFlags2KHR dstStageMask
VK_ACCESS_2_HOST_READ_BIT_KHR // VkAccessFlags2KHR dstAccessMask
};
VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo(&memoryBarrier2);
{
SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(config.type, vk, DE_FALSE);
beginCommandBuffer(vk, *cmdBuffer);
synchronizationWrapper->cmdSetEvent(*cmdBuffer, *event, &dependencyInfo);
endCommandBuffer(vk, *cmdBuffer);
synchronizationWrapper->addSubmitInfo(
0u, // deUint32 waitSemaphoreInfoCount
DE_NULL, // const VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfos
1u, // deUint32 commandBufferInfoCount
&commandBufferSubmitInfo, // const VkCommandBufferSubmitInfoKHR* pCommandBufferInfos
0u, // deUint32 signalSemaphoreInfoCount
DE_NULL // const VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfos
);
VK_CHECK(synchronizationWrapper->queueSubmit(queue, DE_NULL));
}
VK_CHECK(vk.queueWaitIdle(queue));
if (VK_EVENT_SET != vk.getEventStatus(device, *event))
return tcu::TestStatus::fail("Event should be in signaled state after set");
{
SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(config.type, vk, DE_FALSE);
beginCommandBuffer(vk, *cmdBuffer);
synchronizationWrapper->cmdResetEvent(*cmdBuffer, *event, VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR);
endCommandBuffer(vk, *cmdBuffer);
synchronizationWrapper->addSubmitInfo(
0u, // deUint32 waitSemaphoreInfoCount
DE_NULL, // const VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfos
1u, // deUint32 commandBufferInfoCount
&commandBufferSubmitInfo, // const VkCommandBufferSubmitInfoKHR* pCommandBufferInfos
0u, // deUint32 signalSemaphoreInfoCount
DE_NULL // const VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfos
);
VK_CHECK(synchronizationWrapper->queueSubmit(queue, DE_NULL));
}
VK_CHECK(vk.queueWaitIdle(queue));
if (VK_EVENT_RESET != vk.getEventStatus(device, *event))
return tcu::TestStatus::fail("Event should be in unsignaled state after set");
return tcu::TestStatus::pass("Device set and reset event tests pass");
}
tcu::TestStatus singleSubmissionCase (Context& context, TestConfig config)
{
enum {SET=0, WAIT, COUNT};
const DeviceInterface& vk = context.getDeviceInterface();
const VkDevice device = context.getDevice();
const VkQueue queue = context.getUniversalQueue();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
const Unique<VkFence> fence (createFence(vk, device));
const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
const Move<VkCommandBuffer> ptrCmdBuffer[COUNT] = { makeCommandBuffer(vk, device, *cmdPool), makeCommandBuffer(vk, device, *cmdPool) };
VkCommandBuffer cmdBuffers[COUNT] = {*ptrCmdBuffer[SET], *ptrCmdBuffer[WAIT]};
const Unique<VkEvent> event (createEvent(vk, device, config.flags));
VkCommandBufferSubmitInfoKHR commandBufferSubmitInfo[] {
makeCommonCommandBufferSubmitInfo(cmdBuffers[SET]),
makeCommonCommandBufferSubmitInfo(cmdBuffers[WAIT])
};
VkDependencyInfoKHR dependencyInfo = makeCommonDependencyInfo();
SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(config.type, vk, DE_FALSE);
synchronizationWrapper->addSubmitInfo(
0u, // deUint32 waitSemaphoreInfoCount
DE_NULL, // const VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfos
2u, // deUint32 commandBufferInfoCount
commandBufferSubmitInfo, // const VkCommandBufferSubmitInfoKHR* pCommandBufferInfos
0u, // deUint32 signalSemaphoreInfoCount
DE_NULL // const VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfos
);
beginCommandBuffer(vk, cmdBuffers[SET]);
synchronizationWrapper->cmdSetEvent(cmdBuffers[SET], *event, &dependencyInfo);
endCommandBuffer(vk, cmdBuffers[SET]);
beginCommandBuffer(vk, cmdBuffers[WAIT]);
synchronizationWrapper->cmdWaitEvents(cmdBuffers[WAIT], 1u, &event.get(), &dependencyInfo);
endCommandBuffer(vk, cmdBuffers[WAIT]);
VK_CHECK(synchronizationWrapper->queueSubmit(queue, *fence));
if (VK_SUCCESS != vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, LONG_FENCE_WAIT))
return tcu::TestStatus::fail("Queue should end execution");
return tcu::TestStatus::pass("Wait and set even on device single submission tests pass");
}
tcu::TestStatus multiSubmissionCase(Context& context, TestConfig config)
{
enum { SET = 0, WAIT, COUNT };
const DeviceInterface& vk = context.getDeviceInterface();
const VkDevice device = context.getDevice();
const VkQueue queue = context.getUniversalQueue();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
const Move<VkFence> ptrFence[COUNT] = { createFence(vk, device), createFence(vk, device) };
VkFence fence[COUNT] = { *ptrFence[SET], *ptrFence[WAIT] };
const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
const Move<VkCommandBuffer> ptrCmdBuffer[COUNT] = { makeCommandBuffer(vk, device, *cmdPool), makeCommandBuffer(vk, device, *cmdPool) };
VkCommandBuffer cmdBuffers[COUNT] = { *ptrCmdBuffer[SET], *ptrCmdBuffer[WAIT] };
const Unique<VkEvent> event (createEvent(vk, device, config.flags));
VkCommandBufferSubmitInfoKHR commandBufferSubmitInfo[] =
{
makeCommonCommandBufferSubmitInfo(cmdBuffers[SET]),
makeCommonCommandBufferSubmitInfo(cmdBuffers[WAIT])
};
SynchronizationWrapperPtr synchronizationWrapper[] =
{
getSynchronizationWrapper(config.type, vk, DE_FALSE),
getSynchronizationWrapper(config.type, vk, DE_FALSE)
};
VkDependencyInfoKHR dependencyInfos[] =
{
makeCommonDependencyInfo(),
makeCommonDependencyInfo()
};
synchronizationWrapper[SET]->addSubmitInfo(
0u, // deUint32 waitSemaphoreInfoCount
DE_NULL, // const VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfos
1u, // deUint32 commandBufferInfoCount
&commandBufferSubmitInfo[SET], // const VkCommandBufferSubmitInfoKHR* pCommandBufferInfos
0u, // deUint32 signalSemaphoreInfoCount
DE_NULL // const VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfos
);
synchronizationWrapper[WAIT]->addSubmitInfo(
0u, // deUint32 waitSemaphoreInfoCount
DE_NULL, // const VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfos
1u, // deUint32 commandBufferInfoCount
&commandBufferSubmitInfo[WAIT], // const VkCommandBufferSubmitInfoKHR* pCommandBufferInfos
0u, // deUint32 signalSemaphoreInfoCount
DE_NULL // const VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfos
);
beginCommandBuffer(vk, cmdBuffers[SET]);
synchronizationWrapper[SET]->cmdSetEvent(cmdBuffers[SET], *event, &dependencyInfos[SET]);
endCommandBuffer(vk, cmdBuffers[SET]);
beginCommandBuffer(vk, cmdBuffers[WAIT]);
synchronizationWrapper[WAIT]->cmdWaitEvents(cmdBuffers[WAIT], 1u, &event.get(), &dependencyInfos[WAIT]);
endCommandBuffer(vk, cmdBuffers[WAIT]);
VK_CHECK(synchronizationWrapper[SET]->queueSubmit(queue, fence[SET]));
VK_CHECK(synchronizationWrapper[WAIT]->queueSubmit(queue, fence[WAIT]));
if (VK_SUCCESS != vk.waitForFences(device, 2u, fence, DE_TRUE, LONG_FENCE_WAIT))
return tcu::TestStatus::fail("Queue should end execution");
return tcu::TestStatus::pass("Wait and set even on device multi submission tests pass");
}
tcu::TestStatus secondaryCommandBufferCase (Context& context, TestConfig config)
{
enum {SET=0, WAIT, COUNT};
const DeviceInterface& vk = context.getDeviceInterface();
const VkDevice device = context.getDevice();
const VkQueue queue = context.getUniversalQueue();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
const Unique<VkFence> fence (createFence(vk, device));
const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
const Move<VkCommandBuffer> primaryCmdBuffer (makeCommandBuffer(vk, device, *cmdPool));
const VkCommandBufferAllocateInfo cmdBufferInfo =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
*cmdPool, // VkCommandPool commandPool;
VK_COMMAND_BUFFER_LEVEL_SECONDARY, // VkCommandBufferLevel level;
1u, // deUint32 commandBufferCount;
};
const Move<VkCommandBuffer> prtCmdBuffers[COUNT] = {allocateCommandBuffer (vk, device, &cmdBufferInfo), allocateCommandBuffer (vk, device, &cmdBufferInfo)};
VkCommandBuffer secondaryCmdBuffers[] = {*prtCmdBuffers[SET], *prtCmdBuffers[WAIT]};
const Unique<VkEvent> event (createEvent(vk, device, config.flags));
const VkCommandBufferInheritanceInfo secCmdBufInheritInfo =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, //VkStructureType sType;
DE_NULL, //const void* pNext;
DE_NULL, //VkRenderPass renderPass;
0u, //deUint32 subpass;
DE_NULL, //VkFramebuffer framebuffer;
VK_FALSE, //VkBool32 occlusionQueryEnable;
(VkQueryControlFlags)0u, //VkQueryControlFlags queryFlags;
(VkQueryPipelineStatisticFlags)0u, //VkQueryPipelineStatisticFlags pipelineStatistics;
};
const VkCommandBufferBeginInfo cmdBufferBeginInfo =
{
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // VkCommandBufferUsageFlags flags;
&secCmdBufInheritInfo, // const VkCommandBufferInheritanceInfo* pInheritanceInfo;
};
VkCommandBufferSubmitInfoKHR commandBufferSubmitInfo = makeCommonCommandBufferSubmitInfo(*primaryCmdBuffer);
VkDependencyInfoKHR dependencyInfos[] =
{
makeCommonDependencyInfo(),
makeCommonDependencyInfo()
};
SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(config.type, vk, DE_FALSE);
synchronizationWrapper->addSubmitInfo(
0u, // deUint32 waitSemaphoreInfoCount
DE_NULL, // const VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfos
1u, // deUint32 commandBufferInfoCount
&commandBufferSubmitInfo, // const VkCommandBufferSubmitInfoKHR* pCommandBufferInfos
0u, // deUint32 signalSemaphoreInfoCount
DE_NULL // const VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfos
);
VK_CHECK(vk.beginCommandBuffer(secondaryCmdBuffers[SET], &cmdBufferBeginInfo));
synchronizationWrapper->cmdSetEvent(secondaryCmdBuffers[SET], *event, &dependencyInfos[SET]);
endCommandBuffer(vk, secondaryCmdBuffers[SET]);
VK_CHECK(vk.beginCommandBuffer(secondaryCmdBuffers[WAIT], &cmdBufferBeginInfo));
synchronizationWrapper->cmdWaitEvents(secondaryCmdBuffers[WAIT], 1u, &event.get(), &dependencyInfos[WAIT]);
endCommandBuffer(vk, secondaryCmdBuffers[WAIT]);
beginCommandBuffer(vk, *primaryCmdBuffer);
vk.cmdExecuteCommands(*primaryCmdBuffer, 2u, secondaryCmdBuffers);
endCommandBuffer(vk, *primaryCmdBuffer);
VK_CHECK(synchronizationWrapper->queueSubmit(queue, *fence));
if (VK_SUCCESS != vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, LONG_FENCE_WAIT))
return tcu::TestStatus::fail("Queue should end execution");
return tcu::TestStatus::pass("Wait and set even on device using secondary command buffers tests pass");
}
void checkSupport (Context& context, TestConfig config)
{
if (config.type == SynchronizationType::SYNCHRONIZATION2)
context.requireDeviceFunctionality("VK_KHR_synchronization2");
#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");
#endif // CTS_USES_VULKANSC
}
void checkSecondaryBufferSupport (Context& context, TestConfig config)
{
checkSupport(context, config);
#ifdef CTS_USES_VULKANSC
if (context.getDeviceVulkanSC10Properties().secondaryCommandBufferNullOrImagelessFramebuffer == VK_FALSE)
TCU_THROW(NotSupportedError, "secondaryCommandBufferNullFramebuffer is not supported");
#endif // CTS_USES_VULKANSC
}
} // anonymous
tcu::TestCaseGroup* createBasicEventTests (tcu::TestContext& testCtx)
{
TestConfig config
{
SynchronizationType::LEGACY,
0U
};
de::MovePtr<tcu::TestCaseGroup> basicTests (new tcu::TestCaseGroup(testCtx, "event", "Basic event tests"));
addFunctionCase(basicTests.get(), "host_set_reset", "Basic event tests set and reset on host", checkSupport, hostResetSetEventCase, config);
addFunctionCase(basicTests.get(), "device_set_reset", "Basic event tests set and reset on device", checkSupport, deviceResetSetEventCase, config);
addFunctionCase(basicTests.get(), "single_submit_multi_command_buffer", "Wait and set event single submission on device", checkSupport, singleSubmissionCase, config);
addFunctionCase(basicTests.get(), "multi_submit_multi_command_buffer", "Wait and set event mutli submission on device", checkSupport, multiSubmissionCase, config);
addFunctionCase(basicTests.get(), "multi_secondary_command_buffer", "Event used on secondary command buffer ", checkSecondaryBufferSupport, secondaryCommandBufferCase, config);
return basicTests.release();
}
tcu::TestCaseGroup* createSynchronization2BasicEventTests (tcu::TestContext& testCtx)
{
TestConfig config
{
SynchronizationType::SYNCHRONIZATION2,
0U
};
de::MovePtr<tcu::TestCaseGroup> basicTests (new tcu::TestCaseGroup(testCtx, "event", "Basic event tests"));
addFunctionCase(basicTests.get(), "device_set_reset", "Basic event tests set and reset on device", checkSupport, deviceResetSetEventCase, config);
addFunctionCase(basicTests.get(), "single_submit_multi_command_buffer", "Wait and set event single submission on device", checkSupport, singleSubmissionCase, config);
addFunctionCase(basicTests.get(), "multi_submit_multi_command_buffer", "Wait and set event mutli submission on device", checkSupport, multiSubmissionCase, config);
addFunctionCase(basicTests.get(), "multi_secondary_command_buffer", "Event used on secondary command buffer ", checkSecondaryBufferSupport, secondaryCommandBufferCase, config);
config.flags = VK_EVENT_CREATE_DEVICE_ONLY_BIT_KHR;
addFunctionCase(basicTests.get(), "single_submit_multi_command_buffer_device_only", "Wait and set GPU-only event single submission", checkSupport, singleSubmissionCase, config);
addFunctionCase(basicTests.get(), "multi_submit_multi_command_buffer_device_only", "Wait and set GPU-only event mutli submission", checkSupport, multiSubmissionCase, config);
addFunctionCase(basicTests.get(), "multi_secondary_command_buffer_device_only", "GPU-only event used on secondary command buffer ", checkSecondaryBufferSupport, secondaryCommandBufferCase, config);
return basicTests.release();
}
} // synchronization
} // vkt