diff options
author | Hyunjun Ko <zzoon@igalia.com> | 2023-01-20 11:11:02 +0900 |
---|---|---|
committer | Piotr Byszewski <piotr.byszewski@mobica.com> | 2023-01-27 08:36:42 +0000 |
commit | 717c051d4bcc9b71f13bc6b223e9926dcf9b7bd5 (patch) | |
tree | 75cb0598c45ffdfbdacb17e5c92725688f88e321 | |
parent | 10df72abd005896aec6000e70be0453b1f880f96 (diff) | |
download | VK-GL-CTS-717c051d4bcc9b71f13bc6b223e9926dcf9b7bd5.tar.gz VK-GL-CTS-717c051d4bcc9b71f13bc6b223e9926dcf9b7bd5.tar.bz2 VK-GL-CTS-717c051d4bcc9b71f13bc6b223e9926dcf9b7bd5.zip |
Do not allow to call vkSetEvent after submission, which is invalid.
The spec says:
"If a command buffer submission waits for any events to be signaled,
the application must ensure that command buffer submissions will be
able to complete without any subsequent operations by the application.
Events signaled by the host must be signaled before the command buffer
waits on those events."
This means it's not valid to signal an event on the host after submission
of a command buffer containing a wait for the event. Also it forces the
command buffer to stop for an unknown amount of time, as much as the time
needed for the host to signal the event with vkSetEvent.
However there were some CTS tests doing like this, which should be
fixed.
For vktApiExternalMemoryTests.cpp,
There was a vkSetEvent call after submission to hold a command to be
executed before signaling to get a native file descriptor, which is
not valid. So the tests should allow to get -1. Also we do an atomic calculation
to avoid singalling right after submit when trying to get a native fd.
The simple atomic calculation is evaluated to take about 10ms.
For vktApiExternalMemoryTests.cpp and vktMemoryExternalMemoryHostTests.cpp,
replace vkSetEvent with timeline semaphore to signal from the host.
Affects:
dEQP-VK.api.external.semaphore.*
dEQP-VK.api.external.fence.*
dEQP-VK.api.command_buffers.secondary_execute_twice
dEQP-VK.memory.external_memory_host.synchronization.synchronization
VK-GL-CTS Issue: 4075
Components: Vulkan
Change-Id: I5544bb15a418bbbbd6552ca04bec673a56ca3109
4 files changed, 530 insertions, 207 deletions
diff --git a/external/vulkancts/modules/vulkan/api/vktApiCommandBuffersTests.cpp b/external/vulkancts/modules/vulkan/api/vktApiCommandBuffersTests.cpp index 067cc697a..905533469 100644 --- a/external/vulkancts/modules/vulkan/api/vktApiCommandBuffersTests.cpp +++ b/external/vulkancts/modules/vulkan/api/vktApiCommandBuffersTests.cpp @@ -3413,8 +3413,8 @@ tcu::TestStatus executeSecondaryBufferTwiceTest(Context& context) // record secondary command buffer VK_CHECK(vk.beginCommandBuffer(cmdBuffers[ndx], &secCmdBufBeginInfo)); { - // wait for event - vk.cmdWaitEvents(cmdBuffers[ndx], 1, &eventOne.get(), VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, DE_NULL, 0u, DE_NULL, 0u, DE_NULL); + // set event + vk.cmdSetEvent(cmdBuffers[ndx], *eventOne, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); } // end recording of secondary buffers endCommandBuffer(vk, cmdBuffers[ndx]); @@ -3440,54 +3440,69 @@ tcu::TestStatus executeSecondaryBufferTwiceTest(Context& context) const Unique<VkFence> fenceOne (createFence(vk, vkDevice)); const Unique<VkFence> fenceTwo (createFence(vk, vkDevice)); - const VkSubmitInfo submitInfoOne = + const uint64_t semaphoreWaitValue = 1ull; + const VkPipelineStageFlags semaphoreWaitStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + const auto semaphore = createSemaphoreType(vk, vkDevice, VK_SEMAPHORE_TYPE_TIMELINE); + + // Use timeline semaphore to wait for signal from the host. + const VkTimelineSemaphoreSubmitInfo timelineWaitSubmitInfo = { - 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 + VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + 1u, // uint32_t waitSemaphoreValueCount; + &semaphoreWaitValue, // const uint64_t* pWaitSemaphoreValues; + 0u, // uint32_t signalSemaphoreValueCount; + nullptr, // const uint64_t* pSignalSemaphoreValues; }; - // 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 submitInfo = + { + VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType; + &timelineWaitSubmitInfo, // const void* pNext; + 1u, // uint32_t waitSemaphoreCount; + &semaphore.get(), // const VkSemaphore* pWaitSemaphores; + &semaphoreWaitStage, // const VkPipelineStageFlags* pWaitDstStageMask; + 1u, // uint32_t commandBufferCount; + &primCmdBufOne.get(), // const VkCommandBuffer* pCommandBuffers; + 0u, // uint32_t signalSemaphoreCount; + nullptr, // const VkSemaphore* pSignalSemaphores; + }; + VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fenceOne)); - const VkSubmitInfo submitInfoTwo = + const VkSubmitInfo submitInfo2 = { - 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 + VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType; + &timelineWaitSubmitInfo, // const void* pNext; + 1u, // uint32_t waitSemaphoreCount; + &semaphore.get(), // const VkSemaphore* pWaitSemaphores; + &semaphoreWaitStage, // const VkPipelineStageFlags* pWaitDstStageMask; + 1u, // uint32_t commandBufferCount; + &primCmdBufTwo.get(), // const VkCommandBuffer* pCommandBuffers; + 0u, // uint32_t signalSemaphoreCount; + nullptr, // const VkSemaphore* pSignalSemaphores; }; - // submit second primary buffer, the secondary should be executed too - VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfoTwo, *fenceTwo)); + VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo2, *fenceTwo)); - // wait for all buffers to stop at event for 100 microseconds - vk.waitForFences(vkDevice, 1, &fenceOne.get(), 0u, 100000); + // Signal from host + const vk::VkSemaphoreSignalInfo signalInfo = + { + vk::VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + semaphore.get(), // VkSemaphore semaphore; + semaphoreWaitValue, // uint64_t value; + }; - // now all buffers are waiting at eventOne - // set event eventOne - VK_CHECK(vk.setEvent(vkDevice, *eventOne)); + VK_CHECK(vk.signalSemaphore(vkDevice, &signalInfo)); // 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 + // wait for end of execution of fenceTwo VK_CHECK(vk.waitForFences(vkDevice, 1, &fenceTwo.get(), 0u, INFINITE_TIMEOUT)); + TCU_CHECK(vk.getEventStatus(vkDevice, *eventOne) == vk::VK_EVENT_SET); + return tcu::TestStatus::pass("executeSecondaryBufferTwiceTest succeeded"); } @@ -3932,6 +3947,17 @@ void checkEventSupport (Context& context) TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Events are not supported by this implementation"); } +void checkTimelineSemaphoreSupport(Context& context) +{ + context.requireDeviceFunctionality("VK_KHR_timeline_semaphore"); +} + +void checkEventAndTimelineSemaphoreSupport(Context &context) +{ + checkTimelineSemaphoreSupport(context); + checkEventSupport(context); +} + void checkEventSupport (Context& context, const VkCommandBufferLevel) { checkEventSupport(context); @@ -4590,7 +4616,7 @@ tcu::TestCaseGroup* createCommandBuffersTests (tcu::TestContext& testCtx) 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", "", checkEventSupport, executeSecondaryBufferTest); - addFunctionCase (commandBuffersTests.get(), "secondary_execute_twice", "", checkEventSupport, executeSecondaryBufferTwiceTest); + addFunctionCase (commandBuffersTests.get(), "secondary_execute_twice", "", checkEventAndTimelineSemaphoreSupport, 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 */ diff --git a/external/vulkancts/modules/vulkan/api/vktApiExternalMemoryTests.cpp b/external/vulkancts/modules/vulkan/api/vktApiExternalMemoryTests.cpp index 89856daab..4c0ed0bf4 100644 --- a/external/vulkancts/modules/vulkan/api/vktApiExternalMemoryTests.cpp +++ b/external/vulkancts/modules/vulkan/api/vktApiExternalMemoryTests.cpp @@ -21,6 +21,7 @@ #include "vktApiExternalMemoryTests.hpp" #include "vktCustomInstancesDevices.hpp" +#include "../compute/vktComputeTestsUtil.hpp" #include "vktTestCaseUtil.hpp" #include "vkRefUtil.hpp" @@ -30,6 +31,10 @@ #include "vkMemUtil.hpp" #include "vkApiVersion.hpp" #include "vkImageUtil.hpp" +#include "vkObjUtil.hpp" +#include "vkBuilderUtil.hpp" +#include "vkBarrierUtil.hpp" +#include "vkBufferWithMemory.hpp" #include "tcuTestLog.hpp" #include "tcuCommandLine.hpp" @@ -56,6 +61,8 @@ # include <dxgi1_2.h> #endif +#include <chrono> + using tcu::TestLog; using namespace vkt::ExternalMemoryUtil; @@ -67,6 +74,15 @@ namespace { +template<typename T, int size> +T multiplyComponents (const tcu::Vector<T, size>& v) +{ + T accum = 1; + for (int i = 0; i < size; ++i) + accum *= v[i]; + return accum; +} + std::string getFormatCaseName (vk::VkFormat format) { return de::toLower(de::toString(getFormatStr(format)).substr(10)); @@ -400,6 +416,15 @@ vk::VkQueue getQueue (const vk::DeviceInterface& vkd, return queue; } +uint32_t getMaxInvocations(const Context& context, uint32_t idx) +{ + const auto& vki = context.getInstanceInterface(); + const auto physicalDevice = context.getPhysicalDevice(); + const auto properties = vk::getPhysicalDeviceProperties(vki, physicalDevice); + + return properties.limits.maxComputeWorkGroupSize[idx]; +} + void checkSemaphoreSupport (const vk::InstanceInterface& vki, vk::VkPhysicalDevice device, vk::VkExternalSemaphoreHandleTypeFlagBits externalType) @@ -572,54 +597,180 @@ void submitEmptySignal (const vk::DeviceInterface& vkd, VK_CHECK(vkd.queueSubmit(queue, 1, &submit, (vk::VkFence)0u)); } -void submitEmptySignalAndGetSemaphoreNative ( const vk::DeviceInterface& vk, - vk::VkDevice device, - vk::VkQueue queue, - deUint32 queueFamilyIndex, - vk::VkSemaphore semaphore, - vk::VkExternalSemaphoreHandleTypeFlagBits externalType, - NativeHandle& nativeHandle) +void tuneWorkSizeYAndPrepareCommandBuffer( const Context& context, + const vk::DeviceInterface& vk, + vk::VkDevice device, + vk::VkQueue queue, + vk::VkCommandBuffer cmdBuffer, + vk::VkDescriptorSet descriptorSet, + vk::VkPipelineLayout pipelineLayout, + vk::VkPipeline computePipeline, + vk::VkBufferMemoryBarrier computeFinishBarrier, + vk::VkEvent event, + tcu::UVec3* maxWorkSize) + + +{ + // Have it be static so we don't need to do tuning every time, especially for "export_multiple_times" tests. + static uint32_t yWorkSize = 1; + uint64_t timeElapsed = 0; + bool bOutLoop = false; + + const vk::Unique<vk::VkFence> fence(vk::createFence(vk, device)); + + const vk::VkCommandBufferBeginInfo cmdBufferBeginInfo = + { + vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, + nullptr, + vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, + nullptr, + }; + + while (true) { + VK_CHECK(vk.beginCommandBuffer(cmdBuffer, &cmdBufferBeginInfo)); + + /* + * If the handle type is VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR, the spec allowed for implementations to return -1 + * if the fence is already signaled. Previously, to avoid getting -1 in this case, this test had used vkCmdWaitEvents and + * vkSetEvent after submission to get a proper file descriptor before signaling but it's not invalid to call vkSetEvent + * after submission. So we just use vkCmdSetEvent and check the state of the event after submission to see if it's already + * signaled or an error happens while trying to get a file descriptor. + */ + vk.cmdSetEvent(cmdBuffer, event, vk::VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT); + + // And now we do a simple atomic calculation to avoid signalling instantly right after submit. + vk.cmdBindPipeline(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, computePipeline); + //vk.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, nullptr); + vk.cmdBindDescriptorSets(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &descriptorSet, 0u, nullptr); + vk.cmdDispatch(cmdBuffer, maxWorkSize->x(), yWorkSize, maxWorkSize->z()); + vk.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, 0, 0, nullptr, 1u, &computeFinishBarrier, 0, nullptr); + vk.endCommandBuffer(cmdBuffer); + + if (bOutLoop) + break; + + const vk::VkSubmitInfo submit = + { + vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, + nullptr, + + 0u, + nullptr, + nullptr, + + 1u, + &cmdBuffer, + + 0u, + nullptr + }; + + auto timeStart = std::chrono::high_resolution_clock::now(); + + VK_CHECK(vk.queueSubmit(queue, 1, &submit, (vk::VkFence)*fence)); + vk.waitForFences(device, 1u, &fence.get(), true, ~0ull); + + const auto executionTime = std::chrono::high_resolution_clock::now() - timeStart; + auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(executionTime); + + timeElapsed = elapsed.count(); + + // we do loop until we get over 9 miliseconds as an execution time. + if (elapsed.count() > 9) + { + bOutLoop = true; + continue; + } + + yWorkSize *= 2; + + if (yWorkSize > maxWorkSize->y()) + { + yWorkSize = maxWorkSize->y(); + bOutLoop = true; + } + + vk.resetCommandBuffer(cmdBuffer, 0u); + vk.resetFences(device, 1u, &*fence); + }; + + tcu::TestLog& log = context.getTestContext().getLog(); + log << tcu::TestLog::Message + << "Execution time to get a native file descriptor is " << timeElapsed << "ms with Y WorkSize " << yWorkSize + << tcu::TestLog::EndMessage; + + return; +} + +void submitAtomicCalculationsAndGetSemaphoreNative (const Context& context, + const vk::DeviceInterface& vk, + vk::VkDevice device, + vk::Allocator& alloc, + vk::VkQueue queue, + deUint32 queueFamilyIndex, + vk::VkSemaphore semaphore, + vk::VkExternalSemaphoreHandleTypeFlagBits externalType, + NativeHandle& nativeHandle) { - const vk::Unique<vk::VkCommandPool> cmdPool(createCommandPool(vk, device, vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex, DE_NULL)); + const vk::Unique<vk::VkCommandPool> cmdPool(createCommandPool(vk, device, vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex, nullptr)); const vk::Unique<vk::VkCommandBuffer> cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY)); const vk::VkEventCreateInfo eventCreateInfo = { vk::VK_STRUCTURE_TYPE_EVENT_CREATE_INFO, - DE_NULL, + nullptr, 0u }; - const vk::Unique<vk::VkEvent> event(createEvent(vk, device, &eventCreateInfo, DE_NULL)); + const vk::Unique<vk::VkEvent> event(createEvent(vk, device, &eventCreateInfo, nullptr)); - const vk::VkCommandBufferBeginInfo cmdBufferBeginInfo = - { - vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, - DE_NULL, - vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, - DE_NULL, - }; + const uint32_t maxXWorkSize = getMaxInvocations(context, 0); + const uint32_t maxYWorkSize = getMaxInvocations(context, 1); + + tcu::UVec3 workSize = { maxXWorkSize, maxYWorkSize, 1u }; + const uint32_t workGroupCount = multiplyComponents(workSize); + + const vk::VkDeviceSize outputBufferSize = sizeof(uint32_t) * workGroupCount; + const vk::BufferWithMemory outputBuffer (vk, device, alloc, makeBufferCreateInfo(outputBufferSize, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), vk::MemoryRequirement::Local); - VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo)); - /* - The submitEmptySignal function calls vkQueueSubmit with an empty VkSubmitInfo structure and a - VkSemaphore to be signalled when the work is finished. Because there is no work in the submission, vkQueueSubmit - may signal the semaphore immediately. When a semaphore's file descriptor is obtained using vkGetFenceFdKHR, if the - handle type is VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR, vkGetFenceFdKHR is allowed to return -1 if the fence - is already signalled, instead of a file descriptor, . In order to make sure that a valid file descriptor is returned - we use vkCmdWaitEvents to make sure that vkQueueSubmit doesn't signal the fence. - */ - vk.cmdWaitEvents(*cmdBuffer, 1, &event.get(), vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, DE_NULL, 0, DE_NULL, 0, DE_NULL); - vk.endCommandBuffer(*cmdBuffer); + // Create a compute shader + const vk::Unique<vk::VkShaderModule> compShader(createShaderModule(vk, device, context.getBinaryCollection().get("compute"), 0u)); + + // Create descriptorSetLayout + vk::DescriptorSetLayoutBuilder layoutBuilder; + layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT); + vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout(layoutBuilder.build(vk, device)); + + // Create compute pipeline + const vk::Unique<vk::VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout)); + const vk::Unique<vk::VkPipeline> computePipeline(compute::makeComputePipeline(vk, device, *pipelineLayout, *compShader)); + + // Create descriptor pool + const vk::Unique<vk::VkDescriptorPool> descriptorPool( + vk::DescriptorPoolBuilder() + .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) + .build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1)); + + + const vk::Move<vk::VkDescriptorSet> descriptorSet (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout)); + const vk::VkDescriptorBufferInfo outputBufferInfo = makeDescriptorBufferInfo(*outputBuffer, 0ull, outputBufferSize); + const vk::VkBufferMemoryBarrier computeFinishBarrier = vk::makeBufferMemoryBarrier(vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_ACCESS_HOST_READ_BIT, *outputBuffer, 0ull, outputBufferSize); + + vk::DescriptorSetUpdateBuilder() + .writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &outputBufferInfo) + .update(vk, device); + + // Now start tuning work size of Y to have time enough to get a fd at the device. + tuneWorkSizeYAndPrepareCommandBuffer(context, vk, device, queue, *cmdBuffer, *descriptorSet, *pipelineLayout, *computePipeline, computeFinishBarrier, *event, &workSize); const vk::VkSubmitInfo submit = { vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, - DE_NULL, + nullptr, 0u, - DE_NULL, - DE_NULL, + nullptr, + nullptr, 1u, &cmdBuffer.get(), @@ -628,11 +779,14 @@ void submitEmptySignalAndGetSemaphoreNative ( const vk::DeviceInterface& vk &semaphore }; + VK_CHECK(vk.queueSubmit(queue, 1, &submit, (vk::VkFence)0u)); getSemaphoreNative(vk, device, semaphore, externalType, nativeHandle); - VK_CHECK(vk.setEvent(device, *event)); + // Allow -1, that is valid if signalled properly. + if (nativeHandle.getFd() == -1) + TCU_CHECK(vk.getEventStatus(device, *event) == vk::VK_EVENT_SET); VK_CHECK(vk.queueWaitIdle(queue)); } @@ -684,16 +838,18 @@ void submitEmptySignal (const vk::DeviceInterface& vkd, VK_CHECK(vkd.queueSubmit(queue, 1, &submit, fence)); } -void submitEmptySignalAndGetFenceNative ( const vk::DeviceInterface& vk, - vk::VkDevice device, - vk::VkQueue queue, - deUint32 queueFamilyIndex, - vk::VkFence fence, - vk::VkExternalFenceHandleTypeFlagBits externalType, - NativeHandle& nativeHandle, - bool expectFenceUnsignaled = true) +void submitAtomicCalculationsAndGetFenceNative (const Context& context, + const vk::DeviceInterface& vk, + vk::VkDevice device, + vk::Allocator& alloc, + vk::VkQueue queue, + deUint32 queueFamilyIndex, + vk::VkFence fence, + vk::VkExternalFenceHandleTypeFlagBits externalType, + NativeHandle& nativeHandle, + bool expectFenceUnsignaled = true) { - const vk::Unique<vk::VkCommandPool> cmdPool(createCommandPool(vk, device, vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex, DE_NULL)); + const vk::Unique<vk::VkCommandPool> cmdPool(createCommandPool(vk, device, vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex, nullptr)); const vk::Unique<vk::VkCommandBuffer> cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY)); const vk::VkEventCreateInfo eventCreateInfo = @@ -703,27 +859,46 @@ void submitEmptySignalAndGetFenceNative ( const vk::DeviceInterface& vk, 0u }; - const vk::Unique<vk::VkEvent> event(createEvent(vk, device, &eventCreateInfo, DE_NULL)); + const vk::Unique<vk::VkEvent> event(createEvent(vk, device, &eventCreateInfo, DE_NULL)); - const vk::VkCommandBufferBeginInfo cmdBufferBeginInfo = - { - vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, - DE_NULL, - vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, - DE_NULL, - }; + const uint32_t maxXWorkSize = getMaxInvocations(context, 0); + const uint32_t maxYWorkSize = getMaxInvocations(context, 1); + + tcu::UVec3 workSize = { maxXWorkSize, maxYWorkSize, 1u }; + const uint32_t workGroupCount = multiplyComponents(workSize); - VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo)); - /* - The submitEmptySignal function calls vkQueueSubmit with an empty VkSubmitInfo structure and a - VkFence to be signalled when the work is finished. Because there is no work in the submission, vkQueueSubmit - could signal the fence immediately. When a fence's file descriptor is obtained using vkGetFenceFdKHR, if the - handle type is VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR, vkGetFenceFdKHR is allowed to return -1 instead of a - file descriptor, if the fence is already signalled. In order to make sure that a valid file descriptor is returned - we use vkCmdWaitEvents to make sure that vkQueueSubmit doesn't signal the fence. - */ - vk.cmdWaitEvents(*cmdBuffer, 1, &event.get(), vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0, DE_NULL, 0, DE_NULL, 0, DE_NULL); - vk.endCommandBuffer(*cmdBuffer); + const vk::VkDeviceSize outputBufferSize = sizeof(uint32_t) * workGroupCount; + const vk::BufferWithMemory outputBuffer (vk, device, alloc, makeBufferCreateInfo(outputBufferSize, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), vk::MemoryRequirement::Local); + + // Create a compute shader + const vk::Unique<vk::VkShaderModule> compShader(createShaderModule(vk, device, context.getBinaryCollection().get("compute"), 0u)); + + // Create descriptorSetLayout + vk::DescriptorSetLayoutBuilder layoutBuilder; + layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT); + vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout(layoutBuilder.build(vk, device)); + + // Create compute pipeline + const vk::Unique<vk::VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout)); + const vk::Unique<vk::VkPipeline> computePipeline(compute::makeComputePipeline(vk, device, *pipelineLayout, *compShader)); + + // Create descriptor pool + const vk::Unique<vk::VkDescriptorPool> descriptorPool( + vk::DescriptorPoolBuilder() + .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) + .build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1)); + + + const vk::Move<vk::VkDescriptorSet> descriptorSet (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout)); + const vk::VkDescriptorBufferInfo outputBufferInfo = makeDescriptorBufferInfo(*outputBuffer, 0ull, outputBufferSize); + const vk::VkBufferMemoryBarrier computeFinishBarrier = vk::makeBufferMemoryBarrier(vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_ACCESS_HOST_READ_BIT, *outputBuffer, 0ull, outputBufferSize); + + vk::DescriptorSetUpdateBuilder() + .writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &outputBufferInfo) + .update(vk, device); + + // Now start tuning work size of Y to have time enough to get a fd at the device. + tuneWorkSizeYAndPrepareCommandBuffer(context, vk, device, queue, *cmdBuffer, *descriptorSet, *pipelineLayout, *computePipeline, computeFinishBarrier, *event, &workSize); const vk::VkSubmitInfo submit = { @@ -744,8 +919,9 @@ void submitEmptySignalAndGetFenceNative ( const vk::DeviceInterface& vk, VK_CHECK(vk.queueSubmit(queue, 1, &submit, fence)); getFenceNative(vk, device, fence, externalType, nativeHandle, expectFenceUnsignaled); - - VK_CHECK(vk.setEvent(device, *event)); + // Allow -1, that is valid if signalled properly. + if (nativeHandle.getFd() == -1) + TCU_CHECK(vk.getEventStatus(device, *event) == vk::VK_EVENT_SET); VK_CHECK(vk.queueWaitIdle(queue)); } @@ -795,6 +971,26 @@ struct SemaphoreTestConfig Permanence permanence; }; +template<class TestConfig> void initProgramsToGetNativeFd(vk::SourceCollections& dst, const TestConfig) +{ + const tcu::IVec3 localSize = { 64, 1, 1 }; + + std::ostringstream src; + src << "#version 310 es\n" + << "layout (local_size_x = " << localSize.x() << ", local_size_y = " << localSize.y() << ", local_size_z = " << localSize.z() << ") in;\n" + << "layout(binding = 0) writeonly buffer Output {\n" + << " uint values[];\n" + << "};\n" + << "\n" + << "void main (void) {\n" + << " uint offset = gl_NumWorkGroups.x*gl_NumWorkGroups.y*gl_WorkGroupID.z + gl_NumWorkGroups.x*gl_WorkGroupID.y + gl_WorkGroupID.x;\n" + << "\n" + << " atomicAdd(values[offset], 1u);\n" + << "}\n"; + + dst.glslSources.add("compute") << glu::ComputeSource(src.str()); +} + tcu::TestStatus testSemaphoreWin32Create (Context& context, const SemaphoreTestConfig config) { @@ -882,12 +1078,17 @@ tcu::TestStatus testSemaphoreImportTwice (Context& context, { const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex)); const vk::DeviceDriver vkd (vkp, instance, *device); + vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice)); const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex)); const vk::Unique<vk::VkSemaphore> semaphore (createExportableSemaphore(vkd, *device, config.externalType)); NativeHandle handleA; if (transference == TRANSFERENCE_COPY) - submitEmptySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphore, config.externalType, handleA); + { + submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphore, config.externalType, handleA); + if (handleA.getFd() == -1) + return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference"); + } else getSemaphoreNative(vkd, *device, *semaphore, config.externalType, handleA); @@ -929,13 +1130,18 @@ tcu::TestStatus testSemaphoreImportReimport (Context& context, { const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex)); const vk::DeviceDriver vkd (vkp, instance, *device); + vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice)); const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex)); const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType)); NativeHandle handleA; if (transference == TRANSFERENCE_COPY) - submitEmptySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handleA); + { + submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, handleA); + if (handleA.getFd() == -1) + return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference"); + } else getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handleA); @@ -969,18 +1175,22 @@ tcu::TestStatus testSemaphoreSignalExportImportWait (Context& context, const vk::InstanceDriver& vki (instance.getDriver()); const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine())); const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u)); + const Transference transference (getHandelTypeTransferences(config.externalType)); checkSemaphoreSupport(vki, physicalDevice, config.externalType); { const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex)); const vk::DeviceDriver vkd (vkp, instance, *device); + vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice)); const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex)); const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType)); { NativeHandle handle; - submitEmptySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle); + submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle); + if (transference == TRANSFERENCE_COPY && handle.getFd() == -1) + return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference"); { const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u; @@ -1053,7 +1263,7 @@ tcu::TestStatus testSemaphoreExportImportSignalWait (Context& context, const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType)); NativeHandle handle; - submitEmptySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle); + getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle); const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags)); @@ -1082,6 +1292,7 @@ tcu::TestStatus testSemaphoreSignalImport (Context& context, const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u; const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex)); const vk::DeviceDriver vkd (vkp, instance, *device); + vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice)); const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex)); const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType)); @@ -1092,7 +1303,11 @@ tcu::TestStatus testSemaphoreSignalImport (Context& context, VK_CHECK(vkd.queueWaitIdle(queue)); if (transference == TRANSFERENCE_COPY) - submitEmptySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle); + { + submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle); + if (handle.getFd() == -1) + return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference"); + } else getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle); @@ -1117,7 +1332,6 @@ tcu::TestStatus testSemaphoreSignalImport (Context& context, tcu::TestStatus testSemaphoreSignalWaitImport (Context& context, const SemaphoreTestConfig config) { - const Transference transference (getHandelTypeTransferences(config.externalType)); const vk::PlatformInterface& vkp (context.getPlatformInterface()); const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u)); const vk::InstanceDriver& vki (instance.getDriver()); @@ -1136,10 +1350,7 @@ tcu::TestStatus testSemaphoreSignalWaitImport (Context& context, const vk::Unique<vk::VkSemaphore> semaphoreB (createSemaphore(vkd, *device)); NativeHandle handle; - if (transference == TRANSFERENCE_COPY) - submitEmptySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle); - else - getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle); + getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle); submitEmptySignal(vkd, queue, *semaphoreB); submitEmptyWait(vkd, queue, *semaphoreB); @@ -1148,15 +1359,8 @@ tcu::TestStatus testSemaphoreSignalWaitImport (Context& context, importSemaphore(vkd, *device, *semaphoreB, config.externalType, handle, flags); - if (transference == TRANSFERENCE_COPY) - submitEmptyWait(vkd, queue, *semaphoreB); - else if (transference == TRANSFERENCE_REFERENCE) - { - submitEmptySignal(vkd, queue, *semaphoreA); - submitEmptyWait(vkd, queue, *semaphoreB); - } - else - DE_FATAL("Unknown transference."); + submitEmptySignal(vkd, queue, *semaphoreA); + submitEmptyWait(vkd, queue, *semaphoreB); VK_CHECK(vkd.queueWaitIdle(queue)); @@ -1193,7 +1397,7 @@ tcu::TestStatus testSemaphoreImportSyncFdSignaled (Context& context, tcu::TestStatus testSemaphoreMultipleExports (Context& context, const SemaphoreTestConfig config) { - const size_t exportCount = 4 * 1024; + const size_t exportCount = 1024; const Transference transference (getHandelTypeTransferences(config.externalType)); const vk::PlatformInterface& vkp (context.getPlatformInterface()); const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u)); @@ -1206,6 +1410,7 @@ tcu::TestStatus testSemaphoreMultipleExports (Context& context, { const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex)); const vk::DeviceDriver vkd (vkp, instance, *device); + vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice)); const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex)); const vk::Unique<vk::VkSemaphore> semaphore (createExportableSemaphore(vkd, *device, config.externalType)); @@ -1214,7 +1419,11 @@ tcu::TestStatus testSemaphoreMultipleExports (Context& context, NativeHandle handle; if (transference == TRANSFERENCE_COPY) - submitEmptySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphore, config.externalType, handle); + { + submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphore, config.externalType, handle); + if (handle.getFd() == -1) + return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference"); + } else getSemaphoreNative(vkd, *device, *semaphore, config.externalType, handle); } @@ -1245,12 +1454,17 @@ tcu::TestStatus testSemaphoreMultipleImports (Context& context, const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u; const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex)); const vk::DeviceDriver vkd (vkp, instance, *device); + vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice)); const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex)); const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType)); NativeHandle handleA; if (transference == TRANSFERENCE_COPY) - submitEmptySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handleA); + { + submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, handleA); + if (handleA.getFd() == -1) + return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference"); + } else getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handleA); @@ -1295,12 +1509,15 @@ tcu::TestStatus testSemaphoreTransference (Context& context, const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u; const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex)); const vk::DeviceDriver vkd (vkp, instance, *device); + vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice)); const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex)); const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType)); NativeHandle handle; - submitEmptySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle); + submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle); + if (transference == TRANSFERENCE_COPY && handle.getFd() == -1) + return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference"); { const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags)); @@ -1388,6 +1605,7 @@ tcu::TestStatus testSemaphoreFdDup (Context& context, const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u; const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex)); const vk::DeviceDriver vkd (vkp, instance, *device); + vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice)); const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex)); TestLog& log = context.getTestContext().getLog(); @@ -1397,7 +1615,11 @@ tcu::TestStatus testSemaphoreFdDup (Context& context, NativeHandle fd; if (transference == TRANSFERENCE_COPY) - submitEmptySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, fd); + { + submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, fd); + if (fd.getFd() == -1) + return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference"); + } else getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, fd); @@ -1451,6 +1673,7 @@ tcu::TestStatus testSemaphoreFdDup2 (Context& context, const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u; const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex)); const vk::DeviceDriver vkd (vkp, instance, *device); + vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice)); const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex)); TestLog& log = context.getTestContext().getLog(); @@ -1462,8 +1685,10 @@ tcu::TestStatus testSemaphoreFdDup2 (Context& context, if (transference == TRANSFERENCE_COPY) { - submitEmptySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, fd); - submitEmptySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreB, config.externalType, secondFd); + submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, fd); + submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreB, config.externalType, secondFd); + if (fd.getFd() == -1 || secondFd.getFd() == -1) + return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference"); } else { @@ -1520,6 +1745,7 @@ tcu::TestStatus testSemaphoreFdDup3 (Context& context, { const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex)); const vk::DeviceDriver vkd (vkp, instance, *device); + vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice)); const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex)); TestLog& log = context.getTestContext().getLog(); @@ -1531,8 +1757,10 @@ tcu::TestStatus testSemaphoreFdDup3 (Context& context, if (transference == TRANSFERENCE_COPY) { - submitEmptySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, fd); - submitEmptySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreB, config.externalType, secondFd); + submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, fd); + submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreB, config.externalType, secondFd); + if (fd.getFd() == -1 || secondFd.getFd() == -1) + return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference"); } else { @@ -1590,6 +1818,7 @@ tcu::TestStatus testSemaphoreFdSendOverSocket (Context& context, { const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex)); const vk::DeviceDriver vkd (vkp, instance, *device); + vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice)); const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex)); TestLog& log = context.getTestContext().getLog(); @@ -1597,7 +1826,11 @@ tcu::TestStatus testSemaphoreFdSendOverSocket (Context& context, NativeHandle fd; if (transference == TRANSFERENCE_COPY) - submitEmptySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphore, config.externalType, fd); + { + submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphore, config.externalType, fd); + if (fd.getFd() == -1) + return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference"); + } else getSemaphoreNative(vkd, *device, *semaphore, config.externalType, fd); @@ -1759,7 +1992,6 @@ struct FenceTestConfig Permanence permanence; }; - tcu::TestStatus testFenceWin32Create (Context& context, const FenceTestConfig config) { @@ -1847,12 +2079,17 @@ tcu::TestStatus testFenceImportTwice (Context& context, { const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex)); const vk::DeviceDriver vkd (vkp, instance, *device); + vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice)); const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex)); const vk::Unique<vk::VkFence> fence (createExportableFence(vkd, *device, config.externalType)); NativeHandle handleA; if (transference == TRANSFERENCE_COPY) - submitEmptySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fence, config.externalType, handleA); + { + submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fence, config.externalType, handleA); + if (handleA.getFd() == -1) + return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference"); + } else getFenceNative(vkd, *device, *fence, config.externalType, handleA); @@ -1894,13 +2131,18 @@ tcu::TestStatus testFenceImportReimport (Context& context, { const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex)); const vk::DeviceDriver vkd (vkp, instance, *device); + vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice)); const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex)); const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType)); NativeHandle handleA; if (transference == TRANSFERENCE_COPY) - submitEmptySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handleA); + { + submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, handleA); + if (handleA.getFd() == -1) + return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference"); + } else getFenceNative(vkd, *device, *fenceA, config.externalType, handleA); @@ -1940,13 +2182,16 @@ tcu::TestStatus testFenceSignalExportImportWait (Context& context, { const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex)); const vk::DeviceDriver vkd (vkp, instance, *device); + vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice)); const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex)); const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType)); { NativeHandle handle; - submitEmptySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handle); + submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, handle); + if (handle.getFd() == -1) + return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference"); { const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u; @@ -2073,6 +2318,7 @@ tcu::TestStatus testFenceSignalImport (Context& context, const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u; const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex)); const vk::DeviceDriver vkd (vkp, instance, *device); + vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice)); const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex)); const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType)); @@ -2083,7 +2329,11 @@ tcu::TestStatus testFenceSignalImport (Context& context, VK_CHECK(vkd.queueWaitIdle(queue)); if (transference == TRANSFERENCE_COPY) - submitEmptySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handle); + { + submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, handle); + if (handle.getFd() == -1) + return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference"); + } else getFenceNative(vkd, *device, *fenceA, config.externalType, handle); @@ -2121,6 +2371,7 @@ tcu::TestStatus testFenceReset (Context& context, const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u; const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex)); const vk::DeviceDriver vkd (vkp, instance, *device); + vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice)); const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex)); const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType)); @@ -2131,7 +2382,10 @@ tcu::TestStatus testFenceReset (Context& context, submitEmptySignal(vkd, queue, *fenceB); VK_CHECK(vkd.queueWaitIdle(queue)); - submitEmptySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handle); + submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, handle); + if (handle.getFd() == -1) + return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference"); + NativeHandle handleB (handle); importFence(vkd, *device, *fenceB, config.externalType, handleB, flags); importFence(vkd, *device, *fenceC, config.externalType, handle, flags); @@ -2173,7 +2427,6 @@ tcu::TestStatus testFenceReset (Context& context, tcu::TestStatus testFenceSignalWaitImport (Context& context, const FenceTestConfig config) { - const Transference transference (getHandelTypeTransferences(config.externalType)); const vk::PlatformInterface& vkp (context.getPlatformInterface()); const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType)); const vk::InstanceDriver& vki (instance.getDriver()); @@ -2192,10 +2445,7 @@ tcu::TestStatus testFenceSignalWaitImport (Context& context, const vk::Unique<vk::VkFence> fenceB (createFence(vkd, *device)); NativeHandle handle; - if (transference == TRANSFERENCE_COPY) - submitEmptySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handle); - else - getFenceNative(vkd, *device, *fenceA, config.externalType, handle); + getFenceNative(vkd, *device, *fenceA, config.externalType, handle); submitEmptySignal(vkd, queue, *fenceB); VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull)); @@ -2204,15 +2454,8 @@ tcu::TestStatus testFenceSignalWaitImport (Context& context, importFence(vkd, *device, *fenceB, config.externalType, handle, flags); - if (transference == TRANSFERENCE_COPY) - VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull)); - else if (transference == TRANSFERENCE_REFERENCE) - { - submitEmptySignal(vkd, queue, *fenceA); - VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull)); - } - else - DE_FATAL("Unknown transference."); + submitEmptySignal(vkd, queue, *fenceA); + VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull)); VK_CHECK(vkd.queueWaitIdle(queue)); @@ -2223,7 +2466,7 @@ tcu::TestStatus testFenceSignalWaitImport (Context& context, tcu::TestStatus testFenceMultipleExports (Context& context, const FenceTestConfig config) { - const size_t exportCount = 4 * 1024; + const size_t exportCount = 1024; const Transference transference (getHandelTypeTransferences(config.externalType)); const vk::PlatformInterface& vkp (context.getPlatformInterface()); const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType)); @@ -2236,6 +2479,7 @@ tcu::TestStatus testFenceMultipleExports (Context& context, { const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex)); const vk::DeviceDriver vkd (vkp, instance, *device); + vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice)); const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex)); const vk::Unique<vk::VkFence> fence (createExportableFence(vkd, *device, config.externalType)); @@ -2244,7 +2488,11 @@ tcu::TestStatus testFenceMultipleExports (Context& context, NativeHandle handle; if (transference == TRANSFERENCE_COPY) - submitEmptySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fence, config.externalType, handle, exportNdx == 0 /* expect fence to be signaled after first pass */); + { + submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fence, config.externalType, handle, exportNdx == 0 /* expect fence to be signaled after first pass */); + if (handle.getFd() == -1) + return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference"); + } else getFenceNative(vkd, *device, *fence, config.externalType, handle, exportNdx == 0 /* expect fence to be signaled after first pass */); } @@ -2275,12 +2523,17 @@ tcu::TestStatus testFenceMultipleImports (Context& context, const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u; const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex)); const vk::DeviceDriver vkd (vkp, instance, *device); + vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice)); const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex)); const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType)); NativeHandle handleA; if (transference == TRANSFERENCE_COPY) - submitEmptySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handleA); + { + submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, handleA); + if (handleA.getFd() == -1) + return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference"); + } else getFenceNative(vkd, *device, *fenceA, config.externalType, handleA); @@ -2325,12 +2578,15 @@ tcu::TestStatus testFenceTransference (Context& context, const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u; const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex)); const vk::DeviceDriver vkd (vkp, instance, *device); + vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice)); const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex)); const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType)); NativeHandle handle; - submitEmptySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handle); + submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, handle); + if (handle.getFd() == -1) + return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference"); { const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handle, flags)); @@ -2424,6 +2680,7 @@ tcu::TestStatus testFenceFdDup (Context& context, const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u; const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex)); const vk::DeviceDriver vkd (vkp, instance, *device); + vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice)); const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex)); TestLog& log = context.getTestContext().getLog(); @@ -2433,7 +2690,11 @@ tcu::TestStatus testFenceFdDup (Context& context, NativeHandle fd; if (transference == TRANSFERENCE_COPY) - submitEmptySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, fd); + { + submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, fd); + if (fd.getFd() == -1) + return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference"); + } else getFenceNative(vkd, *device, *fenceA, config.externalType, fd); @@ -2487,6 +2748,7 @@ tcu::TestStatus testFenceFdDup2 (Context& context, const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u; const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex)); const vk::DeviceDriver vkd (vkp, instance, *device); + vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice)); const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex)); TestLog& log = context.getTestContext().getLog(); @@ -2498,8 +2760,10 @@ tcu::TestStatus testFenceFdDup2 (Context& context, if (transference == TRANSFERENCE_COPY) { - submitEmptySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, fd); - submitEmptySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceB, config.externalType, secondFd); + submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, fd); + submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceB, config.externalType, secondFd); + if (fd.getFd() == -1 || secondFd.getFd() == -1) + return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference"); } else { @@ -2556,6 +2820,7 @@ tcu::TestStatus testFenceFdDup3 (Context& context, { const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex)); const vk::DeviceDriver vkd (vkp, instance, *device); + vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice)); const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex)); TestLog& log = context.getTestContext().getLog(); @@ -2567,8 +2832,10 @@ tcu::TestStatus testFenceFdDup3 (Context& context, if (transference == TRANSFERENCE_COPY) { - submitEmptySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, fd); - submitEmptySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceB, config.externalType, secondFd); + submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, fd); + submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceB, config.externalType, secondFd); + if (fd.getFd() == -1 || secondFd.getFd() == -1) + return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference"); } else { @@ -2626,6 +2893,7 @@ tcu::TestStatus testFenceFdSendOverSocket (Context& context, { const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex)); const vk::DeviceDriver vkd (vkp, instance, *device); + vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice)); const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex)); TestLog& log = context.getTestContext().getLog(); @@ -2633,7 +2901,11 @@ tcu::TestStatus testFenceFdSendOverSocket (Context& context, NativeHandle fd; if (transference == TRANSFERENCE_COPY) - submitEmptySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fence, config.externalType, fd); + { + submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fence, config.externalType, fd); + if (fd.getFd() == -1) + return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference"); + } else getFenceNative(vkd, *device, *fence, config.externalType, fd); @@ -3975,29 +4247,29 @@ de::MovePtr<tcu::TestCaseGroup> createFenceTests (tcu::TestContext& testCtx, vk: addFunctionCase(fenceGroup.get(), std::string("create_win32_") + permanenceName, "Test creating fence with win32 properties.", testFenceWin32Create, config); } - addFunctionCase(fenceGroup.get(), std::string("import_twice_") + permanenceName, "Test importing fence twice.", checkSupport, testFenceImportTwice, config); - addFunctionCase(fenceGroup.get(), std::string("reimport_") + permanenceName, "Test importing again over previously imported fence.", checkSupport, testFenceImportReimport, config); - addFunctionCase(fenceGroup.get(), std::string("import_multiple_times_") + permanenceName, "Test importing fence multiple times.", checkSupport, testFenceMultipleImports, config); - addFunctionCase(fenceGroup.get(), std::string("signal_export_import_wait_") + permanenceName, "Test signaling, exporting, importing and waiting for the sempahore.", checkEvent, testFenceSignalExportImportWait, config); - addFunctionCase(fenceGroup.get(), std::string("signal_import_") + permanenceName, "Test signaling and importing the fence.", checkSupport, testFenceSignalImport, config); - addFunctionCase(fenceGroup.get(), std::string("reset_") + permanenceName, "Test resetting the fence.", checkEvent, testFenceReset, config); - addFunctionCase(fenceGroup.get(), std::string("transference_") + permanenceName, "Test fences transference.", checkEvent, testFenceTransference, config); + addFunctionCaseWithPrograms(fenceGroup.get(), std::string("import_twice_") + permanenceName, "Test importing fence twice.", checkSupport, initProgramsToGetNativeFd, testFenceImportTwice, config); + addFunctionCaseWithPrograms(fenceGroup.get(), std::string("reimport_") + permanenceName, "Test importing again over previously imported fence.", checkSupport, initProgramsToGetNativeFd, testFenceImportReimport, config); + addFunctionCaseWithPrograms(fenceGroup.get(), std::string("import_multiple_times_") + permanenceName, "Test importing fence multiple times.", checkSupport, initProgramsToGetNativeFd, testFenceMultipleImports, config); + addFunctionCaseWithPrograms(fenceGroup.get(), std::string("signal_export_import_wait_") + permanenceName, "Test signaling, exporting, importing and waiting for the sempahore.", checkEvent, initProgramsToGetNativeFd, testFenceSignalExportImportWait, config); + addFunctionCaseWithPrograms(fenceGroup.get(), std::string("signal_import_") + permanenceName, "Test signaling and importing the fence.", checkSupport, initProgramsToGetNativeFd, testFenceSignalImport, config); + addFunctionCaseWithPrograms(fenceGroup.get(), std::string("reset_") + permanenceName, "Test resetting the fence.", checkEvent, initProgramsToGetNativeFd, testFenceReset, config); + addFunctionCaseWithPrograms(fenceGroup.get(), std::string("transference_") + permanenceName, "Test fences transference.", checkEvent, initProgramsToGetNativeFd, testFenceTransference, config); if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT) { - addFunctionCase(fenceGroup.get(), std::string("import_signaled_") + permanenceName, "Test import signaled fence fd.", testFenceImportSyncFdSignaled, config); + addFunctionCaseWithPrograms(fenceGroup.get(), std::string("import_signaled_") + permanenceName, "Test import signaled fence fd.", initProgramsToGetNativeFd, testFenceImportSyncFdSignaled, config); } if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT || externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT) { // \note Not supported on WIN32 handles - addFunctionCase(fenceGroup.get(), std::string("export_multiple_times_") + permanenceName, "Test exporting fence multiple times.", checkSupport, testFenceMultipleExports, config); + addFunctionCaseWithPrograms(fenceGroup.get(), std::string("export_multiple_times_") + permanenceName, "Test exporting fence multiple times.", checkSupport, initProgramsToGetNativeFd, testFenceMultipleExports, config); - addFunctionCase(fenceGroup.get(), std::string("dup_") + permanenceName, "Test calling dup() on exported fence.", checkSupport, testFenceFdDup, config); - addFunctionCase(fenceGroup.get(), std::string("dup2_") + permanenceName, "Test calling dup2() on exported fence.", checkSupport, testFenceFdDup2, config); - addFunctionCase(fenceGroup.get(), std::string("dup3_") + permanenceName, "Test calling dup3() on exported fence.", checkSupport, testFenceFdDup3, config); - addFunctionCase(fenceGroup.get(), std::string("send_over_socket_") + permanenceName, "Test sending fence fd over socket.", checkSupport, testFenceFdSendOverSocket, config); + addFunctionCaseWithPrograms(fenceGroup.get(), std::string("dup_") + permanenceName, "Test calling dup() on exported fence.", checkSupport, initProgramsToGetNativeFd, testFenceFdDup, config); + addFunctionCaseWithPrograms(fenceGroup.get(), std::string("dup2_") + permanenceName, "Test calling dup2() on exported fence.", checkSupport, initProgramsToGetNativeFd, testFenceFdDup2, config); + addFunctionCaseWithPrograms(fenceGroup.get(), std::string("dup3_") + permanenceName, "Test calling dup3() on exported fence.", checkSupport, initProgramsToGetNativeFd, testFenceFdDup3, config); + addFunctionCaseWithPrograms(fenceGroup.get(), std::string("send_over_socket_") + permanenceName, "Test sending fence fd over socket.", checkSupport, initProgramsToGetNativeFd, testFenceFdSendOverSocket, config); } if (getHandelTypeTransferences(externalType) == TRANSFERENCE_REFERENCE) @@ -4376,16 +4648,16 @@ de::MovePtr<tcu::TestCaseGroup> createSemaphoreTests (tcu::TestContext& testCtx, addFunctionCase(semaphoreGroup.get(), std::string("create_win32_") + permanenceName, "Test creating semaphore with win32 properties.", testSemaphoreWin32Create, config); } - addFunctionCase(semaphoreGroup.get(), std::string("import_twice_") + permanenceName, "Test importing semaphore twice.", checkSupport, testSemaphoreImportTwice, config); - addFunctionCase(semaphoreGroup.get(), std::string("reimport_") + permanenceName, "Test importing again over previously imported semaphore.", checkSupport, testSemaphoreImportReimport, config); - addFunctionCase(semaphoreGroup.get(), std::string("import_multiple_times_") + permanenceName, "Test importing semaphore multiple times.", checkSupport, testSemaphoreMultipleImports, config); - addFunctionCase(semaphoreGroup.get(), std::string("signal_export_import_wait_") + permanenceName, "Test signaling, exporting, importing and waiting for the sempahore.", checkEvent, testSemaphoreSignalExportImportWait, config); - addFunctionCase(semaphoreGroup.get(), std::string("signal_import_") + permanenceName, "Test signaling and importing the semaphore.", checkSupport, testSemaphoreSignalImport, config); - addFunctionCase(semaphoreGroup.get(), std::string("transference_") + permanenceName, "Test semaphores transference.", checkEvent, testSemaphoreTransference, config); + addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("import_twice_") + permanenceName, "Test importing semaphore twice.", checkSupport, initProgramsToGetNativeFd, testSemaphoreImportTwice, config); + addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("reimport_") + permanenceName, "Test importing again over previously imported semaphore.", checkSupport, initProgramsToGetNativeFd, testSemaphoreImportReimport, config); + addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("import_multiple_times_") + permanenceName, "Test importing semaphore multiple times.", checkSupport, initProgramsToGetNativeFd, testSemaphoreMultipleImports, config); + addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("signal_export_import_wait_") + permanenceName, "Test signaling, exporting, importing and waiting for the sempahore.", checkEvent, initProgramsToGetNativeFd, testSemaphoreSignalExportImportWait, config); + addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("signal_import_") + permanenceName, "Test signaling and importing the semaphore.", checkSupport, initProgramsToGetNativeFd, testSemaphoreSignalImport, config); + addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("transference_") + permanenceName, "Test semaphores transference.", checkEvent, initProgramsToGetNativeFd, testSemaphoreTransference, config); if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT) { - addFunctionCase(semaphoreGroup.get(), std::string("import_signaled_") + permanenceName, "Test import signaled semaphore fd.", testSemaphoreImportSyncFdSignaled, config); + addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("import_signaled_") + permanenceName, "Test import signaled semaphore fd.", initProgramsToGetNativeFd, testSemaphoreImportSyncFdSignaled, config); } @@ -4393,12 +4665,12 @@ de::MovePtr<tcu::TestCaseGroup> createSemaphoreTests (tcu::TestContext& testCtx, || externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT) { // \note Not supported on WIN32 handles - addFunctionCase(semaphoreGroup.get(), std::string("export_multiple_times_") + permanenceName, "Test exporting semaphore multiple times.", checkSupport, testSemaphoreMultipleExports, config); + addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("export_multiple_times_") + permanenceName, "Test exporting semaphore multiple times.", checkSupport, initProgramsToGetNativeFd, testSemaphoreMultipleExports, config); - addFunctionCase(semaphoreGroup.get(), std::string("dup_") + permanenceName, "Test calling dup() on exported semaphore.", checkSupport, testSemaphoreFdDup, config); - addFunctionCase(semaphoreGroup.get(), std::string("dup2_") + permanenceName, "Test calling dup2() on exported semaphore.", checkSupport, testSemaphoreFdDup2, config); - addFunctionCase(semaphoreGroup.get(), std::string("dup3_") + permanenceName, "Test calling dup3() on exported semaphore.", checkSupport, testSemaphoreFdDup3, config); - addFunctionCase(semaphoreGroup.get(), std::string("send_over_socket_") + permanenceName, "Test sending semaphore fd over socket.", checkSupport, testSemaphoreFdSendOverSocket, config); + addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("dup_") + permanenceName, "Test calling dup() on exported semaphore.", checkSupport, initProgramsToGetNativeFd, testSemaphoreFdDup, config); + addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("dup2_") + permanenceName, "Test calling dup2() on exported semaphore.", checkSupport, initProgramsToGetNativeFd, testSemaphoreFdDup2, config); + addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("dup3_") + permanenceName, "Test calling dup3() on exported semaphore.", checkSupport, initProgramsToGetNativeFd, testSemaphoreFdDup3, config); + addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("send_over_socket_") + permanenceName, "Test sending semaphore fd over socket.", checkSupport, initProgramsToGetNativeFd, testSemaphoreFdSendOverSocket, config); } if (getHandelTypeTransferences(externalType) == TRANSFERENCE_REFERENCE) diff --git a/external/vulkancts/modules/vulkan/memory/vktMemoryExternalMemoryHostTests.cpp b/external/vulkancts/modules/vulkan/memory/vktMemoryExternalMemoryHostTests.cpp index d5d3e50e4..c340f265a 100644 --- a/external/vulkancts/modules/vulkan/memory/vktMemoryExternalMemoryHostTests.cpp +++ b/external/vulkancts/modules/vulkan/memory/vktMemoryExternalMemoryHostTests.cpp @@ -169,7 +169,6 @@ protected: Move<VkCommandBuffer> m_cmdBufferCopy; Move<VkFence> m_fence_1; Move<VkFence> m_fence_2; - Move<VkEvent> m_event; }; ExternalMemoryHostBaseTestInstance::ExternalMemoryHostBaseTestInstance (Context& context, VkDeviceSize allocationSize) @@ -843,8 +842,6 @@ tcu::TestStatus ExternalMemoryHostSynchronizationTestInstance::iterate () m_cmdPool = createCommandPool(m_vkd, m_device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex); m_cmdBuffer = allocateCommandBuffer(m_vkd, m_device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY); m_cmdBufferCopy = allocateCommandBuffer(m_vkd, m_device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY); - - m_event = createEvent(m_vkd, m_device); m_fence_1 = createFence(m_vkd, m_device); m_fence_2 = createFence(m_vkd, m_device); @@ -860,7 +857,35 @@ tcu::TestStatus ExternalMemoryHostSynchronizationTestInstance::iterate () endCommandBuffer(m_vkd, *m_cmdBufferCopy); submitCommands(*m_cmdBuffer, *m_fence_1); - submitCommands(*m_cmdBufferCopy, *m_fence_2); + + const uint64_t semaphoreWaitValue = 1ull; + const VkPipelineStageFlags semaphoreWaitStage = VK_PIPELINE_STAGE_TRANSFER_BIT; + const auto semaphore = createSemaphoreType(m_vkd, m_device, VK_SEMAPHORE_TYPE_TIMELINE); + + // Use timeline semaphore to signal from host. + const VkTimelineSemaphoreSubmitInfo timelineWaitSubmitInfo = + { + VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + 1u, // uint32_t waitSemaphoreValueCount; + &semaphoreWaitValue, // const uint64_t* pWaitSemaphoreValues; + 0u, // uint32_t signalSemaphoreValueCount; + nullptr, // const uint64_t* pSignalSemaphoreValues; + }; + + const VkSubmitInfo submit = + { + VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType; + &timelineWaitSubmitInfo, // const void* pNext; + 1u, // uint32_t waitSemaphoreCount; + &semaphore.get(), // const VkSemaphore* pWaitSemaphores; + &semaphoreWaitStage, // const VkPipelineStageFlags* pWaitDstStageMask; + 1u, // uint32_t commandBufferCount; + &m_cmdBufferCopy.get(), // const VkCommandBuffer* pCommandBuffers; + 0u, // uint32_t signalSemaphoreCount; + nullptr, // const VkSemaphore* pSignalSemaphores; + }; + VK_CHECK(m_vkd.queueSubmit(m_queue, 1u, &submit, *m_fence_2)); //wait for fence_1 and modify image on host VK_CHECK(m_vkd.waitForFences(m_device, 1u, &m_fence_1.get(), DE_TRUE, ~0ull)); @@ -873,7 +898,17 @@ tcu::TestStatus ExternalMemoryHostSynchronizationTestInstance::iterate () if (deMemCmp(m_hostMemoryAlloc, pointerReturnedByMapMemory, (size_t)dataBufferSize) != 0) TCU_FAIL("Failed memcmp check."); m_vkd.unmapMemory(m_device, *m_deviceMemoryAllocatedFromHostPointer); - VK_CHECK(m_vkd.setEvent(m_device, *m_event)); + + // Signal from host + const vk::VkSemaphoreSignalInfo signalInfo = + { + vk::VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + semaphore.get(), // VkSemaphore semaphore; + semaphoreWaitValue, // uint64_t value; + }; + + VK_CHECK(m_vkd.signalSemaphore(m_device, &signalInfo)); //wait for fence_2 before checking result VK_CHECK(m_vkd.waitForFences(m_device, 1u, &m_fence_2.get(), DE_TRUE, ~0ull)); @@ -912,19 +947,6 @@ void ExternalMemoryHostSynchronizationTestInstance::prepareBufferForHostAccess ( void ExternalMemoryHostSynchronizationTestInstance::copyResultBuffertoBuffer (VkDeviceSize size) { - const VkBufferMemoryBarrier bufferBarrier = - { - VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; - DE_NULL, // const void* pNext; - VK_ACCESS_HOST_WRITE_BIT, // VkAccessFlags srcAccessMask; - VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask; - VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; - VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; - *m_dataBuffer, // VkBuffer buffer; - 0u, // VkDeviceSize offset; - size // VkDeviceSize size; - }; - const VkBufferCopy region_all = { 0, //VkDeviceSize srcOffset; @@ -932,7 +954,6 @@ void ExternalMemoryHostSynchronizationTestInstance::copyResultBuffertoBuffer (Vk size //VkDeviceSize size; }; - m_vkd.cmdWaitEvents(*m_cmdBufferCopy, 1, &m_event.get(), VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, DE_NULL, 1, &bufferBarrier, 0, DE_NULL); m_vkd.cmdCopyBuffer(*m_cmdBufferCopy, *m_dataBuffer, *m_resultBuffer, 1, ®ion_all); } @@ -1067,11 +1088,10 @@ void checkSupport (Context& context) context.requireDeviceFunctionality("VK_EXT_external_memory_host"); } -void checkEvent (Context& context) +void checkTimelineSemaphore (Context& context) { checkSupport(context); - if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") && !context.getPortabilitySubsetFeatures().events) - TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Events are not supported by this implementation"); + context.requireDeviceFunctionality("VK_KHR_timeline_semaphore"); } } // unnamed namespace @@ -1119,7 +1139,7 @@ tcu::TestCaseGroup* createMemoryExternalMemoryHostTests (tcu::TestContext& testC synchronization->addChild(new InstanceFactory1WithSupport<ExternalMemoryHostSynchronizationTestInstance, TestParams, FunctionSupport0, AddPrograms> (testCtx, tcu::NODETYPE_SELF_VALIDATE, "synchronization", "synchronization", AddPrograms(), - TestParams(testFormats[0].format, true), checkEvent)); + TestParams(testFormats[0].format, true), checkTimelineSemaphore)); group->addChild(synchronization.release()); return group.release(); } diff --git a/external/vulkancts/modules/vulkan/util/vktExternalMemoryUtil.cpp b/external/vulkancts/modules/vulkan/util/vktExternalMemoryUtil.cpp index cee510284..4cb73b177 100644 --- a/external/vulkancts/modules/vulkan/util/vktExternalMemoryUtil.cpp +++ b/external/vulkancts/modules/vulkan/util/vktExternalMemoryUtil.cpp @@ -614,7 +614,7 @@ void getFenceNative (const vk::DeviceInterface& vkd, if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT) { - TCU_CHECK(!expectFenceUnsignaled || (fd >= 0)); + TCU_CHECK(!expectFenceUnsignaled || (fd >= 0) || (fd == -1)); } else { @@ -803,7 +803,12 @@ void getSemaphoreNative (const vk::DeviceInterface& vkd, int fd = -1; VK_CHECK(vkd.getSemaphoreFdKHR(device, &info, &fd)); - TCU_CHECK(fd >= 0); + + if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT) + TCU_CHECK(fd >= -1); + else + TCU_CHECK(fd >= 0); + nativeHandle = fd; } else if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT |