1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2016 Google Inc.
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
19 * \brief Vulkan external memory API tests
20 *//*--------------------------------------------------------------------*/
22 #include "vktApiExternalMemoryTests.hpp"
23 #include "vktCustomInstancesDevices.hpp"
25 #include "vktTestCaseUtil.hpp"
26 #include "vkRefUtil.hpp"
27 #include "vkDeviceUtil.hpp"
28 #include "vkQueryUtil.hpp"
29 #include "vkPlatform.hpp"
30 #include "vkMemUtil.hpp"
31 #include "vkApiVersion.hpp"
32 #include "vkImageUtil.hpp"
34 #include "tcuTestLog.hpp"
35 #include "tcuCommandLine.hpp"
37 #include "deUniquePtr.hpp"
38 #include "deStringUtil.hpp"
39 #include "deRandom.hpp"
43 #include "vktExternalMemoryUtil.hpp"
45 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
49 # include <sys/types.h>
50 # include <sys/socket.h>
53 #if (DE_OS == DE_OS_WIN32)
54 # define WIN32_LEAN_AND_MEAN
60 using namespace vkt::ExternalMemoryUtil;
70 std::string getFormatCaseName (vk::VkFormat format)
72 return de::toLower(de::toString(getFormatStr(format)).substr(10));
75 vk::VkMemoryDedicatedRequirements getMemoryDedicatedRequirements (const vk::DeviceInterface& vkd,
79 const vk::VkBufferMemoryRequirementsInfo2 requirementInfo =
81 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2,
85 vk::VkMemoryDedicatedRequirements dedicatedRequirements =
87 vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
92 vk::VkMemoryRequirements2 requirements =
94 vk::VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
95 &dedicatedRequirements,
99 vkd.getBufferMemoryRequirements2(device, &requirementInfo, &requirements);
101 return dedicatedRequirements;
104 vk::VkMemoryDedicatedRequirements getMemoryDedicatedRequirements (const vk::DeviceInterface& vkd,
108 const vk::VkImageMemoryRequirementsInfo2 requirementInfo =
110 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
114 vk::VkMemoryDedicatedRequirements dedicatedRequirements =
116 vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
121 vk::VkMemoryRequirements2 requirements =
123 vk::VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
124 &dedicatedRequirements,
128 vkd.getImageMemoryRequirements2(device, &requirementInfo, &requirements);
130 return dedicatedRequirements;
133 void writeHostMemory (const vk::DeviceInterface& vkd,
135 vk::VkDeviceMemory memory,
139 void* const ptr = vk::mapMemory(vkd, device, memory, 0, size, 0);
141 deMemcpy(ptr, data, size);
143 flushMappedMemoryRange(vkd, device, memory, 0, VK_WHOLE_SIZE);
145 vkd.unmapMemory(device, memory);
148 void checkHostMemory (const vk::DeviceInterface& vkd,
150 vk::VkDeviceMemory memory,
154 void* const ptr = vk::mapMemory(vkd, device, memory, 0, size, 0);
156 invalidateMappedMemoryRange(vkd, device, memory, 0, VK_WHOLE_SIZE);
158 if (deMemCmp(ptr, data, size) != 0)
159 TCU_FAIL("Memory contents don't match");
161 vkd.unmapMemory(device, memory);
164 std::vector<deUint8> genTestData (deUint32 seed, size_t size)
166 de::Random rng (seed);
167 std::vector<deUint8> data (size);
169 for (size_t ndx = 0; ndx < size; ndx++)
171 data[ndx] = rng.getUint8();
177 deUint32 chooseQueueFamilyIndex (const vk::InstanceInterface& vki,
178 vk::VkPhysicalDevice device,
179 vk::VkQueueFlags requireFlags)
181 const std::vector<vk::VkQueueFamilyProperties> properties (vk::getPhysicalDeviceQueueFamilyProperties(vki, device));
183 for (deUint32 queueFamilyIndex = 0; queueFamilyIndex < (deUint32)properties.size(); queueFamilyIndex++)
185 if ((properties[queueFamilyIndex].queueFlags & requireFlags) == requireFlags)
186 return queueFamilyIndex;
189 TCU_THROW(NotSupportedError, "Queue type not supported");
192 std::vector<std::string> getInstanceExtensions (const deUint32 instanceVersion,
193 const vk::VkExternalSemaphoreHandleTypeFlags externalSemaphoreTypes,
194 const vk::VkExternalMemoryHandleTypeFlags externalMemoryTypes,
195 const vk::VkExternalFenceHandleTypeFlags externalFenceTypes)
197 std::vector<std::string> instanceExtensions;
199 if (!vk::isCoreInstanceExtension(instanceVersion, "VK_KHR_get_physical_device_properties2"))
200 instanceExtensions.push_back("VK_KHR_get_physical_device_properties2");
202 if (externalSemaphoreTypes != 0)
203 if (!vk::isCoreInstanceExtension(instanceVersion, "VK_KHR_external_semaphore_capabilities"))
204 instanceExtensions.push_back("VK_KHR_external_semaphore_capabilities");
206 if (externalMemoryTypes != 0)
207 if (!vk::isCoreInstanceExtension(instanceVersion, "VK_KHR_external_memory_capabilities"))
208 instanceExtensions.push_back("VK_KHR_external_memory_capabilities");
210 if (externalFenceTypes != 0)
211 if (!vk::isCoreInstanceExtension(instanceVersion, "VK_KHR_external_fence_capabilities"))
212 instanceExtensions.push_back("VK_KHR_external_fence_capabilities");
214 return instanceExtensions;
217 CustomInstance createTestInstance (Context& context,
218 const vk::VkExternalSemaphoreHandleTypeFlags externalSemaphoreTypes,
219 const vk::VkExternalMemoryHandleTypeFlags externalMemoryTypes,
220 const vk::VkExternalFenceHandleTypeFlags externalFenceTypes)
224 return vkt::createCustomInstanceWithExtensions(context, getInstanceExtensions(context.getUsedApiVersion(), externalSemaphoreTypes, externalMemoryTypes, externalFenceTypes));
226 catch (const vk::Error& error)
228 if (error.getError() == vk::VK_ERROR_EXTENSION_NOT_PRESENT)
229 TCU_THROW(NotSupportedError, "Required extensions not supported");
235 vk::Move<vk::VkDevice> createTestDevice (const Context& context,
236 const vk::PlatformInterface& vkp,
237 vk::VkInstance instance,
238 const vk::InstanceInterface& vki,
239 vk::VkPhysicalDevice physicalDevice,
240 const vk::VkExternalSemaphoreHandleTypeFlags externalSemaphoreTypes,
241 const vk::VkExternalMemoryHandleTypeFlags externalMemoryTypes,
242 const vk::VkExternalFenceHandleTypeFlags externalFenceTypes,
243 deUint32 queueFamilyIndex,
244 bool useDedicatedAllocs = false,
245 void * protectedFeatures = DE_NULL)
247 const deUint32 apiVersion = context.getUsedApiVersion();
248 bool useExternalSemaphore = false;
249 bool useExternalFence = false;
250 bool useExternalMemory = false;
251 std::vector<const char*> deviceExtensions;
253 if ((externalSemaphoreTypes
254 & (vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT
255 | vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT)) != 0)
257 deviceExtensions.push_back("VK_KHR_external_semaphore_fd");
258 useExternalSemaphore = true;
261 if ((externalFenceTypes
262 & (vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT
263 | vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT)) != 0)
265 deviceExtensions.push_back("VK_KHR_external_fence_fd");
266 useExternalFence = true;
269 if (useDedicatedAllocs)
271 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_dedicated_allocation"))
272 deviceExtensions.push_back("VK_KHR_dedicated_allocation");
273 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_get_memory_requirements2"))
274 deviceExtensions.push_back("VK_KHR_get_memory_requirements2");
277 if ((externalMemoryTypes
278 & (vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT
279 | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT)) != 0)
281 deviceExtensions.push_back("VK_KHR_external_memory_fd");
282 useExternalMemory = true;
285 if ((externalMemoryTypes
286 & vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT) != 0)
288 deviceExtensions.push_back("VK_EXT_external_memory_dma_buf");
289 useExternalMemory = true;
292 if ((externalSemaphoreTypes
293 & (vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
294 | vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)) != 0)
296 deviceExtensions.push_back("VK_KHR_external_semaphore_win32");
297 useExternalSemaphore = true;
300 if ((externalFenceTypes
301 & (vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT
302 | vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)) != 0)
304 deviceExtensions.push_back("VK_KHR_external_fence_win32");
305 useExternalFence = true;
308 if ((externalMemoryTypes
309 & (vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
310 | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT
311 | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT
312 | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT
313 | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT
314 | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT)) != 0)
316 deviceExtensions.push_back("VK_KHR_external_memory_win32");
317 useExternalMemory = true;
320 if ((externalMemoryTypes
321 & vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID) != 0)
323 deviceExtensions.push_back("VK_ANDROID_external_memory_android_hardware_buffer");
324 useExternalMemory = true;
325 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_sampler_ycbcr_conversion"))
326 deviceExtensions.push_back("VK_KHR_sampler_ycbcr_conversion");
327 if (!vk::isCoreDeviceExtension(apiVersion, "VK_EXT_queue_family_foreign"))
328 deviceExtensions.push_back("VK_EXT_queue_family_foreign");
331 if (useExternalSemaphore)
333 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_external_semaphore"))
334 deviceExtensions.push_back("VK_KHR_external_semaphore");
337 if (useExternalFence)
339 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_external_fence"))
340 deviceExtensions.push_back("VK_KHR_external_fence");
343 if (useExternalMemory)
345 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_external_memory"))
346 deviceExtensions.push_back("VK_KHR_external_memory");
349 const float priority = 0.5f;
350 const vk::VkDeviceQueueCreateInfo queues[] =
353 vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
362 const vk::VkDeviceCreateInfo deviceCreateInfo =
364 vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
368 DE_LENGTH_OF_ARRAY(queues),
374 (deUint32)deviceExtensions.size(),
375 deviceExtensions.empty() ? DE_NULL : &deviceExtensions[0],
381 return createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), vkp, instance, vki, physicalDevice, &deviceCreateInfo);
383 catch (const vk::Error& error)
385 if (error.getError() == vk::VK_ERROR_EXTENSION_NOT_PRESENT)
386 TCU_THROW(NotSupportedError, "Required extensions not supported");
392 vk::VkQueue getQueue (const vk::DeviceInterface& vkd,
394 deUint32 queueFamilyIndex)
398 vkd.getDeviceQueue(device, queueFamilyIndex, 0, &queue);
403 void checkSemaphoreSupport (const vk::InstanceInterface& vki,
404 vk::VkPhysicalDevice device,
405 vk::VkExternalSemaphoreHandleTypeFlagBits externalType)
407 const vk::VkPhysicalDeviceExternalSemaphoreInfo info =
409 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO,
413 vk::VkExternalSemaphoreProperties properties =
415 vk::VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES,
422 vki.getPhysicalDeviceExternalSemaphoreProperties(device, &info, &properties);
424 if ((properties.externalSemaphoreFeatures & vk::VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT) == 0)
425 TCU_THROW(NotSupportedError, "Semaphore doesn't support exporting in external type");
427 if ((properties.externalSemaphoreFeatures & vk::VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT) == 0)
428 TCU_THROW(NotSupportedError, "Semaphore doesn't support importing in external type");
431 void checkFenceSupport (const vk::InstanceInterface& vki,
432 vk::VkPhysicalDevice device,
433 vk::VkExternalFenceHandleTypeFlagBits externalType)
435 const vk::VkPhysicalDeviceExternalFenceInfo info =
437 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO,
441 vk::VkExternalFenceProperties properties =
443 vk::VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES,
450 vki.getPhysicalDeviceExternalFenceProperties(device, &info, &properties);
452 if ((properties.externalFenceFeatures & vk::VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT) == 0)
453 TCU_THROW(NotSupportedError, "Fence doesn't support exporting in external type");
455 if ((properties.externalFenceFeatures & vk::VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT) == 0)
456 TCU_THROW(NotSupportedError, "Fence doesn't support importing in external type");
459 void checkBufferSupport (const vk::InstanceInterface& vki,
460 vk::VkPhysicalDevice device,
461 vk::VkExternalMemoryHandleTypeFlagBits externalType,
462 vk::VkBufferViewCreateFlags createFlag,
463 vk::VkBufferUsageFlags usageFlag,
466 const vk::VkPhysicalDeviceExternalBufferInfo info =
468 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO,
475 vk::VkExternalBufferProperties properties =
477 vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES,
483 vki.getPhysicalDeviceExternalBufferProperties(device, &info, &properties);
485 if ((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) == 0)
486 TCU_THROW(NotSupportedError, "External handle type doesn't support exporting buffer");
488 if ((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) == 0)
489 TCU_THROW(NotSupportedError, "External handle type doesn't support importing buffer");
491 if (!dedicated && (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0)
492 TCU_THROW(NotSupportedError, "External handle type requires dedicated allocation");
495 void checkImageSupport (const vk::InstanceInterface& vki,
496 vk::VkPhysicalDevice device,
497 vk::VkExternalMemoryHandleTypeFlagBits externalType,
498 vk::VkImageViewCreateFlags createFlag,
499 vk::VkImageUsageFlags usageFlag,
501 vk::VkImageTiling tiling,
504 const vk::VkPhysicalDeviceExternalImageFormatInfo externalInfo =
506 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
510 const vk::VkPhysicalDeviceImageFormatInfo2 info =
512 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
516 vk::VK_IMAGE_TYPE_2D,
521 vk::VkExternalImageFormatProperties externalProperties =
523 vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES,
527 vk::VkImageFormatProperties2 properties =
529 vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
540 vki.getPhysicalDeviceImageFormatProperties2(device, &info, &properties);
542 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) == 0)
543 TCU_THROW(NotSupportedError, "External handle type doesn't support exporting image");
545 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) == 0)
546 TCU_THROW(NotSupportedError, "External handle type doesn't support importing image");
548 if (!dedicated && (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0)
549 TCU_THROW(NotSupportedError, "External handle type requires dedicated allocation");
552 void submitEmptySignal (const vk::DeviceInterface& vkd,
554 vk::VkSemaphore semaphore)
556 const vk::VkSubmitInfo submit =
558 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
572 VK_CHECK(vkd.queueSubmit(queue, 1, &submit, (vk::VkFence)0u));
575 void submitEmptySignalAndGetSemaphoreNative ( const vk::DeviceInterface& vk,
578 deUint32 queueFamilyIndex,
579 vk::VkSemaphore semaphore,
580 vk::VkExternalSemaphoreHandleTypeFlagBits externalType,
581 NativeHandle& nativeHandle)
583 const vk::Unique<vk::VkCommandPool> cmdPool(createCommandPool(vk, device, vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex, DE_NULL));
584 const vk::Unique<vk::VkCommandBuffer> cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
586 const vk::VkEventCreateInfo eventCreateInfo =
588 vk::VK_STRUCTURE_TYPE_EVENT_CREATE_INFO,
593 const vk::Unique<vk::VkEvent> event(createEvent(vk, device, &eventCreateInfo, DE_NULL));
595 const vk::VkCommandBufferBeginInfo cmdBufferBeginInfo =
597 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
599 vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
603 VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
605 The submitEmptySignal function calls vkQueueSubmit with an empty VkSubmitInfo structure and a
606 VkSemaphore to be signalled when the work is finished. Because there is no work in the submission, vkQueueSubmit
607 may signal the semaphore immediately. When a semaphore's file descriptor is obtained using vkGetFenceFdKHR, if the
608 handle type is VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR, vkGetFenceFdKHR is allowed to return -1 if the fence
609 is already signalled, instead of a file descriptor, . In order to make sure that a valid file descriptor is returned
610 we use vkCmdWaitEvents to make sure that vkQueueSubmit doesn't signal the fence.
612 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);
613 vk.endCommandBuffer(*cmdBuffer);
615 const vk::VkSubmitInfo submit =
617 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
631 VK_CHECK(vk.queueSubmit(queue, 1, &submit, (vk::VkFence)0u));
633 getSemaphoreNative(vk, device, semaphore, externalType, nativeHandle);
635 VK_CHECK(vk.setEvent(device, *event));
637 VK_CHECK(vk.queueWaitIdle(queue));
640 void submitEmptyWait (const vk::DeviceInterface& vkd,
642 vk::VkSemaphore semaphore)
644 const vk::VkPipelineStageFlags stage = vk::VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
645 const vk::VkSubmitInfo submit =
647 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
661 VK_CHECK(vkd.queueSubmit(queue, 1, &submit, (vk::VkFence)0u));
664 void submitEmptySignal (const vk::DeviceInterface& vkd,
668 const vk::VkSubmitInfo submit =
670 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
684 VK_CHECK(vkd.queueSubmit(queue, 1, &submit, fence));
687 void submitEmptySignalAndGetFenceNative ( const vk::DeviceInterface& vk,
690 deUint32 queueFamilyIndex,
692 vk::VkExternalFenceHandleTypeFlagBits externalType,
693 NativeHandle& nativeHandle,
694 bool expectFenceUnsignaled = true)
696 const vk::Unique<vk::VkCommandPool> cmdPool(createCommandPool(vk, device, vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex, DE_NULL));
697 const vk::Unique<vk::VkCommandBuffer> cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
699 const vk::VkEventCreateInfo eventCreateInfo =
701 vk::VK_STRUCTURE_TYPE_EVENT_CREATE_INFO,
706 const vk::Unique<vk::VkEvent> event(createEvent(vk, device, &eventCreateInfo, DE_NULL));
708 const vk::VkCommandBufferBeginInfo cmdBufferBeginInfo =
710 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
712 vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
716 VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
718 The submitEmptySignal function calls vkQueueSubmit with an empty VkSubmitInfo structure and a
719 VkFence to be signalled when the work is finished. Because there is no work in the submission, vkQueueSubmit
720 could signal the fence immediately. When a fence's file descriptor is obtained using vkGetFenceFdKHR, if the
721 handle type is VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR, vkGetFenceFdKHR is allowed to return -1 instead of a
722 file descriptor, if the fence is already signalled. In order to make sure that a valid file descriptor is returned
723 we use vkCmdWaitEvents to make sure that vkQueueSubmit doesn't signal the fence.
725 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);
726 vk.endCommandBuffer(*cmdBuffer);
728 const vk::VkSubmitInfo submit =
730 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
744 VK_CHECK(vk.queueSubmit(queue, 1, &submit, fence));
746 getFenceNative(vk, device, fence, externalType, nativeHandle, expectFenceUnsignaled);
748 VK_CHECK(vk.setEvent(device, *event));
750 VK_CHECK(vk.queueWaitIdle(queue));
753 struct TestSemaphoreQueriesParameters
755 vk::VkSemaphoreType semaphoreType;
756 vk::VkExternalSemaphoreHandleTypeFlagBits externalType;
758 TestSemaphoreQueriesParameters (vk::VkSemaphoreType semaphoreType_,
759 vk::VkExternalSemaphoreHandleTypeFlagBits externalType_)
760 : semaphoreType (semaphoreType_)
761 , externalType (externalType_)
765 tcu::TestStatus testSemaphoreQueries (Context& context, const TestSemaphoreQueriesParameters params)
767 const CustomInstance instance (createTestInstance(context, params.externalType, 0u, 0u));
768 const vk::InstanceDriver& vki (instance.getDriver());
769 const vk::VkPhysicalDevice device (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
771 TestLog& log = context.getTestContext().getLog();
773 const vk::VkSemaphoreTypeCreateInfo semaphoreTypeInfo =
775 vk::VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO,
777 params.semaphoreType,
780 const vk::VkPhysicalDeviceExternalSemaphoreInfo info =
782 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO,
786 vk::VkExternalSemaphoreProperties properties =
788 vk::VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES,
795 vki.getPhysicalDeviceExternalSemaphoreProperties(device, &info, &properties);
796 log << TestLog::Message << properties << TestLog::EndMessage;
798 TCU_CHECK(properties.pNext == DE_NULL);
799 TCU_CHECK(properties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES);
801 if (params.semaphoreType == vk::VK_SEMAPHORE_TYPE_TIMELINE)
803 context.requireDeviceFunctionality("VK_KHR_timeline_semaphore");
805 if (properties.compatibleHandleTypes & vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT)
806 return tcu::TestStatus::fail("Timeline semaphores are not compatible with SYNC_FD");
808 if (properties.exportFromImportedHandleTypes & vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT)
809 return tcu::TestStatus::fail("Timeline semaphores imported from SYNC_FD");
812 return tcu::TestStatus::pass("Pass");
815 struct SemaphoreTestConfig
817 SemaphoreTestConfig (vk::VkExternalSemaphoreHandleTypeFlagBits externalType_,
818 Permanence permanence_)
819 : externalType (externalType_)
820 , permanence (permanence_)
824 vk::VkExternalSemaphoreHandleTypeFlagBits externalType;
825 Permanence permanence;
828 tcu::TestStatus testSemaphoreWin32Create (Context& context,
829 const SemaphoreTestConfig config)
831 #if (DE_OS == DE_OS_WIN32)
832 const Transference transference (getHandelTypeTransferences(config.externalType));
833 const vk::PlatformInterface& vkp (context.getPlatformInterface());
834 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
835 const vk::InstanceDriver& vki (instance.getDriver());
836 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
837 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
839 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
842 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
843 const vk::DeviceDriver vkd (vkp, instance, *device);
844 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
845 const vk::VkExportSemaphoreWin32HandleInfoKHR win32ExportInfo =
847 vk::VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR,
850 (vk::pt::Win32SecurityAttributesPtr)DE_NULL,
851 DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
852 (vk::pt::Win32LPCWSTR)DE_NULL
854 const vk::VkExportSemaphoreCreateInfo exportCreateInfo=
856 vk::VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO,
858 (vk::VkExternalMemoryHandleTypeFlags)config.externalType
860 const vk::VkSemaphoreCreateInfo createInfo =
862 vk::VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
866 const vk::Unique<vk::VkSemaphore> semaphore (vk::createSemaphore(vkd, *device, &createInfo));
868 if (transference == TRANSFERENCE_COPY)
869 submitEmptySignal(vkd, queue, *semaphore);
871 NativeHandle handleA;
872 getSemaphoreNative(vkd, *device, *semaphore, config.externalType, handleA);
875 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
876 const vk::Unique<vk::VkSemaphore> semaphoreA (createAndImportSemaphore(vkd, *device, config.externalType, handleA, flags));
878 if (transference == TRANSFERENCE_COPY)
879 submitEmptyWait(vkd, queue, *semaphoreA);
880 else if (transference == TRANSFERENCE_REFERENCE)
882 submitEmptySignal(vkd, queue, *semaphore);
883 submitEmptyWait(vkd, queue, *semaphoreA);
886 DE_FATAL("Unknown transference.");
888 VK_CHECK(vkd.queueWaitIdle(queue));
891 return tcu::TestStatus::pass("Pass");
896 TCU_THROW(NotSupportedError, "Platform doesn't support win32 handles");
900 tcu::TestStatus testSemaphoreImportTwice (Context& context,
901 const SemaphoreTestConfig config)
903 const Transference transference (getHandelTypeTransferences(config.externalType));
904 const vk::PlatformInterface& vkp (context.getPlatformInterface());
905 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
906 const vk::InstanceDriver& vki (instance.getDriver());
907 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
908 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
910 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
913 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
914 const vk::DeviceDriver vkd (vkp, instance, *device);
915 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
916 const vk::Unique<vk::VkSemaphore> semaphore (createExportableSemaphore(vkd, *device, config.externalType));
917 NativeHandle handleA;
919 if (transference == TRANSFERENCE_COPY)
920 submitEmptySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphore, config.externalType, handleA);
922 getSemaphoreNative(vkd, *device, *semaphore, config.externalType, handleA);
925 NativeHandle handleB (handleA);
926 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
927 const vk::Unique<vk::VkSemaphore> semaphoreA (createAndImportSemaphore(vkd, *device, config.externalType, handleA, flags));
928 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handleB, flags));
930 if (transference == TRANSFERENCE_COPY)
931 submitEmptyWait(vkd, queue, *semaphoreA);
932 else if (transference == TRANSFERENCE_REFERENCE)
934 submitEmptySignal(vkd, queue, *semaphoreA);
935 submitEmptyWait(vkd, queue, *semaphoreB);
938 DE_FATAL("Unknown transference.");
940 VK_CHECK(vkd.queueWaitIdle(queue));
943 return tcu::TestStatus::pass("Pass");
947 tcu::TestStatus testSemaphoreImportReimport (Context& context,
948 const SemaphoreTestConfig config)
950 const Transference transference (getHandelTypeTransferences(config.externalType));
951 const vk::PlatformInterface& vkp (context.getPlatformInterface());
952 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
953 const vk::InstanceDriver& vki (instance.getDriver());
954 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
955 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
957 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
960 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
961 const vk::DeviceDriver vkd (vkp, instance, *device);
962 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
964 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
965 NativeHandle handleA;
967 if (transference == TRANSFERENCE_COPY)
968 submitEmptySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handleA);
970 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handleA);
972 NativeHandle handleB (handleA);
973 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
974 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handleA, flags));
976 importSemaphore(vkd, *device, *semaphoreB, config.externalType, handleB, flags);
978 if (transference == TRANSFERENCE_COPY)
979 submitEmptyWait(vkd, queue, *semaphoreB);
980 else if (transference == TRANSFERENCE_REFERENCE)
982 submitEmptySignal(vkd, queue, *semaphoreA);
983 submitEmptyWait(vkd, queue, *semaphoreB);
986 DE_FATAL("Unknown transference.");
988 VK_CHECK(vkd.queueWaitIdle(queue));
990 return tcu::TestStatus::pass("Pass");
994 tcu::TestStatus testSemaphoreSignalExportImportWait (Context& context,
995 const SemaphoreTestConfig config)
997 const vk::PlatformInterface& vkp (context.getPlatformInterface());
998 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
999 const vk::InstanceDriver& vki (instance.getDriver());
1000 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1001 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1003 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1006 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1007 const vk::DeviceDriver vkd (vkp, instance, *device);
1008 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1009 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1011 NativeHandle handle;
1013 submitEmptySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
1016 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1017 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1018 submitEmptyWait(vkd, queue, *semaphoreB);
1020 VK_CHECK(vkd.queueWaitIdle(queue));
1024 return tcu::TestStatus::pass("Pass");
1028 tcu::TestStatus testSemaphoreExportSignalImportWait (Context& context,
1029 const SemaphoreTestConfig config)
1031 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1032 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1033 const vk::InstanceDriver& vki (instance.getDriver());
1034 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1035 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1036 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1038 DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
1039 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1042 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1043 const vk::DeviceDriver vkd (vkp, instance, *device);
1044 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1046 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1047 NativeHandle handle;
1049 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
1051 submitEmptySignal(vkd, queue, *semaphoreA);
1054 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1056 submitEmptyWait(vkd, queue, *semaphoreB);
1057 VK_CHECK(vkd.queueWaitIdle(queue));
1061 return tcu::TestStatus::pass("Pass");
1065 tcu::TestStatus testSemaphoreExportImportSignalWait (Context& context,
1066 const SemaphoreTestConfig config)
1068 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1069 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1070 const vk::InstanceDriver& vki (instance.getDriver());
1071 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1072 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1074 DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
1075 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1078 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1079 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1080 const vk::DeviceDriver vkd (vkp, instance, *device);
1081 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1083 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1084 NativeHandle handle;
1086 submitEmptySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
1088 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1090 submitEmptySignal(vkd, queue, *semaphoreA);
1091 submitEmptyWait(vkd, queue, *semaphoreB);
1093 VK_CHECK(vkd.queueWaitIdle(queue));
1095 return tcu::TestStatus::pass("Pass");
1099 tcu::TestStatus testSemaphoreSignalImport (Context& context,
1100 const SemaphoreTestConfig config)
1102 const Transference transference (getHandelTypeTransferences(config.externalType));
1103 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1104 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1105 const vk::InstanceDriver& vki (instance.getDriver());
1106 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1107 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1109 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1112 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1113 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1114 const vk::DeviceDriver vkd (vkp, instance, *device);
1115 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1117 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1118 const vk::Unique<vk::VkSemaphore> semaphoreB (createSemaphore(vkd, *device));
1119 NativeHandle handle;
1121 submitEmptySignal(vkd, queue, *semaphoreB);
1122 VK_CHECK(vkd.queueWaitIdle(queue));
1124 if (transference == TRANSFERENCE_COPY)
1125 submitEmptySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
1127 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
1129 importSemaphore(vkd, *device, *semaphoreB, config.externalType, handle, flags);
1131 if (transference == TRANSFERENCE_COPY)
1132 submitEmptyWait(vkd, queue, *semaphoreB);
1133 else if (transference == TRANSFERENCE_REFERENCE)
1135 submitEmptySignal(vkd, queue, *semaphoreA);
1136 submitEmptyWait(vkd, queue, *semaphoreB);
1139 DE_FATAL("Unknown transference.");
1141 VK_CHECK(vkd.queueWaitIdle(queue));
1143 return tcu::TestStatus::pass("Pass");
1147 tcu::TestStatus testSemaphoreSignalWaitImport (Context& context,
1148 const SemaphoreTestConfig config)
1150 const Transference transference (getHandelTypeTransferences(config.externalType));
1151 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1152 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1153 const vk::InstanceDriver& vki (instance.getDriver());
1154 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1155 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1157 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1160 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1161 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1162 const vk::DeviceDriver vkd (vkp, instance, *device);
1163 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1165 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1166 const vk::Unique<vk::VkSemaphore> semaphoreB (createSemaphore(vkd, *device));
1167 NativeHandle handle;
1169 if (transference == TRANSFERENCE_COPY)
1170 submitEmptySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
1172 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
1174 submitEmptySignal(vkd, queue, *semaphoreB);
1175 submitEmptyWait(vkd, queue, *semaphoreB);
1177 VK_CHECK(vkd.queueWaitIdle(queue));
1179 importSemaphore(vkd, *device, *semaphoreB, config.externalType, handle, flags);
1181 if (transference == TRANSFERENCE_COPY)
1182 submitEmptyWait(vkd, queue, *semaphoreB);
1183 else if (transference == TRANSFERENCE_REFERENCE)
1185 submitEmptySignal(vkd, queue, *semaphoreA);
1186 submitEmptyWait(vkd, queue, *semaphoreB);
1189 DE_FATAL("Unknown transference.");
1191 VK_CHECK(vkd.queueWaitIdle(queue));
1193 return tcu::TestStatus::pass("Pass");
1197 tcu::TestStatus testSemaphoreImportSyncFdSignaled (Context& context,
1198 const SemaphoreTestConfig config)
1200 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1201 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1202 const vk::InstanceDriver& vki (instance.getDriver());
1203 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1204 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1205 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1207 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1210 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1211 const vk::DeviceDriver vkd (vkp, instance, *device);
1212 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1213 NativeHandle handle = -1;
1214 const vk::Unique<vk::VkSemaphore> semaphore (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1216 submitEmptyWait(vkd, queue, *semaphore);
1217 VK_CHECK(vkd.queueWaitIdle(queue));
1219 return tcu::TestStatus::pass("Pass");
1223 tcu::TestStatus testSemaphoreMultipleExports (Context& context,
1224 const SemaphoreTestConfig config)
1226 const size_t exportCount = 4 * 1024;
1227 const Transference transference (getHandelTypeTransferences(config.externalType));
1228 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1229 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1230 const vk::InstanceDriver& vki (instance.getDriver());
1231 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1232 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1234 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1237 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1238 const vk::DeviceDriver vkd (vkp, instance, *device);
1239 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1240 const vk::Unique<vk::VkSemaphore> semaphore (createExportableSemaphore(vkd, *device, config.externalType));
1242 for (size_t exportNdx = 0; exportNdx < exportCount; exportNdx++)
1244 NativeHandle handle;
1246 if (transference == TRANSFERENCE_COPY)
1247 submitEmptySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphore, config.externalType, handle);
1249 getSemaphoreNative(vkd, *device, *semaphore, config.externalType, handle);
1252 submitEmptySignal(vkd, queue, *semaphore);
1253 submitEmptyWait(vkd, queue, *semaphore);
1255 VK_CHECK(vkd.queueWaitIdle(queue));
1258 return tcu::TestStatus::pass("Pass");
1261 tcu::TestStatus testSemaphoreMultipleImports (Context& context,
1262 const SemaphoreTestConfig config)
1264 const size_t importCount = 4 * 1024;
1265 const Transference transference (getHandelTypeTransferences(config.externalType));
1266 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1267 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1268 const vk::InstanceDriver& vki (instance.getDriver());
1269 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1270 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1272 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1275 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1276 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1277 const vk::DeviceDriver vkd (vkp, instance, *device);
1278 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1279 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1280 NativeHandle handleA;
1282 if (transference == TRANSFERENCE_COPY)
1283 submitEmptySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handleA);
1285 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handleA);
1287 for (size_t importNdx = 0; importNdx < importCount; importNdx++)
1289 NativeHandle handleB (handleA);
1290 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handleB, flags));
1293 if (transference == TRANSFERENCE_COPY)
1295 importSemaphore(vkd, *device, *semaphoreA, config.externalType, handleA, flags);
1296 submitEmptyWait(vkd, queue, *semaphoreA);
1298 else if (transference == TRANSFERENCE_REFERENCE)
1300 submitEmptySignal(vkd, queue, *semaphoreA);
1301 submitEmptyWait(vkd, queue, *semaphoreA);
1304 DE_FATAL("Unknown transference.");
1306 VK_CHECK(vkd.queueWaitIdle(queue));
1309 return tcu::TestStatus::pass("Pass");
1312 tcu::TestStatus testSemaphoreTransference (Context& context,
1313 const SemaphoreTestConfig config)
1315 const Transference transference (getHandelTypeTransferences(config.externalType));
1316 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1317 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1318 const vk::InstanceDriver& vki (instance.getDriver());
1319 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1320 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1322 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1325 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1326 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1327 const vk::DeviceDriver vkd (vkp, instance, *device);
1328 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1330 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1331 NativeHandle handle;
1333 submitEmptySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
1336 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1338 if (config.permanence == PERMANENCE_PERMANENT)
1340 if (transference == TRANSFERENCE_COPY)
1342 submitEmptySignal(vkd, queue, *semaphoreA);
1343 submitEmptyWait(vkd, queue, *semaphoreB);
1344 VK_CHECK(vkd.queueWaitIdle(queue));
1346 submitEmptySignal(vkd, queue, *semaphoreB);
1348 submitEmptyWait(vkd, queue, *semaphoreA);
1349 submitEmptyWait(vkd, queue, *semaphoreB);
1350 VK_CHECK(vkd.queueWaitIdle(queue));
1352 else if (transference== TRANSFERENCE_REFERENCE)
1354 submitEmptyWait(vkd, queue, *semaphoreB);
1355 VK_CHECK(vkd.queueWaitIdle(queue));
1357 submitEmptySignal(vkd, queue, *semaphoreA);
1358 submitEmptyWait(vkd, queue, *semaphoreB);
1360 submitEmptySignal(vkd, queue, *semaphoreB);
1361 submitEmptyWait(vkd, queue, *semaphoreA);
1362 VK_CHECK(vkd.queueWaitIdle(queue));
1365 DE_FATAL("Unknown transference.");
1367 else if (config.permanence == PERMANENCE_TEMPORARY)
1369 if (transference == TRANSFERENCE_COPY)
1371 submitEmptySignal(vkd, queue, *semaphoreA);
1372 submitEmptyWait(vkd, queue, *semaphoreB);
1373 VK_CHECK(vkd.queueWaitIdle(queue));
1375 submitEmptySignal(vkd, queue, *semaphoreB);
1377 submitEmptyWait(vkd, queue, *semaphoreA);
1378 submitEmptyWait(vkd, queue, *semaphoreB);
1379 VK_CHECK(vkd.queueWaitIdle(queue));
1381 else if (transference== TRANSFERENCE_REFERENCE)
1383 submitEmptyWait(vkd, queue, *semaphoreB);
1384 VK_CHECK(vkd.queueWaitIdle(queue));
1386 submitEmptySignal(vkd, queue, *semaphoreA);
1387 submitEmptySignal(vkd, queue, *semaphoreB);
1389 submitEmptyWait(vkd, queue, *semaphoreB);
1390 submitEmptyWait(vkd, queue, *semaphoreA);
1391 VK_CHECK(vkd.queueWaitIdle(queue));
1394 DE_FATAL("Unknown transference.");
1397 DE_FATAL("Unknown permanence.");
1400 return tcu::TestStatus::pass("Pass");
1404 tcu::TestStatus testSemaphoreFdDup (Context& context,
1405 const SemaphoreTestConfig config)
1407 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
1408 const Transference transference (getHandelTypeTransferences(config.externalType));
1409 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1410 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1411 const vk::InstanceDriver& vki (instance.getDriver());
1412 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1413 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1415 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1418 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1419 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1420 const vk::DeviceDriver vkd (vkp, instance, *device);
1421 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1423 TestLog& log = context.getTestContext().getLog();
1424 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1429 if (transference == TRANSFERENCE_COPY)
1430 submitEmptySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, fd);
1432 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, fd);
1434 NativeHandle newFd (dup(fd.getFd()));
1436 if (newFd.getFd() < 0)
1437 log << TestLog::Message << "dup() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
1439 TCU_CHECK_MSG(newFd.getFd() >= 0, "Failed to call dup() for semaphores fd");
1442 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, newFd, flags));
1444 if (transference == TRANSFERENCE_COPY)
1445 submitEmptyWait(vkd, queue, *semaphoreB);
1446 else if (transference == TRANSFERENCE_REFERENCE)
1448 submitEmptySignal(vkd, queue, *semaphoreA);
1449 submitEmptyWait(vkd, queue, *semaphoreB);
1452 DE_FATAL("Unknown permanence.");
1454 VK_CHECK(vkd.queueWaitIdle(queue));
1458 return tcu::TestStatus::pass("Pass");
1463 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
1467 tcu::TestStatus testSemaphoreFdDup2 (Context& context,
1468 const SemaphoreTestConfig config)
1470 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
1471 const Transference transference (getHandelTypeTransferences(config.externalType));
1472 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1473 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1474 const vk::InstanceDriver& vki (instance.getDriver());
1475 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1476 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1478 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1481 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1482 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1483 const vk::DeviceDriver vkd (vkp, instance, *device);
1484 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1486 TestLog& log = context.getTestContext().getLog();
1487 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1488 const vk::Unique<vk::VkSemaphore> semaphoreB (createExportableSemaphore(vkd, *device, config.externalType));
1491 NativeHandle fd, secondFd;
1493 if (transference == TRANSFERENCE_COPY)
1495 submitEmptySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, fd);
1496 submitEmptySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreB, config.externalType, secondFd);
1500 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, fd);
1501 getSemaphoreNative(vkd, *device, *semaphoreB, config.externalType, secondFd);
1504 int newFd (dup2(fd.getFd(), secondFd.getFd()));
1507 log << TestLog::Message << "dup2() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
1509 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup2() for fences fd");
1512 const vk::Unique<vk::VkSemaphore> semaphoreC (createAndImportSemaphore(vkd, *device, config.externalType, secondFd, flags));
1514 if (transference == TRANSFERENCE_COPY)
1515 submitEmptyWait(vkd, queue, *semaphoreC);
1516 else if (transference == TRANSFERENCE_REFERENCE)
1518 submitEmptySignal(vkd, queue, *semaphoreA);
1519 submitEmptyWait(vkd, queue, *semaphoreC);
1522 DE_FATAL("Unknown permanence.");
1524 VK_CHECK(vkd.queueWaitIdle(queue));
1528 return tcu::TestStatus::pass("Pass");
1533 TCU_THROW(NotSupportedError, "Platform doesn't support dup2()");
1537 tcu::TestStatus testSemaphoreFdDup3 (Context& context,
1538 const SemaphoreTestConfig config)
1540 #if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
1541 const Transference transference (getHandelTypeTransferences(config.externalType));
1542 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1543 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1544 const vk::InstanceDriver& vki (instance.getDriver());
1545 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1546 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1548 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1551 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1552 const vk::DeviceDriver vkd (vkp, instance, *device);
1553 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1555 TestLog& log = context.getTestContext().getLog();
1556 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1557 const vk::Unique<vk::VkSemaphore> semaphoreB (createExportableSemaphore(vkd, *device, config.externalType));
1560 NativeHandle fd, secondFd;
1562 if (transference == TRANSFERENCE_COPY)
1564 submitEmptySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, fd);
1565 submitEmptySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreB, config.externalType, secondFd);
1569 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, fd);
1570 getSemaphoreNative(vkd, *device, *semaphoreB, config.externalType, secondFd);
1573 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1574 const int newFd (dup3(fd.getFd(), secondFd.getFd(), 0));
1577 log << TestLog::Message << "dup3() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
1579 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup3() for fences fd");
1582 const vk::Unique<vk::VkSemaphore> semaphoreC (createAndImportSemaphore(vkd, *device, config.externalType, secondFd, flags));
1584 if (transference == TRANSFERENCE_COPY)
1585 submitEmptyWait(vkd, queue, *semaphoreC);
1586 else if (transference == TRANSFERENCE_REFERENCE)
1588 submitEmptySignal(vkd, queue, *semaphoreA);
1589 submitEmptyWait(vkd, queue, *semaphoreC);
1592 DE_FATAL("Unknown permanence.");
1594 VK_CHECK(vkd.queueWaitIdle(queue));
1598 return tcu::TestStatus::pass("Pass");
1603 TCU_THROW(NotSupportedError, "Platform doesn't support dup3()");
1607 tcu::TestStatus testSemaphoreFdSendOverSocket (Context& context,
1608 const SemaphoreTestConfig config)
1610 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
1611 const Transference transference (getHandelTypeTransferences(config.externalType));
1612 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1613 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1614 const vk::InstanceDriver& vki (instance.getDriver());
1615 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1616 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1618 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1621 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1622 const vk::DeviceDriver vkd (vkp, instance, *device);
1623 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1625 TestLog& log = context.getTestContext().getLog();
1626 const vk::Unique<vk::VkSemaphore> semaphore (createExportableSemaphore(vkd, *device, config.externalType));
1629 if (transference == TRANSFERENCE_COPY)
1630 submitEmptySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphore, config.externalType, fd);
1632 getSemaphoreNative(vkd, *device, *semaphore, config.externalType, fd);
1637 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
1639 log << TestLog::Message << "Failed to create socket pair: '" << strerror(errno) << "'" << TestLog::EndMessage;
1640 TCU_FAIL("Failed to create socket pair");
1644 const NativeHandle srcSocket (sv[0]);
1645 const NativeHandle dstSocket (sv[1]);
1646 std::string sendData ("deqp");
1650 const int fdRaw (fd.getFd());
1653 char buffer[CMSG_SPACE(sizeof(int))];
1654 iovec iov = { &sendData[0], sendData.length()};
1656 deMemset(&msg, 0, sizeof(msg));
1658 msg.msg_control = buffer;
1659 msg.msg_controllen = sizeof(buffer);
1663 cmsg = CMSG_FIRSTHDR(&msg);
1664 cmsg->cmsg_level = SOL_SOCKET;
1665 cmsg->cmsg_type = SCM_RIGHTS;
1666 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
1668 deMemcpy(CMSG_DATA(cmsg), &fdRaw, sizeof(int));
1669 msg.msg_controllen = cmsg->cmsg_len;
1671 if (sendmsg(srcSocket.getFd(), &msg, 0) < 0)
1673 log << TestLog::Message << "Failed to send fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
1674 TCU_FAIL("Failed to send fd over socket");
1681 char buffer[CMSG_SPACE(sizeof(int))];
1682 std::string recvData (4, '\0');
1683 iovec iov = { &recvData[0], recvData.length() };
1685 deMemset(&msg, 0, sizeof(msg));
1687 msg.msg_control = buffer;
1688 msg.msg_controllen = sizeof(buffer);
1692 const ssize_t bytes = recvmsg(dstSocket.getFd(), &msg, 0);
1696 log << TestLog::Message << "Failed to recv fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
1697 TCU_FAIL("Failed to recv fd over socket");
1700 else if (bytes != (ssize_t)sendData.length())
1702 TCU_FAIL("recvmsg() returned unpexpected number of bytes");
1706 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1707 const cmsghdr* const cmsg = CMSG_FIRSTHDR(&msg);
1709 deMemcpy(&newFd_, CMSG_DATA(cmsg), sizeof(int));
1710 NativeHandle newFd (newFd_);
1712 TCU_CHECK(cmsg->cmsg_level == SOL_SOCKET);
1713 TCU_CHECK(cmsg->cmsg_type == SCM_RIGHTS);
1714 TCU_CHECK(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
1715 TCU_CHECK(recvData == sendData);
1716 TCU_CHECK_MSG(newFd.getFd() >= 0, "Didn't receive valid fd from socket");
1719 const vk::Unique<vk::VkSemaphore> newSemaphore (createAndImportSemaphore(vkd, *device, config.externalType, newFd, flags));
1721 if (transference == TRANSFERENCE_COPY)
1722 submitEmptyWait(vkd, queue, *newSemaphore);
1723 else if (transference == TRANSFERENCE_REFERENCE)
1725 submitEmptySignal(vkd, queue, *newSemaphore);
1726 submitEmptyWait(vkd, queue, *newSemaphore);
1729 DE_FATAL("Unknown permanence.");
1731 VK_CHECK(vkd.queueWaitIdle(queue));
1739 return tcu::TestStatus::pass("Pass");
1743 TCU_THROW(NotSupportedError, "Platform doesn't support sending file descriptors over socket");
1747 tcu::TestStatus testFenceQueries (Context& context, vk::VkExternalFenceHandleTypeFlagBits externalType)
1749 const CustomInstance instance (createTestInstance(context, 0u, 0u, externalType));
1750 const vk::InstanceDriver& vki (instance.getDriver());
1751 const vk::VkPhysicalDevice device (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1753 TestLog& log = context.getTestContext().getLog();
1755 const vk::VkPhysicalDeviceExternalFenceInfo info =
1757 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO,
1761 vk::VkExternalFenceProperties properties =
1763 vk::VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES,
1770 vki.getPhysicalDeviceExternalFenceProperties(device, &info, &properties);
1771 log << TestLog::Message << properties << TestLog::EndMessage;
1773 TCU_CHECK(properties.pNext == DE_NULL);
1774 TCU_CHECK(properties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES);
1776 return tcu::TestStatus::pass("Pass");
1779 struct FenceTestConfig
1781 FenceTestConfig (vk::VkExternalFenceHandleTypeFlagBits externalType_,
1782 Permanence permanence_)
1783 : externalType (externalType_)
1784 , permanence (permanence_)
1788 vk::VkExternalFenceHandleTypeFlagBits externalType;
1789 Permanence permanence;
1793 tcu::TestStatus testFenceWin32Create (Context& context,
1794 const FenceTestConfig config)
1796 #if (DE_OS == DE_OS_WIN32)
1797 const Transference transference (getHandelTypeTransferences(config.externalType));
1798 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1799 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
1800 const vk::InstanceDriver& vki (instance.getDriver());
1801 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1802 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1804 checkFenceSupport(vki, physicalDevice, config.externalType);
1807 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1808 const vk::DeviceDriver vkd (vkp, instance, *device);
1809 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1810 const vk::VkExportFenceWin32HandleInfoKHR win32ExportInfo =
1812 vk::VK_STRUCTURE_TYPE_EXPORT_FENCE_WIN32_HANDLE_INFO_KHR,
1815 (vk::pt::Win32SecurityAttributesPtr)DE_NULL,
1816 DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
1817 (vk::pt::Win32LPCWSTR)DE_NULL
1819 const vk::VkExportFenceCreateInfo exportCreateInfo=
1821 vk::VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO,
1823 (vk::VkExternalFenceHandleTypeFlags)config.externalType
1825 const vk::VkFenceCreateInfo createInfo =
1827 vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
1831 const vk::Unique<vk::VkFence> fence (vk::createFence(vkd, *device, &createInfo));
1833 if (transference == TRANSFERENCE_COPY)
1834 submitEmptySignal(vkd, queue, *fence);
1836 NativeHandle handleA;
1837 getFenceNative(vkd, *device, *fence, config.externalType, handleA);
1840 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
1841 const vk::Unique<vk::VkFence> fenceA (createAndImportFence(vkd, *device, config.externalType, handleA, flags));
1843 if (transference == TRANSFERENCE_COPY)
1844 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
1845 else if (transference == TRANSFERENCE_REFERENCE)
1847 submitEmptySignal(vkd, queue, *fence);
1848 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
1851 DE_FATAL("Unknown transference.");
1853 VK_CHECK(vkd.queueWaitIdle(queue));
1856 return tcu::TestStatus::pass("Pass");
1861 TCU_THROW(NotSupportedError, "Platform doesn't support win32 handles");
1865 tcu::TestStatus testFenceImportTwice (Context& context,
1866 const FenceTestConfig config)
1868 const Transference transference (getHandelTypeTransferences(config.externalType));
1869 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1870 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
1871 const vk::InstanceDriver& vki (instance.getDriver());
1872 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1873 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1875 checkFenceSupport(vki, physicalDevice, config.externalType);
1878 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1879 const vk::DeviceDriver vkd (vkp, instance, *device);
1880 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1881 const vk::Unique<vk::VkFence> fence (createExportableFence(vkd, *device, config.externalType));
1882 NativeHandle handleA;
1884 if (transference == TRANSFERENCE_COPY)
1885 submitEmptySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fence, config.externalType, handleA);
1887 getFenceNative(vkd, *device, *fence, config.externalType, handleA);
1890 NativeHandle handleB (handleA);
1891 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
1892 const vk::Unique<vk::VkFence> fenceA (createAndImportFence(vkd, *device, config.externalType, handleA, flags));
1893 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handleB, flags));
1895 if (transference == TRANSFERENCE_COPY)
1896 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
1897 else if (transference == TRANSFERENCE_REFERENCE)
1899 submitEmptySignal(vkd, queue, *fenceA);
1900 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1903 DE_FATAL("Unknown transference.");
1905 VK_CHECK(vkd.queueWaitIdle(queue));
1908 return tcu::TestStatus::pass("Pass");
1912 tcu::TestStatus testFenceImportReimport (Context& context,
1913 const FenceTestConfig config)
1915 const Transference transference (getHandelTypeTransferences(config.externalType));
1916 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1917 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
1918 const vk::InstanceDriver& vki (instance.getDriver());
1919 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1920 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1922 checkFenceSupport(vki, physicalDevice, config.externalType);
1925 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1926 const vk::DeviceDriver vkd (vkp, instance, *device);
1927 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1929 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
1930 NativeHandle handleA;
1932 if (transference == TRANSFERENCE_COPY)
1933 submitEmptySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handleA);
1935 getFenceNative(vkd, *device, *fenceA, config.externalType, handleA);
1937 NativeHandle handleB (handleA);
1938 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
1939 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handleA, flags));
1941 importFence(vkd, *device, *fenceB, config.externalType, handleB, flags);
1943 if (transference == TRANSFERENCE_COPY)
1944 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1945 else if (transference == TRANSFERENCE_REFERENCE)
1947 submitEmptySignal(vkd, queue, *fenceA);
1948 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1951 DE_FATAL("Unknown transference.");
1953 VK_CHECK(vkd.queueWaitIdle(queue));
1955 return tcu::TestStatus::pass("Pass");
1959 tcu::TestStatus testFenceSignalExportImportWait (Context& context,
1960 const FenceTestConfig config)
1962 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1963 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
1964 const vk::InstanceDriver& vki (instance.getDriver());
1965 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1966 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1968 checkFenceSupport(vki, physicalDevice, config.externalType);
1971 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1972 const vk::DeviceDriver vkd (vkp, instance, *device);
1973 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1974 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
1977 NativeHandle handle;
1979 submitEmptySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
1982 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
1983 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handle, flags));
1984 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1986 VK_CHECK(vkd.queueWaitIdle(queue));
1990 return tcu::TestStatus::pass("Pass");
1994 tcu::TestStatus testFenceImportSyncFdSignaled (Context& context,
1995 const FenceTestConfig config)
1997 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1998 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
1999 const vk::InstanceDriver& vki (instance.getDriver());
2000 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2001 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2002 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2004 checkFenceSupport(vki, physicalDevice, config.externalType);
2007 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2008 const vk::DeviceDriver vkd (vkp, instance, *device);
2009 NativeHandle handle = -1;
2010 const vk::Unique<vk::VkFence> fence (createAndImportFence(vkd, *device, config.externalType, handle, flags));
2012 if (vkd.waitForFences(*device, 1u, &*fence, VK_TRUE, 0) != vk::VK_SUCCESS)
2013 return tcu::TestStatus::pass("Imported -1 sync fd isn't signaled");
2015 return tcu::TestStatus::pass("Pass");
2019 tcu::TestStatus testFenceExportSignalImportWait (Context& context,
2020 const FenceTestConfig config)
2022 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2023 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2024 const vk::InstanceDriver& vki (instance.getDriver());
2025 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2026 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2027 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2029 DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
2030 checkFenceSupport(vki, physicalDevice, config.externalType);
2033 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2034 const vk::DeviceDriver vkd (vkp, instance, *device);
2035 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2037 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2038 NativeHandle handle;
2040 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2042 submitEmptySignal(vkd, queue, *fenceA);
2045 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handle, flags));
2047 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2048 VK_CHECK(vkd.queueWaitIdle(queue));
2052 return tcu::TestStatus::pass("Pass");
2056 tcu::TestStatus testFenceExportImportSignalWait (Context& context,
2057 const FenceTestConfig config)
2059 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2060 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2061 const vk::InstanceDriver& vki (instance.getDriver());
2062 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2063 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2065 DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
2066 checkFenceSupport(vki, physicalDevice, config.externalType);
2069 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2070 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2071 const vk::DeviceDriver vkd (vkp, instance, *device);
2072 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2074 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2075 NativeHandle handle;
2077 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2079 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handle, flags));
2081 submitEmptySignal(vkd, queue, *fenceA);
2082 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2084 VK_CHECK(vkd.queueWaitIdle(queue));
2086 return tcu::TestStatus::pass("Pass");
2090 tcu::TestStatus testFenceSignalImport (Context& context,
2091 const FenceTestConfig config)
2093 const Transference transference (getHandelTypeTransferences(config.externalType));
2094 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2095 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2096 const vk::InstanceDriver& vki (instance.getDriver());
2097 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2098 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2100 checkFenceSupport(vki, physicalDevice, config.externalType);
2103 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2104 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2105 const vk::DeviceDriver vkd (vkp, instance, *device);
2106 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2108 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2109 const vk::Unique<vk::VkFence> fenceB (createFence(vkd, *device));
2110 NativeHandle handle;
2112 submitEmptySignal(vkd, queue, *fenceB);
2113 VK_CHECK(vkd.queueWaitIdle(queue));
2115 if (transference == TRANSFERENCE_COPY)
2116 submitEmptySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2118 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2120 importFence(vkd, *device, *fenceB, config.externalType, handle, flags);
2122 if (transference == TRANSFERENCE_COPY)
2123 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2124 else if (transference == TRANSFERENCE_REFERENCE)
2126 submitEmptySignal(vkd, queue, *fenceA);
2127 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2130 DE_FATAL("Unknown transference.");
2132 VK_CHECK(vkd.queueWaitIdle(queue));
2134 return tcu::TestStatus::pass("Pass");
2138 tcu::TestStatus testFenceReset (Context& context,
2139 const FenceTestConfig config)
2141 const Transference transference (getHandelTypeTransferences(config.externalType));
2142 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2143 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2144 const vk::InstanceDriver& vki (instance.getDriver());
2145 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2146 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2148 checkFenceSupport(vki, physicalDevice, config.externalType);
2151 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2152 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2153 const vk::DeviceDriver vkd (vkp, instance, *device);
2154 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2156 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2157 const vk::Unique<vk::VkFence> fenceB (createFence(vkd, *device));
2158 const vk::Unique<vk::VkFence> fenceC (createFence(vkd, *device));
2159 NativeHandle handle;
2161 submitEmptySignal(vkd, queue, *fenceB);
2162 VK_CHECK(vkd.queueWaitIdle(queue));
2164 submitEmptySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2165 NativeHandle handleB (handle);
2166 importFence(vkd, *device, *fenceB, config.externalType, handleB, flags);
2167 importFence(vkd, *device, *fenceC, config.externalType, handle, flags);
2169 VK_CHECK(vkd.queueWaitIdle(queue));
2170 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2172 if (config.permanence == PERMANENCE_TEMPORARY || transference == TRANSFERENCE_COPY)
2174 // vkResetFences() should restore fenceBs prior payload and reset that no affecting fenceCs payload
2175 // or fenceB should be separate copy of the payload and not affect fenceC
2176 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2178 // vkResetFences() should have restored fenceBs prior state and should be now reset
2179 // or fenceB should have it's separate payload
2180 submitEmptySignal(vkd, queue, *fenceB);
2181 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2183 else if (config.permanence == PERMANENCE_PERMANENT)
2185 DE_ASSERT(transference == TRANSFERENCE_REFERENCE);
2187 // Reset fences should have reset all of the fences
2188 submitEmptySignal(vkd, queue, *fenceC);
2190 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2191 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2192 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2195 DE_FATAL("Unknown permanence");
2197 VK_CHECK(vkd.queueWaitIdle(queue));
2199 return tcu::TestStatus::pass("Pass");
2203 tcu::TestStatus testFenceSignalWaitImport (Context& context,
2204 const FenceTestConfig config)
2206 const Transference transference (getHandelTypeTransferences(config.externalType));
2207 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2208 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2209 const vk::InstanceDriver& vki (instance.getDriver());
2210 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2211 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2213 checkFenceSupport(vki, physicalDevice, config.externalType);
2216 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2217 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2218 const vk::DeviceDriver vkd (vkp, instance, *device);
2219 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2221 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2222 const vk::Unique<vk::VkFence> fenceB (createFence(vkd, *device));
2223 NativeHandle handle;
2225 if (transference == TRANSFERENCE_COPY)
2226 submitEmptySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2228 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2230 submitEmptySignal(vkd, queue, *fenceB);
2231 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2233 VK_CHECK(vkd.queueWaitIdle(queue));
2235 importFence(vkd, *device, *fenceB, config.externalType, handle, flags);
2237 if (transference == TRANSFERENCE_COPY)
2238 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2239 else if (transference == TRANSFERENCE_REFERENCE)
2241 submitEmptySignal(vkd, queue, *fenceA);
2242 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2245 DE_FATAL("Unknown transference.");
2247 VK_CHECK(vkd.queueWaitIdle(queue));
2249 return tcu::TestStatus::pass("Pass");
2253 tcu::TestStatus testFenceMultipleExports (Context& context,
2254 const FenceTestConfig config)
2256 const size_t exportCount = 4 * 1024;
2257 const Transference transference (getHandelTypeTransferences(config.externalType));
2258 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2259 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2260 const vk::InstanceDriver& vki (instance.getDriver());
2261 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2262 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2264 checkFenceSupport(vki, physicalDevice, config.externalType);
2267 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2268 const vk::DeviceDriver vkd (vkp, instance, *device);
2269 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2270 const vk::Unique<vk::VkFence> fence (createExportableFence(vkd, *device, config.externalType));
2272 for (size_t exportNdx = 0; exportNdx < exportCount; exportNdx++)
2274 NativeHandle handle;
2276 if (transference == TRANSFERENCE_COPY)
2277 submitEmptySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fence, config.externalType, handle, exportNdx == 0 /* expect fence to be signaled after first pass */);
2279 getFenceNative(vkd, *device, *fence, config.externalType, handle, exportNdx == 0 /* expect fence to be signaled after first pass */);
2282 submitEmptySignal(vkd, queue, *fence);
2283 VK_CHECK(vkd.waitForFences(*device, 1u, &*fence, VK_TRUE, ~0ull));
2285 VK_CHECK(vkd.queueWaitIdle(queue));
2288 return tcu::TestStatus::pass("Pass");
2291 tcu::TestStatus testFenceMultipleImports (Context& context,
2292 const FenceTestConfig config)
2294 const size_t importCount = 4 * 1024;
2295 const Transference transference (getHandelTypeTransferences(config.externalType));
2296 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2297 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2298 const vk::InstanceDriver& vki (instance.getDriver());
2299 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2300 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2302 checkFenceSupport(vki, physicalDevice, config.externalType);
2305 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2306 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2307 const vk::DeviceDriver vkd (vkp, instance, *device);
2308 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2309 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2310 NativeHandle handleA;
2312 if (transference == TRANSFERENCE_COPY)
2313 submitEmptySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handleA);
2315 getFenceNative(vkd, *device, *fenceA, config.externalType, handleA);
2317 for (size_t importNdx = 0; importNdx < importCount; importNdx++)
2319 NativeHandle handleB (handleA);
2320 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handleB, flags));
2323 if (transference == TRANSFERENCE_COPY)
2325 importFence(vkd, *device, *fenceA, config.externalType, handleA, flags);
2326 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2328 else if (transference == TRANSFERENCE_REFERENCE)
2330 submitEmptySignal(vkd, queue, *fenceA);
2331 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2334 DE_FATAL("Unknown transference.");
2336 VK_CHECK(vkd.queueWaitIdle(queue));
2339 return tcu::TestStatus::pass("Pass");
2342 tcu::TestStatus testFenceTransference (Context& context,
2343 const FenceTestConfig config)
2345 const Transference transference (getHandelTypeTransferences(config.externalType));
2346 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2347 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2348 const vk::InstanceDriver& vki (instance.getDriver());
2349 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2350 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2352 checkFenceSupport(vki, physicalDevice, config.externalType);
2355 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2356 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2357 const vk::DeviceDriver vkd (vkp, instance, *device);
2358 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2360 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2361 NativeHandle handle;
2363 submitEmptySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2366 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handle, flags));
2368 if (config.permanence == PERMANENCE_PERMANENT)
2370 if (transference == TRANSFERENCE_COPY)
2372 submitEmptySignal(vkd, queue, *fenceA);
2373 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2374 VK_CHECK(vkd.queueWaitIdle(queue));
2376 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2377 submitEmptySignal(vkd, queue, *fenceB);
2379 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2380 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2381 VK_CHECK(vkd.queueWaitIdle(queue));
2383 else if (transference== TRANSFERENCE_REFERENCE)
2385 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2386 VK_CHECK(vkd.queueWaitIdle(queue));
2388 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2389 submitEmptySignal(vkd, queue, *fenceA);
2390 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2392 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceA));
2393 submitEmptySignal(vkd, queue, *fenceB);
2394 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2395 VK_CHECK(vkd.queueWaitIdle(queue));
2398 DE_FATAL("Unknown transference.");
2400 else if (config.permanence == PERMANENCE_TEMPORARY)
2402 if (transference == TRANSFERENCE_COPY)
2404 submitEmptySignal(vkd, queue, *fenceA);
2405 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2406 VK_CHECK(vkd.queueWaitIdle(queue));
2408 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2409 submitEmptySignal(vkd, queue, *fenceB);
2411 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2412 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2413 VK_CHECK(vkd.queueWaitIdle(queue));
2415 else if (transference == TRANSFERENCE_REFERENCE)
2417 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2418 VK_CHECK(vkd.queueWaitIdle(queue));
2420 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceA));
2421 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2422 submitEmptySignal(vkd, queue, *fenceA);
2423 submitEmptySignal(vkd, queue, *fenceB);
2425 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2426 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2427 VK_CHECK(vkd.queueWaitIdle(queue));
2430 DE_FATAL("Unknown transference.");
2433 DE_FATAL("Unknown permanence.");
2436 return tcu::TestStatus::pass("Pass");
2440 tcu::TestStatus testFenceFdDup (Context& context,
2441 const FenceTestConfig config)
2443 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2444 const Transference transference (getHandelTypeTransferences(config.externalType));
2445 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2446 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2447 const vk::InstanceDriver& vki (instance.getDriver());
2448 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2449 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2451 checkFenceSupport(vki, physicalDevice, config.externalType);
2454 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2455 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2456 const vk::DeviceDriver vkd (vkp, instance, *device);
2457 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2459 TestLog& log = context.getTestContext().getLog();
2460 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2465 if (transference == TRANSFERENCE_COPY)
2466 submitEmptySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, fd);
2468 getFenceNative(vkd, *device, *fenceA, config.externalType, fd);
2470 NativeHandle newFd (dup(fd.getFd()));
2472 if (newFd.getFd() < 0)
2473 log << TestLog::Message << "dup() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2475 TCU_CHECK_MSG(newFd.getFd() >= 0, "Failed to call dup() for fences fd");
2478 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, newFd, flags));
2480 if (transference == TRANSFERENCE_COPY)
2481 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2482 else if (transference == TRANSFERENCE_REFERENCE)
2484 submitEmptySignal(vkd, queue, *fenceA);
2485 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2488 DE_FATAL("Unknown permanence.");
2490 VK_CHECK(vkd.queueWaitIdle(queue));
2494 return tcu::TestStatus::pass("Pass");
2499 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
2503 tcu::TestStatus testFenceFdDup2 (Context& context,
2504 const FenceTestConfig config)
2506 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2507 const Transference transference (getHandelTypeTransferences(config.externalType));
2508 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2509 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2510 const vk::InstanceDriver& vki (instance.getDriver());
2511 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2512 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2514 checkFenceSupport(vki, physicalDevice, config.externalType);
2517 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2518 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2519 const vk::DeviceDriver vkd (vkp, instance, *device);
2520 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2522 TestLog& log = context.getTestContext().getLog();
2523 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2524 const vk::Unique<vk::VkFence> fenceB (createExportableFence(vkd, *device, config.externalType));
2527 NativeHandle fd, secondFd;
2529 if (transference == TRANSFERENCE_COPY)
2531 submitEmptySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, fd);
2532 submitEmptySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceB, config.externalType, secondFd);
2536 getFenceNative(vkd, *device, *fenceA, config.externalType, fd);
2537 getFenceNative(vkd, *device, *fenceB, config.externalType, secondFd);
2540 int newFd (dup2(fd.getFd(), secondFd.getFd()));
2543 log << TestLog::Message << "dup2() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2545 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup2() for fences fd");
2548 const vk::Unique<vk::VkFence> fenceC (createAndImportFence(vkd, *device, config.externalType, secondFd, flags));
2550 if (transference == TRANSFERENCE_COPY)
2551 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2552 else if (transference == TRANSFERENCE_REFERENCE)
2554 submitEmptySignal(vkd, queue, *fenceA);
2555 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2558 DE_FATAL("Unknown permanence.");
2560 VK_CHECK(vkd.queueWaitIdle(queue));
2564 return tcu::TestStatus::pass("Pass");
2569 TCU_THROW(NotSupportedError, "Platform doesn't support dup2()");
2573 tcu::TestStatus testFenceFdDup3 (Context& context,
2574 const FenceTestConfig config)
2576 #if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
2577 const Transference transference (getHandelTypeTransferences(config.externalType));
2578 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2579 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2580 const vk::InstanceDriver& vki (instance.getDriver());
2581 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2582 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2584 checkFenceSupport(vki, physicalDevice, config.externalType);
2587 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2588 const vk::DeviceDriver vkd (vkp, instance, *device);
2589 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2591 TestLog& log = context.getTestContext().getLog();
2592 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2593 const vk::Unique<vk::VkFence> fenceB (createExportableFence(vkd, *device, config.externalType));
2596 NativeHandle fd, secondFd;
2598 if (transference == TRANSFERENCE_COPY)
2600 submitEmptySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, fd);
2601 submitEmptySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceB, config.externalType, secondFd);
2605 getFenceNative(vkd, *device, *fenceA, config.externalType, fd);
2606 getFenceNative(vkd, *device, *fenceB, config.externalType, secondFd);
2609 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2610 const int newFd (dup3(fd.getFd(), secondFd.getFd(), 0));
2613 log << TestLog::Message << "dup3() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2615 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup3() for fences fd");
2618 const vk::Unique<vk::VkFence> fenceC (createAndImportFence(vkd, *device, config.externalType, secondFd, flags));
2620 if (transference == TRANSFERENCE_COPY)
2621 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2622 else if (transference == TRANSFERENCE_REFERENCE)
2624 submitEmptySignal(vkd, queue, *fenceA);
2625 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2628 DE_FATAL("Unknown permanence.");
2630 VK_CHECK(vkd.queueWaitIdle(queue));
2634 return tcu::TestStatus::pass("Pass");
2639 TCU_THROW(NotSupportedError, "Platform doesn't support dup3()");
2643 tcu::TestStatus testFenceFdSendOverSocket (Context& context,
2644 const FenceTestConfig config)
2646 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2647 const Transference transference (getHandelTypeTransferences(config.externalType));
2648 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2649 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2650 const vk::InstanceDriver& vki (instance.getDriver());
2651 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2652 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2654 checkFenceSupport(vki, physicalDevice, config.externalType);
2657 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2658 const vk::DeviceDriver vkd (vkp, instance, *device);
2659 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2661 TestLog& log = context.getTestContext().getLog();
2662 const vk::Unique<vk::VkFence> fence (createExportableFence(vkd, *device, config.externalType));
2665 if (transference == TRANSFERENCE_COPY)
2666 submitEmptySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fence, config.externalType, fd);
2668 getFenceNative(vkd, *device, *fence, config.externalType, fd);
2673 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
2675 log << TestLog::Message << "Failed to create socket pair: '" << strerror(errno) << "'" << TestLog::EndMessage;
2676 TCU_FAIL("Failed to create socket pair");
2680 const NativeHandle srcSocket (sv[0]);
2681 const NativeHandle dstSocket (sv[1]);
2682 std::string sendData ("deqp");
2686 const int fdRaw (fd.getFd());
2689 char buffer[CMSG_SPACE(sizeof(int))];
2690 iovec iov = { &sendData[0], sendData.length()};
2692 deMemset(&msg, 0, sizeof(msg));
2694 msg.msg_control = buffer;
2695 msg.msg_controllen = sizeof(buffer);
2699 cmsg = CMSG_FIRSTHDR(&msg);
2700 cmsg->cmsg_level = SOL_SOCKET;
2701 cmsg->cmsg_type = SCM_RIGHTS;
2702 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
2704 deMemcpy(CMSG_DATA(cmsg), &fdRaw, sizeof(int));
2705 msg.msg_controllen = cmsg->cmsg_len;
2707 if (sendmsg(srcSocket.getFd(), &msg, 0) < 0)
2709 log << TestLog::Message << "Failed to send fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
2710 TCU_FAIL("Failed to send fd over socket");
2717 char buffer[CMSG_SPACE(sizeof(int))];
2718 std::string recvData (4, '\0');
2719 iovec iov = { &recvData[0], recvData.length() };
2721 deMemset(&msg, 0, sizeof(msg));
2723 msg.msg_control = buffer;
2724 msg.msg_controllen = sizeof(buffer);
2728 const ssize_t bytes = recvmsg(dstSocket.getFd(), &msg, 0);
2732 log << TestLog::Message << "Failed to recv fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
2733 TCU_FAIL("Failed to recv fd over socket");
2736 else if (bytes != (ssize_t)sendData.length())
2738 TCU_FAIL("recvmsg() returned unpexpected number of bytes");
2742 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2743 const cmsghdr* const cmsg = CMSG_FIRSTHDR(&msg);
2745 deMemcpy(&newFd_, CMSG_DATA(cmsg), sizeof(int));
2746 NativeHandle newFd (newFd_);
2748 TCU_CHECK(cmsg->cmsg_level == SOL_SOCKET);
2749 TCU_CHECK(cmsg->cmsg_type == SCM_RIGHTS);
2750 TCU_CHECK(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
2751 TCU_CHECK(recvData == sendData);
2752 TCU_CHECK_MSG(newFd.getFd() >= 0, "Didn't receive valid fd from socket");
2755 const vk::Unique<vk::VkFence> newFence (createAndImportFence(vkd, *device, config.externalType, newFd, flags));
2757 if (transference == TRANSFERENCE_COPY)
2758 VK_CHECK(vkd.waitForFences(*device, 1u, &*newFence, VK_TRUE, ~0ull));
2759 else if (transference == TRANSFERENCE_REFERENCE)
2761 submitEmptySignal(vkd, queue, *newFence);
2762 VK_CHECK(vkd.waitForFences(*device, 1u, &*newFence, VK_TRUE, ~0ull));
2765 DE_FATAL("Unknown permanence.");
2767 VK_CHECK(vkd.queueWaitIdle(queue));
2775 return tcu::TestStatus::pass("Pass");
2779 TCU_THROW(NotSupportedError, "Platform doesn't support sending file descriptors over socket");
2783 tcu::TestStatus testBufferQueries (Context& context, vk::VkExternalMemoryHandleTypeFlagBits externalType)
2785 const vk::VkBufferCreateFlags createFlags[] =
2788 vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT,
2789 vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT|vk::VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT,
2790 vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT|vk::VK_BUFFER_CREATE_SPARSE_ALIASED_BIT
2792 const vk::VkBufferUsageFlags usageFlags[] =
2794 vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
2795 vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT,
2796 vk::VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT,
2797 vk::VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT,
2798 vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
2799 vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
2800 vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
2801 vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
2802 vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT
2804 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2805 const CustomInstance instance (createTestInstance(context, 0u, externalType, 0u));
2806 const vk::InstanceDriver& vki (instance.getDriver());
2807 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2808 const vk::VkPhysicalDeviceFeatures deviceFeatures (vk::getPhysicalDeviceFeatures(vki, physicalDevice));
2809 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2811 // VkDevice is only created if physical device claims to support any of these types.
2812 vk::Move<vk::VkDevice> device;
2813 de::MovePtr<vk::DeviceDriver> vkd;
2814 bool deviceHasDedicated = false;
2816 TestLog& log = context.getTestContext().getLog();
2818 for (size_t createFlagNdx = 0; createFlagNdx < DE_LENGTH_OF_ARRAY(createFlags); createFlagNdx++)
2819 for (size_t usageFlagNdx = 0; usageFlagNdx < DE_LENGTH_OF_ARRAY(usageFlags); usageFlagNdx++)
2821 const vk::VkBufferViewCreateFlags createFlag = createFlags[createFlagNdx];
2822 const vk::VkBufferUsageFlags usageFlag = usageFlags[usageFlagNdx];
2823 const vk::VkPhysicalDeviceExternalBufferInfo info =
2825 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO,
2831 vk::VkExternalBufferProperties properties =
2833 vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES,
2838 if (((createFlag & vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT) != 0) &&
2839 (deviceFeatures.sparseBinding == VK_FALSE))
2842 if (((createFlag & vk::VK_BUFFER_CREATE_SPARSE_ALIASED_BIT) != 0) &&
2843 (deviceFeatures.sparseResidencyAliased == VK_FALSE))
2846 if (((createFlag & vk::VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT) != 0) &&
2847 (deviceFeatures.sparseResidencyBuffer == VK_FALSE))
2850 vki.getPhysicalDeviceExternalBufferProperties(physicalDevice, &info, &properties);
2852 log << TestLog::Message << properties << TestLog::EndMessage;
2854 TCU_CHECK(properties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES);
2855 TCU_CHECK(properties.pNext == DE_NULL);
2856 // \todo [2017-06-06 pyry] Can we validate anything else? Compatible types?
2858 if ((properties.externalMemoryProperties.externalMemoryFeatures & (vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT|vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT)) != 0)
2860 const bool requiresDedicated = (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
2862 if (!device || (requiresDedicated && !deviceHasDedicated))
2864 // \note We need to re-create with dedicated mem extensions if previous device instance didn't have them
2867 device = createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, externalType, 0u, queueFamilyIndex, requiresDedicated);
2868 vkd = de::MovePtr<vk::DeviceDriver>(new vk::DeviceDriver(vkp, instance, *device));
2869 deviceHasDedicated = requiresDedicated;
2871 catch (const tcu::NotSupportedError& e)
2874 TCU_FAIL("Physical device claims to support handle type but required extensions are not supported");
2879 if ((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) != 0)
2881 DE_ASSERT(!!device);
2884 if (deviceHasDedicated)
2886 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(*vkd, *device, queueFamilyIndex, externalType, 1024u, createFlag, usageFlag));
2887 const vk::VkMemoryDedicatedRequirements reqs (getMemoryDedicatedRequirements(*vkd, *device, *buffer));
2888 const bool propertiesRequiresDedicated = (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
2889 const bool objectRequiresDedicated = (reqs.requiresDedicatedAllocation != VK_FALSE);
2891 if (propertiesRequiresDedicated != objectRequiresDedicated)
2892 TCU_FAIL("vkGetPhysicalDeviceExternalBufferProperties and vkGetBufferMemoryRequirements2 report different dedicated requirements");
2896 // We can't query whether dedicated memory is required or not on per-object basis.
2897 // This check should be redundant as the code above tries to create device with
2898 // VK_KHR_dedicated_allocation & VK_KHR_get_memory_requirements2 if dedicated memory
2899 // is required. However, checking again doesn't hurt.
2900 TCU_CHECK((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) == 0);
2905 return tcu::TestStatus::pass("Pass");
2908 struct MemoryTestConfig
2910 MemoryTestConfig (vk::VkExternalMemoryHandleTypeFlagBits externalType_,
2913 : externalType (externalType_)
2914 , hostVisible (hostVisible_)
2915 , dedicated (dedicated_)
2919 vk::VkExternalMemoryHandleTypeFlagBits externalType;
2924 #if (DE_OS == DE_OS_WIN32)
2925 deUint32 chooseWin32MemoryType(deUint32 bits)
2928 TCU_THROW(NotSupportedError, "No compatible memory type found");
2930 return deCtz32(bits);
2934 tcu::TestStatus testMemoryWin32Create (Context& context, MemoryTestConfig config)
2936 #if (DE_OS == DE_OS_WIN32)
2937 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2938 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
2939 const vk::InstanceDriver& vki (instance.getDriver());
2940 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2941 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2942 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
2943 const vk::DeviceDriver vkd (vkp, instance, *device);
2944 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
2945 const deUint32 seed = 1261033864u;
2946 const vk::VkDeviceSize bufferSize = 1024;
2947 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
2949 const vk::VkPhysicalDeviceMemoryProperties memoryProps = vk::getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice());
2950 const deUint32 compatibleMemTypes = vk::getCompatibleMemoryTypes(memoryProps, config.hostVisible ? vk::MemoryRequirement::HostVisible : vk::MemoryRequirement::Any);
2952 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
2954 // \note Buffer is only allocated to get memory requirements
2955 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
2956 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
2957 const vk::VkExportMemoryWin32HandleInfoKHR win32Info =
2959 vk::VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR,
2962 (vk::pt::Win32SecurityAttributesPtr)DE_NULL,
2963 DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
2964 (vk::pt::Win32LPCWSTR)DE_NULL
2966 const vk::VkExportMemoryAllocateInfo exportInfo =
2968 vk::VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
2970 (vk::VkExternalMemoryHandleTypeFlags)config.externalType
2973 const deUint32 exportedMemoryTypeIndex = chooseWin32MemoryType(requirements.memoryTypeBits & compatibleMemTypes);
2974 const vk::VkMemoryAllocateInfo info =
2976 vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
2979 exportedMemoryTypeIndex
2981 const vk::Unique<vk::VkDeviceMemory> memory (vk::allocateMemory(vkd, *device, &info));
2982 NativeHandle handleA;
2984 if (config.hostVisible)
2985 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
2987 getMemoryNative(vkd, *device, *memory, config.externalType, handleA);
2990 const vk::Unique<vk::VkDeviceMemory> memoryA (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleA));
2992 if (config.hostVisible)
2994 const std::vector<deUint8> testDataA (genTestData(seed ^ 124798807u, (size_t)bufferSize));
2995 const std::vector<deUint8> testDataB (genTestData(seed ^ 970834278u, (size_t)bufferSize));
2997 checkHostMemory(vkd, *device, *memoryA, testData.size(), &testData[0]);
2998 checkHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3000 writeHostMemory(vkd, *device, *memoryA, testDataA.size(), &testDataA[0]);
3001 writeHostMemory(vkd, *device, *memory, testDataA.size(), &testDataB[0]);
3003 checkHostMemory(vkd, *device, *memoryA, testData.size(), &testDataB[0]);
3004 checkHostMemory(vkd, *device, *memory, testData.size(), &testDataB[0]);
3008 return tcu::TestStatus::pass("Pass");
3012 TCU_THROW(NotSupportedError, "Platform doesn't support win32 handles");
3016 deUint32 getExportedMemoryTypeIndex(const vk::InstanceDriver& vki, const vk::VkPhysicalDevice physicalDevice, bool hostVisible, deUint32 memoryBits)
3020 const vk::VkPhysicalDeviceMemoryProperties properties(vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
3021 return chooseHostVisibleMemoryType(memoryBits, properties);
3024 return chooseMemoryType(memoryBits);
3027 tcu::TestStatus testMemoryImportTwice (Context& context, MemoryTestConfig config)
3029 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3030 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3031 const vk::InstanceDriver& vki (instance.getDriver());
3032 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3033 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3034 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3035 const vk::DeviceDriver vkd (vkp, instance, *device);
3036 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3037 const deUint32 seed = 1261033864u;
3038 const vk::VkDeviceSize bufferSize = 1024;
3039 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
3041 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3043 // \note Buffer is only allocated to get memory requirements
3044 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3045 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3046 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3047 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3048 NativeHandle handleA;
3050 if (config.hostVisible)
3051 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3053 getMemoryNative(vkd, *device, *memory, config.externalType, handleA);
3056 const vk::Unique<vk::VkBuffer> bufferA (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3057 const vk::Unique<vk::VkBuffer> bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3058 NativeHandle handleB (handleA);
3059 const vk::Unique<vk::VkDeviceMemory> memoryA (config.dedicated
3060 ? importDedicatedMemory(vkd, *device, *bufferA, requirements, config.externalType, exportedMemoryTypeIndex, handleA)
3061 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleA));
3062 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3063 ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handleB)
3064 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleB));
3066 if (config.hostVisible)
3068 const std::vector<deUint8> testDataA (genTestData(seed ^ 124798807u, (size_t)bufferSize));
3069 const std::vector<deUint8> testDataB (genTestData(seed ^ 970834278u, (size_t)bufferSize));
3071 checkHostMemory(vkd, *device, *memoryA, testData.size(), &testData[0]);
3072 checkHostMemory(vkd, *device, *memoryB, testData.size(), &testData[0]);
3074 writeHostMemory(vkd, *device, *memoryA, testData.size(), &testDataA[0]);
3075 writeHostMemory(vkd, *device, *memoryB, testData.size(), &testDataB[0]);
3077 checkHostMemory(vkd, *device, *memoryA, testData.size(), &testDataB[0]);
3078 checkHostMemory(vkd, *device, *memory, testData.size(), &testDataB[0]);
3082 return tcu::TestStatus::pass("Pass");
3085 tcu::TestStatus testMemoryMultipleImports (Context& context, MemoryTestConfig config)
3087 const size_t count = 4 * 1024;
3088 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3089 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3090 const vk::InstanceDriver& vki (instance.getDriver());
3091 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3092 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3093 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3094 const vk::DeviceDriver vkd (vkp, instance, *device);
3095 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3096 const vk::VkDeviceSize bufferSize = 1024;
3098 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3100 // \note Buffer is only allocated to get memory requirements
3101 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3102 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3103 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3104 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3105 NativeHandle handleA;
3107 getMemoryNative(vkd, *device, *memory, config.externalType, handleA);
3109 for (size_t ndx = 0; ndx < count; ndx++)
3111 const vk::Unique<vk::VkBuffer> bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3112 NativeHandle handleB (handleA);
3113 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3114 ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handleB)
3115 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleB));
3118 return tcu::TestStatus::pass("Pass");
3121 tcu::TestStatus testMemoryMultipleExports (Context& context, MemoryTestConfig config)
3123 const size_t count = 4 * 1024;
3124 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3125 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3126 const vk::InstanceDriver& vki (instance.getDriver());
3127 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3128 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3129 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3130 const vk::DeviceDriver vkd (vkp, instance, *device);
3131 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3132 const vk::VkDeviceSize bufferSize = 1024;
3134 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3136 // \note Buffer is only allocated to get memory requirements
3137 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3138 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3139 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3140 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3142 for (size_t ndx = 0; ndx < count; ndx++)
3144 NativeHandle handle;
3145 getMemoryNative(vkd, *device, *memory, config.externalType, handle);
3148 return tcu::TestStatus::pass("Pass");
3151 tcu::TestStatus testMemoryFdProperties (Context& context, MemoryTestConfig config)
3153 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3154 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3155 const vk::InstanceDriver& vki (instance.getDriver());
3156 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3157 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3158 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3159 const vk::DeviceDriver vkd (vkp, instance, *device);
3160 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3161 const vk::VkDeviceSize bufferSize = 1024;
3163 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3165 // \note Buffer is only allocated to get memory requirements
3166 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3167 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3168 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3169 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3171 vk::VkMemoryFdPropertiesKHR properties;
3172 NativeHandle handle;
3174 getMemoryNative(vkd, *device, *memory, config.externalType, handle);
3175 properties.sType = vk::VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR;
3176 vk::VkResult res = vkd.getMemoryFdPropertiesKHR(*device, config.externalType, handle.getFd(), &properties);
3178 switch (config.externalType)
3180 case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
3181 TCU_CHECK_MSG(res == vk::VK_SUCCESS, "vkGetMemoryFdPropertiesKHR failed for VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT");
3184 // Invalid external memory type for this test.
3189 return tcu::TestStatus::pass("Pass");
3192 tcu::TestStatus testMemoryFdDup (Context& context, MemoryTestConfig config)
3194 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
3195 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3196 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3197 const vk::InstanceDriver& vki (instance.getDriver());
3198 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3199 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3202 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3203 const vk::DeviceDriver vkd (vkp, instance, *device);
3205 TestLog& log = context.getTestContext().getLog();
3206 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3207 const vk::VkDeviceSize bufferSize = 1024;
3208 const deUint32 seed = 851493858u;
3209 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
3211 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3213 // \note Buffer is only allocated to get memory requirements
3214 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3215 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3216 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3217 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3219 if (config.hostVisible)
3220 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3222 const NativeHandle fd (getMemoryFd(vkd, *device, *memory, config.externalType));
3223 NativeHandle newFd (dup(fd.getFd()));
3225 if (newFd.getFd() < 0)
3226 log << TestLog::Message << "dup() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
3228 TCU_CHECK_MSG(newFd.getFd() >= 0, "Failed to call dup() for memorys fd");
3231 const vk::Unique<vk::VkBuffer> newBuffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3232 const vk::Unique<vk::VkDeviceMemory> newMemory (config.dedicated
3233 ? importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType, exportedMemoryTypeIndex, newFd)
3234 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, newFd));
3236 if (config.hostVisible)
3238 const std::vector<deUint8> testDataA (genTestData(seed ^ 672929437u, (size_t)bufferSize));
3240 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3242 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3243 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3247 return tcu::TestStatus::pass("Pass");
3252 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
3256 tcu::TestStatus testMemoryFdDup2 (Context& context, MemoryTestConfig config)
3258 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
3259 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3260 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3261 const vk::InstanceDriver& vki (instance.getDriver());
3262 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3263 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3266 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3267 const vk::DeviceDriver vkd (vkp, instance, *device);
3269 TestLog& log = context.getTestContext().getLog();
3270 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3271 const vk::VkDeviceSize bufferSize = 1024;
3272 const deUint32 seed = 224466865u;
3273 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
3275 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3277 // \note Buffer is only allocated to get memory requirements
3278 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3279 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3280 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3281 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3283 if (config.hostVisible)
3284 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3286 const NativeHandle fd (getMemoryFd(vkd, *device, *memory, config.externalType));
3287 NativeHandle secondFd (getMemoryFd(vkd, *device, *memory, config.externalType));
3288 const int newFd (dup2(fd.getFd(), secondFd.getFd()));
3291 log << TestLog::Message << "dup2() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
3293 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup2() for memorys fd");
3296 const vk::Unique<vk::VkBuffer> newBuffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3297 const vk::Unique<vk::VkDeviceMemory> newMemory (config.dedicated
3298 ? importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType, exportedMemoryTypeIndex, secondFd)
3299 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, secondFd));
3301 if (config.hostVisible)
3303 const std::vector<deUint8> testDataA (genTestData(seed ^ 99012346u, (size_t)bufferSize));
3305 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3307 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3308 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3312 return tcu::TestStatus::pass("Pass");
3317 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
3321 tcu::TestStatus testMemoryFdDup3 (Context& context, MemoryTestConfig config)
3323 #if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
3324 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3325 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3326 const vk::InstanceDriver& vki (instance.getDriver());
3327 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3328 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3331 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3332 const vk::DeviceDriver vkd (vkp, instance, *device);
3334 TestLog& log = context.getTestContext().getLog();
3335 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3336 const vk::VkDeviceSize bufferSize = 1024;
3337 const deUint32 seed = 2554088961u;
3338 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
3340 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3342 // \note Buffer is only allocated to get memory requirements
3343 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3344 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3345 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3346 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3348 if (config.hostVisible)
3349 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3351 const NativeHandle fd (getMemoryFd(vkd, *device, *memory, config.externalType));
3352 NativeHandle secondFd (getMemoryFd(vkd, *device, *memory, config.externalType));
3353 const int newFd (dup3(fd.getFd(), secondFd.getFd(), 0));
3356 log << TestLog::Message << "dup3() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
3358 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup3() for memorys fd");
3361 const vk::Unique<vk::VkBuffer> newBuffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3362 const vk::Unique<vk::VkDeviceMemory> newMemory (config.dedicated
3363 ? importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType, exportedMemoryTypeIndex, secondFd)
3364 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, secondFd));
3366 if (config.hostVisible)
3368 const std::vector<deUint8> testDataA (genTestData(seed ^ 4210342378u, (size_t)bufferSize));
3370 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3372 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3373 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3377 return tcu::TestStatus::pass("Pass");
3382 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
3386 tcu::TestStatus testMemoryFdSendOverSocket (Context& context, MemoryTestConfig config)
3388 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
3389 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3390 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3391 const vk::InstanceDriver& vki (instance.getDriver());
3392 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3393 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3396 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3397 const vk::DeviceDriver vkd (vkp, instance, *device);
3399 TestLog& log = context.getTestContext().getLog();
3400 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3401 const vk::VkDeviceSize bufferSize = 1024;
3402 const deUint32 seed = 3403586456u;
3403 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
3405 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3407 // \note Buffer is only allocated to get memory requirements
3408 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3409 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3410 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3411 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3413 if (config.hostVisible)
3414 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3416 const NativeHandle fd (getMemoryFd(vkd, *device, *memory, config.externalType));
3421 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
3423 log << TestLog::Message << "Failed to create socket pair: '" << strerror(errno) << "'" << TestLog::EndMessage;
3424 TCU_FAIL("Failed to create socket pair");
3428 const NativeHandle srcSocket (sv[0]);
3429 const NativeHandle dstSocket (sv[1]);
3430 std::string sendData ("deqp");
3434 const int fdRaw (fd.getFd());
3437 char tmpBuffer[CMSG_SPACE(sizeof(int))];
3438 iovec iov = { &sendData[0], sendData.length()};
3440 deMemset(&msg, 0, sizeof(msg));
3442 msg.msg_control = tmpBuffer;
3443 msg.msg_controllen = sizeof(tmpBuffer);
3447 cmsg = CMSG_FIRSTHDR(&msg);
3448 cmsg->cmsg_level = SOL_SOCKET;
3449 cmsg->cmsg_type = SCM_RIGHTS;
3450 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
3452 deMemcpy(CMSG_DATA(cmsg), &fdRaw, sizeof(int));
3453 msg.msg_controllen = cmsg->cmsg_len;
3455 if (sendmsg(srcSocket.getFd(), &msg, 0) < 0)
3457 log << TestLog::Message << "Failed to send fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
3458 TCU_FAIL("Failed to send fd over socket");
3465 char tmpBuffer[CMSG_SPACE(sizeof(int))];
3466 std::string recvData (4, '\0');
3467 iovec iov = { &recvData[0], recvData.length() };
3469 deMemset(&msg, 0, sizeof(msg));
3471 msg.msg_control = tmpBuffer;
3472 msg.msg_controllen = sizeof(tmpBuffer);
3476 const ssize_t bytes = recvmsg(dstSocket.getFd(), &msg, 0);
3480 log << TestLog::Message << "Failed to recv fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
3481 TCU_FAIL("Failed to recv fd over socket");
3484 else if (bytes != (ssize_t)sendData.length())
3486 TCU_FAIL("recvmsg() returned unpexpected number of bytes");
3490 const cmsghdr* const cmsg = CMSG_FIRSTHDR(&msg);
3492 deMemcpy(&newFd_, CMSG_DATA(cmsg), sizeof(int));
3493 NativeHandle newFd (newFd_);
3495 TCU_CHECK(cmsg->cmsg_level == SOL_SOCKET);
3496 TCU_CHECK(cmsg->cmsg_type == SCM_RIGHTS);
3497 TCU_CHECK(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
3498 TCU_CHECK(recvData == sendData);
3499 TCU_CHECK_MSG(newFd.getFd() >= 0, "Didn't receive valid fd from socket");
3502 const vk::Unique<vk::VkBuffer> newBuffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3503 const vk::Unique<vk::VkDeviceMemory> newMemory (config.dedicated
3504 ? importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType, exportedMemoryTypeIndex, newFd)
3505 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, newFd));
3507 if (config.hostVisible)
3509 const std::vector<deUint8> testDataA (genTestData(seed ^ 23478978u, (size_t)bufferSize));
3511 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3513 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3514 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3523 return tcu::TestStatus::pass("Pass");
3527 TCU_THROW(NotSupportedError, "Platform doesn't support sending file descriptors over socket");
3531 struct BufferTestConfig
3533 BufferTestConfig (vk::VkExternalMemoryHandleTypeFlagBits externalType_,
3535 : externalType (externalType_)
3536 , dedicated (dedicated_)
3540 vk::VkExternalMemoryHandleTypeFlagBits externalType;
3544 tcu::TestStatus testBufferBindExportImportBind (Context& context,
3545 const BufferTestConfig config)
3547 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3548 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3549 const vk::InstanceDriver& vki (instance.getDriver());
3550 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3551 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3552 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3553 const vk::DeviceDriver vkd (vkp, instance, *device);
3554 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3555 const vk::VkDeviceSize bufferSize = 1024;
3557 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3559 // \note Buffer is only allocated to get memory requirements
3560 const vk::Unique<vk::VkBuffer> bufferA (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3561 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *bufferA));
3562 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
3563 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *bufferA : (vk::VkBuffer)0));
3564 NativeHandle handle;
3566 VK_CHECK(vkd.bindBufferMemory(*device, *bufferA, *memoryA, 0u));
3568 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3571 const vk::Unique<vk::VkBuffer> bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3572 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3573 ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handle)
3574 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3576 VK_CHECK(vkd.bindBufferMemory(*device, *bufferB, *memoryB, 0u));
3579 return tcu::TestStatus::pass("Pass");
3582 tcu::TestStatus testBufferExportBindImportBind (Context& context,
3583 const BufferTestConfig config)
3585 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3586 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3587 const vk::InstanceDriver& vki (instance.getDriver());
3588 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3589 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3590 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3591 const vk::DeviceDriver vkd (vkp, instance, *device);
3592 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3593 const vk::VkDeviceSize bufferSize = 1024;
3595 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3597 // \note Buffer is only allocated to get memory requirements
3598 const vk::Unique<vk::VkBuffer> bufferA (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3599 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *bufferA));
3600 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
3601 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *bufferA : (vk::VkBuffer)0));
3602 NativeHandle handle;
3604 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3605 VK_CHECK(vkd.bindBufferMemory(*device, *bufferA, *memoryA, 0u));
3608 const vk::Unique<vk::VkBuffer> bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3609 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3610 ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handle)
3611 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3613 VK_CHECK(vkd.bindBufferMemory(*device, *bufferB, *memoryB, 0u));
3616 return tcu::TestStatus::pass("Pass");
3619 tcu::TestStatus testBufferExportImportBindBind (Context& context,
3620 const BufferTestConfig config)
3622 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3623 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3624 const vk::InstanceDriver& vki (instance.getDriver());
3625 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3626 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3627 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3628 const vk::DeviceDriver vkd (vkp, instance, *device);
3629 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3630 const vk::VkDeviceSize bufferSize = 1024;
3632 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3634 // \note Buffer is only allocated to get memory requirements
3635 const vk::Unique<vk::VkBuffer> bufferA (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3636 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *bufferA));
3637 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
3638 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *bufferA : (vk::VkBuffer)0));
3639 NativeHandle handle;
3641 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3644 const vk::Unique<vk::VkBuffer> bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3645 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3646 ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handle)
3647 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3649 VK_CHECK(vkd.bindBufferMemory(*device, *bufferA, *memoryA, 0u));
3650 VK_CHECK(vkd.bindBufferMemory(*device, *bufferB, *memoryB, 0u));
3653 return tcu::TestStatus::pass("Pass");
3656 tcu::TestStatus testImageQueries (Context& context, vk::VkExternalMemoryHandleTypeFlagBits externalType)
3658 const vk::VkImageCreateFlags createFlags[] =
3661 vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT,
3662 vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT|vk::VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT,
3663 vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT|vk::VK_IMAGE_CREATE_SPARSE_ALIASED_BIT,
3664 vk::VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT,
3665 vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT
3667 const vk::VkImageUsageFlags usageFlags[] =
3669 vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
3670 vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT,
3671 vk::VK_IMAGE_USAGE_SAMPLED_BIT,
3672 vk::VK_IMAGE_USAGE_STORAGE_BIT,
3673 vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
3674 vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
3675 vk::VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
3676 vk::VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
3677 vk::VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT,
3678 vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT
3680 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3681 const CustomInstance instance (createTestInstance(context, 0u, externalType, 0u));
3682 const vk::InstanceDriver& vki (instance.getDriver());
3683 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3684 const vk::VkPhysicalDeviceFeatures deviceFeatures (vk::getPhysicalDeviceFeatures(vki, physicalDevice));
3685 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3687 // VkDevice is only created if physical device claims to support any of these types.
3688 vk::Move<vk::VkDevice> device;
3689 de::MovePtr<vk::DeviceDriver> vkd;
3690 bool deviceHasDedicated = false;
3692 TestLog& log = context.getTestContext().getLog();
3694 for (size_t createFlagNdx = 0; createFlagNdx < DE_LENGTH_OF_ARRAY(createFlags); createFlagNdx++)
3695 for (size_t usageFlagNdx = 0; usageFlagNdx < DE_LENGTH_OF_ARRAY(usageFlags); usageFlagNdx++)
3697 const vk::VkImageViewCreateFlags createFlag = createFlags[createFlagNdx];
3698 const vk::VkImageUsageFlags usageFlag = usageFlags[usageFlagNdx];
3699 const vk::VkFormat format =
3700 (usageFlags[usageFlagNdx] & vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? vk::VK_FORMAT_D16_UNORM : vk::VK_FORMAT_R8G8B8A8_UNORM;
3701 const vk::VkImageType type = vk::VK_IMAGE_TYPE_2D;
3702 const vk::VkImageTiling tiling = vk::VK_IMAGE_TILING_OPTIMAL;
3703 const vk::VkPhysicalDeviceExternalImageFormatInfo externalInfo =
3705 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
3709 const vk::VkPhysicalDeviceImageFormatInfo2 info =
3711 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
3720 vk::VkExternalImageFormatProperties externalProperties =
3722 vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES,
3726 vk::VkImageFormatProperties2 properties =
3728 vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
3729 &externalProperties,
3739 if (((createFlag & vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT) != 0) &&
3740 (deviceFeatures.sparseBinding == VK_FALSE))
3743 if (((createFlag & vk::VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT) != 0) &&
3744 (deviceFeatures.sparseResidencyImage2D == VK_FALSE))
3747 if (((createFlag & vk::VK_IMAGE_CREATE_SPARSE_ALIASED_BIT) != 0) &&
3748 (deviceFeatures.sparseResidencyAliased == VK_FALSE))
3751 if (vki.getPhysicalDeviceImageFormatProperties2(physicalDevice, &info, &properties) == vk::VK_ERROR_FORMAT_NOT_SUPPORTED) {
3755 log << TestLog::Message << externalProperties << TestLog::EndMessage;
3756 TCU_CHECK(externalProperties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES);
3757 TCU_CHECK(externalProperties.pNext == DE_NULL);
3758 // \todo [2017-06-06 pyry] Can we validate anything else? Compatible types?
3760 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & (vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT|vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT)) != 0)
3762 const bool requiresDedicated = (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
3764 if (!device || (requiresDedicated && !deviceHasDedicated))
3766 // \note We need to re-create with dedicated mem extensions if previous device instance didn't have them
3769 device = createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, externalType, 0u, queueFamilyIndex, requiresDedicated);
3770 vkd = de::MovePtr<vk::DeviceDriver>(new vk::DeviceDriver(vkp, instance, *device));
3771 deviceHasDedicated = requiresDedicated;
3773 catch (const tcu::NotSupportedError& e)
3776 TCU_FAIL("Physical device claims to support handle type but required extensions are not supported");
3781 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) != 0)
3783 DE_ASSERT(!!device);
3786 if (deviceHasDedicated)
3788 // Memory requirements cannot be queried without binding the image.
3789 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
3792 const vk::Unique<vk::VkImage> image (createExternalImage(*vkd, *device, queueFamilyIndex, externalType, format, 16u, 16u, tiling, createFlag, usageFlag));
3793 const vk::VkMemoryDedicatedRequirements reqs (getMemoryDedicatedRequirements(*vkd, *device, *image));
3794 const bool propertiesRequiresDedicated = (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
3795 const bool objectRequiresDedicated = (reqs.requiresDedicatedAllocation != VK_FALSE);
3797 if (propertiesRequiresDedicated != objectRequiresDedicated)
3798 TCU_FAIL("vkGetPhysicalDeviceExternalBufferProperties and vkGetBufferMemoryRequirements2 report different dedicated requirements");
3802 // We can't query whether dedicated memory is required or not on per-object basis.
3803 // This check should be redundant as the code above tries to create device with
3804 // VK_KHR_dedicated_allocation & VK_KHR_get_memory_requirements2 if dedicated memory
3805 // is required. However, checking again doesn't hurt.
3806 TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) == 0);
3811 return tcu::TestStatus::pass("Pass");
3814 struct ImageTestConfig
3816 ImageTestConfig (vk::VkExternalMemoryHandleTypeFlagBits externalType_,
3818 : externalType (externalType_)
3819 , dedicated (dedicated_)
3823 vk::VkExternalMemoryHandleTypeFlagBits externalType;
3827 tcu::TestStatus testImageBindExportImportBind (Context& context,
3828 const ImageTestConfig config)
3830 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3831 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3832 const vk::InstanceDriver& vki (instance.getDriver());
3833 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3834 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3835 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3836 const vk::DeviceDriver vkd (vkp, instance, *device);
3837 const vk::VkImageUsageFlags usage = vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT | (config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID ? vk::VK_IMAGE_USAGE_SAMPLED_BIT : 0);
3838 const vk::VkFormat format = vk::VK_FORMAT_R8G8B8A8_UNORM;
3839 const deUint32 width = 64u;
3840 const deUint32 height = 64u;
3841 const vk::VkImageTiling tiling = vk::VK_IMAGE_TILING_OPTIMAL;
3843 checkImageSupport(vki, physicalDevice, config.externalType, 0u, usage, format, tiling, config.dedicated);
3845 const vk::Unique<vk::VkImage> imageA (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3846 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *imageA, config.externalType));
3847 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
3848 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *imageA : (vk::VkImage)0));
3849 NativeHandle handle;
3851 VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
3853 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3856 const vk::Unique<vk::VkImage> imageB (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3857 const deUint32 idx = config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID ? ~0u : exportedMemoryTypeIndex;
3858 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3859 ? importDedicatedMemory(vkd, *device, *imageB, requirements, config.externalType, idx, handle)
3860 : importMemory(vkd, *device, requirements, config.externalType, idx, handle));
3862 VK_CHECK(vkd.bindImageMemory(*device, *imageB, *memoryB, 0u));
3865 return tcu::TestStatus::pass("Pass");
3868 tcu::TestStatus testImageExportBindImportBind (Context& context,
3869 const ImageTestConfig config)
3871 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3872 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3873 const vk::InstanceDriver& vki (instance.getDriver());
3874 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3875 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3876 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3877 const vk::DeviceDriver vkd (vkp, instance, *device);
3878 const vk::VkImageUsageFlags usage = vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT | (config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID ? vk::VK_IMAGE_USAGE_SAMPLED_BIT : 0);
3879 const vk::VkFormat format = vk::VK_FORMAT_R8G8B8A8_UNORM;
3880 const deUint32 width = 64u;
3881 const deUint32 height = 64u;
3882 const vk::VkImageTiling tiling = vk::VK_IMAGE_TILING_OPTIMAL;
3884 checkImageSupport(vki, physicalDevice, config.externalType, 0u, usage, format, tiling, config.dedicated);
3886 const vk::Unique<vk::VkImage> imageA (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3887 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *imageA, config.externalType));
3888 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
3889 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *imageA : (vk::VkImage)0));
3890 NativeHandle handle;
3892 if (config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID && config.dedicated)
3894 // AHB required the image memory to be bound first.
3895 VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
3896 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3900 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3901 VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
3905 const vk::Unique<vk::VkImage> imageB (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3906 const deUint32 idx = config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID ? ~0u : exportedMemoryTypeIndex;
3907 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3908 ? importDedicatedMemory(vkd, *device, *imageB, requirements, config.externalType, idx, handle)
3909 : importMemory(vkd, *device, requirements, config.externalType, idx, handle));
3911 VK_CHECK(vkd.bindImageMemory(*device, *imageB, *memoryB, 0u));
3914 return tcu::TestStatus::pass("Pass");
3917 tcu::TestStatus testImageExportImportBindBind (Context& context,
3918 const ImageTestConfig config)
3920 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3921 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3922 const vk::InstanceDriver& vki (instance.getDriver());
3923 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3924 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3925 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3926 const vk::DeviceDriver vkd (vkp, instance, *device);
3927 const vk::VkImageUsageFlags usage = vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT | (config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID ? vk::VK_IMAGE_USAGE_SAMPLED_BIT : 0);
3928 const vk::VkFormat format = vk::VK_FORMAT_R8G8B8A8_UNORM;
3929 const deUint32 width = 64u;
3930 const deUint32 height = 64u;
3931 const vk::VkImageTiling tiling = vk::VK_IMAGE_TILING_OPTIMAL;
3933 checkImageSupport(vki, physicalDevice, config.externalType, 0u, usage, format, tiling, config.dedicated);
3935 if (config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID && config.dedicated)
3937 // AHB required the image memory to be bound first, which is not possible in this test.
3938 TCU_THROW(NotSupportedError, "Unsupported for Android Hardware Buffer");
3941 // \note Image is only allocated to get memory requirements
3942 const vk::Unique<vk::VkImage> imageA (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3943 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *imageA, config.externalType));
3944 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
3945 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *imageA : (vk::VkImage)0));
3946 NativeHandle handle;
3948 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3951 const vk::Unique<vk::VkImage> imageB (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3952 const deUint32 idx = config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID ? ~0u : exportedMemoryTypeIndex;
3953 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3954 ? importDedicatedMemory(vkd, *device, *imageB, requirements, config.externalType, idx, handle)
3955 : importMemory(vkd, *device, requirements, config.externalType, idx, handle));
3957 VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
3958 VK_CHECK(vkd.bindImageMemory(*device, *imageB, *memoryB, 0u));
3961 return tcu::TestStatus::pass("Pass");
3964 template<class TestConfig> void checkEvent (Context& context, const TestConfig)
3966 if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") && !context.getPortabilitySubsetFeatures().events)
3967 TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Events are not supported by this implementation");
3970 template<class TestConfig> void checkSupport (Context& context, const TestConfig config)
3972 const Transference transference (getHandelTypeTransferences(config.externalType));
3973 if (transference == TRANSFERENCE_COPY)
3974 checkEvent(context, config);
3977 de::MovePtr<tcu::TestCaseGroup> createFenceTests (tcu::TestContext& testCtx, vk::VkExternalFenceHandleTypeFlagBits externalType)
3981 const char* const name;
3982 const Permanence permanence;
3985 { "temporary", PERMANENCE_TEMPORARY },
3986 { "permanent", PERMANENCE_PERMANENT }
3989 de::MovePtr<tcu::TestCaseGroup> fenceGroup (new tcu::TestCaseGroup(testCtx, externalFenceTypeToName(externalType), externalFenceTypeToName(externalType)));
3991 addFunctionCase(fenceGroup.get(), "info", "Test external fence queries.", testFenceQueries, externalType);
3993 for (size_t permanenceNdx = 0; permanenceNdx < DE_LENGTH_OF_ARRAY(permanences); permanenceNdx++)
3995 const Permanence permanence (permanences[permanenceNdx].permanence);
3996 const char* const permanenceName (permanences[permanenceNdx].name);
3997 const FenceTestConfig config (externalType, permanence);
3999 if (!isSupportedPermanence(externalType, permanence))
4002 if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT
4003 || externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
4005 addFunctionCase(fenceGroup.get(), std::string("create_win32_") + permanenceName, "Test creating fence with win32 properties.", testFenceWin32Create, config);
4008 addFunctionCase(fenceGroup.get(), std::string("import_twice_") + permanenceName, "Test importing fence twice.", checkSupport, testFenceImportTwice, config);
4009 addFunctionCase(fenceGroup.get(), std::string("reimport_") + permanenceName, "Test importing again over previously imported fence.", checkSupport, testFenceImportReimport, config);
4010 addFunctionCase(fenceGroup.get(), std::string("import_multiple_times_") + permanenceName, "Test importing fence multiple times.", checkSupport, testFenceMultipleImports, config);
4011 addFunctionCase(fenceGroup.get(), std::string("signal_export_import_wait_") + permanenceName, "Test signaling, exporting, importing and waiting for the sempahore.", checkEvent, testFenceSignalExportImportWait, config);
4012 addFunctionCase(fenceGroup.get(), std::string("signal_import_") + permanenceName, "Test signaling and importing the fence.", checkSupport, testFenceSignalImport, config);
4013 addFunctionCase(fenceGroup.get(), std::string("reset_") + permanenceName, "Test resetting the fence.", checkEvent, testFenceReset, config);
4014 addFunctionCase(fenceGroup.get(), std::string("transference_") + permanenceName, "Test fences transference.", checkEvent, testFenceTransference, config);
4016 if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT)
4018 addFunctionCase(fenceGroup.get(), std::string("import_signaled_") + permanenceName, "Test import signaled fence fd.", testFenceImportSyncFdSignaled, config);
4021 if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT
4022 || externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT)
4024 // \note Not supported on WIN32 handles
4025 addFunctionCase(fenceGroup.get(), std::string("export_multiple_times_") + permanenceName, "Test exporting fence multiple times.", checkSupport, testFenceMultipleExports, config);
4027 addFunctionCase(fenceGroup.get(), std::string("dup_") + permanenceName, "Test calling dup() on exported fence.", checkSupport, testFenceFdDup, config);
4028 addFunctionCase(fenceGroup.get(), std::string("dup2_") + permanenceName, "Test calling dup2() on exported fence.", checkSupport, testFenceFdDup2, config);
4029 addFunctionCase(fenceGroup.get(), std::string("dup3_") + permanenceName, "Test calling dup3() on exported fence.", checkSupport, testFenceFdDup3, config);
4030 addFunctionCase(fenceGroup.get(), std::string("send_over_socket_") + permanenceName, "Test sending fence fd over socket.", checkSupport, testFenceFdSendOverSocket, config);
4033 if (getHandelTypeTransferences(externalType) == TRANSFERENCE_REFERENCE)
4035 addFunctionCase(fenceGroup.get(), std::string("signal_wait_import_") + permanenceName, "Test signaling and then waiting for the the sepmahore.", testFenceSignalWaitImport, config);
4036 addFunctionCase(fenceGroup.get(), std::string("export_signal_import_wait_") + permanenceName, "Test exporting, signaling, importing and waiting for the fence.", testFenceExportSignalImportWait, config);
4037 addFunctionCase(fenceGroup.get(), std::string("export_import_signal_wait_") + permanenceName, "Test exporting, importing, signaling and waiting for the fence.", testFenceExportImportSignalWait, config);
4044 bool ValidateAHardwareBuffer(vk::VkFormat format, deUint64 requiredAhbUsage, const vk::DeviceDriver& vkd, const vk::VkDevice& device, vk::VkImageCreateFlags createFlag, deUint32 layerCount, bool& enableMaxLayerTest)
4046 DE_UNREF(createFlag);
4048 AndroidHardwareBufferExternalApi* ahbApi = AndroidHardwareBufferExternalApi::getInstance();
4051 TCU_THROW(NotSupportedError, "Platform doesn't support Android Hardware Buffer handles");
4054 #if (DE_OS == DE_OS_ANDROID)
4055 // If CubeMap create flag is used and AHB doesn't support CubeMap return false.
4056 if(!AndroidHardwareBufferExternalApi::supportsCubeMap() && (createFlag & vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT))
4060 vk::pt::AndroidHardwareBufferPtr ahb = ahbApi->allocate(64u, 64u, layerCount, ahbApi->vkFormatToAhbFormat(format), requiredAhbUsage);
4061 if (ahb.internal == DE_NULL)
4063 enableMaxLayerTest = false;
4064 // try again with layerCount '1'
4065 ahb = ahbApi->allocate(64u, 64u, 1u, ahbApi->vkFormatToAhbFormat(format), requiredAhbUsage);
4066 if (ahb.internal == DE_NULL)
4071 NativeHandle nativeHandle(ahb);
4073 const vk::VkComponentMapping mappingA = { vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY };
4074 const vk::VkComponentMapping mappingB = { vk::VK_COMPONENT_SWIZZLE_R, vk::VK_COMPONENT_SWIZZLE_G, vk::VK_COMPONENT_SWIZZLE_B, vk::VK_COMPONENT_SWIZZLE_A };
4076 for (int variantIdx = 0; variantIdx < 2; ++variantIdx)
4078 // Both mappings should be equivalent and work.
4079 const vk::VkComponentMapping& mapping = ((variantIdx == 0) ? mappingA : mappingB);
4081 vk::VkAndroidHardwareBufferFormatPropertiesANDROID formatProperties =
4083 vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID,
4085 vk::VK_FORMAT_UNDEFINED,
4089 vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY,
4090 vk::VK_SAMPLER_YCBCR_RANGE_ITU_FULL,
4091 vk::VK_CHROMA_LOCATION_COSITED_EVEN,
4092 vk::VK_CHROMA_LOCATION_COSITED_EVEN
4095 vk::VkAndroidHardwareBufferPropertiesANDROID bufferProperties =
4097 vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID,
4103 VK_CHECK(vkd.getAndroidHardwareBufferPropertiesANDROID(device, ahb, &bufferProperties));
4104 TCU_CHECK(formatProperties.format != vk::VK_FORMAT_UNDEFINED);
4105 TCU_CHECK(formatProperties.format == format);
4106 TCU_CHECK(formatProperties.externalFormat != 0u);
4107 TCU_CHECK((formatProperties.formatFeatures & vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) != 0u);
4108 TCU_CHECK((formatProperties.formatFeatures & (vk::VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT | vk::VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT)) != 0u);
4114 tcu::TestStatus testAndroidHardwareBufferImageFormat (Context& context, vk::VkFormat format)
4116 AndroidHardwareBufferExternalApi* ahbApi = AndroidHardwareBufferExternalApi::getInstance();
4119 TCU_THROW(NotSupportedError, "Platform doesn't support Android Hardware Buffer handles");
4122 const vk::VkExternalMemoryHandleTypeFlagBits externalMemoryType = vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
4123 const vk::PlatformInterface& vkp (context.getPlatformInterface());
4124 const CustomInstance instance (createTestInstance(context, 0u, externalMemoryType, 0u));
4125 const vk::InstanceDriver& vki (instance.getDriver());
4126 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
4128 vk::VkPhysicalDeviceProtectedMemoryFeatures protectedFeatures;
4129 protectedFeatures.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES;
4130 protectedFeatures.pNext = DE_NULL;
4131 protectedFeatures.protectedMemory = VK_FALSE;
4133 vk::VkPhysicalDeviceFeatures2 deviceFeatures;
4134 deviceFeatures.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
4135 deviceFeatures.pNext = &protectedFeatures;
4137 vki.getPhysicalDeviceFeatures2(physicalDevice, &deviceFeatures);
4139 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
4140 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, externalMemoryType, 0u, queueFamilyIndex, false, &protectedFeatures));
4141 const vk::DeviceDriver vkd (vkp, instance, *device);
4142 TestLog& log = context.getTestContext().getLog();
4143 const vk::VkPhysicalDeviceLimits limits = getPhysicalDeviceProperties(vki, physicalDevice).limits;
4145 const vk::VkImageUsageFlagBits framebufferUsageFlag = vk::isDepthStencilFormat(format) ? vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
4146 : vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
4148 const vk::VkImageUsageFlagBits usageFlags[] =
4150 vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
4151 vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT,
4152 vk::VK_IMAGE_USAGE_SAMPLED_BIT,
4153 vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT,
4154 framebufferUsageFlag,
4156 const vk::VkImageCreateFlagBits createFlags[] =
4158 vk::VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT,
4159 vk::VK_IMAGE_CREATE_EXTENDED_USAGE_BIT,
4160 vk::VK_IMAGE_CREATE_PROTECTED_BIT,
4161 vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT,
4163 const vk::VkImageTiling tilings[] =
4165 vk::VK_IMAGE_TILING_OPTIMAL,
4166 vk::VK_IMAGE_TILING_LINEAR,
4168 deUint64 mustSupportAhbUsageFlags = ahbApi->mustSupportAhbUsageFlags();
4169 const size_t one = 1u;
4170 const size_t numOfUsageFlags = DE_LENGTH_OF_ARRAY(usageFlags);
4171 const size_t numOfCreateFlags = DE_LENGTH_OF_ARRAY(createFlags);
4172 const size_t numOfFlagCombos = one << (numOfUsageFlags + numOfCreateFlags);
4173 const size_t numOfTilings = DE_LENGTH_OF_ARRAY(tilings);
4175 for (size_t combo = 0; combo < numOfFlagCombos; combo++)
4177 vk::VkImageUsageFlags usage = 0;
4178 vk::VkImageCreateFlags createFlag = 0;
4179 deUint64 requiredAhbUsage = 0;
4180 bool enableMaxLayerTest = true;
4181 for (size_t usageNdx = 0; usageNdx < numOfUsageFlags; usageNdx++)
4183 if ((combo & (one << usageNdx)) == 0)
4185 usage |= usageFlags[usageNdx];
4186 requiredAhbUsage |= ahbApi->vkUsageToAhbUsage(usageFlags[usageNdx]);
4188 for (size_t createFlagNdx = 0; createFlagNdx < numOfCreateFlags; createFlagNdx++)
4190 const size_t bit = numOfUsageFlags + createFlagNdx;
4191 if ((combo & (one << bit)) == 0)
4193 if (((createFlags[createFlagNdx] & vk::VK_IMAGE_CREATE_PROTECTED_BIT) == vk::VK_IMAGE_CREATE_PROTECTED_BIT ) &&
4194 (protectedFeatures.protectedMemory == VK_FALSE))
4197 createFlag |= createFlags[createFlagNdx];
4198 requiredAhbUsage |= ahbApi->vkCreateToAhbUsage(createFlags[createFlagNdx]);
4201 // Only test a combination if the usage flags include at least one of the AHARDWAREBUFFER_USAGE_GPU_* flag.
4202 if ((requiredAhbUsage & mustSupportAhbUsageFlags) == 0u)
4205 // Only test a combination if AHardwareBuffer can be successfully allocated for it.
4206 if (!ValidateAHardwareBuffer(format, requiredAhbUsage, vkd, *device, createFlag, limits.maxImageArrayLayers, enableMaxLayerTest))
4209 bool foundAnyUsableTiling = false;
4210 for (size_t tilingIndex = 0; tilingIndex < numOfTilings; tilingIndex++)
4212 const vk::VkImageTiling tiling = tilings[tilingIndex];
4214 const vk::VkPhysicalDeviceExternalImageFormatInfo externalInfo =
4216 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
4218 vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID
4220 const vk::VkPhysicalDeviceImageFormatInfo2 info =
4222 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
4225 vk::VK_IMAGE_TYPE_2D,
4231 vk::VkAndroidHardwareBufferUsageANDROID ahbUsageProperties =
4233 vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID,
4237 vk::VkExternalImageFormatProperties externalProperties =
4239 vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES,
4240 &ahbUsageProperties,
4243 vk::VkImageFormatProperties2 properties =
4245 vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
4246 &externalProperties,
4256 if (vki.getPhysicalDeviceImageFormatProperties2(physicalDevice, &info, &properties) == vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
4258 log << TestLog::Message << "Tiling " << tiling << " is not supported." << TestLog::EndMessage;
4262 foundAnyUsableTiling = true;
4264 TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) != 0);
4265 TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) != 0);
4266 TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0);
4267 deUint32 maxWidth = properties.imageFormatProperties.maxExtent.width;
4268 deUint32 maxHeight = properties.imageFormatProperties.maxExtent.height;
4269 TCU_CHECK(maxWidth >= 4096);
4270 TCU_CHECK(maxHeight >= 4096);
4271 // Even if not requested, at least one of GPU_* usage flags must be present.
4272 TCU_CHECK((ahbUsageProperties.androidHardwareBufferUsage & mustSupportAhbUsageFlags) != 0u);
4273 // The AHB usage flags corresponding to the create and usage flags used in info must be present.
4274 TCU_CHECK((ahbUsageProperties.androidHardwareBufferUsage & requiredAhbUsage) == requiredAhbUsage);
4276 log << TestLog::Message << "Required flags: " << std::hex << requiredAhbUsage << " Actual flags: " << std::hex << ahbUsageProperties.androidHardwareBufferUsage
4277 << TestLog::EndMessage;
4290 deUint32 exportedMemoryTypeIndex = 0;
4292 if (createFlag & vk::VK_IMAGE_CREATE_PROTECTED_BIT)
4294 const vk::VkPhysicalDeviceMemoryProperties memProperties(vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
4296 for (deUint32 memoryTypeIndex = 0; memoryTypeIndex < VK_MAX_MEMORY_TYPES; memoryTypeIndex++)
4298 if (memProperties.memoryTypes[memoryTypeIndex].propertyFlags & vk::VK_MEMORY_PROPERTY_PROTECTED_BIT)
4300 exportedMemoryTypeIndex = memoryTypeIndex;
4306 for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(sizes); i++)
4308 const vk::Unique<vk::VkImage> image (createExternalImage(vkd, *device, queueFamilyIndex, externalMemoryType, format, sizes[i].width, sizes[i].height, tiling, createFlag, usage));
4309 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *image, externalMemoryType));
4310 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, externalMemoryType, *image));
4311 NativeHandle handle;
4313 VK_CHECK(vkd.bindImageMemory(*device, *image, *memory, 0u));
4314 getMemoryNative(vkd, *device, *memory, externalMemoryType, handle);
4316 deUint32 ahbFormat = 0;
4317 deUint64 anhUsage = 0;
4318 ahbApi->describe(handle.getAndroidHardwareBuffer(), DE_NULL, DE_NULL, DE_NULL, &ahbFormat, &anhUsage, DE_NULL);
4319 TCU_CHECK(ahbFormat == ahbApi->vkFormatToAhbFormat(format));
4320 TCU_CHECK((anhUsage & requiredAhbUsage) == requiredAhbUsage);
4322 // Let watchdog know we're alive
4323 context.getTestContext().touchWatchdog();
4326 if (properties.imageFormatProperties.maxMipLevels >= 7u)
4328 const vk::Unique<vk::VkImage> image (createExternalImage(vkd, *device, queueFamilyIndex, externalMemoryType, format, 64u, 64u, tiling, createFlag, usage, 7u));
4329 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *image, externalMemoryType));
4330 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, externalMemoryType, *image));
4331 NativeHandle handle;
4333 VK_CHECK(vkd.bindImageMemory(*device, *image, *memory, 0u));
4334 getMemoryNative(vkd, *device, *memory, externalMemoryType, handle);
4336 deUint32 ahbFormat = 0;
4337 deUint64 anhUsage = 0;
4338 ahbApi->describe(handle.getAndroidHardwareBuffer(), DE_NULL, DE_NULL, DE_NULL, &ahbFormat, &anhUsage, DE_NULL);
4339 TCU_CHECK(ahbFormat == ahbApi->vkFormatToAhbFormat(format));
4340 TCU_CHECK((anhUsage & requiredAhbUsage) == requiredAhbUsage);
4343 if ((properties.imageFormatProperties.maxArrayLayers > 1u) && enableMaxLayerTest)
4345 const vk::Unique<vk::VkImage> image (createExternalImage(vkd, *device, queueFamilyIndex, externalMemoryType, format, 64u, 64u, tiling, createFlag, usage, 1u, properties.imageFormatProperties.maxArrayLayers));
4346 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *image, externalMemoryType));
4347 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, externalMemoryType, *image));
4348 NativeHandle handle;
4350 VK_CHECK(vkd.bindImageMemory(*device, *image, *memory, 0u));
4351 getMemoryNative(vkd, *device, *memory, externalMemoryType, handle);
4353 deUint32 ahbFormat = 0;
4354 deUint64 anhUsage = 0;
4355 ahbApi->describe(handle.getAndroidHardwareBuffer(), DE_NULL, DE_NULL, DE_NULL, &ahbFormat, &anhUsage, DE_NULL);
4356 TCU_CHECK(ahbFormat == ahbApi->vkFormatToAhbFormat(format));
4357 TCU_CHECK((anhUsage & requiredAhbUsage) == requiredAhbUsage);
4361 TCU_CHECK(foundAnyUsableTiling);
4363 return tcu::TestStatus::pass("Pass");
4366 de::MovePtr<tcu::TestCaseGroup> createFenceTests (tcu::TestContext& testCtx)
4368 de::MovePtr<tcu::TestCaseGroup> fenceGroup (new tcu::TestCaseGroup(testCtx, "fence", "Tests for external fences."));
4370 fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT).release());
4371 fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT).release());
4372 fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT).release());
4373 fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT).release());
4378 de::MovePtr<tcu::TestCaseGroup> createSemaphoreTests (tcu::TestContext& testCtx, vk::VkExternalSemaphoreHandleTypeFlagBits externalType)
4382 const char* const name;
4383 const Permanence permanence;
4386 { "temporary", PERMANENCE_TEMPORARY },
4387 { "permanent", PERMANENCE_PERMANENT }
4391 const char* const name;
4392 vk::VkSemaphoreType type;
4393 } semaphoreTypes[] =
4395 { "binary", vk::VK_SEMAPHORE_TYPE_BINARY },
4396 { "timeline", vk::VK_SEMAPHORE_TYPE_TIMELINE },
4399 de::MovePtr<tcu::TestCaseGroup> semaphoreGroup (new tcu::TestCaseGroup(testCtx, externalSemaphoreTypeToName(externalType), externalSemaphoreTypeToName(externalType)));
4401 for (size_t semaphoreTypeIdx = 0; semaphoreTypeIdx < DE_LENGTH_OF_ARRAY(permanences); semaphoreTypeIdx++)
4403 addFunctionCase(semaphoreGroup.get(), std::string("info_") + semaphoreTypes[semaphoreTypeIdx].name,
4404 "Test external semaphore queries.", testSemaphoreQueries,
4405 TestSemaphoreQueriesParameters(semaphoreTypes[semaphoreTypeIdx].type, externalType));
4408 for (size_t permanenceNdx = 0; permanenceNdx < DE_LENGTH_OF_ARRAY(permanences); permanenceNdx++)
4410 const Permanence permanence (permanences[permanenceNdx].permanence);
4411 const char* const permanenceName (permanences[permanenceNdx].name);
4412 const SemaphoreTestConfig config (externalType, permanence);
4414 if (!isSupportedPermanence(externalType, permanence))
4417 if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
4418 || externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
4420 addFunctionCase(semaphoreGroup.get(), std::string("create_win32_") + permanenceName, "Test creating semaphore with win32 properties.", testSemaphoreWin32Create, config);
4423 addFunctionCase(semaphoreGroup.get(), std::string("import_twice_") + permanenceName, "Test importing semaphore twice.", checkSupport, testSemaphoreImportTwice, config);
4424 addFunctionCase(semaphoreGroup.get(), std::string("reimport_") + permanenceName, "Test importing again over previously imported semaphore.", checkSupport, testSemaphoreImportReimport, config);
4425 addFunctionCase(semaphoreGroup.get(), std::string("import_multiple_times_") + permanenceName, "Test importing semaphore multiple times.", checkSupport, testSemaphoreMultipleImports, config);
4426 addFunctionCase(semaphoreGroup.get(), std::string("signal_export_import_wait_") + permanenceName, "Test signaling, exporting, importing and waiting for the sempahore.", checkEvent, testSemaphoreSignalExportImportWait, config);
4427 addFunctionCase(semaphoreGroup.get(), std::string("signal_import_") + permanenceName, "Test signaling and importing the semaphore.", checkSupport, testSemaphoreSignalImport, config);
4428 addFunctionCase(semaphoreGroup.get(), std::string("transference_") + permanenceName, "Test semaphores transference.", checkEvent, testSemaphoreTransference, config);
4430 if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT)
4432 addFunctionCase(semaphoreGroup.get(), std::string("import_signaled_") + permanenceName, "Test import signaled semaphore fd.", testSemaphoreImportSyncFdSignaled, config);
4436 if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT
4437 || externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT)
4439 // \note Not supported on WIN32 handles
4440 addFunctionCase(semaphoreGroup.get(), std::string("export_multiple_times_") + permanenceName, "Test exporting semaphore multiple times.", checkSupport, testSemaphoreMultipleExports, config);
4442 addFunctionCase(semaphoreGroup.get(), std::string("dup_") + permanenceName, "Test calling dup() on exported semaphore.", checkSupport, testSemaphoreFdDup, config);
4443 addFunctionCase(semaphoreGroup.get(), std::string("dup2_") + permanenceName, "Test calling dup2() on exported semaphore.", checkSupport, testSemaphoreFdDup2, config);
4444 addFunctionCase(semaphoreGroup.get(), std::string("dup3_") + permanenceName, "Test calling dup3() on exported semaphore.", checkSupport, testSemaphoreFdDup3, config);
4445 addFunctionCase(semaphoreGroup.get(), std::string("send_over_socket_") + permanenceName, "Test sending semaphore fd over socket.", checkSupport, testSemaphoreFdSendOverSocket, config);
4448 if (getHandelTypeTransferences(externalType) == TRANSFERENCE_REFERENCE)
4450 addFunctionCase(semaphoreGroup.get(), std::string("signal_wait_import_") + permanenceName, "Test signaling and then waiting for the the sepmahore.", testSemaphoreSignalWaitImport, config);
4451 addFunctionCase(semaphoreGroup.get(), std::string("export_signal_import_wait_") + permanenceName, "Test exporting, signaling, importing and waiting for the semaphore.", testSemaphoreExportSignalImportWait, config);
4452 addFunctionCase(semaphoreGroup.get(), std::string("export_import_signal_wait_") + permanenceName, "Test exporting, importing, signaling and waiting for the semaphore.", checkEvent, testSemaphoreExportImportSignalWait, config);
4456 return semaphoreGroup;
4459 de::MovePtr<tcu::TestCaseGroup> createSemaphoreTests (tcu::TestContext& testCtx)
4461 de::MovePtr<tcu::TestCaseGroup> semaphoreGroup (new tcu::TestCaseGroup(testCtx, "semaphore", "Tests for external semaphores."));
4463 semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT).release());
4464 semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT).release());
4465 semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT).release());
4466 semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT).release());
4468 return semaphoreGroup;
4471 de::MovePtr<tcu::TestCaseGroup> createMemoryTests (tcu::TestContext& testCtx, vk::VkExternalMemoryHandleTypeFlagBits externalType)
4473 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, externalMemoryTypeToName(externalType), "Tests for external memory"));
4475 for (size_t dedicatedNdx = 0; dedicatedNdx < 2; dedicatedNdx++)
4477 const bool dedicated (dedicatedNdx == 1);
4478 de::MovePtr<tcu::TestCaseGroup> dedicatedGroup (new tcu::TestCaseGroup(testCtx, dedicated ? "dedicated" : "suballocated", ""));
4480 for (size_t hostVisibleNdx = 0; hostVisibleNdx < 2; hostVisibleNdx++)
4482 const bool hostVisible (hostVisibleNdx == 1);
4483 de::MovePtr<tcu::TestCaseGroup> hostVisibleGroup (new tcu::TestCaseGroup(testCtx, hostVisible ? "host_visible" : "device_only", ""));
4484 const MemoryTestConfig memoryConfig (externalType, hostVisible, dedicated);
4486 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
4487 || externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
4489 addFunctionCase(hostVisibleGroup.get(), "create_win32", "Test creating memory with win32 properties .", testMemoryWin32Create, memoryConfig);
4492 addFunctionCase(hostVisibleGroup.get(), "import_twice", "Test importing memory object twice.", testMemoryImportTwice, memoryConfig);
4493 addFunctionCase(hostVisibleGroup.get(), "import_multiple_times", "Test importing memory object multiple times.", testMemoryMultipleImports, memoryConfig);
4495 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT
4496 || externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT)
4498 addFunctionCase(hostVisibleGroup.get(), "dup", "Test calling dup() on exported memory.", testMemoryFdDup, memoryConfig);
4499 addFunctionCase(hostVisibleGroup.get(), "dup2", "Test calling dup2() on exported memory.", testMemoryFdDup2, memoryConfig);
4500 addFunctionCase(hostVisibleGroup.get(), "dup3", "Test calling dup3() on exported memory.", testMemoryFdDup3, memoryConfig);
4501 addFunctionCase(hostVisibleGroup.get(), "send_over_socket", "Test sending memory fd over socket.", testMemoryFdSendOverSocket, memoryConfig);
4502 // \note Not supported on WIN32 handles
4503 addFunctionCase(hostVisibleGroup.get(), "export_multiple_times", "Test exporting memory multiple times.", testMemoryMultipleExports, memoryConfig);
4506 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT)
4508 addFunctionCase(hostVisibleGroup.get(), "fd_properties", "Test obtaining the FD memory properties", testMemoryFdProperties, memoryConfig);
4511 dedicatedGroup->addChild(hostVisibleGroup.release());
4515 de::MovePtr<tcu::TestCaseGroup> bufferGroup (new tcu::TestCaseGroup(testCtx, "buffer", ""));
4516 const BufferTestConfig bufferConfig (externalType, dedicated);
4518 addFunctionCase(bufferGroup.get(), "info", "External buffer memory info query.", testBufferQueries, externalType);
4519 addFunctionCase(bufferGroup.get(), "bind_export_import_bind", "Test binding, exporting, importing and binding buffer.", testBufferBindExportImportBind, bufferConfig);
4520 addFunctionCase(bufferGroup.get(), "export_bind_import_bind", "Test exporting, binding, importing and binding buffer.", testBufferExportBindImportBind, bufferConfig);
4521 addFunctionCase(bufferGroup.get(), "export_import_bind_bind", "Test exporting, importing and binding buffer.", testBufferExportImportBindBind, bufferConfig);
4523 dedicatedGroup->addChild(bufferGroup.release());
4527 de::MovePtr<tcu::TestCaseGroup> imageGroup (new tcu::TestCaseGroup(testCtx, "image", ""));
4528 const ImageTestConfig imageConfig (externalType, dedicated);
4530 addFunctionCase(imageGroup.get(), "info", "External image memory info query.", testImageQueries, externalType);
4531 addFunctionCase(imageGroup.get(), "bind_export_import_bind", "Test binding, exporting, importing and binding image.", testImageBindExportImportBind, imageConfig);
4532 addFunctionCase(imageGroup.get(), "export_bind_import_bind", "Test exporting, binding, importing and binding image.", testImageExportBindImportBind, imageConfig);
4533 addFunctionCase(imageGroup.get(), "export_import_bind_bind", "Test exporting, importing and binding image.", testImageExportImportBindBind, imageConfig);
4535 dedicatedGroup->addChild(imageGroup.release());
4538 group->addChild(dedicatedGroup.release());
4541 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
4543 de::MovePtr<tcu::TestCaseGroup> formatGroup (new tcu::TestCaseGroup(testCtx, "image_formats", "Test minimum image format support"));
4545 const vk::VkFormat ahbFormats[] =
4547 vk::VK_FORMAT_R8G8B8_UNORM,
4548 vk::VK_FORMAT_R8G8B8A8_UNORM,
4549 vk::VK_FORMAT_R5G6B5_UNORM_PACK16,
4550 vk::VK_FORMAT_R16G16B16A16_SFLOAT,
4551 vk::VK_FORMAT_A2B10G10R10_UNORM_PACK32,
4552 vk::VK_FORMAT_D16_UNORM,
4553 vk::VK_FORMAT_X8_D24_UNORM_PACK32,
4554 vk::VK_FORMAT_D24_UNORM_S8_UINT,
4555 vk::VK_FORMAT_D32_SFLOAT,
4556 vk::VK_FORMAT_D32_SFLOAT_S8_UINT,
4557 vk::VK_FORMAT_S8_UINT,
4559 const size_t numOfAhbFormats = DE_LENGTH_OF_ARRAY(ahbFormats);
4561 for (size_t ahbFormatNdx = 0; ahbFormatNdx < numOfAhbFormats; ahbFormatNdx++)
4563 const vk::VkFormat format = ahbFormats[ahbFormatNdx];
4564 const std::string testCaseName = getFormatCaseName(format);
4566 addFunctionCase(formatGroup.get(), testCaseName, "", testAndroidHardwareBufferImageFormat, format);
4569 group->addChild(formatGroup.release());
4575 de::MovePtr<tcu::TestCaseGroup> createMemoryTests (tcu::TestContext& testCtx)
4577 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "memory", "Tests for external memory"));
4579 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT).release());
4580 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT).release());
4581 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT).release());
4582 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID).release());
4583 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT).release());
4590 tcu::TestCaseGroup* createExternalMemoryTests (tcu::TestContext& testCtx)
4592 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "external", "Tests for external Vulkan objects"));
4594 group->addChild(createSemaphoreTests(testCtx).release());
4595 group->addChild(createMemoryTests(testCtx).release());
4596 group->addChild(createFenceTests(testCtx).release());
4598 return group.release();