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 submitDummySignal (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 submitDummySignalAndGetSemaphoreNative ( 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 submitDummySignal 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_BOTTOM_OF_PIPE_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 submitDummyWait (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 submitDummySignal (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 submitDummySignalAndGetFenceNative ( 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 submitDummySignal 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_BOTTOM_OF_PIPE_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 tcu::TestStatus testSemaphoreQueries (Context& context, vk::VkExternalSemaphoreHandleTypeFlagBits externalType)
755 const CustomInstance instance (createTestInstance(context, externalType, 0u, 0u));
756 const vk::InstanceDriver& vki (instance.getDriver());
757 const vk::VkPhysicalDevice device (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
759 TestLog& log = context.getTestContext().getLog();
761 const vk::VkPhysicalDeviceExternalSemaphoreInfo info =
763 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO,
767 vk::VkExternalSemaphoreProperties properties =
769 vk::VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES,
776 vki.getPhysicalDeviceExternalSemaphoreProperties(device, &info, &properties);
777 log << TestLog::Message << properties << TestLog::EndMessage;
779 TCU_CHECK(properties.pNext == DE_NULL);
780 TCU_CHECK(properties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES);
782 return tcu::TestStatus::pass("Pass");
785 struct SemaphoreTestConfig
787 SemaphoreTestConfig (vk::VkExternalSemaphoreHandleTypeFlagBits externalType_,
788 Permanence permanence_)
789 : externalType (externalType_)
790 , permanence (permanence_)
794 vk::VkExternalSemaphoreHandleTypeFlagBits externalType;
795 Permanence permanence;
798 tcu::TestStatus testSemaphoreWin32Create (Context& context,
799 const SemaphoreTestConfig config)
801 #if (DE_OS == DE_OS_WIN32)
802 const Transference transference (getHandelTypeTransferences(config.externalType));
803 const vk::PlatformInterface& vkp (context.getPlatformInterface());
804 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
805 const vk::InstanceDriver& vki (instance.getDriver());
806 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
807 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
809 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
812 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
813 const vk::DeviceDriver vkd (vkp, instance, *device);
814 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
815 const vk::VkExportSemaphoreWin32HandleInfoKHR win32ExportInfo =
817 vk::VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR,
820 (vk::pt::Win32SecurityAttributesPtr)DE_NULL,
821 DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
822 (vk::pt::Win32LPCWSTR)DE_NULL
824 const vk::VkExportSemaphoreCreateInfo exportCreateInfo=
826 vk::VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO,
828 (vk::VkExternalMemoryHandleTypeFlags)config.externalType
830 const vk::VkSemaphoreCreateInfo createInfo =
832 vk::VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
836 const vk::Unique<vk::VkSemaphore> semaphore (vk::createSemaphore(vkd, *device, &createInfo));
838 if (transference == TRANSFERENCE_COPY)
839 submitDummySignal(vkd, queue, *semaphore);
841 NativeHandle handleA;
842 getSemaphoreNative(vkd, *device, *semaphore, config.externalType, handleA);
845 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
846 const vk::Unique<vk::VkSemaphore> semaphoreA (createAndImportSemaphore(vkd, *device, config.externalType, handleA, flags));
848 if (transference == TRANSFERENCE_COPY)
849 submitDummyWait(vkd, queue, *semaphoreA);
850 else if (transference == TRANSFERENCE_REFERENCE)
852 submitDummySignal(vkd, queue, *semaphore);
853 submitDummyWait(vkd, queue, *semaphoreA);
856 DE_FATAL("Unknown transference.");
858 VK_CHECK(vkd.queueWaitIdle(queue));
861 return tcu::TestStatus::pass("Pass");
866 TCU_THROW(NotSupportedError, "Platform doesn't support win32 handles");
870 tcu::TestStatus testSemaphoreImportTwice (Context& context,
871 const SemaphoreTestConfig config)
873 const Transference transference (getHandelTypeTransferences(config.externalType));
874 const vk::PlatformInterface& vkp (context.getPlatformInterface());
875 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
876 const vk::InstanceDriver& vki (instance.getDriver());
877 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
878 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
880 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
883 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
884 const vk::DeviceDriver vkd (vkp, instance, *device);
885 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
886 const vk::Unique<vk::VkSemaphore> semaphore (createExportableSemaphore(vkd, *device, config.externalType));
887 NativeHandle handleA;
889 if (transference == TRANSFERENCE_COPY)
890 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphore, config.externalType, handleA);
892 getSemaphoreNative(vkd, *device, *semaphore, config.externalType, handleA);
895 NativeHandle handleB (handleA);
896 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
897 const vk::Unique<vk::VkSemaphore> semaphoreA (createAndImportSemaphore(vkd, *device, config.externalType, handleA, flags));
898 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handleB, flags));
900 if (transference == TRANSFERENCE_COPY)
901 submitDummyWait(vkd, queue, *semaphoreA);
902 else if (transference == TRANSFERENCE_REFERENCE)
904 submitDummySignal(vkd, queue, *semaphoreA);
905 submitDummyWait(vkd, queue, *semaphoreB);
908 DE_FATAL("Unknown transference.");
910 VK_CHECK(vkd.queueWaitIdle(queue));
913 return tcu::TestStatus::pass("Pass");
917 tcu::TestStatus testSemaphoreImportReimport (Context& context,
918 const SemaphoreTestConfig config)
920 const Transference transference (getHandelTypeTransferences(config.externalType));
921 const vk::PlatformInterface& vkp (context.getPlatformInterface());
922 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
923 const vk::InstanceDriver& vki (instance.getDriver());
924 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
925 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
927 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
930 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
931 const vk::DeviceDriver vkd (vkp, instance, *device);
932 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
934 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
935 NativeHandle handleA;
937 if (transference == TRANSFERENCE_COPY)
938 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handleA);
940 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handleA);
942 NativeHandle handleB (handleA);
943 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
944 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handleA, flags));
946 importSemaphore(vkd, *device, *semaphoreB, config.externalType, handleB, flags);
948 if (transference == TRANSFERENCE_COPY)
949 submitDummyWait(vkd, queue, *semaphoreB);
950 else if (transference == TRANSFERENCE_REFERENCE)
952 submitDummySignal(vkd, queue, *semaphoreA);
953 submitDummyWait(vkd, queue, *semaphoreB);
956 DE_FATAL("Unknown transference.");
958 VK_CHECK(vkd.queueWaitIdle(queue));
960 return tcu::TestStatus::pass("Pass");
964 tcu::TestStatus testSemaphoreSignalExportImportWait (Context& context,
965 const SemaphoreTestConfig config)
967 const vk::PlatformInterface& vkp (context.getPlatformInterface());
968 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
969 const vk::InstanceDriver& vki (instance.getDriver());
970 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
971 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
973 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
976 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
977 const vk::DeviceDriver vkd (vkp, instance, *device);
978 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
979 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
983 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
986 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
987 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
988 submitDummyWait(vkd, queue, *semaphoreB);
990 VK_CHECK(vkd.queueWaitIdle(queue));
994 return tcu::TestStatus::pass("Pass");
998 tcu::TestStatus testSemaphoreExportSignalImportWait (Context& context,
999 const SemaphoreTestConfig config)
1001 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1002 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1003 const vk::InstanceDriver& vki (instance.getDriver());
1004 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1005 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1006 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1008 DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
1009 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1012 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1013 const vk::DeviceDriver vkd (vkp, instance, *device);
1014 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1016 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1017 NativeHandle handle;
1019 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
1021 submitDummySignal(vkd, queue, *semaphoreA);
1024 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1026 submitDummyWait(vkd, queue, *semaphoreB);
1027 VK_CHECK(vkd.queueWaitIdle(queue));
1031 return tcu::TestStatus::pass("Pass");
1035 tcu::TestStatus testSemaphoreExportImportSignalWait (Context& context,
1036 const SemaphoreTestConfig config)
1038 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1039 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1040 const vk::InstanceDriver& vki (instance.getDriver());
1041 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1042 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1044 DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
1045 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1048 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1049 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1050 const vk::DeviceDriver vkd (vkp, instance, *device);
1051 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1053 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1054 NativeHandle handle;
1056 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
1058 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1060 submitDummySignal(vkd, queue, *semaphoreA);
1061 submitDummyWait(vkd, queue, *semaphoreB);
1063 VK_CHECK(vkd.queueWaitIdle(queue));
1065 return tcu::TestStatus::pass("Pass");
1069 tcu::TestStatus testSemaphoreSignalImport (Context& context,
1070 const SemaphoreTestConfig config)
1072 const Transference transference (getHandelTypeTransferences(config.externalType));
1073 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1074 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1075 const vk::InstanceDriver& vki (instance.getDriver());
1076 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1077 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1079 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1082 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1083 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1084 const vk::DeviceDriver vkd (vkp, instance, *device);
1085 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1087 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1088 const vk::Unique<vk::VkSemaphore> semaphoreB (createSemaphore(vkd, *device));
1089 NativeHandle handle;
1091 submitDummySignal(vkd, queue, *semaphoreB);
1092 VK_CHECK(vkd.queueWaitIdle(queue));
1094 if (transference == TRANSFERENCE_COPY)
1095 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
1097 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
1099 importSemaphore(vkd, *device, *semaphoreB, config.externalType, handle, flags);
1101 if (transference == TRANSFERENCE_COPY)
1102 submitDummyWait(vkd, queue, *semaphoreB);
1103 else if (transference == TRANSFERENCE_REFERENCE)
1105 submitDummySignal(vkd, queue, *semaphoreA);
1106 submitDummyWait(vkd, queue, *semaphoreB);
1109 DE_FATAL("Unknown transference.");
1111 VK_CHECK(vkd.queueWaitIdle(queue));
1113 return tcu::TestStatus::pass("Pass");
1117 tcu::TestStatus testSemaphoreSignalWaitImport (Context& context,
1118 const SemaphoreTestConfig config)
1120 const Transference transference (getHandelTypeTransferences(config.externalType));
1121 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1122 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1123 const vk::InstanceDriver& vki (instance.getDriver());
1124 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1125 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1127 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1130 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1131 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1132 const vk::DeviceDriver vkd (vkp, instance, *device);
1133 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1135 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1136 const vk::Unique<vk::VkSemaphore> semaphoreB (createSemaphore(vkd, *device));
1137 NativeHandle handle;
1139 if (transference == TRANSFERENCE_COPY)
1140 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
1142 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
1144 submitDummySignal(vkd, queue, *semaphoreB);
1145 submitDummyWait(vkd, queue, *semaphoreB);
1147 VK_CHECK(vkd.queueWaitIdle(queue));
1149 importSemaphore(vkd, *device, *semaphoreB, config.externalType, handle, flags);
1151 if (transference == TRANSFERENCE_COPY)
1152 submitDummyWait(vkd, queue, *semaphoreB);
1153 else if (transference == TRANSFERENCE_REFERENCE)
1155 submitDummySignal(vkd, queue, *semaphoreA);
1156 submitDummyWait(vkd, queue, *semaphoreB);
1159 DE_FATAL("Unknown transference.");
1161 VK_CHECK(vkd.queueWaitIdle(queue));
1163 return tcu::TestStatus::pass("Pass");
1167 tcu::TestStatus testSemaphoreImportSyncFdSignaled (Context& context,
1168 const SemaphoreTestConfig config)
1170 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1171 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1172 const vk::InstanceDriver& vki (instance.getDriver());
1173 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1174 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1175 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1177 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1180 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1181 const vk::DeviceDriver vkd (vkp, instance, *device);
1182 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1183 NativeHandle handle = -1;
1184 const vk::Unique<vk::VkSemaphore> semaphore (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1186 submitDummyWait(vkd, queue, *semaphore);
1188 return tcu::TestStatus::pass("Pass");
1192 tcu::TestStatus testSemaphoreMultipleExports (Context& context,
1193 const SemaphoreTestConfig config)
1195 const size_t exportCount = 4 * 1024;
1196 const Transference transference (getHandelTypeTransferences(config.externalType));
1197 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1198 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1199 const vk::InstanceDriver& vki (instance.getDriver());
1200 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1201 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1203 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1206 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1207 const vk::DeviceDriver vkd (vkp, instance, *device);
1208 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1209 const vk::Unique<vk::VkSemaphore> semaphore (createExportableSemaphore(vkd, *device, config.externalType));
1211 for (size_t exportNdx = 0; exportNdx < exportCount; exportNdx++)
1213 NativeHandle handle;
1215 if (transference == TRANSFERENCE_COPY)
1216 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphore, config.externalType, handle);
1218 getSemaphoreNative(vkd, *device, *semaphore, config.externalType, handle);
1221 submitDummySignal(vkd, queue, *semaphore);
1222 submitDummyWait(vkd, queue, *semaphore);
1224 VK_CHECK(vkd.queueWaitIdle(queue));
1227 return tcu::TestStatus::pass("Pass");
1230 tcu::TestStatus testSemaphoreMultipleImports (Context& context,
1231 const SemaphoreTestConfig config)
1233 const size_t importCount = 4 * 1024;
1234 const Transference transference (getHandelTypeTransferences(config.externalType));
1235 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1236 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1237 const vk::InstanceDriver& vki (instance.getDriver());
1238 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1239 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1241 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1244 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1245 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1246 const vk::DeviceDriver vkd (vkp, instance, *device);
1247 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1248 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1249 NativeHandle handleA;
1251 if (transference == TRANSFERENCE_COPY)
1252 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handleA);
1254 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handleA);
1256 for (size_t importNdx = 0; importNdx < importCount; importNdx++)
1258 NativeHandle handleB (handleA);
1259 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handleB, flags));
1262 if (transference == TRANSFERENCE_COPY)
1264 importSemaphore(vkd, *device, *semaphoreA, config.externalType, handleA, flags);
1265 submitDummyWait(vkd, queue, *semaphoreA);
1267 else if (transference == TRANSFERENCE_REFERENCE)
1269 submitDummySignal(vkd, queue, *semaphoreA);
1270 submitDummyWait(vkd, queue, *semaphoreA);
1273 DE_FATAL("Unknown transference.");
1275 VK_CHECK(vkd.queueWaitIdle(queue));
1278 return tcu::TestStatus::pass("Pass");
1281 tcu::TestStatus testSemaphoreTransference (Context& context,
1282 const SemaphoreTestConfig config)
1284 const Transference transference (getHandelTypeTransferences(config.externalType));
1285 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1286 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1287 const vk::InstanceDriver& vki (instance.getDriver());
1288 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1289 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1291 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1294 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1295 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1296 const vk::DeviceDriver vkd (vkp, instance, *device);
1297 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1299 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1300 NativeHandle handle;
1302 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
1305 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1307 if (config.permanence == PERMANENCE_PERMANENT)
1309 if (transference == TRANSFERENCE_COPY)
1311 submitDummySignal(vkd, queue, *semaphoreA);
1312 submitDummyWait(vkd, queue, *semaphoreB);
1313 VK_CHECK(vkd.queueWaitIdle(queue));
1315 submitDummySignal(vkd, queue, *semaphoreB);
1317 submitDummyWait(vkd, queue, *semaphoreA);
1318 submitDummyWait(vkd, queue, *semaphoreB);
1319 VK_CHECK(vkd.queueWaitIdle(queue));
1321 else if (transference== TRANSFERENCE_REFERENCE)
1323 submitDummyWait(vkd, queue, *semaphoreB);
1324 VK_CHECK(vkd.queueWaitIdle(queue));
1326 submitDummySignal(vkd, queue, *semaphoreA);
1327 submitDummyWait(vkd, queue, *semaphoreB);
1329 submitDummySignal(vkd, queue, *semaphoreB);
1330 submitDummyWait(vkd, queue, *semaphoreA);
1331 VK_CHECK(vkd.queueWaitIdle(queue));
1334 DE_FATAL("Unknown transference.");
1336 else if (config.permanence == PERMANENCE_TEMPORARY)
1338 if (transference == TRANSFERENCE_COPY)
1340 submitDummySignal(vkd, queue, *semaphoreA);
1341 submitDummyWait(vkd, queue, *semaphoreB);
1342 VK_CHECK(vkd.queueWaitIdle(queue));
1344 submitDummySignal(vkd, queue, *semaphoreB);
1346 submitDummyWait(vkd, queue, *semaphoreA);
1347 submitDummyWait(vkd, queue, *semaphoreB);
1348 VK_CHECK(vkd.queueWaitIdle(queue));
1350 else if (transference== TRANSFERENCE_REFERENCE)
1352 submitDummyWait(vkd, queue, *semaphoreB);
1353 VK_CHECK(vkd.queueWaitIdle(queue));
1355 submitDummySignal(vkd, queue, *semaphoreA);
1356 submitDummySignal(vkd, queue, *semaphoreB);
1358 submitDummyWait(vkd, queue, *semaphoreB);
1359 submitDummyWait(vkd, queue, *semaphoreA);
1360 VK_CHECK(vkd.queueWaitIdle(queue));
1363 DE_FATAL("Unknown transference.");
1366 DE_FATAL("Unknown permanence.");
1369 return tcu::TestStatus::pass("Pass");
1373 tcu::TestStatus testSemaphoreFdDup (Context& context,
1374 const SemaphoreTestConfig config)
1376 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
1377 const Transference transference (getHandelTypeTransferences(config.externalType));
1378 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1379 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1380 const vk::InstanceDriver& vki (instance.getDriver());
1381 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1382 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1384 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1387 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1388 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1389 const vk::DeviceDriver vkd (vkp, instance, *device);
1390 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1392 TestLog& log = context.getTestContext().getLog();
1393 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1398 if (transference == TRANSFERENCE_COPY)
1399 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, fd);
1401 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, fd);
1403 NativeHandle newFd (dup(fd.getFd()));
1405 if (newFd.getFd() < 0)
1406 log << TestLog::Message << "dup() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
1408 TCU_CHECK_MSG(newFd.getFd() >= 0, "Failed to call dup() for semaphores fd");
1411 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, newFd, flags));
1413 if (transference == TRANSFERENCE_COPY)
1414 submitDummyWait(vkd, queue, *semaphoreB);
1415 else if (transference == TRANSFERENCE_REFERENCE)
1417 submitDummySignal(vkd, queue, *semaphoreA);
1418 submitDummyWait(vkd, queue, *semaphoreB);
1421 DE_FATAL("Unknown permanence.");
1423 VK_CHECK(vkd.queueWaitIdle(queue));
1427 return tcu::TestStatus::pass("Pass");
1432 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
1436 tcu::TestStatus testSemaphoreFdDup2 (Context& context,
1437 const SemaphoreTestConfig config)
1439 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
1440 const Transference transference (getHandelTypeTransferences(config.externalType));
1441 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1442 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1443 const vk::InstanceDriver& vki (instance.getDriver());
1444 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1445 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1447 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1450 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1451 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1452 const vk::DeviceDriver vkd (vkp, instance, *device);
1453 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1455 TestLog& log = context.getTestContext().getLog();
1456 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1457 const vk::Unique<vk::VkSemaphore> semaphoreB (createExportableSemaphore(vkd, *device, config.externalType));
1460 NativeHandle fd, secondFd;
1462 if (transference == TRANSFERENCE_COPY)
1464 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, fd);
1465 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreB, config.externalType, secondFd);
1469 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, fd);
1470 getSemaphoreNative(vkd, *device, *semaphoreB, config.externalType, secondFd);
1473 int newFd (dup2(fd.getFd(), secondFd.getFd()));
1476 log << TestLog::Message << "dup2() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
1478 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup2() for fences fd");
1481 const vk::Unique<vk::VkSemaphore> semaphoreC (createAndImportSemaphore(vkd, *device, config.externalType, secondFd, flags));
1483 if (transference == TRANSFERENCE_COPY)
1484 submitDummyWait(vkd, queue, *semaphoreC);
1485 else if (transference == TRANSFERENCE_REFERENCE)
1487 submitDummySignal(vkd, queue, *semaphoreA);
1488 submitDummyWait(vkd, queue, *semaphoreC);
1491 DE_FATAL("Unknown permanence.");
1493 VK_CHECK(vkd.queueWaitIdle(queue));
1497 return tcu::TestStatus::pass("Pass");
1502 TCU_THROW(NotSupportedError, "Platform doesn't support dup2()");
1506 tcu::TestStatus testSemaphoreFdDup3 (Context& context,
1507 const SemaphoreTestConfig config)
1509 #if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
1510 const Transference transference (getHandelTypeTransferences(config.externalType));
1511 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1512 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1513 const vk::InstanceDriver& vki (instance.getDriver());
1514 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1515 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1517 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1520 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1521 const vk::DeviceDriver vkd (vkp, instance, *device);
1522 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1524 TestLog& log = context.getTestContext().getLog();
1525 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1526 const vk::Unique<vk::VkSemaphore> semaphoreB (createExportableSemaphore(vkd, *device, config.externalType));
1529 NativeHandle fd, secondFd;
1531 if (transference == TRANSFERENCE_COPY)
1533 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, fd);
1534 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreB, config.externalType, secondFd);
1538 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, fd);
1539 getSemaphoreNative(vkd, *device, *semaphoreB, config.externalType, secondFd);
1542 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1543 const int newFd (dup3(fd.getFd(), secondFd.getFd(), 0));
1546 log << TestLog::Message << "dup3() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
1548 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup3() for fences fd");
1551 const vk::Unique<vk::VkSemaphore> semaphoreC (createAndImportSemaphore(vkd, *device, config.externalType, secondFd, flags));
1553 if (transference == TRANSFERENCE_COPY)
1554 submitDummyWait(vkd, queue, *semaphoreC);
1555 else if (transference == TRANSFERENCE_REFERENCE)
1557 submitDummySignal(vkd, queue, *semaphoreA);
1558 submitDummyWait(vkd, queue, *semaphoreC);
1561 DE_FATAL("Unknown permanence.");
1563 VK_CHECK(vkd.queueWaitIdle(queue));
1567 return tcu::TestStatus::pass("Pass");
1572 TCU_THROW(NotSupportedError, "Platform doesn't support dup3()");
1576 tcu::TestStatus testSemaphoreFdSendOverSocket (Context& context,
1577 const SemaphoreTestConfig config)
1579 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
1580 const Transference transference (getHandelTypeTransferences(config.externalType));
1581 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1582 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1583 const vk::InstanceDriver& vki (instance.getDriver());
1584 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1585 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1587 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1590 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1591 const vk::DeviceDriver vkd (vkp, instance, *device);
1592 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1594 TestLog& log = context.getTestContext().getLog();
1595 const vk::Unique<vk::VkSemaphore> semaphore (createExportableSemaphore(vkd, *device, config.externalType));
1598 if (transference == TRANSFERENCE_COPY)
1599 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphore, config.externalType, fd);
1601 getSemaphoreNative(vkd, *device, *semaphore, config.externalType, fd);
1606 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
1608 log << TestLog::Message << "Failed to create socket pair: '" << strerror(errno) << "'" << TestLog::EndMessage;
1609 TCU_FAIL("Failed to create socket pair");
1613 const NativeHandle srcSocket (sv[0]);
1614 const NativeHandle dstSocket (sv[1]);
1615 std::string sendData ("deqp");
1619 const int fdRaw (fd.getFd());
1622 char buffer[CMSG_SPACE(sizeof(int))];
1623 iovec iov = { &sendData[0], sendData.length()};
1625 deMemset(&msg, 0, sizeof(msg));
1627 msg.msg_control = buffer;
1628 msg.msg_controllen = sizeof(buffer);
1632 cmsg = CMSG_FIRSTHDR(&msg);
1633 cmsg->cmsg_level = SOL_SOCKET;
1634 cmsg->cmsg_type = SCM_RIGHTS;
1635 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
1637 deMemcpy(CMSG_DATA(cmsg), &fdRaw, sizeof(int));
1638 msg.msg_controllen = cmsg->cmsg_len;
1640 if (sendmsg(srcSocket.getFd(), &msg, 0) < 0)
1642 log << TestLog::Message << "Failed to send fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
1643 TCU_FAIL("Failed to send fd over socket");
1650 char buffer[CMSG_SPACE(sizeof(int))];
1651 std::string recvData (4, '\0');
1652 iovec iov = { &recvData[0], recvData.length() };
1654 deMemset(&msg, 0, sizeof(msg));
1656 msg.msg_control = buffer;
1657 msg.msg_controllen = sizeof(buffer);
1661 const ssize_t bytes = recvmsg(dstSocket.getFd(), &msg, 0);
1665 log << TestLog::Message << "Failed to recv fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
1666 TCU_FAIL("Failed to recv fd over socket");
1669 else if (bytes != (ssize_t)sendData.length())
1671 TCU_FAIL("recvmsg() returned unpexpected number of bytes");
1675 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1676 const cmsghdr* const cmsg = CMSG_FIRSTHDR(&msg);
1678 deMemcpy(&newFd_, CMSG_DATA(cmsg), sizeof(int));
1679 NativeHandle newFd (newFd_);
1681 TCU_CHECK(cmsg->cmsg_level == SOL_SOCKET);
1682 TCU_CHECK(cmsg->cmsg_type == SCM_RIGHTS);
1683 TCU_CHECK(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
1684 TCU_CHECK(recvData == sendData);
1685 TCU_CHECK_MSG(newFd.getFd() >= 0, "Didn't receive valid fd from socket");
1688 const vk::Unique<vk::VkSemaphore> newSemaphore (createAndImportSemaphore(vkd, *device, config.externalType, newFd, flags));
1690 if (transference == TRANSFERENCE_COPY)
1691 submitDummyWait(vkd, queue, *newSemaphore);
1692 else if (transference == TRANSFERENCE_REFERENCE)
1694 submitDummySignal(vkd, queue, *newSemaphore);
1695 submitDummyWait(vkd, queue, *newSemaphore);
1698 DE_FATAL("Unknown permanence.");
1700 VK_CHECK(vkd.queueWaitIdle(queue));
1708 return tcu::TestStatus::pass("Pass");
1712 TCU_THROW(NotSupportedError, "Platform doesn't support sending file descriptors over socket");
1716 tcu::TestStatus testFenceQueries (Context& context, vk::VkExternalFenceHandleTypeFlagBits externalType)
1718 const CustomInstance instance (createTestInstance(context, 0u, 0u, externalType));
1719 const vk::InstanceDriver& vki (instance.getDriver());
1720 const vk::VkPhysicalDevice device (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1722 TestLog& log = context.getTestContext().getLog();
1724 const vk::VkPhysicalDeviceExternalFenceInfo info =
1726 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO,
1730 vk::VkExternalFenceProperties properties =
1732 vk::VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES,
1739 vki.getPhysicalDeviceExternalFenceProperties(device, &info, &properties);
1740 log << TestLog::Message << properties << TestLog::EndMessage;
1742 TCU_CHECK(properties.pNext == DE_NULL);
1743 TCU_CHECK(properties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES);
1745 return tcu::TestStatus::pass("Pass");
1748 struct FenceTestConfig
1750 FenceTestConfig (vk::VkExternalFenceHandleTypeFlagBits externalType_,
1751 Permanence permanence_)
1752 : externalType (externalType_)
1753 , permanence (permanence_)
1757 vk::VkExternalFenceHandleTypeFlagBits externalType;
1758 Permanence permanence;
1762 tcu::TestStatus testFenceWin32Create (Context& context,
1763 const FenceTestConfig config)
1765 #if (DE_OS == DE_OS_WIN32)
1766 const Transference transference (getHandelTypeTransferences(config.externalType));
1767 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1768 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
1769 const vk::InstanceDriver& vki (instance.getDriver());
1770 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1771 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1773 checkFenceSupport(vki, physicalDevice, config.externalType);
1776 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1777 const vk::DeviceDriver vkd (vkp, instance, *device);
1778 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1779 const vk::VkExportFenceWin32HandleInfoKHR win32ExportInfo =
1781 vk::VK_STRUCTURE_TYPE_EXPORT_FENCE_WIN32_HANDLE_INFO_KHR,
1784 (vk::pt::Win32SecurityAttributesPtr)DE_NULL,
1785 DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
1786 (vk::pt::Win32LPCWSTR)DE_NULL
1788 const vk::VkExportFenceCreateInfo exportCreateInfo=
1790 vk::VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO,
1792 (vk::VkExternalFenceHandleTypeFlags)config.externalType
1794 const vk::VkFenceCreateInfo createInfo =
1796 vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
1800 const vk::Unique<vk::VkFence> fence (vk::createFence(vkd, *device, &createInfo));
1802 if (transference == TRANSFERENCE_COPY)
1803 submitDummySignal(vkd, queue, *fence);
1805 NativeHandle handleA;
1806 getFenceNative(vkd, *device, *fence, config.externalType, handleA);
1809 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
1810 const vk::Unique<vk::VkFence> fenceA (createAndImportFence(vkd, *device, config.externalType, handleA, flags));
1812 if (transference == TRANSFERENCE_COPY)
1813 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
1814 else if (transference == TRANSFERENCE_REFERENCE)
1816 submitDummySignal(vkd, queue, *fence);
1817 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
1820 DE_FATAL("Unknown transference.");
1822 VK_CHECK(vkd.queueWaitIdle(queue));
1825 return tcu::TestStatus::pass("Pass");
1830 TCU_THROW(NotSupportedError, "Platform doesn't support win32 handles");
1834 tcu::TestStatus testFenceImportTwice (Context& context,
1835 const FenceTestConfig config)
1837 const Transference transference (getHandelTypeTransferences(config.externalType));
1838 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1839 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
1840 const vk::InstanceDriver& vki (instance.getDriver());
1841 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1842 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1844 checkFenceSupport(vki, physicalDevice, config.externalType);
1847 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1848 const vk::DeviceDriver vkd (vkp, instance, *device);
1849 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1850 const vk::Unique<vk::VkFence> fence (createExportableFence(vkd, *device, config.externalType));
1851 NativeHandle handleA;
1853 if (transference == TRANSFERENCE_COPY)
1854 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fence, config.externalType, handleA);
1856 getFenceNative(vkd, *device, *fence, config.externalType, handleA);
1859 NativeHandle handleB (handleA);
1860 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
1861 const vk::Unique<vk::VkFence> fenceA (createAndImportFence(vkd, *device, config.externalType, handleA, flags));
1862 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handleB, flags));
1864 if (transference == TRANSFERENCE_COPY)
1865 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
1866 else if (transference == TRANSFERENCE_REFERENCE)
1868 submitDummySignal(vkd, queue, *fenceA);
1869 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1872 DE_FATAL("Unknown transference.");
1874 VK_CHECK(vkd.queueWaitIdle(queue));
1877 return tcu::TestStatus::pass("Pass");
1881 tcu::TestStatus testFenceImportReimport (Context& context,
1882 const FenceTestConfig config)
1884 const Transference transference (getHandelTypeTransferences(config.externalType));
1885 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1886 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
1887 const vk::InstanceDriver& vki (instance.getDriver());
1888 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1889 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1891 checkFenceSupport(vki, physicalDevice, config.externalType);
1894 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1895 const vk::DeviceDriver vkd (vkp, instance, *device);
1896 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1898 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
1899 NativeHandle handleA;
1901 if (transference == TRANSFERENCE_COPY)
1902 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handleA);
1904 getFenceNative(vkd, *device, *fenceA, config.externalType, handleA);
1906 NativeHandle handleB (handleA);
1907 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
1908 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handleA, flags));
1910 importFence(vkd, *device, *fenceB, config.externalType, handleB, flags);
1912 if (transference == TRANSFERENCE_COPY)
1913 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1914 else if (transference == TRANSFERENCE_REFERENCE)
1916 submitDummySignal(vkd, queue, *fenceA);
1917 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1920 DE_FATAL("Unknown transference.");
1922 VK_CHECK(vkd.queueWaitIdle(queue));
1924 return tcu::TestStatus::pass("Pass");
1928 tcu::TestStatus testFenceSignalExportImportWait (Context& context,
1929 const FenceTestConfig config)
1931 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1932 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
1933 const vk::InstanceDriver& vki (instance.getDriver());
1934 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1935 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1937 checkFenceSupport(vki, physicalDevice, config.externalType);
1940 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1941 const vk::DeviceDriver vkd (vkp, instance, *device);
1942 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1943 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
1946 NativeHandle handle;
1948 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
1951 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
1952 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handle, flags));
1953 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1955 VK_CHECK(vkd.queueWaitIdle(queue));
1959 return tcu::TestStatus::pass("Pass");
1963 tcu::TestStatus testFenceImportSyncFdSignaled (Context& context,
1964 const FenceTestConfig config)
1966 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1967 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
1968 const vk::InstanceDriver& vki (instance.getDriver());
1969 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1970 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1971 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
1973 checkFenceSupport(vki, physicalDevice, config.externalType);
1976 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1977 const vk::DeviceDriver vkd (vkp, instance, *device);
1978 NativeHandle handle = -1;
1979 const vk::Unique<vk::VkFence> fence (createAndImportFence(vkd, *device, config.externalType, handle, flags));
1981 if (vkd.waitForFences(*device, 1u, &*fence, VK_TRUE, 0) != vk::VK_SUCCESS)
1982 return tcu::TestStatus::pass("Imported -1 sync fd isn't signaled");
1984 return tcu::TestStatus::pass("Pass");
1988 tcu::TestStatus testFenceExportSignalImportWait (Context& context,
1989 const FenceTestConfig config)
1991 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1992 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
1993 const vk::InstanceDriver& vki (instance.getDriver());
1994 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1995 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1996 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
1998 DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
1999 checkFenceSupport(vki, physicalDevice, config.externalType);
2002 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2003 const vk::DeviceDriver vkd (vkp, instance, *device);
2004 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2006 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2007 NativeHandle handle;
2009 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2011 submitDummySignal(vkd, queue, *fenceA);
2014 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handle, flags));
2016 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2017 VK_CHECK(vkd.queueWaitIdle(queue));
2021 return tcu::TestStatus::pass("Pass");
2025 tcu::TestStatus testFenceExportImportSignalWait (Context& context,
2026 const FenceTestConfig config)
2028 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2029 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2030 const vk::InstanceDriver& vki (instance.getDriver());
2031 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2032 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2034 DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
2035 checkFenceSupport(vki, physicalDevice, config.externalType);
2038 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2039 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2040 const vk::DeviceDriver vkd (vkp, instance, *device);
2041 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2043 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2044 NativeHandle handle;
2046 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2048 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handle, flags));
2050 submitDummySignal(vkd, queue, *fenceA);
2051 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2053 VK_CHECK(vkd.queueWaitIdle(queue));
2055 return tcu::TestStatus::pass("Pass");
2059 tcu::TestStatus testFenceSignalImport (Context& context,
2060 const FenceTestConfig config)
2062 const Transference transference (getHandelTypeTransferences(config.externalType));
2063 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2064 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2065 const vk::InstanceDriver& vki (instance.getDriver());
2066 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2067 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2069 checkFenceSupport(vki, physicalDevice, config.externalType);
2072 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2073 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2074 const vk::DeviceDriver vkd (vkp, instance, *device);
2075 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2077 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2078 const vk::Unique<vk::VkFence> fenceB (createFence(vkd, *device));
2079 NativeHandle handle;
2081 submitDummySignal(vkd, queue, *fenceB);
2082 VK_CHECK(vkd.queueWaitIdle(queue));
2084 if (transference == TRANSFERENCE_COPY)
2085 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2087 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2089 importFence(vkd, *device, *fenceB, config.externalType, handle, flags);
2091 if (transference == TRANSFERENCE_COPY)
2092 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2093 else if (transference == TRANSFERENCE_REFERENCE)
2095 submitDummySignal(vkd, queue, *fenceA);
2096 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2099 DE_FATAL("Unknown transference.");
2101 VK_CHECK(vkd.queueWaitIdle(queue));
2103 return tcu::TestStatus::pass("Pass");
2107 tcu::TestStatus testFenceReset (Context& context,
2108 const FenceTestConfig config)
2110 const Transference transference (getHandelTypeTransferences(config.externalType));
2111 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2112 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2113 const vk::InstanceDriver& vki (instance.getDriver());
2114 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2115 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2117 checkFenceSupport(vki, physicalDevice, config.externalType);
2120 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2121 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2122 const vk::DeviceDriver vkd (vkp, instance, *device);
2123 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2125 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2126 const vk::Unique<vk::VkFence> fenceB (createFence(vkd, *device));
2127 const vk::Unique<vk::VkFence> fenceC (createFence(vkd, *device));
2128 NativeHandle handle;
2130 submitDummySignal(vkd, queue, *fenceB);
2131 VK_CHECK(vkd.queueWaitIdle(queue));
2133 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2134 NativeHandle handleB (handle);
2135 importFence(vkd, *device, *fenceB, config.externalType, handleB, flags);
2136 importFence(vkd, *device, *fenceC, config.externalType, handle, flags);
2138 VK_CHECK(vkd.queueWaitIdle(queue));
2139 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2141 if (config.permanence == PERMANENCE_TEMPORARY || transference == TRANSFERENCE_COPY)
2143 // vkResetFences() should restore fenceBs prior payload and reset that no affecting fenceCs payload
2144 // or fenceB should be separate copy of the payload and not affect fenceC
2145 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2147 // vkResetFences() should have restored fenceBs prior state and should be now reset
2148 // or fenceB should have it's separate payload
2149 submitDummySignal(vkd, queue, *fenceB);
2150 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2152 else if (config.permanence == PERMANENCE_PERMANENT)
2154 DE_ASSERT(transference == TRANSFERENCE_REFERENCE);
2156 // Reset fences should have reset all of the fences
2157 submitDummySignal(vkd, queue, *fenceC);
2159 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2160 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2161 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2164 DE_FATAL("Unknown permanence");
2166 VK_CHECK(vkd.queueWaitIdle(queue));
2168 return tcu::TestStatus::pass("Pass");
2172 tcu::TestStatus testFenceSignalWaitImport (Context& context,
2173 const FenceTestConfig config)
2175 const Transference transference (getHandelTypeTransferences(config.externalType));
2176 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2177 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2178 const vk::InstanceDriver& vki (instance.getDriver());
2179 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2180 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2182 checkFenceSupport(vki, physicalDevice, config.externalType);
2185 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2186 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2187 const vk::DeviceDriver vkd (vkp, instance, *device);
2188 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2190 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2191 const vk::Unique<vk::VkFence> fenceB (createFence(vkd, *device));
2192 NativeHandle handle;
2194 if (transference == TRANSFERENCE_COPY)
2195 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2197 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2199 submitDummySignal(vkd, queue, *fenceB);
2200 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2202 VK_CHECK(vkd.queueWaitIdle(queue));
2204 importFence(vkd, *device, *fenceB, config.externalType, handle, flags);
2206 if (transference == TRANSFERENCE_COPY)
2207 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2208 else if (transference == TRANSFERENCE_REFERENCE)
2210 submitDummySignal(vkd, queue, *fenceA);
2211 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2214 DE_FATAL("Unknown transference.");
2216 VK_CHECK(vkd.queueWaitIdle(queue));
2218 return tcu::TestStatus::pass("Pass");
2222 tcu::TestStatus testFenceMultipleExports (Context& context,
2223 const FenceTestConfig config)
2225 const size_t exportCount = 4 * 1024;
2226 const Transference transference (getHandelTypeTransferences(config.externalType));
2227 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2228 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2229 const vk::InstanceDriver& vki (instance.getDriver());
2230 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2231 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2233 checkFenceSupport(vki, physicalDevice, config.externalType);
2236 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2237 const vk::DeviceDriver vkd (vkp, instance, *device);
2238 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2239 const vk::Unique<vk::VkFence> fence (createExportableFence(vkd, *device, config.externalType));
2241 for (size_t exportNdx = 0; exportNdx < exportCount; exportNdx++)
2243 NativeHandle handle;
2245 if (transference == TRANSFERENCE_COPY)
2246 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fence, config.externalType, handle, exportNdx == 0 /* expect fence to be signaled after first pass */);
2248 getFenceNative(vkd, *device, *fence, config.externalType, handle, exportNdx == 0 /* expect fence to be signaled after first pass */);
2251 submitDummySignal(vkd, queue, *fence);
2252 VK_CHECK(vkd.waitForFences(*device, 1u, &*fence, VK_TRUE, ~0ull));
2254 VK_CHECK(vkd.queueWaitIdle(queue));
2257 return tcu::TestStatus::pass("Pass");
2260 tcu::TestStatus testFenceMultipleImports (Context& context,
2261 const FenceTestConfig config)
2263 const size_t importCount = 4 * 1024;
2264 const Transference transference (getHandelTypeTransferences(config.externalType));
2265 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2266 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2267 const vk::InstanceDriver& vki (instance.getDriver());
2268 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2269 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2271 checkFenceSupport(vki, physicalDevice, config.externalType);
2274 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2275 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2276 const vk::DeviceDriver vkd (vkp, instance, *device);
2277 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2278 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2279 NativeHandle handleA;
2281 if (transference == TRANSFERENCE_COPY)
2282 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handleA);
2284 getFenceNative(vkd, *device, *fenceA, config.externalType, handleA);
2286 for (size_t importNdx = 0; importNdx < importCount; importNdx++)
2288 NativeHandle handleB (handleA);
2289 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handleB, flags));
2292 if (transference == TRANSFERENCE_COPY)
2294 importFence(vkd, *device, *fenceA, config.externalType, handleA, flags);
2295 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2297 else if (transference == TRANSFERENCE_REFERENCE)
2299 submitDummySignal(vkd, queue, *fenceA);
2300 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2303 DE_FATAL("Unknown transference.");
2305 VK_CHECK(vkd.queueWaitIdle(queue));
2308 return tcu::TestStatus::pass("Pass");
2311 tcu::TestStatus testFenceTransference (Context& context,
2312 const FenceTestConfig config)
2314 const Transference transference (getHandelTypeTransferences(config.externalType));
2315 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2316 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2317 const vk::InstanceDriver& vki (instance.getDriver());
2318 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2319 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2321 checkFenceSupport(vki, physicalDevice, config.externalType);
2324 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2325 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2326 const vk::DeviceDriver vkd (vkp, instance, *device);
2327 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2329 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2330 NativeHandle handle;
2332 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2335 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handle, flags));
2337 if (config.permanence == PERMANENCE_PERMANENT)
2339 if (transference == TRANSFERENCE_COPY)
2341 submitDummySignal(vkd, queue, *fenceA);
2342 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2343 VK_CHECK(vkd.queueWaitIdle(queue));
2345 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2346 submitDummySignal(vkd, queue, *fenceB);
2348 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2349 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2350 VK_CHECK(vkd.queueWaitIdle(queue));
2352 else if (transference== TRANSFERENCE_REFERENCE)
2354 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2355 VK_CHECK(vkd.queueWaitIdle(queue));
2357 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2358 submitDummySignal(vkd, queue, *fenceA);
2359 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2361 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceA));
2362 submitDummySignal(vkd, queue, *fenceB);
2363 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2364 VK_CHECK(vkd.queueWaitIdle(queue));
2367 DE_FATAL("Unknown transference.");
2369 else if (config.permanence == PERMANENCE_TEMPORARY)
2371 if (transference == TRANSFERENCE_COPY)
2373 submitDummySignal(vkd, queue, *fenceA);
2374 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2375 VK_CHECK(vkd.queueWaitIdle(queue));
2377 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2378 submitDummySignal(vkd, queue, *fenceB);
2380 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2381 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2382 VK_CHECK(vkd.queueWaitIdle(queue));
2384 else if (transference == TRANSFERENCE_REFERENCE)
2386 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2387 VK_CHECK(vkd.queueWaitIdle(queue));
2389 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceA));
2390 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2391 submitDummySignal(vkd, queue, *fenceA);
2392 submitDummySignal(vkd, queue, *fenceB);
2394 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2395 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2396 VK_CHECK(vkd.queueWaitIdle(queue));
2399 DE_FATAL("Unknown transference.");
2402 DE_FATAL("Unknown permanence.");
2405 return tcu::TestStatus::pass("Pass");
2409 tcu::TestStatus testFenceFdDup (Context& context,
2410 const FenceTestConfig config)
2412 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2413 const Transference transference (getHandelTypeTransferences(config.externalType));
2414 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2415 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2416 const vk::InstanceDriver& vki (instance.getDriver());
2417 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2418 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2420 checkFenceSupport(vki, physicalDevice, config.externalType);
2423 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2424 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2425 const vk::DeviceDriver vkd (vkp, instance, *device);
2426 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2428 TestLog& log = context.getTestContext().getLog();
2429 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2434 if (transference == TRANSFERENCE_COPY)
2435 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, fd);
2437 getFenceNative(vkd, *device, *fenceA, config.externalType, fd);
2439 NativeHandle newFd (dup(fd.getFd()));
2441 if (newFd.getFd() < 0)
2442 log << TestLog::Message << "dup() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2444 TCU_CHECK_MSG(newFd.getFd() >= 0, "Failed to call dup() for fences fd");
2447 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, newFd, flags));
2449 if (transference == TRANSFERENCE_COPY)
2450 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2451 else if (transference == TRANSFERENCE_REFERENCE)
2453 submitDummySignal(vkd, queue, *fenceA);
2454 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2457 DE_FATAL("Unknown permanence.");
2459 VK_CHECK(vkd.queueWaitIdle(queue));
2463 return tcu::TestStatus::pass("Pass");
2468 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
2472 tcu::TestStatus testFenceFdDup2 (Context& context,
2473 const FenceTestConfig config)
2475 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2476 const Transference transference (getHandelTypeTransferences(config.externalType));
2477 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2478 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2479 const vk::InstanceDriver& vki (instance.getDriver());
2480 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2481 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2483 checkFenceSupport(vki, physicalDevice, config.externalType);
2486 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2487 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2488 const vk::DeviceDriver vkd (vkp, instance, *device);
2489 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2491 TestLog& log = context.getTestContext().getLog();
2492 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2493 const vk::Unique<vk::VkFence> fenceB (createExportableFence(vkd, *device, config.externalType));
2496 NativeHandle fd, secondFd;
2498 if (transference == TRANSFERENCE_COPY)
2500 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, fd);
2501 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceB, config.externalType, secondFd);
2505 getFenceNative(vkd, *device, *fenceA, config.externalType, fd);
2506 getFenceNative(vkd, *device, *fenceB, config.externalType, secondFd);
2509 int newFd (dup2(fd.getFd(), secondFd.getFd()));
2512 log << TestLog::Message << "dup2() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2514 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup2() for fences fd");
2517 const vk::Unique<vk::VkFence> fenceC (createAndImportFence(vkd, *device, config.externalType, secondFd, flags));
2519 if (transference == TRANSFERENCE_COPY)
2520 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2521 else if (transference == TRANSFERENCE_REFERENCE)
2523 submitDummySignal(vkd, queue, *fenceA);
2524 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2527 DE_FATAL("Unknown permanence.");
2529 VK_CHECK(vkd.queueWaitIdle(queue));
2533 return tcu::TestStatus::pass("Pass");
2538 TCU_THROW(NotSupportedError, "Platform doesn't support dup2()");
2542 tcu::TestStatus testFenceFdDup3 (Context& context,
2543 const FenceTestConfig config)
2545 #if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
2546 const Transference transference (getHandelTypeTransferences(config.externalType));
2547 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2548 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2549 const vk::InstanceDriver& vki (instance.getDriver());
2550 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2551 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2553 checkFenceSupport(vki, physicalDevice, config.externalType);
2556 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2557 const vk::DeviceDriver vkd (vkp, instance, *device);
2558 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2560 TestLog& log = context.getTestContext().getLog();
2561 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2562 const vk::Unique<vk::VkFence> fenceB (createExportableFence(vkd, *device, config.externalType));
2565 NativeHandle fd, secondFd;
2567 if (transference == TRANSFERENCE_COPY)
2569 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, fd);
2570 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceB, config.externalType, secondFd);
2574 getFenceNative(vkd, *device, *fenceA, config.externalType, fd);
2575 getFenceNative(vkd, *device, *fenceB, config.externalType, secondFd);
2578 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2579 const int newFd (dup3(fd.getFd(), secondFd.getFd(), 0));
2582 log << TestLog::Message << "dup3() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2584 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup3() for fences fd");
2587 const vk::Unique<vk::VkFence> fenceC (createAndImportFence(vkd, *device, config.externalType, secondFd, flags));
2589 if (transference == TRANSFERENCE_COPY)
2590 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2591 else if (transference == TRANSFERENCE_REFERENCE)
2593 submitDummySignal(vkd, queue, *fenceA);
2594 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2597 DE_FATAL("Unknown permanence.");
2599 VK_CHECK(vkd.queueWaitIdle(queue));
2603 return tcu::TestStatus::pass("Pass");
2608 TCU_THROW(NotSupportedError, "Platform doesn't support dup3()");
2612 tcu::TestStatus testFenceFdSendOverSocket (Context& context,
2613 const FenceTestConfig config)
2615 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2616 const Transference transference (getHandelTypeTransferences(config.externalType));
2617 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2618 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2619 const vk::InstanceDriver& vki (instance.getDriver());
2620 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2621 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2623 checkFenceSupport(vki, physicalDevice, config.externalType);
2626 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2627 const vk::DeviceDriver vkd (vkp, instance, *device);
2628 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2630 TestLog& log = context.getTestContext().getLog();
2631 const vk::Unique<vk::VkFence> fence (createExportableFence(vkd, *device, config.externalType));
2634 if (transference == TRANSFERENCE_COPY)
2635 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fence, config.externalType, fd);
2637 getFenceNative(vkd, *device, *fence, config.externalType, fd);
2642 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
2644 log << TestLog::Message << "Failed to create socket pair: '" << strerror(errno) << "'" << TestLog::EndMessage;
2645 TCU_FAIL("Failed to create socket pair");
2649 const NativeHandle srcSocket (sv[0]);
2650 const NativeHandle dstSocket (sv[1]);
2651 std::string sendData ("deqp");
2655 const int fdRaw (fd.getFd());
2658 char buffer[CMSG_SPACE(sizeof(int))];
2659 iovec iov = { &sendData[0], sendData.length()};
2661 deMemset(&msg, 0, sizeof(msg));
2663 msg.msg_control = buffer;
2664 msg.msg_controllen = sizeof(buffer);
2668 cmsg = CMSG_FIRSTHDR(&msg);
2669 cmsg->cmsg_level = SOL_SOCKET;
2670 cmsg->cmsg_type = SCM_RIGHTS;
2671 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
2673 deMemcpy(CMSG_DATA(cmsg), &fdRaw, sizeof(int));
2674 msg.msg_controllen = cmsg->cmsg_len;
2676 if (sendmsg(srcSocket.getFd(), &msg, 0) < 0)
2678 log << TestLog::Message << "Failed to send fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
2679 TCU_FAIL("Failed to send fd over socket");
2686 char buffer[CMSG_SPACE(sizeof(int))];
2687 std::string recvData (4, '\0');
2688 iovec iov = { &recvData[0], recvData.length() };
2690 deMemset(&msg, 0, sizeof(msg));
2692 msg.msg_control = buffer;
2693 msg.msg_controllen = sizeof(buffer);
2697 const ssize_t bytes = recvmsg(dstSocket.getFd(), &msg, 0);
2701 log << TestLog::Message << "Failed to recv fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
2702 TCU_FAIL("Failed to recv fd over socket");
2705 else if (bytes != (ssize_t)sendData.length())
2707 TCU_FAIL("recvmsg() returned unpexpected number of bytes");
2711 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2712 const cmsghdr* const cmsg = CMSG_FIRSTHDR(&msg);
2714 deMemcpy(&newFd_, CMSG_DATA(cmsg), sizeof(int));
2715 NativeHandle newFd (newFd_);
2717 TCU_CHECK(cmsg->cmsg_level == SOL_SOCKET);
2718 TCU_CHECK(cmsg->cmsg_type == SCM_RIGHTS);
2719 TCU_CHECK(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
2720 TCU_CHECK(recvData == sendData);
2721 TCU_CHECK_MSG(newFd.getFd() >= 0, "Didn't receive valid fd from socket");
2724 const vk::Unique<vk::VkFence> newFence (createAndImportFence(vkd, *device, config.externalType, newFd, flags));
2726 if (transference == TRANSFERENCE_COPY)
2727 VK_CHECK(vkd.waitForFences(*device, 1u, &*newFence, VK_TRUE, ~0ull));
2728 else if (transference == TRANSFERENCE_REFERENCE)
2730 submitDummySignal(vkd, queue, *newFence);
2731 VK_CHECK(vkd.waitForFences(*device, 1u, &*newFence, VK_TRUE, ~0ull));
2734 DE_FATAL("Unknown permanence.");
2736 VK_CHECK(vkd.queueWaitIdle(queue));
2744 return tcu::TestStatus::pass("Pass");
2748 TCU_THROW(NotSupportedError, "Platform doesn't support sending file descriptors over socket");
2752 tcu::TestStatus testBufferQueries (Context& context, vk::VkExternalMemoryHandleTypeFlagBits externalType)
2754 const vk::VkBufferCreateFlags createFlags[] =
2757 vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT,
2758 vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT|vk::VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT,
2759 vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT|vk::VK_BUFFER_CREATE_SPARSE_ALIASED_BIT
2761 const vk::VkBufferUsageFlags usageFlags[] =
2763 vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
2764 vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT,
2765 vk::VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT,
2766 vk::VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT,
2767 vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
2768 vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
2769 vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
2770 vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
2771 vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT
2773 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2774 const CustomInstance instance (createTestInstance(context, 0u, externalType, 0u));
2775 const vk::InstanceDriver& vki (instance.getDriver());
2776 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2777 const vk::VkPhysicalDeviceFeatures deviceFeatures (vk::getPhysicalDeviceFeatures(vki, physicalDevice));
2778 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2780 // VkDevice is only created if physical device claims to support any of these types.
2781 vk::Move<vk::VkDevice> device;
2782 de::MovePtr<vk::DeviceDriver> vkd;
2783 bool deviceHasDedicated = false;
2785 TestLog& log = context.getTestContext().getLog();
2787 for (size_t createFlagNdx = 0; createFlagNdx < DE_LENGTH_OF_ARRAY(createFlags); createFlagNdx++)
2788 for (size_t usageFlagNdx = 0; usageFlagNdx < DE_LENGTH_OF_ARRAY(usageFlags); usageFlagNdx++)
2790 const vk::VkBufferViewCreateFlags createFlag = createFlags[createFlagNdx];
2791 const vk::VkBufferUsageFlags usageFlag = usageFlags[usageFlagNdx];
2792 const vk::VkPhysicalDeviceExternalBufferInfo info =
2794 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO,
2800 vk::VkExternalBufferProperties properties =
2802 vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES,
2807 if (((createFlag & vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT) != 0) &&
2808 (deviceFeatures.sparseBinding == VK_FALSE))
2811 if (((createFlag & vk::VK_BUFFER_CREATE_SPARSE_ALIASED_BIT) != 0) &&
2812 (deviceFeatures.sparseResidencyAliased == VK_FALSE))
2815 if (((createFlag & vk::VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT) != 0) &&
2816 (deviceFeatures.sparseResidencyBuffer == VK_FALSE))
2819 vki.getPhysicalDeviceExternalBufferProperties(physicalDevice, &info, &properties);
2821 log << TestLog::Message << properties << TestLog::EndMessage;
2823 TCU_CHECK(properties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES);
2824 TCU_CHECK(properties.pNext == DE_NULL);
2825 // \todo [2017-06-06 pyry] Can we validate anything else? Compatible types?
2827 if ((properties.externalMemoryProperties.externalMemoryFeatures & (vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT|vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT)) != 0)
2829 const bool requiresDedicated = (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
2831 if (!device || (requiresDedicated && !deviceHasDedicated))
2833 // \note We need to re-create with dedicated mem extensions if previous device instance didn't have them
2836 device = createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, externalType, 0u, queueFamilyIndex, requiresDedicated);
2837 vkd = de::MovePtr<vk::DeviceDriver>(new vk::DeviceDriver(vkp, instance, *device));
2838 deviceHasDedicated = requiresDedicated;
2840 catch (const tcu::NotSupportedError& e)
2843 TCU_FAIL("Physical device claims to support handle type but required extensions are not supported");
2848 if ((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) != 0)
2850 DE_ASSERT(!!device);
2853 if (deviceHasDedicated)
2855 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(*vkd, *device, queueFamilyIndex, externalType, 1024u, createFlag, usageFlag));
2856 const vk::VkMemoryDedicatedRequirements reqs (getMemoryDedicatedRequirements(*vkd, *device, *buffer));
2857 const bool propertiesRequiresDedicated = (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
2858 const bool objectRequiresDedicated = (reqs.requiresDedicatedAllocation != VK_FALSE);
2860 if (propertiesRequiresDedicated != objectRequiresDedicated)
2861 TCU_FAIL("vkGetPhysicalDeviceExternalBufferProperties and vkGetBufferMemoryRequirements2 report different dedicated requirements");
2865 // We can't query whether dedicated memory is required or not on per-object basis.
2866 // This check should be redundant as the code above tries to create device with
2867 // VK_KHR_dedicated_allocation & VK_KHR_get_memory_requirements2 if dedicated memory
2868 // is required. However, checking again doesn't hurt.
2869 TCU_CHECK((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) == 0);
2874 return tcu::TestStatus::pass("Pass");
2877 struct MemoryTestConfig
2879 MemoryTestConfig (vk::VkExternalMemoryHandleTypeFlagBits externalType_,
2882 : externalType (externalType_)
2883 , hostVisible (hostVisible_)
2884 , dedicated (dedicated_)
2888 vk::VkExternalMemoryHandleTypeFlagBits externalType;
2893 #if (DE_OS == DE_OS_WIN32)
2894 deUint32 chooseWin32MemoryType(deUint32 bits)
2897 TCU_THROW(NotSupportedError, "No compatible memory type found");
2899 return deCtz32(bits);
2903 tcu::TestStatus testMemoryWin32Create (Context& context, MemoryTestConfig config)
2905 #if (DE_OS == DE_OS_WIN32)
2906 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2907 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
2908 const vk::InstanceDriver& vki (instance.getDriver());
2909 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2910 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2911 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
2912 const vk::DeviceDriver vkd (vkp, instance, *device);
2913 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
2914 const deUint32 seed = 1261033864u;
2915 const vk::VkDeviceSize bufferSize = 1024;
2916 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
2918 const vk::VkPhysicalDeviceMemoryProperties memoryProps = vk::getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice());
2919 const deUint32 compatibleMemTypes = vk::getCompatibleMemoryTypes(memoryProps, config.hostVisible ? vk::MemoryRequirement::HostVisible : vk::MemoryRequirement::Any);
2921 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
2923 // \note Buffer is only allocated to get memory requirements
2924 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
2925 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
2926 const vk::VkExportMemoryWin32HandleInfoKHR win32Info =
2928 vk::VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR,
2931 (vk::pt::Win32SecurityAttributesPtr)DE_NULL,
2932 DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
2933 (vk::pt::Win32LPCWSTR)DE_NULL
2935 const vk::VkExportMemoryAllocateInfo exportInfo =
2937 vk::VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
2939 (vk::VkExternalMemoryHandleTypeFlags)config.externalType
2942 const deUint32 exportedMemoryTypeIndex = chooseWin32MemoryType(requirements.memoryTypeBits & compatibleMemTypes);
2943 const vk::VkMemoryAllocateInfo info =
2945 vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
2948 exportedMemoryTypeIndex
2950 const vk::Unique<vk::VkDeviceMemory> memory (vk::allocateMemory(vkd, *device, &info));
2951 NativeHandle handleA;
2953 if (config.hostVisible)
2954 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
2956 getMemoryNative(vkd, *device, *memory, config.externalType, handleA);
2959 const vk::Unique<vk::VkDeviceMemory> memoryA (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleA));
2961 if (config.hostVisible)
2963 const std::vector<deUint8> testDataA (genTestData(seed ^ 124798807u, (size_t)bufferSize));
2964 const std::vector<deUint8> testDataB (genTestData(seed ^ 970834278u, (size_t)bufferSize));
2966 checkHostMemory(vkd, *device, *memoryA, testData.size(), &testData[0]);
2967 checkHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
2969 writeHostMemory(vkd, *device, *memoryA, testDataA.size(), &testDataA[0]);
2970 writeHostMemory(vkd, *device, *memory, testDataA.size(), &testDataB[0]);
2972 checkHostMemory(vkd, *device, *memoryA, testData.size(), &testDataB[0]);
2973 checkHostMemory(vkd, *device, *memory, testData.size(), &testDataB[0]);
2977 return tcu::TestStatus::pass("Pass");
2981 TCU_THROW(NotSupportedError, "Platform doesn't support win32 handles");
2985 deUint32 getExportedMemoryTypeIndex(const vk::InstanceDriver& vki, const vk::VkPhysicalDevice physicalDevice, bool hostVisible, deUint32 memoryBits)
2989 const vk::VkPhysicalDeviceMemoryProperties properties(vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2990 return chooseHostVisibleMemoryType(memoryBits, properties);
2993 return chooseMemoryType(memoryBits);
2996 tcu::TestStatus testMemoryImportTwice (Context& context, MemoryTestConfig config)
2998 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2999 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3000 const vk::InstanceDriver& vki (instance.getDriver());
3001 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3002 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3003 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3004 const vk::DeviceDriver vkd (vkp, instance, *device);
3005 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3006 const deUint32 seed = 1261033864u;
3007 const vk::VkDeviceSize bufferSize = 1024;
3008 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
3010 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3012 // \note Buffer is only allocated to get memory requirements
3013 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3014 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3015 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3016 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3017 NativeHandle handleA;
3019 if (config.hostVisible)
3020 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3022 getMemoryNative(vkd, *device, *memory, config.externalType, handleA);
3025 const vk::Unique<vk::VkBuffer> bufferA (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3026 const vk::Unique<vk::VkBuffer> bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3027 NativeHandle handleB (handleA);
3028 const vk::Unique<vk::VkDeviceMemory> memoryA (config.dedicated
3029 ? importDedicatedMemory(vkd, *device, *bufferA, requirements, config.externalType, exportedMemoryTypeIndex, handleA)
3030 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleA));
3031 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3032 ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handleB)
3033 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleB));
3035 if (config.hostVisible)
3037 const std::vector<deUint8> testDataA (genTestData(seed ^ 124798807u, (size_t)bufferSize));
3038 const std::vector<deUint8> testDataB (genTestData(seed ^ 970834278u, (size_t)bufferSize));
3040 checkHostMemory(vkd, *device, *memoryA, testData.size(), &testData[0]);
3041 checkHostMemory(vkd, *device, *memoryB, testData.size(), &testData[0]);
3043 writeHostMemory(vkd, *device, *memoryA, testData.size(), &testDataA[0]);
3044 writeHostMemory(vkd, *device, *memoryB, testData.size(), &testDataB[0]);
3046 checkHostMemory(vkd, *device, *memoryA, testData.size(), &testDataB[0]);
3047 checkHostMemory(vkd, *device, *memory, testData.size(), &testDataB[0]);
3051 return tcu::TestStatus::pass("Pass");
3054 tcu::TestStatus testMemoryMultipleImports (Context& context, MemoryTestConfig config)
3056 const size_t count = 4 * 1024;
3057 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3058 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3059 const vk::InstanceDriver& vki (instance.getDriver());
3060 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3061 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3062 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3063 const vk::DeviceDriver vkd (vkp, instance, *device);
3064 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3065 const vk::VkDeviceSize bufferSize = 1024;
3067 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3069 // \note Buffer is only allocated to get memory requirements
3070 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3071 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3072 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3073 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3074 NativeHandle handleA;
3076 getMemoryNative(vkd, *device, *memory, config.externalType, handleA);
3078 for (size_t ndx = 0; ndx < count; ndx++)
3080 const vk::Unique<vk::VkBuffer> bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3081 NativeHandle handleB (handleA);
3082 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3083 ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handleB)
3084 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleB));
3087 return tcu::TestStatus::pass("Pass");
3090 tcu::TestStatus testMemoryMultipleExports (Context& context, MemoryTestConfig config)
3092 const size_t count = 4 * 1024;
3093 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3094 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3095 const vk::InstanceDriver& vki (instance.getDriver());
3096 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3097 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3098 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3099 const vk::DeviceDriver vkd (vkp, instance, *device);
3100 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3101 const vk::VkDeviceSize bufferSize = 1024;
3103 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3105 // \note Buffer is only allocated to get memory requirements
3106 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3107 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3108 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3109 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3111 for (size_t ndx = 0; ndx < count; ndx++)
3113 NativeHandle handle;
3114 getMemoryNative(vkd, *device, *memory, config.externalType, handle);
3117 return tcu::TestStatus::pass("Pass");
3120 tcu::TestStatus testMemoryFdProperties (Context& context, MemoryTestConfig config)
3122 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3123 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3124 const vk::InstanceDriver& vki (instance.getDriver());
3125 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3126 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3127 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3128 const vk::DeviceDriver vkd (vkp, instance, *device);
3129 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3130 const vk::VkDeviceSize bufferSize = 1024;
3132 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3134 // \note Buffer is only allocated to get memory requirements
3135 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3136 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3137 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3138 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3140 vk::VkMemoryFdPropertiesKHR properties;
3141 NativeHandle handle;
3143 getMemoryNative(vkd, *device, *memory, config.externalType, handle);
3144 properties.sType = vk::VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR;
3145 vk::VkResult res = vkd.getMemoryFdPropertiesKHR(*device, config.externalType, handle.getFd(), &properties);
3147 switch (config.externalType)
3149 case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
3150 TCU_CHECK_MSG(res == vk::VK_SUCCESS, "vkGetMemoryFdPropertiesKHR failed for VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT");
3153 // Invalid external memory type for this test.
3158 return tcu::TestStatus::pass("Pass");
3161 tcu::TestStatus testMemoryFdDup (Context& context, MemoryTestConfig config)
3163 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
3164 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3165 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3166 const vk::InstanceDriver& vki (instance.getDriver());
3167 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3168 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3171 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3172 const vk::DeviceDriver vkd (vkp, instance, *device);
3174 TestLog& log = context.getTestContext().getLog();
3175 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3176 const vk::VkDeviceSize bufferSize = 1024;
3177 const deUint32 seed = 851493858u;
3178 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
3180 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3182 // \note Buffer is only allocated to get memory requirements
3183 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3184 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3185 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3186 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3188 if (config.hostVisible)
3189 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3191 const NativeHandle fd (getMemoryFd(vkd, *device, *memory, config.externalType));
3192 NativeHandle newFd (dup(fd.getFd()));
3194 if (newFd.getFd() < 0)
3195 log << TestLog::Message << "dup() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
3197 TCU_CHECK_MSG(newFd.getFd() >= 0, "Failed to call dup() for memorys fd");
3200 const vk::Unique<vk::VkBuffer> newBuffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3201 const vk::Unique<vk::VkDeviceMemory> newMemory (config.dedicated
3202 ? importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType, exportedMemoryTypeIndex, newFd)
3203 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, newFd));
3205 if (config.hostVisible)
3207 const std::vector<deUint8> testDataA (genTestData(seed ^ 672929437u, (size_t)bufferSize));
3209 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3211 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3212 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3216 return tcu::TestStatus::pass("Pass");
3221 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
3225 tcu::TestStatus testMemoryFdDup2 (Context& context, MemoryTestConfig config)
3227 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
3228 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3229 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3230 const vk::InstanceDriver& vki (instance.getDriver());
3231 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3232 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3235 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3236 const vk::DeviceDriver vkd (vkp, instance, *device);
3238 TestLog& log = context.getTestContext().getLog();
3239 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3240 const vk::VkDeviceSize bufferSize = 1024;
3241 const deUint32 seed = 224466865u;
3242 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
3244 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3246 // \note Buffer is only allocated to get memory requirements
3247 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3248 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3249 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3250 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3252 if (config.hostVisible)
3253 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3255 const NativeHandle fd (getMemoryFd(vkd, *device, *memory, config.externalType));
3256 NativeHandle secondFd (getMemoryFd(vkd, *device, *memory, config.externalType));
3257 const int newFd (dup2(fd.getFd(), secondFd.getFd()));
3260 log << TestLog::Message << "dup2() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
3262 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup2() for memorys fd");
3265 const vk::Unique<vk::VkBuffer> newBuffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3266 const vk::Unique<vk::VkDeviceMemory> newMemory (config.dedicated
3267 ? importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType, exportedMemoryTypeIndex, secondFd)
3268 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, secondFd));
3270 if (config.hostVisible)
3272 const std::vector<deUint8> testDataA (genTestData(seed ^ 99012346u, (size_t)bufferSize));
3274 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3276 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3277 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3281 return tcu::TestStatus::pass("Pass");
3286 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
3290 tcu::TestStatus testMemoryFdDup3 (Context& context, MemoryTestConfig config)
3292 #if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
3293 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3294 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3295 const vk::InstanceDriver& vki (instance.getDriver());
3296 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3297 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3300 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3301 const vk::DeviceDriver vkd (vkp, instance, *device);
3303 TestLog& log = context.getTestContext().getLog();
3304 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3305 const vk::VkDeviceSize bufferSize = 1024;
3306 const deUint32 seed = 2554088961u;
3307 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
3309 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3311 // \note Buffer is only allocated to get memory requirements
3312 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3313 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3314 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3315 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3317 if (config.hostVisible)
3318 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3320 const NativeHandle fd (getMemoryFd(vkd, *device, *memory, config.externalType));
3321 NativeHandle secondFd (getMemoryFd(vkd, *device, *memory, config.externalType));
3322 const int newFd (dup3(fd.getFd(), secondFd.getFd(), 0));
3325 log << TestLog::Message << "dup3() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
3327 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup3() for memorys fd");
3330 const vk::Unique<vk::VkBuffer> newBuffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3331 const vk::Unique<vk::VkDeviceMemory> newMemory (config.dedicated
3332 ? importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType, exportedMemoryTypeIndex, secondFd)
3333 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, secondFd));
3335 if (config.hostVisible)
3337 const std::vector<deUint8> testDataA (genTestData(seed ^ 4210342378u, (size_t)bufferSize));
3339 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3341 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3342 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3346 return tcu::TestStatus::pass("Pass");
3351 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
3355 tcu::TestStatus testMemoryFdSendOverSocket (Context& context, MemoryTestConfig config)
3357 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
3358 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3359 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3360 const vk::InstanceDriver& vki (instance.getDriver());
3361 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3362 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3365 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3366 const vk::DeviceDriver vkd (vkp, instance, *device);
3368 TestLog& log = context.getTestContext().getLog();
3369 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3370 const vk::VkDeviceSize bufferSize = 1024;
3371 const deUint32 seed = 3403586456u;
3372 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
3374 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3376 // \note Buffer is only allocated to get memory requirements
3377 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3378 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3379 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3380 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3382 if (config.hostVisible)
3383 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3385 const NativeHandle fd (getMemoryFd(vkd, *device, *memory, config.externalType));
3390 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
3392 log << TestLog::Message << "Failed to create socket pair: '" << strerror(errno) << "'" << TestLog::EndMessage;
3393 TCU_FAIL("Failed to create socket pair");
3397 const NativeHandle srcSocket (sv[0]);
3398 const NativeHandle dstSocket (sv[1]);
3399 std::string sendData ("deqp");
3403 const int fdRaw (fd.getFd());
3406 char tmpBuffer[CMSG_SPACE(sizeof(int))];
3407 iovec iov = { &sendData[0], sendData.length()};
3409 deMemset(&msg, 0, sizeof(msg));
3411 msg.msg_control = tmpBuffer;
3412 msg.msg_controllen = sizeof(tmpBuffer);
3416 cmsg = CMSG_FIRSTHDR(&msg);
3417 cmsg->cmsg_level = SOL_SOCKET;
3418 cmsg->cmsg_type = SCM_RIGHTS;
3419 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
3421 deMemcpy(CMSG_DATA(cmsg), &fdRaw, sizeof(int));
3422 msg.msg_controllen = cmsg->cmsg_len;
3424 if (sendmsg(srcSocket.getFd(), &msg, 0) < 0)
3426 log << TestLog::Message << "Failed to send fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
3427 TCU_FAIL("Failed to send fd over socket");
3434 char tmpBuffer[CMSG_SPACE(sizeof(int))];
3435 std::string recvData (4, '\0');
3436 iovec iov = { &recvData[0], recvData.length() };
3438 deMemset(&msg, 0, sizeof(msg));
3440 msg.msg_control = tmpBuffer;
3441 msg.msg_controllen = sizeof(tmpBuffer);
3445 const ssize_t bytes = recvmsg(dstSocket.getFd(), &msg, 0);
3449 log << TestLog::Message << "Failed to recv fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
3450 TCU_FAIL("Failed to recv fd over socket");
3453 else if (bytes != (ssize_t)sendData.length())
3455 TCU_FAIL("recvmsg() returned unpexpected number of bytes");
3459 const cmsghdr* const cmsg = CMSG_FIRSTHDR(&msg);
3461 deMemcpy(&newFd_, CMSG_DATA(cmsg), sizeof(int));
3462 NativeHandle newFd (newFd_);
3464 TCU_CHECK(cmsg->cmsg_level == SOL_SOCKET);
3465 TCU_CHECK(cmsg->cmsg_type == SCM_RIGHTS);
3466 TCU_CHECK(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
3467 TCU_CHECK(recvData == sendData);
3468 TCU_CHECK_MSG(newFd.getFd() >= 0, "Didn't receive valid fd from socket");
3471 const vk::Unique<vk::VkBuffer> newBuffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3472 const vk::Unique<vk::VkDeviceMemory> newMemory (config.dedicated
3473 ? importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType, exportedMemoryTypeIndex, newFd)
3474 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, newFd));
3476 if (config.hostVisible)
3478 const std::vector<deUint8> testDataA (genTestData(seed ^ 23478978u, (size_t)bufferSize));
3480 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3482 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3483 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3492 return tcu::TestStatus::pass("Pass");
3496 TCU_THROW(NotSupportedError, "Platform doesn't support sending file descriptors over socket");
3500 struct BufferTestConfig
3502 BufferTestConfig (vk::VkExternalMemoryHandleTypeFlagBits externalType_,
3504 : externalType (externalType_)
3505 , dedicated (dedicated_)
3509 vk::VkExternalMemoryHandleTypeFlagBits externalType;
3513 tcu::TestStatus testBufferBindExportImportBind (Context& context,
3514 const BufferTestConfig config)
3516 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3517 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3518 const vk::InstanceDriver& vki (instance.getDriver());
3519 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3520 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3521 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3522 const vk::DeviceDriver vkd (vkp, instance, *device);
3523 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3524 const vk::VkDeviceSize bufferSize = 1024;
3526 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3528 // \note Buffer is only allocated to get memory requirements
3529 const vk::Unique<vk::VkBuffer> bufferA (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3530 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *bufferA));
3531 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
3532 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *bufferA : (vk::VkBuffer)0));
3533 NativeHandle handle;
3535 VK_CHECK(vkd.bindBufferMemory(*device, *bufferA, *memoryA, 0u));
3537 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3540 const vk::Unique<vk::VkBuffer> bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3541 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3542 ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handle)
3543 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3545 VK_CHECK(vkd.bindBufferMemory(*device, *bufferB, *memoryB, 0u));
3548 return tcu::TestStatus::pass("Pass");
3551 tcu::TestStatus testBufferExportBindImportBind (Context& context,
3552 const BufferTestConfig config)
3554 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3555 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3556 const vk::InstanceDriver& vki (instance.getDriver());
3557 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3558 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3559 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3560 const vk::DeviceDriver vkd (vkp, instance, *device);
3561 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3562 const vk::VkDeviceSize bufferSize = 1024;
3564 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3566 // \note Buffer is only allocated to get memory requirements
3567 const vk::Unique<vk::VkBuffer> bufferA (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3568 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *bufferA));
3569 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
3570 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *bufferA : (vk::VkBuffer)0));
3571 NativeHandle handle;
3573 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3574 VK_CHECK(vkd.bindBufferMemory(*device, *bufferA, *memoryA, 0u));
3577 const vk::Unique<vk::VkBuffer> bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3578 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3579 ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handle)
3580 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3582 VK_CHECK(vkd.bindBufferMemory(*device, *bufferB, *memoryB, 0u));
3585 return tcu::TestStatus::pass("Pass");
3588 tcu::TestStatus testBufferExportImportBindBind (Context& context,
3589 const BufferTestConfig config)
3591 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3592 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3593 const vk::InstanceDriver& vki (instance.getDriver());
3594 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3595 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3596 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3597 const vk::DeviceDriver vkd (vkp, instance, *device);
3598 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3599 const vk::VkDeviceSize bufferSize = 1024;
3601 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3603 // \note Buffer is only allocated to get memory requirements
3604 const vk::Unique<vk::VkBuffer> bufferA (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3605 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *bufferA));
3606 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
3607 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *bufferA : (vk::VkBuffer)0));
3608 NativeHandle handle;
3610 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3613 const vk::Unique<vk::VkBuffer> bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3614 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3615 ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handle)
3616 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3618 VK_CHECK(vkd.bindBufferMemory(*device, *bufferA, *memoryA, 0u));
3619 VK_CHECK(vkd.bindBufferMemory(*device, *bufferB, *memoryB, 0u));
3622 return tcu::TestStatus::pass("Pass");
3625 tcu::TestStatus testImageQueries (Context& context, vk::VkExternalMemoryHandleTypeFlagBits externalType)
3627 const vk::VkImageCreateFlags createFlags[] =
3630 vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT,
3631 vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT|vk::VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT,
3632 vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT|vk::VK_IMAGE_CREATE_SPARSE_ALIASED_BIT,
3633 vk::VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT,
3634 vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT
3636 const vk::VkImageUsageFlags usageFlags[] =
3638 vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
3639 vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT,
3640 vk::VK_IMAGE_USAGE_SAMPLED_BIT,
3641 vk::VK_IMAGE_USAGE_STORAGE_BIT,
3642 vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
3643 vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
3644 vk::VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
3645 vk::VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
3646 vk::VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT,
3647 vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT
3649 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3650 const CustomInstance instance (createTestInstance(context, 0u, externalType, 0u));
3651 const vk::InstanceDriver& vki (instance.getDriver());
3652 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3653 const vk::VkPhysicalDeviceFeatures deviceFeatures (vk::getPhysicalDeviceFeatures(vki, physicalDevice));
3654 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3656 // VkDevice is only created if physical device claims to support any of these types.
3657 vk::Move<vk::VkDevice> device;
3658 de::MovePtr<vk::DeviceDriver> vkd;
3659 bool deviceHasDedicated = false;
3661 TestLog& log = context.getTestContext().getLog();
3663 for (size_t createFlagNdx = 0; createFlagNdx < DE_LENGTH_OF_ARRAY(createFlags); createFlagNdx++)
3664 for (size_t usageFlagNdx = 0; usageFlagNdx < DE_LENGTH_OF_ARRAY(usageFlags); usageFlagNdx++)
3666 const vk::VkImageViewCreateFlags createFlag = createFlags[createFlagNdx];
3667 const vk::VkImageUsageFlags usageFlag = usageFlags[usageFlagNdx];
3668 const vk::VkFormat format = vk::VK_FORMAT_R8G8B8A8_UNORM;
3669 const vk::VkImageType type = vk::VK_IMAGE_TYPE_2D;
3670 const vk::VkImageTiling tiling = vk::VK_IMAGE_TILING_OPTIMAL;
3671 const vk::VkPhysicalDeviceExternalImageFormatInfo externalInfo =
3673 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
3677 const vk::VkPhysicalDeviceImageFormatInfo2 info =
3679 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
3688 vk::VkExternalImageFormatProperties externalProperties =
3690 vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES,
3694 vk::VkImageFormatProperties2 properties =
3696 vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
3697 &externalProperties,
3707 if (((createFlag & vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT) != 0) &&
3708 (deviceFeatures.sparseBinding == VK_FALSE))
3711 if (((createFlag & vk::VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT) != 0) &&
3712 (deviceFeatures.sparseResidencyImage2D == VK_FALSE))
3715 if (((createFlag & vk::VK_IMAGE_CREATE_SPARSE_ALIASED_BIT) != 0) &&
3716 (deviceFeatures.sparseResidencyAliased == VK_FALSE))
3719 vki.getPhysicalDeviceImageFormatProperties2(physicalDevice, &info, &properties);
3721 log << TestLog::Message << externalProperties << TestLog::EndMessage;
3722 TCU_CHECK(externalProperties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES);
3723 TCU_CHECK(externalProperties.pNext == DE_NULL);
3724 // \todo [2017-06-06 pyry] Can we validate anything else? Compatible types?
3726 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & (vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT|vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT)) != 0)
3728 const bool requiresDedicated = (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
3730 if (!device || (requiresDedicated && !deviceHasDedicated))
3732 // \note We need to re-create with dedicated mem extensions if previous device instance didn't have them
3735 device = createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, externalType, 0u, queueFamilyIndex, requiresDedicated);
3736 vkd = de::MovePtr<vk::DeviceDriver>(new vk::DeviceDriver(vkp, instance, *device));
3737 deviceHasDedicated = requiresDedicated;
3739 catch (const tcu::NotSupportedError& e)
3742 TCU_FAIL("Physical device claims to support handle type but required extensions are not supported");
3747 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) != 0)
3749 DE_ASSERT(!!device);
3752 if (deviceHasDedicated)
3754 // Memory requirements cannot be queried without binding the image.
3755 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
3758 const vk::Unique<vk::VkImage> image (createExternalImage(*vkd, *device, queueFamilyIndex, externalType, format, 16u, 16u, tiling, createFlag, usageFlag));
3759 const vk::VkMemoryDedicatedRequirements reqs (getMemoryDedicatedRequirements(*vkd, *device, *image));
3760 const bool propertiesRequiresDedicated = (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
3761 const bool objectRequiresDedicated = (reqs.requiresDedicatedAllocation != VK_FALSE);
3763 if (propertiesRequiresDedicated != objectRequiresDedicated)
3764 TCU_FAIL("vkGetPhysicalDeviceExternalBufferProperties and vkGetBufferMemoryRequirements2 report different dedicated requirements");
3768 // We can't query whether dedicated memory is required or not on per-object basis.
3769 // This check should be redundant as the code above tries to create device with
3770 // VK_KHR_dedicated_allocation & VK_KHR_get_memory_requirements2 if dedicated memory
3771 // is required. However, checking again doesn't hurt.
3772 TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) == 0);
3777 return tcu::TestStatus::pass("Pass");
3780 struct ImageTestConfig
3782 ImageTestConfig (vk::VkExternalMemoryHandleTypeFlagBits externalType_,
3784 : externalType (externalType_)
3785 , dedicated (dedicated_)
3789 vk::VkExternalMemoryHandleTypeFlagBits externalType;
3793 tcu::TestStatus testImageBindExportImportBind (Context& context,
3794 const ImageTestConfig config)
3796 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3797 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3798 const vk::InstanceDriver& vki (instance.getDriver());
3799 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3800 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3801 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3802 const vk::DeviceDriver vkd (vkp, instance, *device);
3803 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);
3804 const vk::VkFormat format = vk::VK_FORMAT_R8G8B8A8_UNORM;
3805 const deUint32 width = 64u;
3806 const deUint32 height = 64u;
3807 const vk::VkImageTiling tiling = vk::VK_IMAGE_TILING_OPTIMAL;
3809 checkImageSupport(vki, physicalDevice, config.externalType, 0u, usage, format, tiling, config.dedicated);
3811 const vk::Unique<vk::VkImage> imageA (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3812 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *imageA, config.externalType));
3813 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
3814 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *imageA : (vk::VkImage)0));
3815 NativeHandle handle;
3817 VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
3819 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3822 const vk::Unique<vk::VkImage> imageB (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3823 const deUint32 idx = config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID ? ~0u : exportedMemoryTypeIndex;
3824 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3825 ? importDedicatedMemory(vkd, *device, *imageB, requirements, config.externalType, idx, handle)
3826 : importMemory(vkd, *device, requirements, config.externalType, idx, handle));
3828 VK_CHECK(vkd.bindImageMemory(*device, *imageB, *memoryB, 0u));
3831 return tcu::TestStatus::pass("Pass");
3834 tcu::TestStatus testImageExportBindImportBind (Context& context,
3835 const ImageTestConfig config)
3837 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3838 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3839 const vk::InstanceDriver& vki (instance.getDriver());
3840 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3841 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3842 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3843 const vk::DeviceDriver vkd (vkp, instance, *device);
3844 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);
3845 const vk::VkFormat format = vk::VK_FORMAT_R8G8B8A8_UNORM;
3846 const deUint32 width = 64u;
3847 const deUint32 height = 64u;
3848 const vk::VkImageTiling tiling = vk::VK_IMAGE_TILING_OPTIMAL;
3850 checkImageSupport(vki, physicalDevice, config.externalType, 0u, usage, format, tiling, config.dedicated);
3852 const vk::Unique<vk::VkImage> imageA (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3853 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *imageA, config.externalType));
3854 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
3855 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *imageA : (vk::VkImage)0));
3856 NativeHandle handle;
3858 if (config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID && config.dedicated)
3860 // AHB required the image memory to be bound first.
3861 VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
3862 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3866 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3867 VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
3871 const vk::Unique<vk::VkImage> imageB (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3872 const deUint32 idx = config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID ? ~0u : exportedMemoryTypeIndex;
3873 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3874 ? importDedicatedMemory(vkd, *device, *imageB, requirements, config.externalType, idx, handle)
3875 : importMemory(vkd, *device, requirements, config.externalType, idx, handle));
3877 VK_CHECK(vkd.bindImageMemory(*device, *imageB, *memoryB, 0u));
3880 return tcu::TestStatus::pass("Pass");
3883 tcu::TestStatus testImageExportImportBindBind (Context& context,
3884 const ImageTestConfig config)
3886 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3887 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3888 const vk::InstanceDriver& vki (instance.getDriver());
3889 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3890 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3891 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3892 const vk::DeviceDriver vkd (vkp, instance, *device);
3893 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);
3894 const vk::VkFormat format = vk::VK_FORMAT_R8G8B8A8_UNORM;
3895 const deUint32 width = 64u;
3896 const deUint32 height = 64u;
3897 const vk::VkImageTiling tiling = vk::VK_IMAGE_TILING_OPTIMAL;
3899 checkImageSupport(vki, physicalDevice, config.externalType, 0u, usage, format, tiling, config.dedicated);
3901 if (config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID && config.dedicated)
3903 // AHB required the image memory to be bound first, which is not possible in this test.
3904 TCU_THROW(NotSupportedError, "Unsupported for Android Hardware Buffer");
3907 // \note Image is only allocated to get memory requirements
3908 const vk::Unique<vk::VkImage> imageA (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3909 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *imageA, config.externalType));
3910 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
3911 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *imageA : (vk::VkImage)0));
3912 NativeHandle handle;
3914 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3917 const vk::Unique<vk::VkImage> imageB (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3918 const deUint32 idx = config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID ? ~0u : exportedMemoryTypeIndex;
3919 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3920 ? importDedicatedMemory(vkd, *device, *imageB, requirements, config.externalType, idx, handle)
3921 : importMemory(vkd, *device, requirements, config.externalType, idx, handle));
3923 VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
3924 VK_CHECK(vkd.bindImageMemory(*device, *imageB, *memoryB, 0u));
3927 return tcu::TestStatus::pass("Pass");
3930 template<class TestConfig> void checkEvent (Context& context, const TestConfig)
3932 if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") && !context.getPortabilitySubsetFeatures().events)
3933 TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Events are not supported by this implementation");
3936 template<class TestConfig> void checkSupport (Context& context, const TestConfig config)
3938 const Transference transference (getHandelTypeTransferences(config.externalType));
3939 if (transference == TRANSFERENCE_COPY)
3940 checkEvent(context, config);
3943 de::MovePtr<tcu::TestCaseGroup> createFenceTests (tcu::TestContext& testCtx, vk::VkExternalFenceHandleTypeFlagBits externalType)
3947 const char* const name;
3948 const Permanence permanence;
3951 { "temporary", PERMANENCE_TEMPORARY },
3952 { "permanent", PERMANENCE_PERMANENT }
3955 de::MovePtr<tcu::TestCaseGroup> fenceGroup (new tcu::TestCaseGroup(testCtx, externalFenceTypeToName(externalType), externalFenceTypeToName(externalType)));
3957 addFunctionCase(fenceGroup.get(), "info", "Test external fence queries.", testFenceQueries, externalType);
3959 for (size_t permanenceNdx = 0; permanenceNdx < DE_LENGTH_OF_ARRAY(permanences); permanenceNdx++)
3961 const Permanence permanence (permanences[permanenceNdx].permanence);
3962 const char* const permanenceName (permanences[permanenceNdx].name);
3963 const FenceTestConfig config (externalType, permanence);
3965 if (!isSupportedPermanence(externalType, permanence))
3968 if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT
3969 || externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
3971 addFunctionCase(fenceGroup.get(), std::string("create_win32_") + permanenceName, "Test creating fence with win32 properties.", testFenceWin32Create, config);
3974 addFunctionCase(fenceGroup.get(), std::string("import_twice_") + permanenceName, "Test importing fence twice.", checkSupport, testFenceImportTwice, config);
3975 addFunctionCase(fenceGroup.get(), std::string("reimport_") + permanenceName, "Test importing again over previously imported fence.", checkSupport, testFenceImportReimport, config);
3976 addFunctionCase(fenceGroup.get(), std::string("import_multiple_times_") + permanenceName, "Test importing fence multiple times.", checkSupport, testFenceMultipleImports, config);
3977 addFunctionCase(fenceGroup.get(), std::string("signal_export_import_wait_") + permanenceName, "Test signaling, exporting, importing and waiting for the sempahore.", checkEvent, testFenceSignalExportImportWait, config);
3978 addFunctionCase(fenceGroup.get(), std::string("signal_import_") + permanenceName, "Test signaling and importing the fence.", checkSupport, testFenceSignalImport, config);
3979 addFunctionCase(fenceGroup.get(), std::string("reset_") + permanenceName, "Test resetting the fence.", checkEvent, testFenceReset, config);
3980 addFunctionCase(fenceGroup.get(), std::string("transference_") + permanenceName, "Test fences transference.", checkEvent, testFenceTransference, config);
3982 if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT)
3984 addFunctionCase(fenceGroup.get(), std::string("import_signaled_") + permanenceName, "Test import signaled fence fd.", testFenceImportSyncFdSignaled, config);
3987 if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT
3988 || externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT)
3990 // \note Not supported on WIN32 handles
3991 addFunctionCase(fenceGroup.get(), std::string("export_multiple_times_") + permanenceName, "Test exporting fence multiple times.", checkSupport, testFenceMultipleExports, config);
3993 addFunctionCase(fenceGroup.get(), std::string("dup_") + permanenceName, "Test calling dup() on exported fence.", checkSupport, testFenceFdDup, config);
3994 addFunctionCase(fenceGroup.get(), std::string("dup2_") + permanenceName, "Test calling dup2() on exported fence.", checkSupport, testFenceFdDup2, config);
3995 addFunctionCase(fenceGroup.get(), std::string("dup3_") + permanenceName, "Test calling dup3() on exported fence.", checkSupport, testFenceFdDup3, config);
3996 addFunctionCase(fenceGroup.get(), std::string("send_over_socket_") + permanenceName, "Test sending fence fd over socket.", checkSupport, testFenceFdSendOverSocket, config);
3999 if (getHandelTypeTransferences(externalType) == TRANSFERENCE_REFERENCE)
4001 addFunctionCase(fenceGroup.get(), std::string("signal_wait_import_") + permanenceName, "Test signaling and then waiting for the the sepmahore.", testFenceSignalWaitImport, config);
4002 addFunctionCase(fenceGroup.get(), std::string("export_signal_import_wait_") + permanenceName, "Test exporting, signaling, importing and waiting for the fence.", testFenceExportSignalImportWait, config);
4003 addFunctionCase(fenceGroup.get(), std::string("export_import_signal_wait_") + permanenceName, "Test exporting, importing, signaling and waiting for the fence.", testFenceExportImportSignalWait, config);
4010 bool ValidateAHardwareBuffer(vk::VkFormat format, deUint64 requiredAhbUsage, const vk::DeviceDriver& vkd, const vk::VkDevice& device, vk::VkImageCreateFlags createFlag, deUint32 layerCount, bool& enableMaxLayerTest)
4012 DE_UNREF(createFlag);
4014 AndroidHardwareBufferExternalApi* ahbApi = AndroidHardwareBufferExternalApi::getInstance();
4017 TCU_THROW(NotSupportedError, "Platform doesn't support Android Hardware Buffer handles");
4020 #if (DE_OS == DE_OS_ANDROID)
4021 // If CubeMap create flag is used and AHB doesn't support CubeMap return false.
4022 if(!AndroidHardwareBufferExternalApi::supportsCubeMap() && (createFlag & vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT))
4026 vk::pt::AndroidHardwareBufferPtr ahb = ahbApi->allocate(64u, 64u, layerCount, ahbApi->vkFormatToAhbFormat(format), requiredAhbUsage);
4027 if (ahb.internal == DE_NULL)
4029 enableMaxLayerTest = false;
4030 // try again with layerCount '1'
4031 ahb = ahbApi->allocate(64u, 64u, 1u, ahbApi->vkFormatToAhbFormat(format), requiredAhbUsage);
4032 if (ahb.internal == DE_NULL)
4037 NativeHandle nativeHandle(ahb);
4039 const vk::VkComponentMapping mappingA = { vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY };
4040 const vk::VkComponentMapping mappingB = { vk::VK_COMPONENT_SWIZZLE_R, vk::VK_COMPONENT_SWIZZLE_G, vk::VK_COMPONENT_SWIZZLE_B, vk::VK_COMPONENT_SWIZZLE_A };
4042 for (int variantIdx = 0; variantIdx < 2; ++variantIdx)
4044 // Both mappings should be equivalent and work.
4045 const vk::VkComponentMapping& mapping = ((variantIdx == 0) ? mappingA : mappingB);
4047 vk::VkAndroidHardwareBufferFormatPropertiesANDROID formatProperties =
4049 vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID,
4051 vk::VK_FORMAT_UNDEFINED,
4055 vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY,
4056 vk::VK_SAMPLER_YCBCR_RANGE_ITU_FULL,
4057 vk::VK_CHROMA_LOCATION_COSITED_EVEN,
4058 vk::VK_CHROMA_LOCATION_COSITED_EVEN
4061 vk::VkAndroidHardwareBufferPropertiesANDROID bufferProperties =
4063 vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID,
4069 VK_CHECK(vkd.getAndroidHardwareBufferPropertiesANDROID(device, ahb, &bufferProperties));
4070 TCU_CHECK(formatProperties.format != vk::VK_FORMAT_UNDEFINED);
4071 TCU_CHECK(formatProperties.format == format);
4072 TCU_CHECK(formatProperties.externalFormat != 0u);
4073 TCU_CHECK((formatProperties.formatFeatures & vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) != 0u);
4074 TCU_CHECK((formatProperties.formatFeatures & (vk::VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT | vk::VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT)) != 0u);
4080 tcu::TestStatus testAndroidHardwareBufferImageFormat (Context& context, vk::VkFormat format)
4082 AndroidHardwareBufferExternalApi* ahbApi = AndroidHardwareBufferExternalApi::getInstance();
4085 TCU_THROW(NotSupportedError, "Platform doesn't support Android Hardware Buffer handles");
4088 const vk::VkExternalMemoryHandleTypeFlagBits externalMemoryType = vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
4089 const vk::PlatformInterface& vkp (context.getPlatformInterface());
4090 const CustomInstance instance (createTestInstance(context, 0u, externalMemoryType, 0u));
4091 const vk::InstanceDriver& vki (instance.getDriver());
4092 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
4093 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
4094 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, externalMemoryType, 0u, queueFamilyIndex));
4095 const vk::DeviceDriver vkd (vkp, instance, *device);
4096 TestLog& log = context.getTestContext().getLog();
4097 const vk::VkPhysicalDeviceLimits limits = getPhysicalDeviceProperties(vki, physicalDevice).limits;
4099 const vk::VkImageUsageFlagBits framebufferUsageFlag = vk::isDepthStencilFormat(format) ? vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
4100 : vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
4102 const vk::VkImageUsageFlagBits usageFlags[] =
4104 vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
4105 vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT,
4106 vk::VK_IMAGE_USAGE_SAMPLED_BIT,
4107 vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT,
4108 framebufferUsageFlag,
4110 const vk::VkImageCreateFlagBits createFlags[] =
4112 vk::VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT,
4113 vk::VK_IMAGE_CREATE_EXTENDED_USAGE_BIT,
4114 vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT,
4116 const vk::VkImageTiling tilings[] =
4118 vk::VK_IMAGE_TILING_OPTIMAL,
4119 vk::VK_IMAGE_TILING_LINEAR,
4121 deUint64 mustSupportAhbUsageFlags = ahbApi->mustSupportAhbUsageFlags();
4122 const size_t one = 1u;
4123 const size_t numOfUsageFlags = DE_LENGTH_OF_ARRAY(usageFlags);
4124 const size_t numOfCreateFlags = DE_LENGTH_OF_ARRAY(createFlags);
4125 const size_t numOfFlagCombos = one << (numOfUsageFlags + numOfCreateFlags);
4126 const size_t numOfTilings = DE_LENGTH_OF_ARRAY(tilings);
4128 for (size_t combo = 0; combo < numOfFlagCombos; combo++)
4130 vk::VkImageUsageFlags usage = 0;
4131 vk::VkImageCreateFlags createFlag = 0;
4132 deUint64 requiredAhbUsage = 0;
4133 bool enableMaxLayerTest = true;
4134 for (size_t usageNdx = 0; usageNdx < numOfUsageFlags; usageNdx++)
4136 if ((combo & (one << usageNdx)) == 0)
4138 usage |= usageFlags[usageNdx];
4139 requiredAhbUsage |= ahbApi->vkUsageToAhbUsage(usageFlags[usageNdx]);
4141 for (size_t createFlagNdx = 0; createFlagNdx < numOfCreateFlags; createFlagNdx++)
4143 const size_t bit = numOfUsageFlags + createFlagNdx;
4144 if ((combo & (one << bit)) == 0)
4146 createFlag |= createFlags[createFlagNdx];
4147 requiredAhbUsage |= ahbApi->vkCreateToAhbUsage(createFlags[createFlagNdx]);
4150 // Only test a combination if the usage flags include at least one of the AHARDWAREBUFFER_USAGE_GPU_* flag.
4151 if ((requiredAhbUsage & mustSupportAhbUsageFlags) == 0u)
4154 // Only test a combination if AHardwareBuffer can be successfully allocated for it.
4155 if (!ValidateAHardwareBuffer(format, requiredAhbUsage, vkd, *device, createFlag, limits.maxImageArrayLayers, enableMaxLayerTest))
4158 bool foundAnyUsableTiling = false;
4159 for (size_t tilingIndex = 0; tilingIndex < numOfTilings; tilingIndex++)
4161 const vk::VkImageTiling tiling = tilings[tilingIndex];
4163 const vk::VkPhysicalDeviceExternalImageFormatInfo externalInfo =
4165 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
4167 vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID
4169 const vk::VkPhysicalDeviceImageFormatInfo2 info =
4171 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
4174 vk::VK_IMAGE_TYPE_2D,
4180 vk::VkAndroidHardwareBufferUsageANDROID ahbUsageProperties =
4182 vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID,
4186 vk::VkExternalImageFormatProperties externalProperties =
4188 vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES,
4189 &ahbUsageProperties,
4192 vk::VkImageFormatProperties2 properties =
4194 vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
4195 &externalProperties,
4205 if (vki.getPhysicalDeviceImageFormatProperties2(physicalDevice, &info, &properties) == vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
4207 log << TestLog::Message << "Tiling " << tiling << " is not supported." << TestLog::EndMessage;
4211 foundAnyUsableTiling = true;
4213 TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) != 0);
4214 TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) != 0);
4215 TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0);
4216 deUint32 maxWidth = properties.imageFormatProperties.maxExtent.width;
4217 deUint32 maxHeight = properties.imageFormatProperties.maxExtent.height;
4218 TCU_CHECK(maxWidth >= 4096);
4219 TCU_CHECK(maxHeight >= 4096);
4220 // Even if not requested, at least one of GPU_* usage flags must be present.
4221 TCU_CHECK((ahbUsageProperties.androidHardwareBufferUsage & mustSupportAhbUsageFlags) != 0u);
4222 // The AHB usage flags corresponding to the create and usage flags used in info must be present.
4223 TCU_CHECK((ahbUsageProperties.androidHardwareBufferUsage & requiredAhbUsage) == requiredAhbUsage);
4225 log << TestLog::Message << "Required flags: " << std::hex << requiredAhbUsage << " Actual flags: " << std::hex << ahbUsageProperties.androidHardwareBufferUsage
4226 << TestLog::EndMessage;
4238 for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(sizes); i++)
4240 const vk::Unique<vk::VkImage> image (createExternalImage(vkd, *device, queueFamilyIndex, externalMemoryType, format, sizes[i].width, sizes[i].height, tiling, createFlag, usage));
4241 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *image, externalMemoryType));
4242 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
4243 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, externalMemoryType, *image));
4244 NativeHandle handle;
4246 VK_CHECK(vkd.bindImageMemory(*device, *image, *memory, 0u));
4247 getMemoryNative(vkd, *device, *memory, externalMemoryType, handle);
4249 deUint32 ahbFormat = 0;
4250 deUint64 anhUsage = 0;
4251 ahbApi->describe(handle.getAndroidHardwareBuffer(), DE_NULL, DE_NULL, DE_NULL, &ahbFormat, &anhUsage, DE_NULL);
4252 TCU_CHECK(ahbFormat == ahbApi->vkFormatToAhbFormat(format));
4253 TCU_CHECK((anhUsage & requiredAhbUsage) == requiredAhbUsage);
4255 // Let watchdog know we're alive
4256 context.getTestContext().touchWatchdog();
4259 if (properties.imageFormatProperties.maxMipLevels > 1u)
4261 const vk::Unique<vk::VkImage> image (createExternalImage(vkd, *device, queueFamilyIndex, externalMemoryType, format, 64u, 64u, tiling, createFlag, usage, properties.imageFormatProperties.maxMipLevels));
4262 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *image, externalMemoryType));
4263 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
4264 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, externalMemoryType, *image));
4265 NativeHandle handle;
4267 VK_CHECK(vkd.bindImageMemory(*device, *image, *memory, 0u));
4268 getMemoryNative(vkd, *device, *memory, externalMemoryType, handle);
4270 deUint32 ahbFormat = 0;
4271 deUint64 anhUsage = 0;
4272 ahbApi->describe(handle.getAndroidHardwareBuffer(), DE_NULL, DE_NULL, DE_NULL, &ahbFormat, &anhUsage, DE_NULL);
4273 TCU_CHECK(ahbFormat == ahbApi->vkFormatToAhbFormat(format));
4274 TCU_CHECK((anhUsage & requiredAhbUsage) == requiredAhbUsage);
4277 if ((properties.imageFormatProperties.maxArrayLayers > 1u) && enableMaxLayerTest)
4279 const vk::Unique<vk::VkImage> image (createExternalImage(vkd, *device, queueFamilyIndex, externalMemoryType, format, 64u, 64u, tiling, createFlag, usage, 1u, properties.imageFormatProperties.maxArrayLayers));
4280 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *image, externalMemoryType));
4281 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
4282 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, externalMemoryType, *image));
4283 NativeHandle handle;
4285 VK_CHECK(vkd.bindImageMemory(*device, *image, *memory, 0u));
4286 getMemoryNative(vkd, *device, *memory, externalMemoryType, handle);
4288 deUint32 ahbFormat = 0;
4289 deUint64 anhUsage = 0;
4290 ahbApi->describe(handle.getAndroidHardwareBuffer(), DE_NULL, DE_NULL, DE_NULL, &ahbFormat, &anhUsage, DE_NULL);
4291 TCU_CHECK(ahbFormat == ahbApi->vkFormatToAhbFormat(format));
4292 TCU_CHECK((anhUsage & requiredAhbUsage) == requiredAhbUsage);
4296 TCU_CHECK(foundAnyUsableTiling);
4298 return tcu::TestStatus::pass("Pass");
4301 de::MovePtr<tcu::TestCaseGroup> createFenceTests (tcu::TestContext& testCtx)
4303 de::MovePtr<tcu::TestCaseGroup> fenceGroup (new tcu::TestCaseGroup(testCtx, "fence", "Tests for external fences."));
4305 fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT).release());
4306 fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT).release());
4307 fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT).release());
4308 fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT).release());
4313 de::MovePtr<tcu::TestCaseGroup> createSemaphoreTests (tcu::TestContext& testCtx, vk::VkExternalSemaphoreHandleTypeFlagBits externalType)
4317 const char* const name;
4318 const Permanence permanence;
4321 { "temporary", PERMANENCE_TEMPORARY },
4322 { "permanent", PERMANENCE_PERMANENT }
4325 de::MovePtr<tcu::TestCaseGroup> semaphoreGroup (new tcu::TestCaseGroup(testCtx, externalSemaphoreTypeToName(externalType), externalSemaphoreTypeToName(externalType)));
4327 addFunctionCase(semaphoreGroup.get(), "info", "Test external semaphore queries.", testSemaphoreQueries, externalType);
4329 for (size_t permanenceNdx = 0; permanenceNdx < DE_LENGTH_OF_ARRAY(permanences); permanenceNdx++)
4331 const Permanence permanence (permanences[permanenceNdx].permanence);
4332 const char* const permanenceName (permanences[permanenceNdx].name);
4333 const SemaphoreTestConfig config (externalType, permanence);
4335 if (!isSupportedPermanence(externalType, permanence))
4338 if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
4339 || externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
4341 addFunctionCase(semaphoreGroup.get(), std::string("create_win32_") + permanenceName, "Test creating semaphore with win32 properties.", testSemaphoreWin32Create, config);
4344 addFunctionCase(semaphoreGroup.get(), std::string("import_twice_") + permanenceName, "Test importing semaphore twice.", checkSupport, testSemaphoreImportTwice, config);
4345 addFunctionCase(semaphoreGroup.get(), std::string("reimport_") + permanenceName, "Test importing again over previously imported semaphore.", checkSupport, testSemaphoreImportReimport, config);
4346 addFunctionCase(semaphoreGroup.get(), std::string("import_multiple_times_") + permanenceName, "Test importing semaphore multiple times.", checkSupport, testSemaphoreMultipleImports, config);
4347 addFunctionCase(semaphoreGroup.get(), std::string("signal_export_import_wait_") + permanenceName, "Test signaling, exporting, importing and waiting for the sempahore.", checkEvent, testSemaphoreSignalExportImportWait, config);
4348 addFunctionCase(semaphoreGroup.get(), std::string("signal_import_") + permanenceName, "Test signaling and importing the semaphore.", checkSupport, testSemaphoreSignalImport, config);
4349 addFunctionCase(semaphoreGroup.get(), std::string("transference_") + permanenceName, "Test semaphores transference.", checkEvent, testSemaphoreTransference, config);
4351 if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT)
4353 addFunctionCase(semaphoreGroup.get(), std::string("import_signaled_") + permanenceName, "Test import signaled semaphore fd.", testSemaphoreImportSyncFdSignaled, config);
4357 if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT
4358 || externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT)
4360 // \note Not supported on WIN32 handles
4361 addFunctionCase(semaphoreGroup.get(), std::string("export_multiple_times_") + permanenceName, "Test exporting semaphore multiple times.", checkSupport, testSemaphoreMultipleExports, config);
4363 addFunctionCase(semaphoreGroup.get(), std::string("dup_") + permanenceName, "Test calling dup() on exported semaphore.", checkSupport, testSemaphoreFdDup, config);
4364 addFunctionCase(semaphoreGroup.get(), std::string("dup2_") + permanenceName, "Test calling dup2() on exported semaphore.", checkSupport, testSemaphoreFdDup2, config);
4365 addFunctionCase(semaphoreGroup.get(), std::string("dup3_") + permanenceName, "Test calling dup3() on exported semaphore.", checkSupport, testSemaphoreFdDup3, config);
4366 addFunctionCase(semaphoreGroup.get(), std::string("send_over_socket_") + permanenceName, "Test sending semaphore fd over socket.", checkSupport, testSemaphoreFdSendOverSocket, config);
4369 if (getHandelTypeTransferences(externalType) == TRANSFERENCE_REFERENCE)
4371 addFunctionCase(semaphoreGroup.get(), std::string("signal_wait_import_") + permanenceName, "Test signaling and then waiting for the the sepmahore.", testSemaphoreSignalWaitImport, config);
4372 addFunctionCase(semaphoreGroup.get(), std::string("export_signal_import_wait_") + permanenceName, "Test exporting, signaling, importing and waiting for the semaphore.", testSemaphoreExportSignalImportWait, config);
4373 addFunctionCase(semaphoreGroup.get(), std::string("export_import_signal_wait_") + permanenceName, "Test exporting, importing, signaling and waiting for the semaphore.", checkEvent, testSemaphoreExportImportSignalWait, config);
4377 return semaphoreGroup;
4380 de::MovePtr<tcu::TestCaseGroup> createSemaphoreTests (tcu::TestContext& testCtx)
4382 de::MovePtr<tcu::TestCaseGroup> semaphoreGroup (new tcu::TestCaseGroup(testCtx, "semaphore", "Tests for external semaphores."));
4384 semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT).release());
4385 semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT).release());
4386 semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT).release());
4387 semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT).release());
4389 return semaphoreGroup;
4392 de::MovePtr<tcu::TestCaseGroup> createMemoryTests (tcu::TestContext& testCtx, vk::VkExternalMemoryHandleTypeFlagBits externalType)
4394 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, externalMemoryTypeToName(externalType), "Tests for external memory"));
4396 for (size_t dedicatedNdx = 0; dedicatedNdx < 2; dedicatedNdx++)
4398 const bool dedicated (dedicatedNdx == 1);
4399 de::MovePtr<tcu::TestCaseGroup> dedicatedGroup (new tcu::TestCaseGroup(testCtx, dedicated ? "dedicated" : "suballocated", ""));
4401 for (size_t hostVisibleNdx = 0; hostVisibleNdx < 2; hostVisibleNdx++)
4403 const bool hostVisible (hostVisibleNdx == 1);
4404 de::MovePtr<tcu::TestCaseGroup> hostVisibleGroup (new tcu::TestCaseGroup(testCtx, hostVisible ? "host_visible" : "device_only", ""));
4405 const MemoryTestConfig memoryConfig (externalType, hostVisible, dedicated);
4407 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
4408 || externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
4410 addFunctionCase(hostVisibleGroup.get(), "create_win32", "Test creating memory with win32 properties .", testMemoryWin32Create, memoryConfig);
4413 addFunctionCase(hostVisibleGroup.get(), "import_twice", "Test importing memory object twice.", testMemoryImportTwice, memoryConfig);
4414 addFunctionCase(hostVisibleGroup.get(), "import_multiple_times", "Test importing memory object multiple times.", testMemoryMultipleImports, memoryConfig);
4416 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT
4417 || externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT)
4419 addFunctionCase(hostVisibleGroup.get(), "dup", "Test calling dup() on exported memory.", testMemoryFdDup, memoryConfig);
4420 addFunctionCase(hostVisibleGroup.get(), "dup2", "Test calling dup2() on exported memory.", testMemoryFdDup2, memoryConfig);
4421 addFunctionCase(hostVisibleGroup.get(), "dup3", "Test calling dup3() on exported memory.", testMemoryFdDup3, memoryConfig);
4422 addFunctionCase(hostVisibleGroup.get(), "send_over_socket", "Test sending memory fd over socket.", testMemoryFdSendOverSocket, memoryConfig);
4423 // \note Not supported on WIN32 handles
4424 addFunctionCase(hostVisibleGroup.get(), "export_multiple_times", "Test exporting memory multiple times.", testMemoryMultipleExports, memoryConfig);
4427 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT)
4429 addFunctionCase(hostVisibleGroup.get(), "fd_properties", "Test obtaining the FD memory properties", testMemoryFdProperties, memoryConfig);
4432 dedicatedGroup->addChild(hostVisibleGroup.release());
4436 de::MovePtr<tcu::TestCaseGroup> bufferGroup (new tcu::TestCaseGroup(testCtx, "buffer", ""));
4437 const BufferTestConfig bufferConfig (externalType, dedicated);
4439 addFunctionCase(bufferGroup.get(), "info", "External buffer memory info query.", testBufferQueries, externalType);
4440 addFunctionCase(bufferGroup.get(), "bind_export_import_bind", "Test binding, exporting, importing and binding buffer.", testBufferBindExportImportBind, bufferConfig);
4441 addFunctionCase(bufferGroup.get(), "export_bind_import_bind", "Test exporting, binding, importing and binding buffer.", testBufferExportBindImportBind, bufferConfig);
4442 addFunctionCase(bufferGroup.get(), "export_import_bind_bind", "Test exporting, importing and binding buffer.", testBufferExportImportBindBind, bufferConfig);
4444 dedicatedGroup->addChild(bufferGroup.release());
4448 de::MovePtr<tcu::TestCaseGroup> imageGroup (new tcu::TestCaseGroup(testCtx, "image", ""));
4449 const ImageTestConfig imageConfig (externalType, dedicated);
4451 addFunctionCase(imageGroup.get(), "info", "External image memory info query.", testImageQueries, externalType);
4452 addFunctionCase(imageGroup.get(), "bind_export_import_bind", "Test binding, exporting, importing and binding image.", testImageBindExportImportBind, imageConfig);
4453 addFunctionCase(imageGroup.get(), "export_bind_import_bind", "Test exporting, binding, importing and binding image.", testImageExportBindImportBind, imageConfig);
4454 addFunctionCase(imageGroup.get(), "export_import_bind_bind", "Test exporting, importing and binding image.", testImageExportImportBindBind, imageConfig);
4456 dedicatedGroup->addChild(imageGroup.release());
4459 group->addChild(dedicatedGroup.release());
4462 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
4464 de::MovePtr<tcu::TestCaseGroup> formatGroup (new tcu::TestCaseGroup(testCtx, "image_formats", "Test minimum image format support"));
4466 const vk::VkFormat ahbFormats[] =
4468 vk::VK_FORMAT_R8G8B8_UNORM,
4469 vk::VK_FORMAT_R8G8B8A8_UNORM,
4470 vk::VK_FORMAT_R5G6B5_UNORM_PACK16,
4471 vk::VK_FORMAT_R16G16B16A16_SFLOAT,
4472 vk::VK_FORMAT_A2B10G10R10_UNORM_PACK32,
4473 vk::VK_FORMAT_D16_UNORM,
4474 vk::VK_FORMAT_X8_D24_UNORM_PACK32,
4475 vk::VK_FORMAT_D24_UNORM_S8_UINT,
4476 vk::VK_FORMAT_D32_SFLOAT,
4477 vk::VK_FORMAT_D32_SFLOAT_S8_UINT,
4478 vk::VK_FORMAT_S8_UINT,
4480 const size_t numOfAhbFormats = DE_LENGTH_OF_ARRAY(ahbFormats);
4482 for (size_t ahbFormatNdx = 0; ahbFormatNdx < numOfAhbFormats; ahbFormatNdx++)
4484 const vk::VkFormat format = ahbFormats[ahbFormatNdx];
4485 const std::string testCaseName = getFormatCaseName(format);
4487 addFunctionCase(formatGroup.get(), testCaseName, "", testAndroidHardwareBufferImageFormat, format);
4490 group->addChild(formatGroup.release());
4496 de::MovePtr<tcu::TestCaseGroup> createMemoryTests (tcu::TestContext& testCtx)
4498 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "memory", "Tests for external memory"));
4500 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT).release());
4501 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT).release());
4502 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT).release());
4503 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID).release());
4504 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT).release());
4511 tcu::TestCaseGroup* createExternalMemoryTests (tcu::TestContext& testCtx)
4513 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "external", "Tests for external Vulkan objects"));
4515 group->addChild(createSemaphoreTests(testCtx).release());
4516 group->addChild(createMemoryTests(testCtx).release());
4517 group->addChild(createFenceTests(testCtx).release());
4519 return group.release();