/*------------------------------------------------------------------------ * 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 semaphore basic tests *//*--------------------------------------------------------------------*/ #include "vktSynchronizationBasicSemaphoreTests.hpp" #include "vktTestCaseUtil.hpp" #include "vktSynchronizationUtil.hpp" #include "vktCustomInstancesDevices.hpp" #include "vkDefs.hpp" #include "vkPlatform.hpp" #include "vkQueryUtil.hpp" #include "vkCmdUtil.hpp" #include "vkRef.hpp" #include #include "tcuCommandLine.hpp" namespace vkt { namespace synchronization { namespace { using namespace vk; struct TestConfig { bool useTypeCreate; VkSemaphoreType semaphoreType; SynchronizationType type; }; static const int basicChainLength = 32768; Move createTestSemaphore(Context& context, const DeviceInterface& vk, const VkDevice device, const TestConfig& config) { if (config.semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE_KHR && !context.getTimelineSemaphoreFeatures().timelineSemaphore) TCU_THROW(NotSupportedError, "Timeline semaphore not supported"); return Move(config.useTypeCreate ? createSemaphoreType(vk, device, config.semaphoreType) : createSemaphore(vk, device)); } #define FENCE_WAIT ~0ull tcu::TestStatus basicOneQueueCase (Context& context, const TestConfig config) { const DeviceInterface& vk = context.getDeviceInterface(); const VkDevice device = context.getDevice(); const VkQueue queue = context.getUniversalQueue(); const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); const Unique semaphore (createTestSemaphore(context, vk, device, config)); const Unique cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex)); const Unique cmdBuffer (makeCommandBuffer(vk, device, *cmdPool)); const VkCommandBufferBeginInfo info { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType; DE_NULL, // const void* pNext; VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, // VkCommandBufferUsageFlags flags; DE_NULL, // const VkCommandBufferInheritanceInfo* pInheritanceInfo; }; const deUint64 timelineValue = 1u; const Unique fence (createFence(vk, device)); bool usingTimelineSemaphores = config.semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE_KHR; VkCommandBufferSubmitInfoKHR commandBufferInfo = makeCommonCommandBufferSubmitInfo(*cmdBuffer); SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(config.type, vk, usingTimelineSemaphores, 2u); VkSemaphoreSubmitInfoKHR signalSemaphoreSubmitInfo = makeCommonSemaphoreSubmitInfo(semaphore.get(), timelineValue, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR); VkSemaphoreSubmitInfoKHR waitSemaphoreSubmitInfo = makeCommonSemaphoreSubmitInfo(semaphore.get(), timelineValue, VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR); synchronizationWrapper->addSubmitInfo( 0u, // deUint32 waitSemaphoreInfoCount DE_NULL, // const VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfos 1u, // deUint32 commandBufferInfoCount &commandBufferInfo, // const VkCommandBufferSubmitInfoKHR* pCommandBufferInfos 1u, // deUint32 signalSemaphoreInfoCount &signalSemaphoreSubmitInfo, // const VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfos DE_FALSE, usingTimelineSemaphores ); synchronizationWrapper->addSubmitInfo( 1u, // deUint32 waitSemaphoreInfoCount &waitSemaphoreSubmitInfo, // const VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfos 1u, // deUint32 commandBufferInfoCount &commandBufferInfo, // const VkCommandBufferSubmitInfoKHR* pCommandBufferInfos 0u, // deUint32 signalSemaphoreInfoCount DE_NULL, // const VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfos usingTimelineSemaphores, DE_FALSE ); VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &info)); endCommandBuffer(vk, *cmdBuffer); VK_CHECK(synchronizationWrapper->queueSubmit(queue, *fence)); if (VK_SUCCESS != vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, FENCE_WAIT)) return tcu::TestStatus::fail("Basic semaphore tests with one queue failed"); return tcu::TestStatus::pass("Basic semaphore tests with one queue passed"); } tcu::TestStatus basicChainCase(Context & context, TestConfig config) { VkResult err = VK_SUCCESS; const DeviceInterface& vk = context.getDeviceInterface(); const VkDevice& device = context.getDevice(); const VkQueue queue = context.getUniversalQueue(); VkSemaphoreCreateInfo sci = { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, DE_NULL, 0 }; VkFenceCreateInfo fci = { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, DE_NULL, 0 }; VkFence fence; std::vector waitSemaphoreSubmitInfos (basicChainLength, makeCommonSemaphoreSubmitInfo(0u, 0u, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR)); std::vector signalSemaphoreSubmitInfos (basicChainLength, makeCommonSemaphoreSubmitInfo(0u, 0u, VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR)); VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfo = DE_NULL; VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfo = signalSemaphoreSubmitInfos.data(); for (int i = 0; err == VK_SUCCESS && i < basicChainLength; i++) { err = vk.createSemaphore(device, &sci, DE_NULL, &pSignalSemaphoreInfo->semaphore); if (err != VK_SUCCESS) continue; SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(config.type, vk, DE_FALSE); synchronizationWrapper->addSubmitInfo( !!pWaitSemaphoreInfo, // deUint32 waitSemaphoreInfoCount pWaitSemaphoreInfo, // const VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfos 0u, // deUint32 commandBufferInfoCount DE_NULL, // const VkCommandBufferSubmitInfoKHR* pCommandBufferInfos 1u, // deUint32 signalSemaphoreInfoCount pSignalSemaphoreInfo // const VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfos ); err = synchronizationWrapper->queueSubmit(queue, 0); pWaitSemaphoreInfo = &waitSemaphoreSubmitInfos[i]; pWaitSemaphoreInfo->semaphore = pSignalSemaphoreInfo->semaphore; pSignalSemaphoreInfo++; } VK_CHECK(vk.createFence(device, &fci, DE_NULL, &fence)); { SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(config.type, vk, DE_FALSE); synchronizationWrapper->addSubmitInfo(1, pWaitSemaphoreInfo, 0, DE_NULL, 0, DE_NULL); VK_CHECK(synchronizationWrapper->queueSubmit(queue, fence)); } vk.waitForFences(device, 1, &fence, VK_TRUE, ~(0ull)); vk.destroyFence(device, fence, DE_NULL); for (const auto& s : signalSemaphoreSubmitInfos) vk.destroySemaphore(device, s.semaphore, DE_NULL); if (err == VK_SUCCESS) return tcu::TestStatus::pass("Basic semaphore chain test passed"); return tcu::TestStatus::fail("Basic semaphore chain test failed"); } tcu::TestStatus basicChainTimelineCase (Context& context, TestConfig config) { VkResult err = VK_SUCCESS; const DeviceInterface& vk = context.getDeviceInterface(); const VkDevice& device = context.getDevice(); const VkQueue queue = context.getUniversalQueue(); VkSemaphoreTypeCreateInfo scti = { VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO_KHR, DE_NULL, VK_SEMAPHORE_TYPE_TIMELINE_KHR, 0 }; VkSemaphoreCreateInfo sci = { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, &scti, 0 }; VkFenceCreateInfo fci = { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, DE_NULL, 0 }; VkSemaphore semaphore; VkFence fence; VK_CHECK(vk.createSemaphore(device, &sci, DE_NULL, &semaphore)); std::vector waitSemaphoreSubmitInfos (basicChainLength, makeCommonSemaphoreSubmitInfo(semaphore, 0u, VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR)); std::vector signalSemaphoreSubmitInfos (basicChainLength, makeCommonSemaphoreSubmitInfo(semaphore, 0u, VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR)); VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfo = DE_NULL; VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfo = signalSemaphoreSubmitInfos.data(); for (int i = 0; err == VK_SUCCESS && i < basicChainLength; i++) { pSignalSemaphoreInfo->value = static_cast(i+1); SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(config.type, vk, DE_TRUE); synchronizationWrapper->addSubmitInfo( !!pWaitSemaphoreInfo, // deUint32 waitSemaphoreInfoCount pWaitSemaphoreInfo, // const VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfos 0u, // deUint32 commandBufferInfoCount DE_NULL, // const VkCommandBufferSubmitInfoKHR* pCommandBufferInfos 1u, // deUint32 signalSemaphoreInfoCount pSignalSemaphoreInfo, // const VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfos !!pWaitSemaphoreInfo, DE_TRUE ); err = synchronizationWrapper->queueSubmit(queue, 0); pWaitSemaphoreInfo = &waitSemaphoreSubmitInfos[i]; pWaitSemaphoreInfo->value = static_cast(i); pSignalSemaphoreInfo++; } pWaitSemaphoreInfo->value = basicChainLength; SynchronizationWrapperPtr synchronizationWrapper = getSynchronizationWrapper(config.type, vk, DE_TRUE); synchronizationWrapper->addSubmitInfo( 1u, // deUint32 waitSemaphoreInfoCount pWaitSemaphoreInfo, // const VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfos 0u, // deUint32 commandBufferInfoCount DE_NULL, // const VkCommandBufferSubmitInfoKHR* pCommandBufferInfos 0u, // deUint32 signalSemaphoreInfoCount DE_NULL, // const VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfos DE_TRUE ); VK_CHECK(vk.createFence(device, &fci, DE_NULL, &fence)); VK_CHECK(synchronizationWrapper->queueSubmit(queue, fence)); vk.waitForFences(device, 1, &fence, VK_TRUE, ~(0ull)); vk.destroyFence(device, fence, DE_NULL); vk.destroySemaphore(device, semaphore, DE_NULL); if (err == VK_SUCCESS) return tcu::TestStatus::pass("Basic semaphore chain test passed"); return tcu::TestStatus::fail("Basic semaphore chain test failed"); } tcu::TestStatus basicThreadTimelineCase(Context& context, TestConfig) { const DeviceInterface& vk = context.getDeviceInterface(); const VkDevice& device = context.getDevice(); const VkSemaphoreTypeCreateInfo scti = { VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO_KHR, DE_NULL, VK_SEMAPHORE_TYPE_TIMELINE_KHR, 0 }; const VkSemaphoreCreateInfo sci = { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, &scti, 0 }; const VkFenceCreateInfo fci = { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, DE_NULL, 0 }; const vk::Unique semaphore (createSemaphore(vk, device, &sci)); const Unique fence (createFence(vk, device, &fci)); const deUint64 waitTimeout = 50ull * 1000000ull; // miliseconds VkResult threadResult = VK_SUCCESS; // helper creating VkSemaphoreSignalInfo auto makeSemaphoreSignalInfo = [&semaphore](deUint64 value) -> VkSemaphoreSignalInfo { return { VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO, // VkStructureType sType DE_NULL, // const void* pNext *semaphore, // VkSemaphore semaphore value // deUint64 value }; }; // helper creating VkSemaphoreWaitInfo auto makeSemaphoreWaitInfo = [&semaphore](deUint64* valuePtr) -> VkSemaphoreWaitInfo { return { VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO, // VkStructureType sType DE_NULL, // const void* pNext VK_SEMAPHORE_WAIT_ANY_BIT, // VkSemaphoreWaitFlags flags; 1u, // deUint32 semaphoreCount; &*semaphore, // const VkSemaphore* pSemaphores; valuePtr // const deUint64* pValues; }; }; // start thread - semaphore has value 0 de::MovePtr thread(new std::thread([=, &vk, &threadResult] { // wait till semaphore has value 1 deUint64 waitValue = 1; VkSemaphoreWaitInfo waitOne = makeSemaphoreWaitInfo(&waitValue); threadResult = vk.waitSemaphores(device, &waitOne, waitTimeout); if (threadResult == VK_SUCCESS) { // signal semaphore with value 2 VkSemaphoreSignalInfo signalTwo = makeSemaphoreSignalInfo(2); threadResult = vk.signalSemaphore(device, &signalTwo); } })); // wait some time to give thread chance to start deSleep(1); // milisecond // signal semaphore with value 1 VkSemaphoreSignalInfo signalOne = makeSemaphoreSignalInfo(1); vk.signalSemaphore(device, &signalOne); // wait till semaphore has value 2 deUint64 waitValue = 2; VkSemaphoreWaitInfo waitTwo = makeSemaphoreWaitInfo(&waitValue); VkResult mainResult = vk.waitSemaphores(device, &waitTwo, waitTimeout); thread->join(); if (mainResult == VK_SUCCESS) return tcu::TestStatus::pass("Pass"); if ((mainResult == VK_TIMEOUT) || (threadResult == VK_TIMEOUT)) return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Reached wait timeout"); return tcu::TestStatus::fail("Fail"); } tcu::TestStatus basicMultiQueueCase(Context& context, TestConfig config) { enum { NO_MATCH_FOUND = ~((deUint32)0) }; enum QueuesIndexes { FIRST = 0, SECOND, COUNT }; struct Queues { VkQueue queue; deUint32 queueFamilyIndex; }; const DeviceInterface& vk = context.getDeviceInterface(); const InstanceInterface& instance = context.getInstanceInterface(); const VkPhysicalDevice physicalDevice = context.getPhysicalDevice(); vk::Move logicalDevice; std::vector queueFamilyProperties; VkDeviceCreateInfo deviceInfo; VkPhysicalDeviceFeatures deviceFeatures; const float queuePriorities[COUNT] = { 1.0f, 1.0f }; VkDeviceQueueCreateInfo queueInfos[COUNT]; Queues queues[COUNT] = { {DE_NULL, (deUint32)NO_MATCH_FOUND}, {DE_NULL, (deUint32)NO_MATCH_FOUND} }; const VkCommandBufferBeginInfo info = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType; DE_NULL, // const void* pNext; VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, // VkCommandBufferUsageFlags flags; DE_NULL, // const VkCommandBufferInheritanceInfo* pInheritanceInfo; }; Move semaphore; Move cmdPool[COUNT]; Move cmdBuffer[COUNT]; deUint64 timelineValues[COUNT] = { 1ull, 2ull }; Move fence[COUNT]; bool isTimelineSemaphore = config.semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE_KHR; queueFamilyProperties = getPhysicalDeviceQueueFamilyProperties(instance, physicalDevice); for (deUint32 queueNdx = 0; queueNdx < queueFamilyProperties.size(); ++queueNdx) { if (NO_MATCH_FOUND == queues[FIRST].queueFamilyIndex) queues[FIRST].queueFamilyIndex = queueNdx; if (queues[FIRST].queueFamilyIndex != queueNdx || queueFamilyProperties[queueNdx].queueCount > 1u) { queues[SECOND].queueFamilyIndex = queueNdx; break; } } if (queues[FIRST].queueFamilyIndex == NO_MATCH_FOUND || queues[SECOND].queueFamilyIndex == NO_MATCH_FOUND) TCU_THROW(NotSupportedError, "Queues couldn't be created"); for (int queueNdx = 0; queueNdx < COUNT; ++queueNdx) { VkDeviceQueueCreateInfo queueInfo; deMemset(&queueInfo, 0, sizeof(queueInfo)); queueInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; queueInfo.pNext = DE_NULL; queueInfo.flags = (VkDeviceQueueCreateFlags)0u; queueInfo.queueFamilyIndex = queues[queueNdx].queueFamilyIndex; queueInfo.queueCount = (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex) ? 2 : 1; queueInfo.pQueuePriorities = queuePriorities; queueInfos[queueNdx] = queueInfo; if (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex) break; } deMemset(&deviceInfo, 0, sizeof(deviceInfo)); instance.getPhysicalDeviceFeatures(physicalDevice, &deviceFeatures); VkPhysicalDeviceFeatures2 createPhysicalFeature { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, DE_NULL, deviceFeatures }; VkPhysicalDeviceTimelineSemaphoreFeatures timelineSemaphoreFeatures { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES, DE_NULL, DE_TRUE }; VkPhysicalDeviceSynchronization2FeaturesKHR synchronization2Features { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES_KHR, DE_NULL, DE_TRUE }; void** nextPtr = &createPhysicalFeature.pNext; std::vector deviceExtensions; if (isTimelineSemaphore) { deviceExtensions.push_back("VK_KHR_timeline_semaphore"); addToChainVulkanStructure(&nextPtr, timelineSemaphoreFeatures); } if (config.type == SynchronizationType::SYNCHRONIZATION2) { deviceExtensions.push_back("VK_KHR_synchronization2"); addToChainVulkanStructure(&nextPtr, synchronization2Features); } deviceInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; deviceInfo.pNext = &createPhysicalFeature; deviceInfo.enabledExtensionCount = static_cast(deviceExtensions.size()); deviceInfo.ppEnabledExtensionNames = deviceExtensions.empty() ? DE_NULL : deviceExtensions.data(); deviceInfo.enabledLayerCount = 0u; deviceInfo.ppEnabledLayerNames = DE_NULL; deviceInfo.pEnabledFeatures = 0u; deviceInfo.queueCreateInfoCount = (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex) ? 1 : COUNT; deviceInfo.pQueueCreateInfos = queueInfos; logicalDevice = createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), context.getPlatformInterface(), context.getInstance(), instance, physicalDevice, &deviceInfo); for (deUint32 queueReqNdx = 0; queueReqNdx < COUNT; ++queueReqNdx) { if (queues[FIRST].queueFamilyIndex == queues[SECOND].queueFamilyIndex) vk.getDeviceQueue(*logicalDevice, queues[queueReqNdx].queueFamilyIndex, queueReqNdx, &queues[queueReqNdx].queue); else vk.getDeviceQueue(*logicalDevice, queues[queueReqNdx].queueFamilyIndex, 0u, &queues[queueReqNdx].queue); } semaphore = (createTestSemaphore(context, vk, *logicalDevice, config)); cmdPool[FIRST] = (createCommandPool(vk, *logicalDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queues[FIRST].queueFamilyIndex)); cmdPool[SECOND] = (createCommandPool(vk, *logicalDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queues[SECOND].queueFamilyIndex)); cmdBuffer[FIRST] = (makeCommandBuffer(vk, *logicalDevice, *cmdPool[FIRST])); cmdBuffer[SECOND] = (makeCommandBuffer(vk, *logicalDevice, *cmdPool[SECOND])); VK_CHECK(vk.beginCommandBuffer(*cmdBuffer[FIRST], &info)); endCommandBuffer(vk, *cmdBuffer[FIRST]); VK_CHECK(vk.beginCommandBuffer(*cmdBuffer[SECOND], &info)); endCommandBuffer(vk, *cmdBuffer[SECOND]); fence[FIRST] = (createFence(vk, *logicalDevice)); fence[SECOND] = (createFence(vk, *logicalDevice)); VkCommandBufferSubmitInfoKHR commandBufferInfo[] { makeCommonCommandBufferSubmitInfo(*cmdBuffer[FIRST]), makeCommonCommandBufferSubmitInfo(*cmdBuffer[SECOND]) }; VkSemaphoreSubmitInfoKHR signalSemaphoreSubmitInfo[] { makeCommonSemaphoreSubmitInfo(semaphore.get(), timelineValues[FIRST], VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR), makeCommonSemaphoreSubmitInfo(semaphore.get(), timelineValues[SECOND], VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR) }; VkSemaphoreSubmitInfoKHR waitSemaphoreSubmitInfo = makeCommonSemaphoreSubmitInfo(semaphore.get(), timelineValues[FIRST], VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR); { SynchronizationWrapperPtr synchronizationWrapper[] { getSynchronizationWrapper(config.type, vk, isTimelineSemaphore), getSynchronizationWrapper(config.type, vk, isTimelineSemaphore) }; synchronizationWrapper[FIRST]->addSubmitInfo( 0u, // deUint32 waitSemaphoreInfoCount DE_NULL, // const VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfos 1u, // deUint32 commandBufferInfoCount &commandBufferInfo[FIRST], // const VkCommandBufferSubmitInfoKHR* pCommandBufferInfos 1u, // deUint32 signalSemaphoreInfoCount &signalSemaphoreSubmitInfo[FIRST], // const VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfos DE_FALSE, isTimelineSemaphore ); synchronizationWrapper[SECOND]->addSubmitInfo( 1u, // deUint32 waitSemaphoreInfoCount &waitSemaphoreSubmitInfo, // const VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfos 1u, // deUint32 commandBufferInfoCount &commandBufferInfo[SECOND], // const VkCommandBufferSubmitInfoKHR* pCommandBufferInfos 1u, // deUint32 signalSemaphoreInfoCount &signalSemaphoreSubmitInfo[SECOND], // const VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfos isTimelineSemaphore, isTimelineSemaphore ); VK_CHECK(synchronizationWrapper[FIRST]->queueSubmit(queues[FIRST].queue, *fence[FIRST])); VK_CHECK(synchronizationWrapper[SECOND]->queueSubmit(queues[SECOND].queue, *fence[SECOND])); } if (VK_SUCCESS != vk.waitForFences(*logicalDevice, 1u, &fence[FIRST].get(), DE_TRUE, FENCE_WAIT)) return tcu::TestStatus::fail("Basic semaphore tests with multi queue failed"); if (VK_SUCCESS != vk.waitForFences(*logicalDevice, 1u, &fence[SECOND].get(), DE_TRUE, FENCE_WAIT)) return tcu::TestStatus::fail("Basic semaphore tests with multi queue failed"); if (isTimelineSemaphore) { signalSemaphoreSubmitInfo[FIRST].value = 3ull; signalSemaphoreSubmitInfo[SECOND].value = 4ull; waitSemaphoreSubmitInfo.value = 3ull; } // swap semaphore info compared to above submits { SynchronizationWrapperPtr synchronizationWrapper[] { getSynchronizationWrapper(config.type, vk, isTimelineSemaphore), getSynchronizationWrapper(config.type, vk, isTimelineSemaphore) }; synchronizationWrapper[FIRST]->addSubmitInfo( 1u, // deUint32 waitSemaphoreInfoCount &waitSemaphoreSubmitInfo, // const VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfos 1u, // deUint32 commandBufferInfoCount &commandBufferInfo[FIRST], // const VkCommandBufferSubmitInfoKHR* pCommandBufferInfos 1u, // deUint32 signalSemaphoreInfoCount &signalSemaphoreSubmitInfo[SECOND], // const VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfos isTimelineSemaphore, isTimelineSemaphore ); synchronizationWrapper[SECOND]->addSubmitInfo( isTimelineSemaphore ? 0u : 1u, // deUint32 waitSemaphoreInfoCount isTimelineSemaphore ? DE_NULL : &waitSemaphoreSubmitInfo, // const VkSemaphoreSubmitInfoKHR* pWaitSemaphoreInfos 1u, // deUint32 commandBufferInfoCount &commandBufferInfo[SECOND], // const VkCommandBufferSubmitInfoKHR* pCommandBufferInfos 1u, // deUint32 signalSemaphoreInfoCount &signalSemaphoreSubmitInfo[FIRST], // const VkSemaphoreSubmitInfoKHR* pSignalSemaphoreInfos DE_FALSE, isTimelineSemaphore ); VK_CHECK(vk.resetFences(*logicalDevice, 1u, &fence[FIRST].get())); VK_CHECK(vk.resetFences(*logicalDevice, 1u, &fence[SECOND].get())); VK_CHECK(synchronizationWrapper[SECOND]->queueSubmit(queues[SECOND].queue, *fence[SECOND])); VK_CHECK(synchronizationWrapper[FIRST]->queueSubmit(queues[FIRST].queue, *fence[FIRST])); } if (VK_SUCCESS != vk.waitForFences(*logicalDevice, 1u, &fence[FIRST].get(), DE_TRUE, FENCE_WAIT)) return tcu::TestStatus::fail("Basic semaphore tests with multi queue failed"); if (VK_SUCCESS != vk.waitForFences(*logicalDevice, 1u, &fence[SECOND].get(), DE_TRUE, FENCE_WAIT)) return tcu::TestStatus::fail("Basic semaphore tests with multi queue failed"); return tcu::TestStatus::pass("Basic semaphore tests with multi queue passed"); } void checkSupport(Context& context, TestConfig config) { if (config.semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE_KHR) context.requireDeviceFunctionality("VK_KHR_timeline_semaphore"); if (config.type == SynchronizationType::SYNCHRONIZATION2) context.requireDeviceFunctionality("VK_KHR_synchronization2"); } } // anonymous tcu::TestCaseGroup* createBasicBinarySemaphoreTests (tcu::TestContext& testCtx, SynchronizationType type) { de::MovePtr basicTests(new tcu::TestCaseGroup(testCtx, "binary_semaphore", "Basic semaphore tests")); TestConfig config = { 0, VK_SEMAPHORE_TYPE_BINARY_KHR, type, }; for (deUint32 typedCreate = 0; typedCreate < 2; typedCreate++) { config.useTypeCreate = (typedCreate != 0); const std::string createName = config.useTypeCreate ? "_typed" : ""; addFunctionCase(basicTests.get(), "one_queue" + createName, "Basic binary semaphore tests with one queue", checkSupport, basicOneQueueCase, config); addFunctionCase(basicTests.get(), "multi_queue" + createName, "Basic binary semaphore tests with multi queue", checkSupport, basicMultiQueueCase, config); } addFunctionCase(basicTests.get(), "chain", "Binary semaphore chain test", checkSupport, basicChainCase, config); return basicTests.release(); } tcu::TestCaseGroup* createBasicTimelineSemaphoreTests (tcu::TestContext& testCtx, SynchronizationType type) { de::MovePtr basicTests(new tcu::TestCaseGroup(testCtx, "timeline_semaphore", "Basic timeline semaphore tests")); const TestConfig config = { true, VK_SEMAPHORE_TYPE_TIMELINE_KHR, type, }; addFunctionCase(basicTests.get(), "one_queue", "Basic timeline semaphore tests with one queue", checkSupport, basicOneQueueCase, config); addFunctionCase(basicTests.get(), "multi_queue", "Basic timeline semaphore tests with multi queue", checkSupport, basicMultiQueueCase, config); addFunctionCase(basicTests.get(), "chain", "Timeline semaphore chain test", checkSupport, basicChainTimelineCase, config); // dont repeat this test for synchronization2 if (type == SynchronizationType::LEGACY) addFunctionCase(basicTests.get(), "two_threads","Timeline semaphore used by two threads", checkSupport, basicThreadTimelineCase, config); return basicTests.release(); } } // synchronization } // vkt