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)
246 const deUint32 apiVersion = context.getUsedApiVersion();
247 bool useExternalSemaphore = false;
248 bool useExternalFence = false;
249 bool useExternalMemory = false;
250 std::vector<const char*> deviceExtensions;
252 if ((externalSemaphoreTypes
253 & (vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT
254 | vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT)) != 0)
256 deviceExtensions.push_back("VK_KHR_external_semaphore_fd");
257 useExternalSemaphore = true;
260 if ((externalFenceTypes
261 & (vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT
262 | vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT)) != 0)
264 deviceExtensions.push_back("VK_KHR_external_fence_fd");
265 useExternalFence = true;
268 if (useDedicatedAllocs)
270 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_dedicated_allocation"))
271 deviceExtensions.push_back("VK_KHR_dedicated_allocation");
272 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_get_memory_requirements2"))
273 deviceExtensions.push_back("VK_KHR_get_memory_requirements2");
276 if ((externalMemoryTypes
277 & (vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT
278 | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT)) != 0)
280 deviceExtensions.push_back("VK_KHR_external_memory_fd");
281 useExternalMemory = true;
284 if ((externalMemoryTypes
285 & vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT) != 0)
287 deviceExtensions.push_back("VK_EXT_external_memory_dma_buf");
288 useExternalMemory = true;
291 if ((externalSemaphoreTypes
292 & (vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
293 | vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)) != 0)
295 deviceExtensions.push_back("VK_KHR_external_semaphore_win32");
296 useExternalSemaphore = true;
299 if ((externalFenceTypes
300 & (vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT
301 | vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)) != 0)
303 deviceExtensions.push_back("VK_KHR_external_fence_win32");
304 useExternalFence = true;
307 if ((externalMemoryTypes
308 & (vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
309 | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT
310 | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT
311 | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT
312 | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT
313 | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT)) != 0)
315 deviceExtensions.push_back("VK_KHR_external_memory_win32");
316 useExternalMemory = true;
319 if ((externalMemoryTypes
320 & vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID) != 0)
322 deviceExtensions.push_back("VK_ANDROID_external_memory_android_hardware_buffer");
323 useExternalMemory = true;
324 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_sampler_ycbcr_conversion"))
325 deviceExtensions.push_back("VK_KHR_sampler_ycbcr_conversion");
326 if (!vk::isCoreDeviceExtension(apiVersion, "VK_EXT_queue_family_foreign"))
327 deviceExtensions.push_back("VK_EXT_queue_family_foreign");
330 if (useExternalSemaphore)
332 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_external_semaphore"))
333 deviceExtensions.push_back("VK_KHR_external_semaphore");
336 if (useExternalFence)
338 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_external_fence"))
339 deviceExtensions.push_back("VK_KHR_external_fence");
342 if (useExternalMemory)
344 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_external_memory"))
345 deviceExtensions.push_back("VK_KHR_external_memory");
348 const float priority = 0.5f;
349 const vk::VkDeviceQueueCreateInfo queues[] =
352 vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
361 const vk::VkDeviceCreateInfo deviceCreateInfo =
363 vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
367 DE_LENGTH_OF_ARRAY(queues),
373 (deUint32)deviceExtensions.size(),
374 deviceExtensions.empty() ? DE_NULL : &deviceExtensions[0],
380 return createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), vkp, instance, vki, physicalDevice, &deviceCreateInfo);
382 catch (const vk::Error& error)
384 if (error.getError() == vk::VK_ERROR_EXTENSION_NOT_PRESENT)
385 TCU_THROW(NotSupportedError, "Required extensions not supported");
391 vk::VkQueue getQueue (const vk::DeviceInterface& vkd,
393 deUint32 queueFamilyIndex)
397 vkd.getDeviceQueue(device, queueFamilyIndex, 0, &queue);
402 void checkSemaphoreSupport (const vk::InstanceInterface& vki,
403 vk::VkPhysicalDevice device,
404 vk::VkExternalSemaphoreHandleTypeFlagBits externalType)
406 const vk::VkPhysicalDeviceExternalSemaphoreInfo info =
408 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO,
412 vk::VkExternalSemaphoreProperties properties =
414 vk::VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES,
421 vki.getPhysicalDeviceExternalSemaphoreProperties(device, &info, &properties);
423 if ((properties.externalSemaphoreFeatures & vk::VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT) == 0)
424 TCU_THROW(NotSupportedError, "Semaphore doesn't support exporting in external type");
426 if ((properties.externalSemaphoreFeatures & vk::VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT) == 0)
427 TCU_THROW(NotSupportedError, "Semaphore doesn't support importing in external type");
430 void checkFenceSupport (const vk::InstanceInterface& vki,
431 vk::VkPhysicalDevice device,
432 vk::VkExternalFenceHandleTypeFlagBits externalType)
434 const vk::VkPhysicalDeviceExternalFenceInfo info =
436 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO,
440 vk::VkExternalFenceProperties properties =
442 vk::VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES,
449 vki.getPhysicalDeviceExternalFenceProperties(device, &info, &properties);
451 if ((properties.externalFenceFeatures & vk::VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT) == 0)
452 TCU_THROW(NotSupportedError, "Fence doesn't support exporting in external type");
454 if ((properties.externalFenceFeatures & vk::VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT) == 0)
455 TCU_THROW(NotSupportedError, "Fence doesn't support importing in external type");
458 void checkBufferSupport (const vk::InstanceInterface& vki,
459 vk::VkPhysicalDevice device,
460 vk::VkExternalMemoryHandleTypeFlagBits externalType,
461 vk::VkBufferViewCreateFlags createFlag,
462 vk::VkBufferUsageFlags usageFlag,
465 const vk::VkPhysicalDeviceExternalBufferInfo info =
467 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO,
474 vk::VkExternalBufferProperties properties =
476 vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES,
482 vki.getPhysicalDeviceExternalBufferProperties(device, &info, &properties);
484 if ((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) == 0)
485 TCU_THROW(NotSupportedError, "External handle type doesn't support exporting buffer");
487 if ((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) == 0)
488 TCU_THROW(NotSupportedError, "External handle type doesn't support importing buffer");
490 if (!dedicated && (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0)
491 TCU_THROW(NotSupportedError, "External handle type requires dedicated allocation");
494 void checkImageSupport (const vk::InstanceInterface& vki,
495 vk::VkPhysicalDevice device,
496 vk::VkExternalMemoryHandleTypeFlagBits externalType,
497 vk::VkImageViewCreateFlags createFlag,
498 vk::VkImageUsageFlags usageFlag,
500 vk::VkImageTiling tiling,
503 const vk::VkPhysicalDeviceExternalImageFormatInfo externalInfo =
505 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
509 const vk::VkPhysicalDeviceImageFormatInfo2 info =
511 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
515 vk::VK_IMAGE_TYPE_2D,
520 vk::VkExternalImageFormatProperties externalProperties =
522 vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES,
526 vk::VkImageFormatProperties2 properties =
528 vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
539 vki.getPhysicalDeviceImageFormatProperties2(device, &info, &properties);
541 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) == 0)
542 TCU_THROW(NotSupportedError, "External handle type doesn't support exporting image");
544 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) == 0)
545 TCU_THROW(NotSupportedError, "External handle type doesn't support importing image");
547 if (!dedicated && (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0)
548 TCU_THROW(NotSupportedError, "External handle type requires dedicated allocation");
551 void submitDummySignal (const vk::DeviceInterface& vkd,
553 vk::VkSemaphore semaphore)
555 const vk::VkSubmitInfo submit =
557 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
571 VK_CHECK(vkd.queueSubmit(queue, 1, &submit, (vk::VkFence)0u));
574 void submitDummySignalAndGetSemaphoreNative ( const vk::DeviceInterface& vk,
577 deUint32 queueFamilyIndex,
578 vk::VkSemaphore semaphore,
579 vk::VkExternalSemaphoreHandleTypeFlagBits externalType,
580 NativeHandle& nativeHandle)
582 const vk::Unique<vk::VkCommandPool> cmdPool(createCommandPool(vk, device, vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex, DE_NULL));
583 const vk::Unique<vk::VkCommandBuffer> cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
585 const vk::VkEventCreateInfo eventCreateInfo =
587 vk::VK_STRUCTURE_TYPE_EVENT_CREATE_INFO,
592 const vk::Unique<vk::VkEvent> event(createEvent(vk, device, &eventCreateInfo, DE_NULL));
594 const vk::VkCommandBufferBeginInfo cmdBufferBeginInfo =
596 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
598 vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
602 VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
604 The submitDummySignal function calls vkQueueSubmit with an empty VkSubmitInfo structure and a
605 VkSemaphore to be signalled when the work is finished. Because there is no work in the submission, vkQueueSubmit
606 may signal the semaphore immediately. When a semaphore's file descriptor is obtained using vkGetFenceFdKHR, if the
607 handle type is VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR, vkGetFenceFdKHR is allowed to return -1 if the fence
608 is already signalled, instead of a file descriptor, . In order to make sure that a valid file descriptor is returned
609 we use vkCmdWaitEvents to make sure that vkQueueSubmit doesn't signal the fence.
611 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);
612 vk.endCommandBuffer(*cmdBuffer);
614 const vk::VkSubmitInfo submit =
616 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
630 VK_CHECK(vk.queueSubmit(queue, 1, &submit, (vk::VkFence)0u));
632 getSemaphoreNative(vk, device, semaphore, externalType, nativeHandle);
634 VK_CHECK(vk.setEvent(device, *event));
636 VK_CHECK(vk.queueWaitIdle(queue));
639 void submitDummyWait (const vk::DeviceInterface& vkd,
641 vk::VkSemaphore semaphore)
643 const vk::VkPipelineStageFlags stage = vk::VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
644 const vk::VkSubmitInfo submit =
646 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
660 VK_CHECK(vkd.queueSubmit(queue, 1, &submit, (vk::VkFence)0u));
663 void submitDummySignal (const vk::DeviceInterface& vkd,
667 const vk::VkSubmitInfo submit =
669 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
683 VK_CHECK(vkd.queueSubmit(queue, 1, &submit, fence));
686 void submitDummySignalAndGetFenceNative ( const vk::DeviceInterface& vk,
689 deUint32 queueFamilyIndex,
691 vk::VkExternalFenceHandleTypeFlagBits externalType,
692 NativeHandle& nativeHandle,
693 bool expectFenceUnsignaled = true)
695 const vk::Unique<vk::VkCommandPool> cmdPool(createCommandPool(vk, device, vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex, DE_NULL));
696 const vk::Unique<vk::VkCommandBuffer> cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
698 const vk::VkEventCreateInfo eventCreateInfo =
700 vk::VK_STRUCTURE_TYPE_EVENT_CREATE_INFO,
705 const vk::Unique<vk::VkEvent> event(createEvent(vk, device, &eventCreateInfo, DE_NULL));
707 const vk::VkCommandBufferBeginInfo cmdBufferBeginInfo =
709 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
711 vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
715 VK_CHECK(vk.beginCommandBuffer(*cmdBuffer, &cmdBufferBeginInfo));
717 The submitDummySignal function calls vkQueueSubmit with an empty VkSubmitInfo structure and a
718 VkFence to be signalled when the work is finished. Because there is no work in the submission, vkQueueSubmit
719 could signal the fence immediately. When a fence's file descriptor is obtained using vkGetFenceFdKHR, if the
720 handle type is VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT_KHR, vkGetFenceFdKHR is allowed to return -1 instead of a
721 file descriptor, if the fence is already signalled. In order to make sure that a valid file descriptor is returned
722 we use vkCmdWaitEvents to make sure that vkQueueSubmit doesn't signal the fence.
724 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);
725 vk.endCommandBuffer(*cmdBuffer);
727 const vk::VkSubmitInfo submit =
729 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
743 VK_CHECK(vk.queueSubmit(queue, 1, &submit, fence));
745 getFenceNative(vk, device, fence, externalType, nativeHandle, expectFenceUnsignaled);
747 VK_CHECK(vk.setEvent(device, *event));
749 VK_CHECK(vk.queueWaitIdle(queue));
752 tcu::TestStatus testSemaphoreQueries (Context& context, vk::VkExternalSemaphoreHandleTypeFlagBits externalType)
754 const CustomInstance instance (createTestInstance(context, externalType, 0u, 0u));
755 const vk::InstanceDriver& vki (instance.getDriver());
756 const vk::VkPhysicalDevice device (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
758 TestLog& log = context.getTestContext().getLog();
760 const vk::VkPhysicalDeviceExternalSemaphoreInfo info =
762 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO,
766 vk::VkExternalSemaphoreProperties properties =
768 vk::VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES,
775 vki.getPhysicalDeviceExternalSemaphoreProperties(device, &info, &properties);
776 log << TestLog::Message << properties << TestLog::EndMessage;
778 TCU_CHECK(properties.pNext == DE_NULL);
779 TCU_CHECK(properties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES);
781 return tcu::TestStatus::pass("Pass");
784 struct SemaphoreTestConfig
786 SemaphoreTestConfig (vk::VkExternalSemaphoreHandleTypeFlagBits externalType_,
787 Permanence permanence_)
788 : externalType (externalType_)
789 , permanence (permanence_)
793 vk::VkExternalSemaphoreHandleTypeFlagBits externalType;
794 Permanence permanence;
797 tcu::TestStatus testSemaphoreWin32Create (Context& context,
798 const SemaphoreTestConfig config)
800 #if (DE_OS == DE_OS_WIN32)
801 const Transference transference (getHandelTypeTransferences(config.externalType));
802 const vk::PlatformInterface& vkp (context.getPlatformInterface());
803 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
804 const vk::InstanceDriver& vki (instance.getDriver());
805 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
806 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
808 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
811 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
812 const vk::DeviceDriver vkd (vkp, instance, *device);
813 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
814 const vk::VkExportSemaphoreWin32HandleInfoKHR win32ExportInfo =
816 vk::VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR,
819 (vk::pt::Win32SecurityAttributesPtr)DE_NULL,
820 DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
821 (vk::pt::Win32LPCWSTR)DE_NULL
823 const vk::VkExportSemaphoreCreateInfo exportCreateInfo=
825 vk::VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO,
827 (vk::VkExternalMemoryHandleTypeFlags)config.externalType
829 const vk::VkSemaphoreCreateInfo createInfo =
831 vk::VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
835 const vk::Unique<vk::VkSemaphore> semaphore (vk::createSemaphore(vkd, *device, &createInfo));
837 if (transference == TRANSFERENCE_COPY)
838 submitDummySignal(vkd, queue, *semaphore);
840 NativeHandle handleA;
841 getSemaphoreNative(vkd, *device, *semaphore, config.externalType, handleA);
844 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
845 const vk::Unique<vk::VkSemaphore> semaphoreA (createAndImportSemaphore(vkd, *device, config.externalType, handleA, flags));
847 if (transference == TRANSFERENCE_COPY)
848 submitDummyWait(vkd, queue, *semaphoreA);
849 else if (transference == TRANSFERENCE_REFERENCE)
851 submitDummySignal(vkd, queue, *semaphore);
852 submitDummyWait(vkd, queue, *semaphoreA);
855 DE_FATAL("Unknown transference.");
857 VK_CHECK(vkd.queueWaitIdle(queue));
860 return tcu::TestStatus::pass("Pass");
865 TCU_THROW(NotSupportedError, "Platform doesn't support win32 handles");
869 tcu::TestStatus testSemaphoreImportTwice (Context& context,
870 const SemaphoreTestConfig config)
872 const Transference transference (getHandelTypeTransferences(config.externalType));
873 const vk::PlatformInterface& vkp (context.getPlatformInterface());
874 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
875 const vk::InstanceDriver& vki (instance.getDriver());
876 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
877 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
879 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
882 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
883 const vk::DeviceDriver vkd (vkp, instance, *device);
884 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
885 const vk::Unique<vk::VkSemaphore> semaphore (createExportableSemaphore(vkd, *device, config.externalType));
886 NativeHandle handleA;
888 if (transference == TRANSFERENCE_COPY)
889 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphore, config.externalType, handleA);
891 getSemaphoreNative(vkd, *device, *semaphore, config.externalType, handleA);
894 NativeHandle handleB (handleA);
895 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
896 const vk::Unique<vk::VkSemaphore> semaphoreA (createAndImportSemaphore(vkd, *device, config.externalType, handleA, flags));
897 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handleB, flags));
899 if (transference == TRANSFERENCE_COPY)
900 submitDummyWait(vkd, queue, *semaphoreA);
901 else if (transference == TRANSFERENCE_REFERENCE)
903 submitDummySignal(vkd, queue, *semaphoreA);
904 submitDummyWait(vkd, queue, *semaphoreB);
907 DE_FATAL("Unknown transference.");
909 VK_CHECK(vkd.queueWaitIdle(queue));
912 return tcu::TestStatus::pass("Pass");
916 tcu::TestStatus testSemaphoreImportReimport (Context& context,
917 const SemaphoreTestConfig config)
919 const Transference transference (getHandelTypeTransferences(config.externalType));
920 const vk::PlatformInterface& vkp (context.getPlatformInterface());
921 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
922 const vk::InstanceDriver& vki (instance.getDriver());
923 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
924 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
926 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
929 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
930 const vk::DeviceDriver vkd (vkp, instance, *device);
931 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
933 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
934 NativeHandle handleA;
936 if (transference == TRANSFERENCE_COPY)
937 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handleA);
939 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handleA);
941 NativeHandle handleB (handleA);
942 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
943 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handleA, flags));
945 importSemaphore(vkd, *device, *semaphoreB, config.externalType, handleB, flags);
947 if (transference == TRANSFERENCE_COPY)
948 submitDummyWait(vkd, queue, *semaphoreB);
949 else if (transference == TRANSFERENCE_REFERENCE)
951 submitDummySignal(vkd, queue, *semaphoreA);
952 submitDummyWait(vkd, queue, *semaphoreB);
955 DE_FATAL("Unknown transference.");
957 VK_CHECK(vkd.queueWaitIdle(queue));
959 return tcu::TestStatus::pass("Pass");
963 tcu::TestStatus testSemaphoreSignalExportImportWait (Context& context,
964 const SemaphoreTestConfig config)
966 const vk::PlatformInterface& vkp (context.getPlatformInterface());
967 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
968 const vk::InstanceDriver& vki (instance.getDriver());
969 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
970 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
972 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
975 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
976 const vk::DeviceDriver vkd (vkp, instance, *device);
977 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
978 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
982 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
985 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
986 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
987 submitDummyWait(vkd, queue, *semaphoreB);
989 VK_CHECK(vkd.queueWaitIdle(queue));
993 return tcu::TestStatus::pass("Pass");
997 tcu::TestStatus testSemaphoreExportSignalImportWait (Context& context,
998 const SemaphoreTestConfig config)
1000 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1001 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1002 const vk::InstanceDriver& vki (instance.getDriver());
1003 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1004 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1005 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1007 DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
1008 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1011 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1012 const vk::DeviceDriver vkd (vkp, instance, *device);
1013 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1015 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1016 NativeHandle handle;
1018 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
1020 submitDummySignal(vkd, queue, *semaphoreA);
1023 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1025 submitDummyWait(vkd, queue, *semaphoreB);
1026 VK_CHECK(vkd.queueWaitIdle(queue));
1030 return tcu::TestStatus::pass("Pass");
1034 tcu::TestStatus testSemaphoreExportImportSignalWait (Context& context,
1035 const SemaphoreTestConfig config)
1037 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1038 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1039 const vk::InstanceDriver& vki (instance.getDriver());
1040 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1041 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1043 DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
1044 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1047 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1048 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1049 const vk::DeviceDriver vkd (vkp, instance, *device);
1050 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1052 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1053 NativeHandle handle;
1055 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
1057 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1059 submitDummySignal(vkd, queue, *semaphoreA);
1060 submitDummyWait(vkd, queue, *semaphoreB);
1062 VK_CHECK(vkd.queueWaitIdle(queue));
1064 return tcu::TestStatus::pass("Pass");
1068 tcu::TestStatus testSemaphoreSignalImport (Context& context,
1069 const SemaphoreTestConfig config)
1071 const Transference transference (getHandelTypeTransferences(config.externalType));
1072 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1073 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1074 const vk::InstanceDriver& vki (instance.getDriver());
1075 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1076 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1078 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1081 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1082 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1083 const vk::DeviceDriver vkd (vkp, instance, *device);
1084 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1086 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1087 const vk::Unique<vk::VkSemaphore> semaphoreB (createSemaphore(vkd, *device));
1088 NativeHandle handle;
1090 submitDummySignal(vkd, queue, *semaphoreB);
1091 VK_CHECK(vkd.queueWaitIdle(queue));
1093 if (transference == TRANSFERENCE_COPY)
1094 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
1096 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
1098 importSemaphore(vkd, *device, *semaphoreB, config.externalType, handle, flags);
1100 if (transference == TRANSFERENCE_COPY)
1101 submitDummyWait(vkd, queue, *semaphoreB);
1102 else if (transference == TRANSFERENCE_REFERENCE)
1104 submitDummySignal(vkd, queue, *semaphoreA);
1105 submitDummyWait(vkd, queue, *semaphoreB);
1108 DE_FATAL("Unknown transference.");
1110 VK_CHECK(vkd.queueWaitIdle(queue));
1112 return tcu::TestStatus::pass("Pass");
1116 tcu::TestStatus testSemaphoreSignalWaitImport (Context& context,
1117 const SemaphoreTestConfig config)
1119 const Transference transference (getHandelTypeTransferences(config.externalType));
1120 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1121 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1122 const vk::InstanceDriver& vki (instance.getDriver());
1123 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1124 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1126 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1129 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1130 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1131 const vk::DeviceDriver vkd (vkp, instance, *device);
1132 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1134 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1135 const vk::Unique<vk::VkSemaphore> semaphoreB (createSemaphore(vkd, *device));
1136 NativeHandle handle;
1138 if (transference == TRANSFERENCE_COPY)
1139 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
1141 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
1143 submitDummySignal(vkd, queue, *semaphoreB);
1144 submitDummyWait(vkd, queue, *semaphoreB);
1146 VK_CHECK(vkd.queueWaitIdle(queue));
1148 importSemaphore(vkd, *device, *semaphoreB, config.externalType, handle, flags);
1150 if (transference == TRANSFERENCE_COPY)
1151 submitDummyWait(vkd, queue, *semaphoreB);
1152 else if (transference == TRANSFERENCE_REFERENCE)
1154 submitDummySignal(vkd, queue, *semaphoreA);
1155 submitDummyWait(vkd, queue, *semaphoreB);
1158 DE_FATAL("Unknown transference.");
1160 VK_CHECK(vkd.queueWaitIdle(queue));
1162 return tcu::TestStatus::pass("Pass");
1166 tcu::TestStatus testSemaphoreMultipleExports (Context& context,
1167 const SemaphoreTestConfig config)
1169 const size_t exportCount = 4 * 1024;
1170 const Transference transference (getHandelTypeTransferences(config.externalType));
1171 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1172 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1173 const vk::InstanceDriver& vki (instance.getDriver());
1174 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1175 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 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 const vk::Unique<vk::VkSemaphore> semaphore (createExportableSemaphore(vkd, *device, config.externalType));
1185 for (size_t exportNdx = 0; exportNdx < exportCount; exportNdx++)
1187 NativeHandle handle;
1189 if (transference == TRANSFERENCE_COPY)
1190 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphore, config.externalType, handle);
1192 getSemaphoreNative(vkd, *device, *semaphore, config.externalType, handle);
1195 submitDummySignal(vkd, queue, *semaphore);
1196 submitDummyWait(vkd, queue, *semaphore);
1198 VK_CHECK(vkd.queueWaitIdle(queue));
1201 return tcu::TestStatus::pass("Pass");
1204 tcu::TestStatus testSemaphoreMultipleImports (Context& context,
1205 const SemaphoreTestConfig config)
1207 const size_t importCount = 4 * 1024;
1208 const Transference transference (getHandelTypeTransferences(config.externalType));
1209 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1210 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1211 const vk::InstanceDriver& vki (instance.getDriver());
1212 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1213 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1215 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1218 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1219 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1220 const vk::DeviceDriver vkd (vkp, instance, *device);
1221 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1222 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1223 NativeHandle handleA;
1225 if (transference == TRANSFERENCE_COPY)
1226 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handleA);
1228 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handleA);
1230 for (size_t importNdx = 0; importNdx < importCount; importNdx++)
1232 NativeHandle handleB (handleA);
1233 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handleB, flags));
1236 if (transference == TRANSFERENCE_COPY)
1238 importSemaphore(vkd, *device, *semaphoreA, config.externalType, handleA, flags);
1239 submitDummyWait(vkd, queue, *semaphoreA);
1241 else if (transference == TRANSFERENCE_REFERENCE)
1243 submitDummySignal(vkd, queue, *semaphoreA);
1244 submitDummyWait(vkd, queue, *semaphoreA);
1247 DE_FATAL("Unknown transference.");
1249 VK_CHECK(vkd.queueWaitIdle(queue));
1252 return tcu::TestStatus::pass("Pass");
1255 tcu::TestStatus testSemaphoreTransference (Context& context,
1256 const SemaphoreTestConfig config)
1258 const Transference transference (getHandelTypeTransferences(config.externalType));
1259 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1260 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1261 const vk::InstanceDriver& vki (instance.getDriver());
1262 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1263 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1265 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1268 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1269 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1270 const vk::DeviceDriver vkd (vkp, instance, *device);
1271 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1273 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1274 NativeHandle handle;
1276 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
1279 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1281 if (config.permanence == PERMANENCE_PERMANENT)
1283 if (transference == TRANSFERENCE_COPY)
1285 submitDummySignal(vkd, queue, *semaphoreA);
1286 submitDummyWait(vkd, queue, *semaphoreB);
1287 VK_CHECK(vkd.queueWaitIdle(queue));
1289 submitDummySignal(vkd, queue, *semaphoreB);
1291 submitDummyWait(vkd, queue, *semaphoreA);
1292 submitDummyWait(vkd, queue, *semaphoreB);
1293 VK_CHECK(vkd.queueWaitIdle(queue));
1295 else if (transference== TRANSFERENCE_REFERENCE)
1297 submitDummyWait(vkd, queue, *semaphoreB);
1298 VK_CHECK(vkd.queueWaitIdle(queue));
1300 submitDummySignal(vkd, queue, *semaphoreA);
1301 submitDummyWait(vkd, queue, *semaphoreB);
1303 submitDummySignal(vkd, queue, *semaphoreB);
1304 submitDummyWait(vkd, queue, *semaphoreA);
1305 VK_CHECK(vkd.queueWaitIdle(queue));
1308 DE_FATAL("Unknown transference.");
1310 else if (config.permanence == PERMANENCE_TEMPORARY)
1312 if (transference == TRANSFERENCE_COPY)
1314 submitDummySignal(vkd, queue, *semaphoreA);
1315 submitDummyWait(vkd, queue, *semaphoreB);
1316 VK_CHECK(vkd.queueWaitIdle(queue));
1318 submitDummySignal(vkd, queue, *semaphoreB);
1320 submitDummyWait(vkd, queue, *semaphoreA);
1321 submitDummyWait(vkd, queue, *semaphoreB);
1322 VK_CHECK(vkd.queueWaitIdle(queue));
1324 else if (transference== TRANSFERENCE_REFERENCE)
1326 submitDummyWait(vkd, queue, *semaphoreB);
1327 VK_CHECK(vkd.queueWaitIdle(queue));
1329 submitDummySignal(vkd, queue, *semaphoreA);
1330 submitDummySignal(vkd, queue, *semaphoreB);
1332 submitDummyWait(vkd, queue, *semaphoreB);
1333 submitDummyWait(vkd, queue, *semaphoreA);
1334 VK_CHECK(vkd.queueWaitIdle(queue));
1337 DE_FATAL("Unknown transference.");
1340 DE_FATAL("Unknown permanence.");
1343 return tcu::TestStatus::pass("Pass");
1347 tcu::TestStatus testSemaphoreFdDup (Context& context,
1348 const SemaphoreTestConfig config)
1350 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
1351 const Transference transference (getHandelTypeTransferences(config.externalType));
1352 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1353 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1354 const vk::InstanceDriver& vki (instance.getDriver());
1355 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1356 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1358 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1361 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1362 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1363 const vk::DeviceDriver vkd (vkp, instance, *device);
1364 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1366 TestLog& log = context.getTestContext().getLog();
1367 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1372 if (transference == TRANSFERENCE_COPY)
1373 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, fd);
1375 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, fd);
1377 NativeHandle newFd (dup(fd.getFd()));
1379 if (newFd.getFd() < 0)
1380 log << TestLog::Message << "dup() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
1382 TCU_CHECK_MSG(newFd.getFd() >= 0, "Failed to call dup() for semaphores fd");
1385 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, newFd, flags));
1387 if (transference == TRANSFERENCE_COPY)
1388 submitDummyWait(vkd, queue, *semaphoreB);
1389 else if (transference == TRANSFERENCE_REFERENCE)
1391 submitDummySignal(vkd, queue, *semaphoreA);
1392 submitDummyWait(vkd, queue, *semaphoreB);
1395 DE_FATAL("Unknown permanence.");
1397 VK_CHECK(vkd.queueWaitIdle(queue));
1401 return tcu::TestStatus::pass("Pass");
1406 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
1410 tcu::TestStatus testSemaphoreFdDup2 (Context& context,
1411 const SemaphoreTestConfig config)
1413 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
1414 const Transference transference (getHandelTypeTransferences(config.externalType));
1415 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1416 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1417 const vk::InstanceDriver& vki (instance.getDriver());
1418 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1419 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1421 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1424 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1425 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1426 const vk::DeviceDriver vkd (vkp, instance, *device);
1427 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1429 TestLog& log = context.getTestContext().getLog();
1430 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1431 const vk::Unique<vk::VkSemaphore> semaphoreB (createExportableSemaphore(vkd, *device, config.externalType));
1434 NativeHandle fd, secondFd;
1436 if (transference == TRANSFERENCE_COPY)
1438 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, fd);
1439 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreB, config.externalType, secondFd);
1443 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, fd);
1444 getSemaphoreNative(vkd, *device, *semaphoreB, config.externalType, secondFd);
1447 int newFd (dup2(fd.getFd(), secondFd.getFd()));
1450 log << TestLog::Message << "dup2() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
1452 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup2() for fences fd");
1455 const vk::Unique<vk::VkSemaphore> semaphoreC (createAndImportSemaphore(vkd, *device, config.externalType, secondFd, flags));
1457 if (transference == TRANSFERENCE_COPY)
1458 submitDummyWait(vkd, queue, *semaphoreC);
1459 else if (transference == TRANSFERENCE_REFERENCE)
1461 submitDummySignal(vkd, queue, *semaphoreA);
1462 submitDummyWait(vkd, queue, *semaphoreC);
1465 DE_FATAL("Unknown permanence.");
1467 VK_CHECK(vkd.queueWaitIdle(queue));
1471 return tcu::TestStatus::pass("Pass");
1476 TCU_THROW(NotSupportedError, "Platform doesn't support dup2()");
1480 tcu::TestStatus testSemaphoreFdDup3 (Context& context,
1481 const SemaphoreTestConfig config)
1483 #if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
1484 const Transference transference (getHandelTypeTransferences(config.externalType));
1485 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1486 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1487 const vk::InstanceDriver& vki (instance.getDriver());
1488 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1489 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1491 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1494 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1495 const vk::DeviceDriver vkd (vkp, instance, *device);
1496 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1498 TestLog& log = context.getTestContext().getLog();
1499 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1500 const vk::Unique<vk::VkSemaphore> semaphoreB (createExportableSemaphore(vkd, *device, config.externalType));
1503 NativeHandle fd, secondFd;
1505 if (transference == TRANSFERENCE_COPY)
1507 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreA, config.externalType, fd);
1508 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphoreB, config.externalType, secondFd);
1512 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, fd);
1513 getSemaphoreNative(vkd, *device, *semaphoreB, config.externalType, secondFd);
1516 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1517 const int newFd (dup3(fd.getFd(), secondFd.getFd(), 0));
1520 log << TestLog::Message << "dup3() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
1522 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup3() for fences fd");
1525 const vk::Unique<vk::VkSemaphore> semaphoreC (createAndImportSemaphore(vkd, *device, config.externalType, secondFd, flags));
1527 if (transference == TRANSFERENCE_COPY)
1528 submitDummyWait(vkd, queue, *semaphoreC);
1529 else if (transference == TRANSFERENCE_REFERENCE)
1531 submitDummySignal(vkd, queue, *semaphoreA);
1532 submitDummyWait(vkd, queue, *semaphoreC);
1535 DE_FATAL("Unknown permanence.");
1537 VK_CHECK(vkd.queueWaitIdle(queue));
1541 return tcu::TestStatus::pass("Pass");
1546 TCU_THROW(NotSupportedError, "Platform doesn't support dup3()");
1550 tcu::TestStatus testSemaphoreFdSendOverSocket (Context& context,
1551 const SemaphoreTestConfig config)
1553 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
1554 const Transference transference (getHandelTypeTransferences(config.externalType));
1555 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1556 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1557 const vk::InstanceDriver& vki (instance.getDriver());
1558 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1559 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1561 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1564 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1565 const vk::DeviceDriver vkd (vkp, instance, *device);
1566 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1568 TestLog& log = context.getTestContext().getLog();
1569 const vk::Unique<vk::VkSemaphore> semaphore (createExportableSemaphore(vkd, *device, config.externalType));
1572 if (transference == TRANSFERENCE_COPY)
1573 submitDummySignalAndGetSemaphoreNative(vkd, *device, queue, queueFamilyIndex, *semaphore, config.externalType, fd);
1575 getSemaphoreNative(vkd, *device, *semaphore, config.externalType, fd);
1580 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
1582 log << TestLog::Message << "Failed to create socket pair: '" << strerror(errno) << "'" << TestLog::EndMessage;
1583 TCU_FAIL("Failed to create socket pair");
1587 const NativeHandle srcSocket (sv[0]);
1588 const NativeHandle dstSocket (sv[1]);
1589 std::string sendData ("deqp");
1593 const int fdRaw (fd.getFd());
1596 char buffer[CMSG_SPACE(sizeof(int))];
1597 iovec iov = { &sendData[0], sendData.length()};
1599 deMemset(&msg, 0, sizeof(msg));
1601 msg.msg_control = buffer;
1602 msg.msg_controllen = sizeof(buffer);
1606 cmsg = CMSG_FIRSTHDR(&msg);
1607 cmsg->cmsg_level = SOL_SOCKET;
1608 cmsg->cmsg_type = SCM_RIGHTS;
1609 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
1611 deMemcpy(CMSG_DATA(cmsg), &fdRaw, sizeof(int));
1612 msg.msg_controllen = cmsg->cmsg_len;
1614 if (sendmsg(srcSocket.getFd(), &msg, 0) < 0)
1616 log << TestLog::Message << "Failed to send fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
1617 TCU_FAIL("Failed to send fd over socket");
1624 char buffer[CMSG_SPACE(sizeof(int))];
1625 std::string recvData (4, '\0');
1626 iovec iov = { &recvData[0], recvData.length() };
1628 deMemset(&msg, 0, sizeof(msg));
1630 msg.msg_control = buffer;
1631 msg.msg_controllen = sizeof(buffer);
1635 const ssize_t bytes = recvmsg(dstSocket.getFd(), &msg, 0);
1639 log << TestLog::Message << "Failed to recv fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
1640 TCU_FAIL("Failed to recv fd over socket");
1643 else if (bytes != (ssize_t)sendData.length())
1645 TCU_FAIL("recvmsg() returned unpexpected number of bytes");
1649 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1650 const cmsghdr* const cmsg = CMSG_FIRSTHDR(&msg);
1652 deMemcpy(&newFd_, CMSG_DATA(cmsg), sizeof(int));
1653 NativeHandle newFd (newFd_);
1655 TCU_CHECK(cmsg->cmsg_level == SOL_SOCKET);
1656 TCU_CHECK(cmsg->cmsg_type == SCM_RIGHTS);
1657 TCU_CHECK(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
1658 TCU_CHECK(recvData == sendData);
1659 TCU_CHECK_MSG(newFd.getFd() >= 0, "Didn't receive valid fd from socket");
1662 const vk::Unique<vk::VkSemaphore> newSemaphore (createAndImportSemaphore(vkd, *device, config.externalType, newFd, flags));
1664 if (transference == TRANSFERENCE_COPY)
1665 submitDummyWait(vkd, queue, *newSemaphore);
1666 else if (transference == TRANSFERENCE_REFERENCE)
1668 submitDummySignal(vkd, queue, *newSemaphore);
1669 submitDummyWait(vkd, queue, *newSemaphore);
1672 DE_FATAL("Unknown permanence.");
1674 VK_CHECK(vkd.queueWaitIdle(queue));
1682 return tcu::TestStatus::pass("Pass");
1686 TCU_THROW(NotSupportedError, "Platform doesn't support sending file descriptors over socket");
1690 tcu::TestStatus testFenceQueries (Context& context, vk::VkExternalFenceHandleTypeFlagBits externalType)
1692 const CustomInstance instance (createTestInstance(context, 0u, 0u, externalType));
1693 const vk::InstanceDriver& vki (instance.getDriver());
1694 const vk::VkPhysicalDevice device (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1696 TestLog& log = context.getTestContext().getLog();
1698 const vk::VkPhysicalDeviceExternalFenceInfo info =
1700 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO,
1704 vk::VkExternalFenceProperties properties =
1706 vk::VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES,
1713 vki.getPhysicalDeviceExternalFenceProperties(device, &info, &properties);
1714 log << TestLog::Message << properties << TestLog::EndMessage;
1716 TCU_CHECK(properties.pNext == DE_NULL);
1717 TCU_CHECK(properties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES);
1719 return tcu::TestStatus::pass("Pass");
1722 struct FenceTestConfig
1724 FenceTestConfig (vk::VkExternalFenceHandleTypeFlagBits externalType_,
1725 Permanence permanence_)
1726 : externalType (externalType_)
1727 , permanence (permanence_)
1731 vk::VkExternalFenceHandleTypeFlagBits externalType;
1732 Permanence permanence;
1736 tcu::TestStatus testFenceWin32Create (Context& context,
1737 const FenceTestConfig config)
1739 #if (DE_OS == DE_OS_WIN32)
1740 const Transference transference (getHandelTypeTransferences(config.externalType));
1741 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1742 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
1743 const vk::InstanceDriver& vki (instance.getDriver());
1744 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1745 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1747 checkFenceSupport(vki, physicalDevice, config.externalType);
1750 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1751 const vk::DeviceDriver vkd (vkp, instance, *device);
1752 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1753 const vk::VkExportFenceWin32HandleInfoKHR win32ExportInfo =
1755 vk::VK_STRUCTURE_TYPE_EXPORT_FENCE_WIN32_HANDLE_INFO_KHR,
1758 (vk::pt::Win32SecurityAttributesPtr)DE_NULL,
1759 DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
1760 (vk::pt::Win32LPCWSTR)DE_NULL
1762 const vk::VkExportFenceCreateInfo exportCreateInfo=
1764 vk::VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO,
1766 (vk::VkExternalFenceHandleTypeFlags)config.externalType
1768 const vk::VkFenceCreateInfo createInfo =
1770 vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
1774 const vk::Unique<vk::VkFence> fence (vk::createFence(vkd, *device, &createInfo));
1776 if (transference == TRANSFERENCE_COPY)
1777 submitDummySignal(vkd, queue, *fence);
1779 NativeHandle handleA;
1780 getFenceNative(vkd, *device, *fence, config.externalType, handleA);
1783 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
1784 const vk::Unique<vk::VkFence> fenceA (createAndImportFence(vkd, *device, config.externalType, handleA, flags));
1786 if (transference == TRANSFERENCE_COPY)
1787 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
1788 else if (transference == TRANSFERENCE_REFERENCE)
1790 submitDummySignal(vkd, queue, *fence);
1791 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
1794 DE_FATAL("Unknown transference.");
1796 VK_CHECK(vkd.queueWaitIdle(queue));
1799 return tcu::TestStatus::pass("Pass");
1804 TCU_THROW(NotSupportedError, "Platform doesn't support win32 handles");
1808 tcu::TestStatus testFenceImportTwice (Context& context,
1809 const FenceTestConfig config)
1811 const Transference transference (getHandelTypeTransferences(config.externalType));
1812 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1813 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
1814 const vk::InstanceDriver& vki (instance.getDriver());
1815 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1816 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1818 checkFenceSupport(vki, physicalDevice, config.externalType);
1821 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1822 const vk::DeviceDriver vkd (vkp, instance, *device);
1823 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1824 const vk::Unique<vk::VkFence> fence (createExportableFence(vkd, *device, config.externalType));
1825 NativeHandle handleA;
1827 if (transference == TRANSFERENCE_COPY)
1828 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fence, config.externalType, handleA);
1830 getFenceNative(vkd, *device, *fence, config.externalType, handleA);
1833 NativeHandle handleB (handleA);
1834 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
1835 const vk::Unique<vk::VkFence> fenceA (createAndImportFence(vkd, *device, config.externalType, handleA, flags));
1836 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handleB, flags));
1838 if (transference == TRANSFERENCE_COPY)
1839 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
1840 else if (transference == TRANSFERENCE_REFERENCE)
1842 submitDummySignal(vkd, queue, *fenceA);
1843 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1846 DE_FATAL("Unknown transference.");
1848 VK_CHECK(vkd.queueWaitIdle(queue));
1851 return tcu::TestStatus::pass("Pass");
1855 tcu::TestStatus testFenceImportReimport (Context& context,
1856 const FenceTestConfig config)
1858 const Transference transference (getHandelTypeTransferences(config.externalType));
1859 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1860 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
1861 const vk::InstanceDriver& vki (instance.getDriver());
1862 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1863 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1865 checkFenceSupport(vki, physicalDevice, config.externalType);
1868 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1869 const vk::DeviceDriver vkd (vkp, instance, *device);
1870 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1872 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
1873 NativeHandle handleA;
1875 if (transference == TRANSFERENCE_COPY)
1876 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handleA);
1878 getFenceNative(vkd, *device, *fenceA, config.externalType, handleA);
1880 NativeHandle handleB (handleA);
1881 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
1882 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handleA, flags));
1884 importFence(vkd, *device, *fenceB, config.externalType, handleB, flags);
1886 if (transference == TRANSFERENCE_COPY)
1887 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1888 else if (transference == TRANSFERENCE_REFERENCE)
1890 submitDummySignal(vkd, queue, *fenceA);
1891 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1894 DE_FATAL("Unknown transference.");
1896 VK_CHECK(vkd.queueWaitIdle(queue));
1898 return tcu::TestStatus::pass("Pass");
1902 tcu::TestStatus testFenceSignalExportImportWait (Context& context,
1903 const FenceTestConfig config)
1905 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1906 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
1907 const vk::InstanceDriver& vki (instance.getDriver());
1908 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1909 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1911 checkFenceSupport(vki, physicalDevice, config.externalType);
1914 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1915 const vk::DeviceDriver vkd (vkp, instance, *device);
1916 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1917 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
1920 NativeHandle handle;
1922 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
1925 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
1926 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handle, flags));
1927 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1929 VK_CHECK(vkd.queueWaitIdle(queue));
1933 return tcu::TestStatus::pass("Pass");
1937 tcu::TestStatus testFenceExportSignalImportWait (Context& context,
1938 const FenceTestConfig config)
1940 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1941 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
1942 const vk::InstanceDriver& vki (instance.getDriver());
1943 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1944 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1945 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
1947 DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
1948 checkFenceSupport(vki, physicalDevice, config.externalType);
1951 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1952 const vk::DeviceDriver vkd (vkp, instance, *device);
1953 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1955 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
1956 NativeHandle handle;
1958 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
1960 submitDummySignal(vkd, queue, *fenceA);
1963 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handle, flags));
1965 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
1966 VK_CHECK(vkd.queueWaitIdle(queue));
1970 return tcu::TestStatus::pass("Pass");
1974 tcu::TestStatus testFenceExportImportSignalWait (Context& context,
1975 const FenceTestConfig config)
1977 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1978 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
1979 const vk::InstanceDriver& vki (instance.getDriver());
1980 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1981 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1983 DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
1984 checkFenceSupport(vki, physicalDevice, config.externalType);
1987 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
1988 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
1989 const vk::DeviceDriver vkd (vkp, instance, *device);
1990 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1992 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
1993 NativeHandle handle;
1995 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
1997 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handle, flags));
1999 submitDummySignal(vkd, queue, *fenceA);
2000 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2002 VK_CHECK(vkd.queueWaitIdle(queue));
2004 return tcu::TestStatus::pass("Pass");
2008 tcu::TestStatus testFenceSignalImport (Context& context,
2009 const FenceTestConfig config)
2011 const Transference transference (getHandelTypeTransferences(config.externalType));
2012 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2013 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2014 const vk::InstanceDriver& vki (instance.getDriver());
2015 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2016 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2018 checkFenceSupport(vki, physicalDevice, config.externalType);
2021 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2022 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2023 const vk::DeviceDriver vkd (vkp, instance, *device);
2024 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2026 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2027 const vk::Unique<vk::VkFence> fenceB (createFence(vkd, *device));
2028 NativeHandle handle;
2030 submitDummySignal(vkd, queue, *fenceB);
2031 VK_CHECK(vkd.queueWaitIdle(queue));
2033 if (transference == TRANSFERENCE_COPY)
2034 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2036 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2038 importFence(vkd, *device, *fenceB, config.externalType, handle, flags);
2040 if (transference == TRANSFERENCE_COPY)
2041 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2042 else if (transference == TRANSFERENCE_REFERENCE)
2044 submitDummySignal(vkd, queue, *fenceA);
2045 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2048 DE_FATAL("Unknown transference.");
2050 VK_CHECK(vkd.queueWaitIdle(queue));
2052 return tcu::TestStatus::pass("Pass");
2056 tcu::TestStatus testFenceReset (Context& context,
2057 const FenceTestConfig config)
2059 const Transference transference (getHandelTypeTransferences(config.externalType));
2060 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2061 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2062 const vk::InstanceDriver& vki (instance.getDriver());
2063 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2064 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2066 checkFenceSupport(vki, physicalDevice, config.externalType);
2069 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2070 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2071 const vk::DeviceDriver vkd (vkp, instance, *device);
2072 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2074 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2075 const vk::Unique<vk::VkFence> fenceB (createFence(vkd, *device));
2076 const vk::Unique<vk::VkFence> fenceC (createFence(vkd, *device));
2077 NativeHandle handle;
2079 submitDummySignal(vkd, queue, *fenceB);
2080 VK_CHECK(vkd.queueWaitIdle(queue));
2082 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2083 NativeHandle handleB (handle);
2084 importFence(vkd, *device, *fenceB, config.externalType, handleB, flags);
2085 importFence(vkd, *device, *fenceC, config.externalType, handle, flags);
2087 VK_CHECK(vkd.queueWaitIdle(queue));
2088 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2090 if (config.permanence == PERMANENCE_TEMPORARY || transference == TRANSFERENCE_COPY)
2092 // vkResetFences() should restore fenceBs prior payload and reset that no affecting fenceCs payload
2093 // or fenceB should be separate copy of the payload and not affect fenceC
2094 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2096 // vkResetFences() should have restored fenceBs prior state and should be now reset
2097 // or fenceB should have it's separate payload
2098 submitDummySignal(vkd, queue, *fenceB);
2099 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2101 else if (config.permanence == PERMANENCE_PERMANENT)
2103 DE_ASSERT(transference == TRANSFERENCE_REFERENCE);
2105 // Reset fences should have reset all of the fences
2106 submitDummySignal(vkd, queue, *fenceC);
2108 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2109 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2110 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2113 DE_FATAL("Unknown permanence");
2115 VK_CHECK(vkd.queueWaitIdle(queue));
2117 return tcu::TestStatus::pass("Pass");
2121 tcu::TestStatus testFenceSignalWaitImport (Context& context,
2122 const FenceTestConfig config)
2124 const Transference transference (getHandelTypeTransferences(config.externalType));
2125 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2126 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2127 const vk::InstanceDriver& vki (instance.getDriver());
2128 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2129 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2131 checkFenceSupport(vki, physicalDevice, config.externalType);
2134 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2135 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2136 const vk::DeviceDriver vkd (vkp, instance, *device);
2137 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2139 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2140 const vk::Unique<vk::VkFence> fenceB (createFence(vkd, *device));
2141 NativeHandle handle;
2143 if (transference == TRANSFERENCE_COPY)
2144 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2146 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2148 submitDummySignal(vkd, queue, *fenceB);
2149 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2151 VK_CHECK(vkd.queueWaitIdle(queue));
2153 importFence(vkd, *device, *fenceB, config.externalType, handle, flags);
2155 if (transference == TRANSFERENCE_COPY)
2156 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2157 else if (transference == TRANSFERENCE_REFERENCE)
2159 submitDummySignal(vkd, queue, *fenceA);
2160 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2163 DE_FATAL("Unknown transference.");
2165 VK_CHECK(vkd.queueWaitIdle(queue));
2167 return tcu::TestStatus::pass("Pass");
2171 tcu::TestStatus testFenceMultipleExports (Context& context,
2172 const FenceTestConfig config)
2174 const size_t exportCount = 4 * 1024;
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::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2186 const vk::DeviceDriver vkd (vkp, instance, *device);
2187 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2188 const vk::Unique<vk::VkFence> fence (createExportableFence(vkd, *device, config.externalType));
2190 for (size_t exportNdx = 0; exportNdx < exportCount; exportNdx++)
2192 NativeHandle handle;
2194 if (transference == TRANSFERENCE_COPY)
2195 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fence, config.externalType, handle, exportNdx == 0 /* expect fence to be signaled after first pass */);
2197 getFenceNative(vkd, *device, *fence, config.externalType, handle, exportNdx == 0 /* expect fence to be signaled after first pass */);
2200 submitDummySignal(vkd, queue, *fence);
2201 VK_CHECK(vkd.waitForFences(*device, 1u, &*fence, VK_TRUE, ~0ull));
2203 VK_CHECK(vkd.queueWaitIdle(queue));
2206 return tcu::TestStatus::pass("Pass");
2209 tcu::TestStatus testFenceMultipleImports (Context& context,
2210 const FenceTestConfig config)
2212 const size_t importCount = 4 * 1024;
2213 const Transference transference (getHandelTypeTransferences(config.externalType));
2214 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2215 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2216 const vk::InstanceDriver& vki (instance.getDriver());
2217 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2218 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2220 checkFenceSupport(vki, physicalDevice, config.externalType);
2223 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2224 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2225 const vk::DeviceDriver vkd (vkp, instance, *device);
2226 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2227 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2228 NativeHandle handleA;
2230 if (transference == TRANSFERENCE_COPY)
2231 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handleA);
2233 getFenceNative(vkd, *device, *fenceA, config.externalType, handleA);
2235 for (size_t importNdx = 0; importNdx < importCount; importNdx++)
2237 NativeHandle handleB (handleA);
2238 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handleB, flags));
2241 if (transference == TRANSFERENCE_COPY)
2243 importFence(vkd, *device, *fenceA, config.externalType, handleA, flags);
2244 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2246 else if (transference == TRANSFERENCE_REFERENCE)
2248 submitDummySignal(vkd, queue, *fenceA);
2249 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2252 DE_FATAL("Unknown transference.");
2254 VK_CHECK(vkd.queueWaitIdle(queue));
2257 return tcu::TestStatus::pass("Pass");
2260 tcu::TestStatus testFenceTransference (Context& context,
2261 const FenceTestConfig config)
2263 const Transference transference (getHandelTypeTransferences(config.externalType));
2264 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2265 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2266 const vk::InstanceDriver& vki (instance.getDriver());
2267 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2268 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2270 checkFenceSupport(vki, physicalDevice, config.externalType);
2273 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2274 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2275 const vk::DeviceDriver vkd (vkp, instance, *device);
2276 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2278 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2279 NativeHandle handle;
2281 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2284 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handle, flags));
2286 if (config.permanence == PERMANENCE_PERMANENT)
2288 if (transference == TRANSFERENCE_COPY)
2290 submitDummySignal(vkd, queue, *fenceA);
2291 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2292 VK_CHECK(vkd.queueWaitIdle(queue));
2294 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2295 submitDummySignal(vkd, queue, *fenceB);
2297 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2298 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2299 VK_CHECK(vkd.queueWaitIdle(queue));
2301 else if (transference== TRANSFERENCE_REFERENCE)
2303 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2304 VK_CHECK(vkd.queueWaitIdle(queue));
2306 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2307 submitDummySignal(vkd, queue, *fenceA);
2308 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2310 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceA));
2311 submitDummySignal(vkd, queue, *fenceB);
2312 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2313 VK_CHECK(vkd.queueWaitIdle(queue));
2316 DE_FATAL("Unknown transference.");
2318 else if (config.permanence == PERMANENCE_TEMPORARY)
2320 if (transference == TRANSFERENCE_COPY)
2322 submitDummySignal(vkd, queue, *fenceA);
2323 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2324 VK_CHECK(vkd.queueWaitIdle(queue));
2326 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2327 submitDummySignal(vkd, queue, *fenceB);
2329 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2330 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2331 VK_CHECK(vkd.queueWaitIdle(queue));
2333 else if (transference == TRANSFERENCE_REFERENCE)
2335 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2336 VK_CHECK(vkd.queueWaitIdle(queue));
2338 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceA));
2339 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2340 submitDummySignal(vkd, queue, *fenceA);
2341 submitDummySignal(vkd, queue, *fenceB);
2343 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2344 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2345 VK_CHECK(vkd.queueWaitIdle(queue));
2348 DE_FATAL("Unknown transference.");
2351 DE_FATAL("Unknown permanence.");
2354 return tcu::TestStatus::pass("Pass");
2358 tcu::TestStatus testFenceFdDup (Context& context,
2359 const FenceTestConfig config)
2361 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2362 const Transference transference (getHandelTypeTransferences(config.externalType));
2363 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2364 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2365 const vk::InstanceDriver& vki (instance.getDriver());
2366 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2367 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2369 checkFenceSupport(vki, physicalDevice, config.externalType);
2372 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2373 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2374 const vk::DeviceDriver vkd (vkp, instance, *device);
2375 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2377 TestLog& log = context.getTestContext().getLog();
2378 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2383 if (transference == TRANSFERENCE_COPY)
2384 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, fd);
2386 getFenceNative(vkd, *device, *fenceA, config.externalType, fd);
2388 NativeHandle newFd (dup(fd.getFd()));
2390 if (newFd.getFd() < 0)
2391 log << TestLog::Message << "dup() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2393 TCU_CHECK_MSG(newFd.getFd() >= 0, "Failed to call dup() for fences fd");
2396 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, newFd, flags));
2398 if (transference == TRANSFERENCE_COPY)
2399 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2400 else if (transference == TRANSFERENCE_REFERENCE)
2402 submitDummySignal(vkd, queue, *fenceA);
2403 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2406 DE_FATAL("Unknown permanence.");
2408 VK_CHECK(vkd.queueWaitIdle(queue));
2412 return tcu::TestStatus::pass("Pass");
2417 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
2421 tcu::TestStatus testFenceFdDup2 (Context& context,
2422 const FenceTestConfig config)
2424 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2425 const Transference transference (getHandelTypeTransferences(config.externalType));
2426 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2427 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2428 const vk::InstanceDriver& vki (instance.getDriver());
2429 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2430 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2432 checkFenceSupport(vki, physicalDevice, config.externalType);
2435 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2436 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2437 const vk::DeviceDriver vkd (vkp, instance, *device);
2438 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2440 TestLog& log = context.getTestContext().getLog();
2441 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2442 const vk::Unique<vk::VkFence> fenceB (createExportableFence(vkd, *device, config.externalType));
2445 NativeHandle fd, secondFd;
2447 if (transference == TRANSFERENCE_COPY)
2449 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, fd);
2450 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceB, config.externalType, secondFd);
2454 getFenceNative(vkd, *device, *fenceA, config.externalType, fd);
2455 getFenceNative(vkd, *device, *fenceB, config.externalType, secondFd);
2458 int newFd (dup2(fd.getFd(), secondFd.getFd()));
2461 log << TestLog::Message << "dup2() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2463 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup2() for fences fd");
2466 const vk::Unique<vk::VkFence> fenceC (createAndImportFence(vkd, *device, config.externalType, secondFd, flags));
2468 if (transference == TRANSFERENCE_COPY)
2469 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2470 else if (transference == TRANSFERENCE_REFERENCE)
2472 submitDummySignal(vkd, queue, *fenceA);
2473 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2476 DE_FATAL("Unknown permanence.");
2478 VK_CHECK(vkd.queueWaitIdle(queue));
2482 return tcu::TestStatus::pass("Pass");
2487 TCU_THROW(NotSupportedError, "Platform doesn't support dup2()");
2491 tcu::TestStatus testFenceFdDup3 (Context& context,
2492 const FenceTestConfig config)
2494 #if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
2495 const Transference transference (getHandelTypeTransferences(config.externalType));
2496 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2497 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2498 const vk::InstanceDriver& vki (instance.getDriver());
2499 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2500 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2502 checkFenceSupport(vki, physicalDevice, config.externalType);
2505 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2506 const vk::DeviceDriver vkd (vkp, instance, *device);
2507 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2509 TestLog& log = context.getTestContext().getLog();
2510 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2511 const vk::Unique<vk::VkFence> fenceB (createExportableFence(vkd, *device, config.externalType));
2514 NativeHandle fd, secondFd;
2516 if (transference == TRANSFERENCE_COPY)
2518 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceA, config.externalType, fd);
2519 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fenceB, config.externalType, secondFd);
2523 getFenceNative(vkd, *device, *fenceA, config.externalType, fd);
2524 getFenceNative(vkd, *device, *fenceB, config.externalType, secondFd);
2527 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2528 const int newFd (dup3(fd.getFd(), secondFd.getFd(), 0));
2531 log << TestLog::Message << "dup3() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2533 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup3() for fences fd");
2536 const vk::Unique<vk::VkFence> fenceC (createAndImportFence(vkd, *device, config.externalType, secondFd, flags));
2538 if (transference == TRANSFERENCE_COPY)
2539 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2540 else if (transference == TRANSFERENCE_REFERENCE)
2542 submitDummySignal(vkd, queue, *fenceA);
2543 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2546 DE_FATAL("Unknown permanence.");
2548 VK_CHECK(vkd.queueWaitIdle(queue));
2552 return tcu::TestStatus::pass("Pass");
2557 TCU_THROW(NotSupportedError, "Platform doesn't support dup3()");
2561 tcu::TestStatus testFenceFdSendOverSocket (Context& context,
2562 const FenceTestConfig config)
2564 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2565 const Transference transference (getHandelTypeTransferences(config.externalType));
2566 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2567 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2568 const vk::InstanceDriver& vki (instance.getDriver());
2569 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2570 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2572 checkFenceSupport(vki, physicalDevice, config.externalType);
2575 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2576 const vk::DeviceDriver vkd (vkp, instance, *device);
2577 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2579 TestLog& log = context.getTestContext().getLog();
2580 const vk::Unique<vk::VkFence> fence (createExportableFence(vkd, *device, config.externalType));
2583 if (transference == TRANSFERENCE_COPY)
2584 submitDummySignalAndGetFenceNative(vkd, *device, queue, queueFamilyIndex, *fence, config.externalType, fd);
2586 getFenceNative(vkd, *device, *fence, config.externalType, fd);
2591 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
2593 log << TestLog::Message << "Failed to create socket pair: '" << strerror(errno) << "'" << TestLog::EndMessage;
2594 TCU_FAIL("Failed to create socket pair");
2598 const NativeHandle srcSocket (sv[0]);
2599 const NativeHandle dstSocket (sv[1]);
2600 std::string sendData ("deqp");
2604 const int fdRaw (fd.getFd());
2607 char buffer[CMSG_SPACE(sizeof(int))];
2608 iovec iov = { &sendData[0], sendData.length()};
2610 deMemset(&msg, 0, sizeof(msg));
2612 msg.msg_control = buffer;
2613 msg.msg_controllen = sizeof(buffer);
2617 cmsg = CMSG_FIRSTHDR(&msg);
2618 cmsg->cmsg_level = SOL_SOCKET;
2619 cmsg->cmsg_type = SCM_RIGHTS;
2620 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
2622 deMemcpy(CMSG_DATA(cmsg), &fdRaw, sizeof(int));
2623 msg.msg_controllen = cmsg->cmsg_len;
2625 if (sendmsg(srcSocket.getFd(), &msg, 0) < 0)
2627 log << TestLog::Message << "Failed to send fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
2628 TCU_FAIL("Failed to send fd over socket");
2635 char buffer[CMSG_SPACE(sizeof(int))];
2636 std::string recvData (4, '\0');
2637 iovec iov = { &recvData[0], recvData.length() };
2639 deMemset(&msg, 0, sizeof(msg));
2641 msg.msg_control = buffer;
2642 msg.msg_controllen = sizeof(buffer);
2646 const ssize_t bytes = recvmsg(dstSocket.getFd(), &msg, 0);
2650 log << TestLog::Message << "Failed to recv fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
2651 TCU_FAIL("Failed to recv fd over socket");
2654 else if (bytes != (ssize_t)sendData.length())
2656 TCU_FAIL("recvmsg() returned unpexpected number of bytes");
2660 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2661 const cmsghdr* const cmsg = CMSG_FIRSTHDR(&msg);
2663 deMemcpy(&newFd_, CMSG_DATA(cmsg), sizeof(int));
2664 NativeHandle newFd (newFd_);
2666 TCU_CHECK(cmsg->cmsg_level == SOL_SOCKET);
2667 TCU_CHECK(cmsg->cmsg_type == SCM_RIGHTS);
2668 TCU_CHECK(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
2669 TCU_CHECK(recvData == sendData);
2670 TCU_CHECK_MSG(newFd.getFd() >= 0, "Didn't receive valid fd from socket");
2673 const vk::Unique<vk::VkFence> newFence (createAndImportFence(vkd, *device, config.externalType, newFd, flags));
2675 if (transference == TRANSFERENCE_COPY)
2676 VK_CHECK(vkd.waitForFences(*device, 1u, &*newFence, VK_TRUE, ~0ull));
2677 else if (transference == TRANSFERENCE_REFERENCE)
2679 submitDummySignal(vkd, queue, *newFence);
2680 VK_CHECK(vkd.waitForFences(*device, 1u, &*newFence, VK_TRUE, ~0ull));
2683 DE_FATAL("Unknown permanence.");
2685 VK_CHECK(vkd.queueWaitIdle(queue));
2693 return tcu::TestStatus::pass("Pass");
2697 TCU_THROW(NotSupportedError, "Platform doesn't support sending file descriptors over socket");
2701 tcu::TestStatus testBufferQueries (Context& context, vk::VkExternalMemoryHandleTypeFlagBits externalType)
2703 const vk::VkBufferCreateFlags createFlags[] =
2706 vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT,
2707 vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT|vk::VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT,
2708 vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT|vk::VK_BUFFER_CREATE_SPARSE_ALIASED_BIT
2710 const vk::VkBufferUsageFlags usageFlags[] =
2712 vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
2713 vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT,
2714 vk::VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT,
2715 vk::VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT,
2716 vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
2717 vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
2718 vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
2719 vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
2720 vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT
2722 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2723 const CustomInstance instance (createTestInstance(context, 0u, externalType, 0u));
2724 const vk::InstanceDriver& vki (instance.getDriver());
2725 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2726 const vk::VkPhysicalDeviceFeatures deviceFeatures (vk::getPhysicalDeviceFeatures(vki, physicalDevice));
2727 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2729 // VkDevice is only created if physical device claims to support any of these types.
2730 vk::Move<vk::VkDevice> device;
2731 de::MovePtr<vk::DeviceDriver> vkd;
2732 bool deviceHasDedicated = false;
2734 TestLog& log = context.getTestContext().getLog();
2736 for (size_t createFlagNdx = 0; createFlagNdx < DE_LENGTH_OF_ARRAY(createFlags); createFlagNdx++)
2737 for (size_t usageFlagNdx = 0; usageFlagNdx < DE_LENGTH_OF_ARRAY(usageFlags); usageFlagNdx++)
2739 const vk::VkBufferViewCreateFlags createFlag = createFlags[createFlagNdx];
2740 const vk::VkBufferUsageFlags usageFlag = usageFlags[usageFlagNdx];
2741 const vk::VkPhysicalDeviceExternalBufferInfo info =
2743 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO,
2749 vk::VkExternalBufferProperties properties =
2751 vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES,
2756 if (((createFlag & vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT) != 0) &&
2757 (deviceFeatures.sparseBinding == VK_FALSE))
2760 if (((createFlag & vk::VK_BUFFER_CREATE_SPARSE_ALIASED_BIT) != 0) &&
2761 (deviceFeatures.sparseResidencyAliased == VK_FALSE))
2764 if (((createFlag & vk::VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT) != 0) &&
2765 (deviceFeatures.sparseResidencyBuffer == VK_FALSE))
2768 vki.getPhysicalDeviceExternalBufferProperties(physicalDevice, &info, &properties);
2770 log << TestLog::Message << properties << TestLog::EndMessage;
2772 TCU_CHECK(properties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES);
2773 TCU_CHECK(properties.pNext == DE_NULL);
2774 // \todo [2017-06-06 pyry] Can we validate anything else? Compatible types?
2776 if ((properties.externalMemoryProperties.externalMemoryFeatures & (vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT|vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT)) != 0)
2778 const bool requiresDedicated = (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
2780 if (!device || (requiresDedicated && !deviceHasDedicated))
2782 // \note We need to re-create with dedicated mem extensions if previous device instance didn't have them
2785 device = createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, externalType, 0u, queueFamilyIndex, requiresDedicated);
2786 vkd = de::MovePtr<vk::DeviceDriver>(new vk::DeviceDriver(vkp, instance, *device));
2787 deviceHasDedicated = requiresDedicated;
2789 catch (const tcu::NotSupportedError& e)
2792 TCU_FAIL("Physical device claims to support handle type but required extensions are not supported");
2797 if ((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) != 0)
2799 DE_ASSERT(!!device);
2802 if (deviceHasDedicated)
2804 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(*vkd, *device, queueFamilyIndex, externalType, 1024u, createFlag, usageFlag));
2805 const vk::VkMemoryDedicatedRequirements reqs (getMemoryDedicatedRequirements(*vkd, *device, *buffer));
2806 const bool propertiesRequiresDedicated = (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
2807 const bool objectRequiresDedicated = (reqs.requiresDedicatedAllocation != VK_FALSE);
2809 if (propertiesRequiresDedicated != objectRequiresDedicated)
2810 TCU_FAIL("vkGetPhysicalDeviceExternalBufferProperties and vkGetBufferMemoryRequirements2 report different dedicated requirements");
2814 // We can't query whether dedicated memory is required or not on per-object basis.
2815 // This check should be redundant as the code above tries to create device with
2816 // VK_KHR_dedicated_allocation & VK_KHR_get_memory_requirements2 if dedicated memory
2817 // is required. However, checking again doesn't hurt.
2818 TCU_CHECK((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) == 0);
2823 return tcu::TestStatus::pass("Pass");
2826 struct MemoryTestConfig
2828 MemoryTestConfig (vk::VkExternalMemoryHandleTypeFlagBits externalType_,
2831 : externalType (externalType_)
2832 , hostVisible (hostVisible_)
2833 , dedicated (dedicated_)
2837 vk::VkExternalMemoryHandleTypeFlagBits externalType;
2842 #if (DE_OS == DE_OS_WIN32)
2843 deUint32 chooseWin32MemoryType(deUint32 bits)
2846 TCU_THROW(NotSupportedError, "No compatible memory type found");
2848 return deCtz32(bits);
2852 tcu::TestStatus testMemoryWin32Create (Context& context, MemoryTestConfig config)
2854 #if (DE_OS == DE_OS_WIN32)
2855 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2856 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
2857 const vk::InstanceDriver& vki (instance.getDriver());
2858 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2859 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2860 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
2861 const vk::DeviceDriver vkd (vkp, instance, *device);
2862 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
2863 const deUint32 seed = 1261033864u;
2864 const vk::VkDeviceSize bufferSize = 1024;
2865 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
2867 const vk::VkPhysicalDeviceMemoryProperties memoryProps = vk::getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice());
2868 const deUint32 compatibleMemTypes = vk::getCompatibleMemoryTypes(memoryProps, config.hostVisible ? vk::MemoryRequirement::HostVisible : vk::MemoryRequirement::Any);
2870 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
2872 // \note Buffer is only allocated to get memory requirements
2873 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
2874 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
2875 const vk::VkExportMemoryWin32HandleInfoKHR win32Info =
2877 vk::VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR,
2880 (vk::pt::Win32SecurityAttributesPtr)DE_NULL,
2881 DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
2882 (vk::pt::Win32LPCWSTR)DE_NULL
2884 const vk::VkExportMemoryAllocateInfo exportInfo =
2886 vk::VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
2888 (vk::VkExternalMemoryHandleTypeFlags)config.externalType
2891 const deUint32 exportedMemoryTypeIndex = chooseWin32MemoryType(requirements.memoryTypeBits & compatibleMemTypes);
2892 const vk::VkMemoryAllocateInfo info =
2894 vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
2897 exportedMemoryTypeIndex
2899 const vk::Unique<vk::VkDeviceMemory> memory (vk::allocateMemory(vkd, *device, &info));
2900 NativeHandle handleA;
2902 if (config.hostVisible)
2903 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
2905 getMemoryNative(vkd, *device, *memory, config.externalType, handleA);
2908 const vk::Unique<vk::VkDeviceMemory> memoryA (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleA));
2910 if (config.hostVisible)
2912 const std::vector<deUint8> testDataA (genTestData(seed ^ 124798807u, (size_t)bufferSize));
2913 const std::vector<deUint8> testDataB (genTestData(seed ^ 970834278u, (size_t)bufferSize));
2915 checkHostMemory(vkd, *device, *memoryA, testData.size(), &testData[0]);
2916 checkHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
2918 writeHostMemory(vkd, *device, *memoryA, testDataA.size(), &testDataA[0]);
2919 writeHostMemory(vkd, *device, *memory, testDataA.size(), &testDataB[0]);
2921 checkHostMemory(vkd, *device, *memoryA, testData.size(), &testDataB[0]);
2922 checkHostMemory(vkd, *device, *memory, testData.size(), &testDataB[0]);
2926 return tcu::TestStatus::pass("Pass");
2930 TCU_THROW(NotSupportedError, "Platform doesn't support win32 handles");
2934 deUint32 getExportedMemoryTypeIndex(const vk::InstanceDriver& vki, const vk::VkPhysicalDevice physicalDevice, bool hostVisible, deUint32 memoryBits)
2938 const vk::VkPhysicalDeviceMemoryProperties properties(vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2939 return chooseHostVisibleMemoryType(memoryBits, properties);
2942 return chooseMemoryType(memoryBits);
2945 tcu::TestStatus testMemoryImportTwice (Context& context, MemoryTestConfig config)
2947 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2948 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
2949 const vk::InstanceDriver& vki (instance.getDriver());
2950 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2951 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2952 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
2953 const vk::DeviceDriver vkd (vkp, instance, *device);
2954 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
2955 const deUint32 seed = 1261033864u;
2956 const vk::VkDeviceSize bufferSize = 1024;
2957 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
2959 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
2961 // \note Buffer is only allocated to get memory requirements
2962 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
2963 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
2964 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
2965 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
2966 NativeHandle handleA;
2968 if (config.hostVisible)
2969 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
2971 getMemoryNative(vkd, *device, *memory, config.externalType, handleA);
2974 const vk::Unique<vk::VkBuffer> bufferA (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
2975 const vk::Unique<vk::VkBuffer> bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
2976 NativeHandle handleB (handleA);
2977 const vk::Unique<vk::VkDeviceMemory> memoryA (config.dedicated
2978 ? importDedicatedMemory(vkd, *device, *bufferA, requirements, config.externalType, exportedMemoryTypeIndex, handleA)
2979 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleA));
2980 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
2981 ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handleB)
2982 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleB));
2984 if (config.hostVisible)
2986 const std::vector<deUint8> testDataA (genTestData(seed ^ 124798807u, (size_t)bufferSize));
2987 const std::vector<deUint8> testDataB (genTestData(seed ^ 970834278u, (size_t)bufferSize));
2989 checkHostMemory(vkd, *device, *memoryA, testData.size(), &testData[0]);
2990 checkHostMemory(vkd, *device, *memoryB, testData.size(), &testData[0]);
2992 writeHostMemory(vkd, *device, *memoryA, testData.size(), &testDataA[0]);
2993 writeHostMemory(vkd, *device, *memoryB, testData.size(), &testDataB[0]);
2995 checkHostMemory(vkd, *device, *memoryA, testData.size(), &testDataB[0]);
2996 checkHostMemory(vkd, *device, *memory, testData.size(), &testDataB[0]);
3000 return tcu::TestStatus::pass("Pass");
3003 tcu::TestStatus testMemoryMultipleImports (Context& context, MemoryTestConfig config)
3005 const size_t count = 4 * 1024;
3006 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3007 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3008 const vk::InstanceDriver& vki (instance.getDriver());
3009 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3010 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3011 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3012 const vk::DeviceDriver vkd (vkp, instance, *device);
3013 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3014 const vk::VkDeviceSize bufferSize = 1024;
3016 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3018 // \note Buffer is only allocated to get memory requirements
3019 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3020 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3021 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3022 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3023 NativeHandle handleA;
3025 getMemoryNative(vkd, *device, *memory, config.externalType, handleA);
3027 for (size_t ndx = 0; ndx < count; ndx++)
3029 const vk::Unique<vk::VkBuffer> bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3030 NativeHandle handleB (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));
3036 return tcu::TestStatus::pass("Pass");
3039 tcu::TestStatus testMemoryMultipleExports (Context& context, MemoryTestConfig config)
3041 const size_t count = 4 * 1024;
3042 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3043 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3044 const vk::InstanceDriver& vki (instance.getDriver());
3045 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3046 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3047 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3048 const vk::DeviceDriver vkd (vkp, instance, *device);
3049 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3050 const vk::VkDeviceSize bufferSize = 1024;
3052 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3054 // \note Buffer is only allocated to get memory requirements
3055 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3056 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3057 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3058 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3060 for (size_t ndx = 0; ndx < count; ndx++)
3062 NativeHandle handle;
3063 getMemoryNative(vkd, *device, *memory, config.externalType, handle);
3066 return tcu::TestStatus::pass("Pass");
3069 tcu::TestStatus testMemoryFdProperties (Context& context, MemoryTestConfig config)
3071 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3072 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3073 const vk::InstanceDriver& vki (instance.getDriver());
3074 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3075 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3076 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3077 const vk::DeviceDriver vkd (vkp, instance, *device);
3078 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3079 const vk::VkDeviceSize bufferSize = 1024;
3081 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3083 // \note Buffer is only allocated to get memory requirements
3084 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3085 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3086 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3087 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3089 vk::VkMemoryFdPropertiesKHR properties;
3090 NativeHandle handle;
3092 getMemoryNative(vkd, *device, *memory, config.externalType, handle);
3093 properties.sType = vk::VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR;
3094 vk::VkResult res = vkd.getMemoryFdPropertiesKHR(*device, config.externalType, handle.getFd(), &properties);
3096 switch (config.externalType)
3098 case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
3099 TCU_CHECK_MSG(res == vk::VK_SUCCESS, "vkGetMemoryFdPropertiesKHR failed for VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT");
3102 // Invalid external memory type for this test.
3107 return tcu::TestStatus::pass("Pass");
3110 tcu::TestStatus testMemoryFdDup (Context& context, MemoryTestConfig config)
3112 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
3113 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3114 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3115 const vk::InstanceDriver& vki (instance.getDriver());
3116 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3117 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3120 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3121 const vk::DeviceDriver vkd (vkp, instance, *device);
3123 TestLog& log = context.getTestContext().getLog();
3124 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3125 const vk::VkDeviceSize bufferSize = 1024;
3126 const deUint32 seed = 851493858u;
3127 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
3129 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3131 // \note Buffer is only allocated to get memory requirements
3132 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3133 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3134 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3135 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3137 if (config.hostVisible)
3138 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3140 const NativeHandle fd (getMemoryFd(vkd, *device, *memory, config.externalType));
3141 NativeHandle newFd (dup(fd.getFd()));
3143 if (newFd.getFd() < 0)
3144 log << TestLog::Message << "dup() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
3146 TCU_CHECK_MSG(newFd.getFd() >= 0, "Failed to call dup() for memorys fd");
3149 const vk::Unique<vk::VkBuffer> newBuffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3150 const vk::Unique<vk::VkDeviceMemory> newMemory (config.dedicated
3151 ? importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType, exportedMemoryTypeIndex, newFd)
3152 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, newFd));
3154 if (config.hostVisible)
3156 const std::vector<deUint8> testDataA (genTestData(seed ^ 672929437u, (size_t)bufferSize));
3158 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3160 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3161 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3165 return tcu::TestStatus::pass("Pass");
3170 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
3174 tcu::TestStatus testMemoryFdDup2 (Context& context, MemoryTestConfig config)
3176 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
3177 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3178 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3179 const vk::InstanceDriver& vki (instance.getDriver());
3180 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3181 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3184 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3185 const vk::DeviceDriver vkd (vkp, instance, *device);
3187 TestLog& log = context.getTestContext().getLog();
3188 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3189 const vk::VkDeviceSize bufferSize = 1024;
3190 const deUint32 seed = 224466865u;
3191 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
3193 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3195 // \note Buffer is only allocated to get memory requirements
3196 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3197 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3198 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3199 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3201 if (config.hostVisible)
3202 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3204 const NativeHandle fd (getMemoryFd(vkd, *device, *memory, config.externalType));
3205 NativeHandle secondFd (getMemoryFd(vkd, *device, *memory, config.externalType));
3206 const int newFd (dup2(fd.getFd(), secondFd.getFd()));
3209 log << TestLog::Message << "dup2() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
3211 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup2() for memorys fd");
3214 const vk::Unique<vk::VkBuffer> newBuffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3215 const vk::Unique<vk::VkDeviceMemory> newMemory (config.dedicated
3216 ? importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType, exportedMemoryTypeIndex, secondFd)
3217 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, secondFd));
3219 if (config.hostVisible)
3221 const std::vector<deUint8> testDataA (genTestData(seed ^ 99012346u, (size_t)bufferSize));
3223 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3225 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3226 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3230 return tcu::TestStatus::pass("Pass");
3235 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
3239 tcu::TestStatus testMemoryFdDup3 (Context& context, MemoryTestConfig config)
3241 #if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
3242 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3243 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3244 const vk::InstanceDriver& vki (instance.getDriver());
3245 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3246 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3249 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3250 const vk::DeviceDriver vkd (vkp, instance, *device);
3252 TestLog& log = context.getTestContext().getLog();
3253 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3254 const vk::VkDeviceSize bufferSize = 1024;
3255 const deUint32 seed = 2554088961u;
3256 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
3258 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3260 // \note Buffer is only allocated to get memory requirements
3261 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3262 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3263 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3264 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3266 if (config.hostVisible)
3267 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3269 const NativeHandle fd (getMemoryFd(vkd, *device, *memory, config.externalType));
3270 NativeHandle secondFd (getMemoryFd(vkd, *device, *memory, config.externalType));
3271 const int newFd (dup3(fd.getFd(), secondFd.getFd(), 0));
3274 log << TestLog::Message << "dup3() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
3276 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup3() for memorys fd");
3279 const vk::Unique<vk::VkBuffer> newBuffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3280 const vk::Unique<vk::VkDeviceMemory> newMemory (config.dedicated
3281 ? importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType, exportedMemoryTypeIndex, secondFd)
3282 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, secondFd));
3284 if (config.hostVisible)
3286 const std::vector<deUint8> testDataA (genTestData(seed ^ 4210342378u, (size_t)bufferSize));
3288 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3290 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3291 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3295 return tcu::TestStatus::pass("Pass");
3300 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
3304 tcu::TestStatus testMemoryFdSendOverSocket (Context& context, MemoryTestConfig config)
3306 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
3307 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3308 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3309 const vk::InstanceDriver& vki (instance.getDriver());
3310 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3311 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3314 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3315 const vk::DeviceDriver vkd (vkp, instance, *device);
3317 TestLog& log = context.getTestContext().getLog();
3318 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3319 const vk::VkDeviceSize bufferSize = 1024;
3320 const deUint32 seed = 3403586456u;
3321 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
3323 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3325 // \note Buffer is only allocated to get memory requirements
3326 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3327 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3328 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3329 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3331 if (config.hostVisible)
3332 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3334 const NativeHandle fd (getMemoryFd(vkd, *device, *memory, config.externalType));
3339 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
3341 log << TestLog::Message << "Failed to create socket pair: '" << strerror(errno) << "'" << TestLog::EndMessage;
3342 TCU_FAIL("Failed to create socket pair");
3346 const NativeHandle srcSocket (sv[0]);
3347 const NativeHandle dstSocket (sv[1]);
3348 std::string sendData ("deqp");
3352 const int fdRaw (fd.getFd());
3355 char tmpBuffer[CMSG_SPACE(sizeof(int))];
3356 iovec iov = { &sendData[0], sendData.length()};
3358 deMemset(&msg, 0, sizeof(msg));
3360 msg.msg_control = tmpBuffer;
3361 msg.msg_controllen = sizeof(tmpBuffer);
3365 cmsg = CMSG_FIRSTHDR(&msg);
3366 cmsg->cmsg_level = SOL_SOCKET;
3367 cmsg->cmsg_type = SCM_RIGHTS;
3368 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
3370 deMemcpy(CMSG_DATA(cmsg), &fdRaw, sizeof(int));
3371 msg.msg_controllen = cmsg->cmsg_len;
3373 if (sendmsg(srcSocket.getFd(), &msg, 0) < 0)
3375 log << TestLog::Message << "Failed to send fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
3376 TCU_FAIL("Failed to send fd over socket");
3383 char tmpBuffer[CMSG_SPACE(sizeof(int))];
3384 std::string recvData (4, '\0');
3385 iovec iov = { &recvData[0], recvData.length() };
3387 deMemset(&msg, 0, sizeof(msg));
3389 msg.msg_control = tmpBuffer;
3390 msg.msg_controllen = sizeof(tmpBuffer);
3394 const ssize_t bytes = recvmsg(dstSocket.getFd(), &msg, 0);
3398 log << TestLog::Message << "Failed to recv fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
3399 TCU_FAIL("Failed to recv fd over socket");
3402 else if (bytes != (ssize_t)sendData.length())
3404 TCU_FAIL("recvmsg() returned unpexpected number of bytes");
3408 const cmsghdr* const cmsg = CMSG_FIRSTHDR(&msg);
3410 deMemcpy(&newFd_, CMSG_DATA(cmsg), sizeof(int));
3411 NativeHandle newFd (newFd_);
3413 TCU_CHECK(cmsg->cmsg_level == SOL_SOCKET);
3414 TCU_CHECK(cmsg->cmsg_type == SCM_RIGHTS);
3415 TCU_CHECK(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
3416 TCU_CHECK(recvData == sendData);
3417 TCU_CHECK_MSG(newFd.getFd() >= 0, "Didn't receive valid fd from socket");
3420 const vk::Unique<vk::VkBuffer> newBuffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3421 const vk::Unique<vk::VkDeviceMemory> newMemory (config.dedicated
3422 ? importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType, exportedMemoryTypeIndex, newFd)
3423 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, newFd));
3425 if (config.hostVisible)
3427 const std::vector<deUint8> testDataA (genTestData(seed ^ 23478978u, (size_t)bufferSize));
3429 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3431 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3432 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3441 return tcu::TestStatus::pass("Pass");
3445 TCU_THROW(NotSupportedError, "Platform doesn't support sending file descriptors over socket");
3449 struct BufferTestConfig
3451 BufferTestConfig (vk::VkExternalMemoryHandleTypeFlagBits externalType_,
3453 : externalType (externalType_)
3454 , dedicated (dedicated_)
3458 vk::VkExternalMemoryHandleTypeFlagBits externalType;
3462 tcu::TestStatus testBufferBindExportImportBind (Context& context,
3463 const BufferTestConfig config)
3465 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3466 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3467 const vk::InstanceDriver& vki (instance.getDriver());
3468 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3469 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3470 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3471 const vk::DeviceDriver vkd (vkp, instance, *device);
3472 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3473 const vk::VkDeviceSize bufferSize = 1024;
3475 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3477 // \note Buffer is only allocated to get memory requirements
3478 const vk::Unique<vk::VkBuffer> bufferA (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3479 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *bufferA));
3480 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
3481 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *bufferA : (vk::VkBuffer)0));
3482 NativeHandle handle;
3484 VK_CHECK(vkd.bindBufferMemory(*device, *bufferA, *memoryA, 0u));
3486 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3489 const vk::Unique<vk::VkBuffer> bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3490 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3491 ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handle)
3492 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3494 VK_CHECK(vkd.bindBufferMemory(*device, *bufferB, *memoryB, 0u));
3497 return tcu::TestStatus::pass("Pass");
3500 tcu::TestStatus testBufferExportBindImportBind (Context& context,
3501 const BufferTestConfig config)
3503 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3504 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3505 const vk::InstanceDriver& vki (instance.getDriver());
3506 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3507 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3508 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3509 const vk::DeviceDriver vkd (vkp, instance, *device);
3510 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3511 const vk::VkDeviceSize bufferSize = 1024;
3513 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3515 // \note Buffer is only allocated to get memory requirements
3516 const vk::Unique<vk::VkBuffer> bufferA (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3517 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *bufferA));
3518 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
3519 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *bufferA : (vk::VkBuffer)0));
3520 NativeHandle handle;
3522 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3523 VK_CHECK(vkd.bindBufferMemory(*device, *bufferA, *memoryA, 0u));
3526 const vk::Unique<vk::VkBuffer> bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3527 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3528 ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handle)
3529 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3531 VK_CHECK(vkd.bindBufferMemory(*device, *bufferB, *memoryB, 0u));
3534 return tcu::TestStatus::pass("Pass");
3537 tcu::TestStatus testBufferExportImportBindBind (Context& context,
3538 const BufferTestConfig config)
3540 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3541 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3542 const vk::InstanceDriver& vki (instance.getDriver());
3543 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3544 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3545 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3546 const vk::DeviceDriver vkd (vkp, instance, *device);
3547 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3548 const vk::VkDeviceSize bufferSize = 1024;
3550 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3552 // \note Buffer is only allocated to get memory requirements
3553 const vk::Unique<vk::VkBuffer> bufferA (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3554 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *bufferA));
3555 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
3556 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *bufferA : (vk::VkBuffer)0));
3557 NativeHandle handle;
3559 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3562 const vk::Unique<vk::VkBuffer> bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3563 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3564 ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handle)
3565 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3567 VK_CHECK(vkd.bindBufferMemory(*device, *bufferA, *memoryA, 0u));
3568 VK_CHECK(vkd.bindBufferMemory(*device, *bufferB, *memoryB, 0u));
3571 return tcu::TestStatus::pass("Pass");
3574 tcu::TestStatus testImageQueries (Context& context, vk::VkExternalMemoryHandleTypeFlagBits externalType)
3576 const vk::VkImageCreateFlags createFlags[] =
3579 vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT,
3580 vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT|vk::VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT,
3581 vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT|vk::VK_IMAGE_CREATE_SPARSE_ALIASED_BIT,
3582 vk::VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT,
3583 vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT
3585 const vk::VkImageUsageFlags usageFlags[] =
3587 vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
3588 vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT,
3589 vk::VK_IMAGE_USAGE_SAMPLED_BIT,
3590 vk::VK_IMAGE_USAGE_STORAGE_BIT,
3591 vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
3592 vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
3593 vk::VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
3594 vk::VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
3595 vk::VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT,
3596 vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT
3598 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3599 const CustomInstance instance (createTestInstance(context, 0u, externalType, 0u));
3600 const vk::InstanceDriver& vki (instance.getDriver());
3601 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3602 const vk::VkPhysicalDeviceFeatures deviceFeatures (vk::getPhysicalDeviceFeatures(vki, physicalDevice));
3603 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3605 // VkDevice is only created if physical device claims to support any of these types.
3606 vk::Move<vk::VkDevice> device;
3607 de::MovePtr<vk::DeviceDriver> vkd;
3608 bool deviceHasDedicated = false;
3610 TestLog& log = context.getTestContext().getLog();
3612 for (size_t createFlagNdx = 0; createFlagNdx < DE_LENGTH_OF_ARRAY(createFlags); createFlagNdx++)
3613 for (size_t usageFlagNdx = 0; usageFlagNdx < DE_LENGTH_OF_ARRAY(usageFlags); usageFlagNdx++)
3615 const vk::VkImageViewCreateFlags createFlag = createFlags[createFlagNdx];
3616 const vk::VkImageUsageFlags usageFlag = usageFlags[usageFlagNdx];
3617 const vk::VkFormat format = vk::VK_FORMAT_R8G8B8A8_UNORM;
3618 const vk::VkImageType type = vk::VK_IMAGE_TYPE_2D;
3619 const vk::VkImageTiling tiling = vk::VK_IMAGE_TILING_OPTIMAL;
3620 const vk::VkPhysicalDeviceExternalImageFormatInfo externalInfo =
3622 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
3626 const vk::VkPhysicalDeviceImageFormatInfo2 info =
3628 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
3637 vk::VkExternalImageFormatProperties externalProperties =
3639 vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES,
3643 vk::VkImageFormatProperties2 properties =
3645 vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
3646 &externalProperties,
3656 if (((createFlag & vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT) != 0) &&
3657 (deviceFeatures.sparseBinding == VK_FALSE))
3660 if (((createFlag & vk::VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT) != 0) &&
3661 (deviceFeatures.sparseResidencyImage2D == VK_FALSE))
3664 if (((createFlag & vk::VK_IMAGE_CREATE_SPARSE_ALIASED_BIT) != 0) &&
3665 (deviceFeatures.sparseResidencyAliased == VK_FALSE))
3668 vki.getPhysicalDeviceImageFormatProperties2(physicalDevice, &info, &properties);
3670 log << TestLog::Message << externalProperties << TestLog::EndMessage;
3671 TCU_CHECK(externalProperties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES);
3672 TCU_CHECK(externalProperties.pNext == DE_NULL);
3673 // \todo [2017-06-06 pyry] Can we validate anything else? Compatible types?
3675 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & (vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT|vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT)) != 0)
3677 const bool requiresDedicated = (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
3679 if (!device || (requiresDedicated && !deviceHasDedicated))
3681 // \note We need to re-create with dedicated mem extensions if previous device instance didn't have them
3684 device = createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, externalType, 0u, queueFamilyIndex, requiresDedicated);
3685 vkd = de::MovePtr<vk::DeviceDriver>(new vk::DeviceDriver(vkp, instance, *device));
3686 deviceHasDedicated = requiresDedicated;
3688 catch (const tcu::NotSupportedError& e)
3691 TCU_FAIL("Physical device claims to support handle type but required extensions are not supported");
3696 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) != 0)
3698 DE_ASSERT(!!device);
3701 if (deviceHasDedicated)
3703 // Memory requirements cannot be queried without binding the image.
3704 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
3707 const vk::Unique<vk::VkImage> image (createExternalImage(*vkd, *device, queueFamilyIndex, externalType, format, 16u, 16u, tiling, createFlag, usageFlag));
3708 const vk::VkMemoryDedicatedRequirements reqs (getMemoryDedicatedRequirements(*vkd, *device, *image));
3709 const bool propertiesRequiresDedicated = (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
3710 const bool objectRequiresDedicated = (reqs.requiresDedicatedAllocation != VK_FALSE);
3712 if (propertiesRequiresDedicated != objectRequiresDedicated)
3713 TCU_FAIL("vkGetPhysicalDeviceExternalBufferProperties and vkGetBufferMemoryRequirements2 report different dedicated requirements");
3717 // We can't query whether dedicated memory is required or not on per-object basis.
3718 // This check should be redundant as the code above tries to create device with
3719 // VK_KHR_dedicated_allocation & VK_KHR_get_memory_requirements2 if dedicated memory
3720 // is required. However, checking again doesn't hurt.
3721 TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) == 0);
3726 return tcu::TestStatus::pass("Pass");
3729 struct ImageTestConfig
3731 ImageTestConfig (vk::VkExternalMemoryHandleTypeFlagBits externalType_,
3733 : externalType (externalType_)
3734 , dedicated (dedicated_)
3738 vk::VkExternalMemoryHandleTypeFlagBits externalType;
3742 tcu::TestStatus testImageBindExportImportBind (Context& context,
3743 const ImageTestConfig config)
3745 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3746 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3747 const vk::InstanceDriver& vki (instance.getDriver());
3748 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3749 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3750 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3751 const vk::DeviceDriver vkd (vkp, instance, *device);
3752 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);
3753 const vk::VkFormat format = vk::VK_FORMAT_R8G8B8A8_UNORM;
3754 const deUint32 width = 64u;
3755 const deUint32 height = 64u;
3756 const vk::VkImageTiling tiling = vk::VK_IMAGE_TILING_OPTIMAL;
3758 checkImageSupport(vki, physicalDevice, config.externalType, 0u, usage, format, tiling, config.dedicated);
3760 const vk::Unique<vk::VkImage> imageA (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3761 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *imageA, config.externalType));
3762 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
3763 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *imageA : (vk::VkImage)0));
3764 NativeHandle handle;
3766 VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
3768 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3771 const vk::Unique<vk::VkImage> imageB (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3772 const deUint32 idx = config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID ? ~0u : exportedMemoryTypeIndex;
3773 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3774 ? importDedicatedMemory(vkd, *device, *imageB, requirements, config.externalType, idx, handle)
3775 : importMemory(vkd, *device, requirements, config.externalType, idx, handle));
3777 VK_CHECK(vkd.bindImageMemory(*device, *imageB, *memoryB, 0u));
3780 return tcu::TestStatus::pass("Pass");
3783 tcu::TestStatus testImageExportBindImportBind (Context& context,
3784 const ImageTestConfig config)
3786 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3787 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3788 const vk::InstanceDriver& vki (instance.getDriver());
3789 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3790 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3791 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3792 const vk::DeviceDriver vkd (vkp, instance, *device);
3793 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);
3794 const vk::VkFormat format = vk::VK_FORMAT_R8G8B8A8_UNORM;
3795 const deUint32 width = 64u;
3796 const deUint32 height = 64u;
3797 const vk::VkImageTiling tiling = vk::VK_IMAGE_TILING_OPTIMAL;
3799 checkImageSupport(vki, physicalDevice, config.externalType, 0u, usage, format, tiling, config.dedicated);
3801 const vk::Unique<vk::VkImage> imageA (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3802 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *imageA, config.externalType));
3803 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
3804 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *imageA : (vk::VkImage)0));
3805 NativeHandle handle;
3807 if (config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID && config.dedicated)
3809 // AHB required the image memory to be bound first.
3810 VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
3811 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3815 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3816 VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
3820 const vk::Unique<vk::VkImage> imageB (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3821 const deUint32 idx = config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID ? ~0u : exportedMemoryTypeIndex;
3822 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3823 ? importDedicatedMemory(vkd, *device, *imageB, requirements, config.externalType, idx, handle)
3824 : importMemory(vkd, *device, requirements, config.externalType, idx, handle));
3826 VK_CHECK(vkd.bindImageMemory(*device, *imageB, *memoryB, 0u));
3829 return tcu::TestStatus::pass("Pass");
3832 tcu::TestStatus testImageExportImportBindBind (Context& context,
3833 const ImageTestConfig config)
3835 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3836 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3837 const vk::InstanceDriver& vki (instance.getDriver());
3838 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3839 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3840 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3841 const vk::DeviceDriver vkd (vkp, instance, *device);
3842 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);
3843 const vk::VkFormat format = vk::VK_FORMAT_R8G8B8A8_UNORM;
3844 const deUint32 width = 64u;
3845 const deUint32 height = 64u;
3846 const vk::VkImageTiling tiling = vk::VK_IMAGE_TILING_OPTIMAL;
3848 checkImageSupport(vki, physicalDevice, config.externalType, 0u, usage, format, tiling, config.dedicated);
3850 if (config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID && config.dedicated)
3852 // AHB required the image memory to be bound first, which is not possible in this test.
3853 TCU_THROW(NotSupportedError, "Unsupported for Android Hardware Buffer");
3856 // \note Image is only allocated to get memory requirements
3857 const vk::Unique<vk::VkImage> imageA (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3858 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *imageA, config.externalType));
3859 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
3860 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *imageA : (vk::VkImage)0));
3861 NativeHandle handle;
3863 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3866 const vk::Unique<vk::VkImage> imageB (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
3867 const deUint32 idx = config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID ? ~0u : exportedMemoryTypeIndex;
3868 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3869 ? importDedicatedMemory(vkd, *device, *imageB, requirements, config.externalType, idx, handle)
3870 : importMemory(vkd, *device, requirements, config.externalType, idx, handle));
3872 VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
3873 VK_CHECK(vkd.bindImageMemory(*device, *imageB, *memoryB, 0u));
3876 return tcu::TestStatus::pass("Pass");
3878 de::MovePtr<tcu::TestCaseGroup> createFenceTests (tcu::TestContext& testCtx, vk::VkExternalFenceHandleTypeFlagBits externalType)
3882 const char* const name;
3883 const Permanence permanence;
3886 { "temporary", PERMANENCE_TEMPORARY },
3887 { "permanent", PERMANENCE_PERMANENT }
3890 de::MovePtr<tcu::TestCaseGroup> fenceGroup (new tcu::TestCaseGroup(testCtx, externalFenceTypeToName(externalType), externalFenceTypeToName(externalType)));
3892 addFunctionCase(fenceGroup.get(), "info", "Test external fence queries.", testFenceQueries, externalType);
3894 for (size_t permanenceNdx = 0; permanenceNdx < DE_LENGTH_OF_ARRAY(permanences); permanenceNdx++)
3896 const Permanence permanence (permanences[permanenceNdx].permanence);
3897 const char* const permanenceName (permanences[permanenceNdx].name);
3898 const FenceTestConfig config (externalType, permanence);
3900 if (!isSupportedPermanence(externalType, permanence))
3903 if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT
3904 || externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
3906 addFunctionCase(fenceGroup.get(), std::string("create_win32_") + permanenceName, "Test creating fence with win32 properties.", testFenceWin32Create, config);
3909 addFunctionCase(fenceGroup.get(), std::string("import_twice_") + permanenceName, "Test importing fence twice.", testFenceImportTwice, config);
3910 addFunctionCase(fenceGroup.get(), std::string("reimport_") + permanenceName, "Test importing again over previously imported fence.", testFenceImportReimport, config);
3911 addFunctionCase(fenceGroup.get(), std::string("import_multiple_times_") + permanenceName, "Test importing fence multiple times.", testFenceMultipleImports, config);
3912 addFunctionCase(fenceGroup.get(), std::string("signal_export_import_wait_") + permanenceName, "Test signaling, exporting, importing and waiting for the sempahore.", testFenceSignalExportImportWait, config);
3913 addFunctionCase(fenceGroup.get(), std::string("signal_import_") + permanenceName, "Test signaling and importing the fence.", testFenceSignalImport, config);
3914 addFunctionCase(fenceGroup.get(), std::string("reset_") + permanenceName, "Test resetting the fence.", testFenceReset, config);
3915 addFunctionCase(fenceGroup.get(), std::string("transference_") + permanenceName, "Test fences transference.", testFenceTransference, config);
3917 if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT
3918 || externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT)
3920 // \note Not supported on WIN32 handles
3921 addFunctionCase(fenceGroup.get(), std::string("export_multiple_times_") + permanenceName, "Test exporting fence multiple times.", testFenceMultipleExports, config);
3923 addFunctionCase(fenceGroup.get(), std::string("dup_") + permanenceName, "Test calling dup() on exported fence.", testFenceFdDup, config);
3924 addFunctionCase(fenceGroup.get(), std::string("dup2_") + permanenceName, "Test calling dup2() on exported fence.", testFenceFdDup2, config);
3925 addFunctionCase(fenceGroup.get(), std::string("dup3_") + permanenceName, "Test calling dup3() on exported fence.", testFenceFdDup3, config);
3926 addFunctionCase(fenceGroup.get(), std::string("send_over_socket_") + permanenceName, "Test sending fence fd over socket.", testFenceFdSendOverSocket, config);
3929 if (getHandelTypeTransferences(externalType) == TRANSFERENCE_REFERENCE)
3931 addFunctionCase(fenceGroup.get(), std::string("signal_wait_import_") + permanenceName, "Test signaling and then waiting for the the sepmahore.", testFenceSignalWaitImport, config);
3932 addFunctionCase(fenceGroup.get(), std::string("export_signal_import_wait_") + permanenceName, "Test exporting, signaling, importing and waiting for the fence.", testFenceExportSignalImportWait, config);
3933 addFunctionCase(fenceGroup.get(), std::string("export_import_signal_wait_") + permanenceName, "Test exporting, importing, signaling and waiting for the fence.", testFenceExportImportSignalWait, config);
3940 bool ValidateAHardwareBuffer(vk::VkFormat format, deUint64 requiredAhbUsage, const vk::DeviceDriver& vkd, const vk::VkDevice& device, vk::VkImageCreateFlags createFlag, deUint32 layerCount, bool& enableMaxLayerTest)
3942 DE_UNREF(createFlag);
3944 AndroidHardwareBufferExternalApi* ahbApi = AndroidHardwareBufferExternalApi::getInstance();
3947 TCU_THROW(NotSupportedError, "Platform doesn't support Android Hardware Buffer handles");
3950 #if (DE_OS == DE_OS_ANDROID)
3951 // If CubeMap create flag is used and AHB doesn't support CubeMap return false.
3952 if(!AndroidHardwareBufferExternalApi::supportsCubeMap() && (createFlag & vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT))
3956 vk::pt::AndroidHardwareBufferPtr ahb = ahbApi->allocate(64u, 64u, layerCount, ahbApi->vkFormatToAhbFormat(format), requiredAhbUsage);
3957 if (ahb.internal == DE_NULL)
3959 enableMaxLayerTest = false;
3960 // try again with layerCount '1'
3961 ahb = ahbApi->allocate(64u, 64u, 1u, ahbApi->vkFormatToAhbFormat(format), requiredAhbUsage);
3962 if (ahb.internal == DE_NULL)
3967 NativeHandle nativeHandle(ahb);
3968 vk::VkAndroidHardwareBufferFormatPropertiesANDROID formatProperties =
3970 vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID,
3972 vk::VK_FORMAT_UNDEFINED,
3975 { vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY },
3976 vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY,
3977 vk::VK_SAMPLER_YCBCR_RANGE_ITU_FULL,
3978 vk::VK_CHROMA_LOCATION_COSITED_EVEN,
3979 vk::VK_CHROMA_LOCATION_COSITED_EVEN
3981 vk::VkAndroidHardwareBufferPropertiesANDROID bufferProperties =
3983 vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID,
3989 VK_CHECK(vkd.getAndroidHardwareBufferPropertiesANDROID(device, ahb, &bufferProperties));
3990 TCU_CHECK(formatProperties.format != vk::VK_FORMAT_UNDEFINED);
3991 TCU_CHECK(formatProperties.format == format);
3992 TCU_CHECK(formatProperties.externalFormat != 0u);
3993 TCU_CHECK((formatProperties.formatFeatures & vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) != 0u);
3994 TCU_CHECK((formatProperties.formatFeatures & (vk::VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT | vk::VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT)) != 0u);
3998 tcu::TestStatus testAndroidHardwareBufferImageFormat (Context& context, vk::VkFormat format)
4000 AndroidHardwareBufferExternalApi* ahbApi = AndroidHardwareBufferExternalApi::getInstance();
4003 TCU_THROW(NotSupportedError, "Platform doesn't support Android Hardware Buffer handles");
4006 const vk::VkExternalMemoryHandleTypeFlagBits externalMemoryType = vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
4007 const vk::PlatformInterface& vkp (context.getPlatformInterface());
4008 const CustomInstance instance (createTestInstance(context, externalMemoryType, 0u, 0u));
4009 const vk::InstanceDriver& vki (instance.getDriver());
4010 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
4011 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
4012 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, externalMemoryType, 0u, queueFamilyIndex));
4013 const vk::DeviceDriver vkd (vkp, instance, *device);
4014 TestLog& log = context.getTestContext().getLog();
4015 const vk::VkPhysicalDeviceLimits limits = getPhysicalDeviceProperties(vki, physicalDevice).limits;
4017 const vk::VkImageUsageFlagBits framebufferUsageFlag = vk::isDepthStencilFormat(format) ? vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
4018 : vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
4020 const vk::VkImageUsageFlagBits usageFlags[] =
4022 vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
4023 vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT,
4024 vk::VK_IMAGE_USAGE_SAMPLED_BIT,
4025 vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT,
4026 framebufferUsageFlag,
4028 const vk::VkImageCreateFlagBits createFlags[] =
4030 vk::VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT,
4031 vk::VK_IMAGE_CREATE_EXTENDED_USAGE_BIT,
4032 vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT,
4034 const vk::VkImageTiling tilings[] =
4036 vk::VK_IMAGE_TILING_OPTIMAL,
4037 vk::VK_IMAGE_TILING_LINEAR,
4039 deUint64 mustSupportAhbUsageFlags = ahbApi->mustSupportAhbUsageFlags();
4040 const size_t one = 1u;
4041 const size_t numOfUsageFlags = DE_LENGTH_OF_ARRAY(usageFlags);
4042 const size_t numOfCreateFlags = DE_LENGTH_OF_ARRAY(createFlags);
4043 const size_t numOfFlagCombos = one << (numOfUsageFlags + numOfCreateFlags);
4044 const size_t numOfTilings = DE_LENGTH_OF_ARRAY(tilings);
4046 for (size_t combo = 0; combo < numOfFlagCombos; combo++)
4048 vk::VkImageUsageFlags usage = 0;
4049 vk::VkImageCreateFlags createFlag = 0;
4050 deUint64 requiredAhbUsage = 0;
4051 bool enableMaxLayerTest = true;
4052 for (size_t usageNdx = 0; usageNdx < numOfUsageFlags; usageNdx++)
4054 if ((combo & (one << usageNdx)) == 0)
4056 usage |= usageFlags[usageNdx];
4057 requiredAhbUsage |= ahbApi->vkUsageToAhbUsage(usageFlags[usageNdx]);
4059 for (size_t createFlagNdx = 0; createFlagNdx < numOfCreateFlags; createFlagNdx++)
4061 const size_t bit = numOfUsageFlags + createFlagNdx;
4062 if ((combo & (one << bit)) == 0)
4064 createFlag |= createFlags[createFlagNdx];
4065 requiredAhbUsage |= ahbApi->vkCreateToAhbUsage(createFlags[createFlagNdx]);
4068 // Only test a combination if the usage flags include at least one of the AHARDWAREBUFFER_USAGE_GPU_* flag.
4069 if ((requiredAhbUsage & mustSupportAhbUsageFlags) == 0u)
4072 // Only test a combination if AHardwareBuffer can be successfully allocated for it.
4073 if (!ValidateAHardwareBuffer(format, requiredAhbUsage, vkd, *device, createFlag, limits.maxImageArrayLayers, enableMaxLayerTest))
4076 bool foundAnyUsableTiling = false;
4077 for (size_t tilingIndex = 0; tilingIndex < numOfTilings; tilingIndex++)
4079 const vk::VkImageTiling tiling = tilings[tilingIndex];
4081 const vk::VkPhysicalDeviceExternalImageFormatInfo externalInfo =
4083 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
4085 vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID
4087 const vk::VkPhysicalDeviceImageFormatInfo2 info =
4089 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
4092 vk::VK_IMAGE_TYPE_2D,
4098 vk::VkAndroidHardwareBufferUsageANDROID ahbUsageProperties =
4100 vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID,
4104 vk::VkExternalImageFormatProperties externalProperties =
4106 vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES,
4107 &ahbUsageProperties,
4110 vk::VkImageFormatProperties2 properties =
4112 vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
4113 &externalProperties,
4123 if (vki.getPhysicalDeviceImageFormatProperties2(physicalDevice, &info, &properties) == vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
4125 log << TestLog::Message << "Tiling " << tiling << " is not supported." << TestLog::EndMessage;
4129 foundAnyUsableTiling = true;
4131 TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) != 0);
4132 TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) != 0);
4133 TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0);
4134 deUint32 maxWidth = properties.imageFormatProperties.maxExtent.width;
4135 deUint32 maxHeight = properties.imageFormatProperties.maxExtent.height;
4136 TCU_CHECK(maxWidth >= 4096);
4137 TCU_CHECK(maxHeight >= 4096);
4138 // Even if not requested, at least one of GPU_* usage flags must be present.
4139 TCU_CHECK((ahbUsageProperties.androidHardwareBufferUsage & mustSupportAhbUsageFlags) != 0u);
4140 // The AHB usage flags corresponding to the create and usage flags used in info must be present.
4141 TCU_CHECK((ahbUsageProperties.androidHardwareBufferUsage & requiredAhbUsage) == requiredAhbUsage);
4143 log << TestLog::Message << "Required flags: " << std::hex << requiredAhbUsage << " Actual flags: " << std::hex << ahbUsageProperties.androidHardwareBufferUsage
4144 << TestLog::EndMessage;
4156 for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(sizes); i++)
4158 const vk::Unique<vk::VkImage> image (createExternalImage(vkd, *device, queueFamilyIndex, externalMemoryType, format, sizes[i].width, sizes[i].height, tiling, createFlag, usage));
4159 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *image, externalMemoryType));
4160 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
4161 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, externalMemoryType, *image));
4162 NativeHandle handle;
4164 VK_CHECK(vkd.bindImageMemory(*device, *image, *memory, 0u));
4165 getMemoryNative(vkd, *device, *memory, externalMemoryType, handle);
4167 deUint32 ahbFormat = 0;
4168 deUint64 anhUsage = 0;
4169 ahbApi->describe(handle.getAndroidHardwareBuffer(), DE_NULL, DE_NULL, DE_NULL, &ahbFormat, &anhUsage, DE_NULL);
4170 TCU_CHECK(ahbFormat == ahbApi->vkFormatToAhbFormat(format));
4171 TCU_CHECK((anhUsage & requiredAhbUsage) == requiredAhbUsage);
4173 // Let watchdog know we're alive
4174 context.getTestContext().touchWatchdog();
4177 if (properties.imageFormatProperties.maxMipLevels >= 7u)
4179 const vk::Unique<vk::VkImage> image (createExternalImage(vkd, *device, queueFamilyIndex, externalMemoryType, format, 64u, 64u, tiling, createFlag, usage, 7u));
4180 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *image, externalMemoryType));
4181 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
4182 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, externalMemoryType, *image));
4183 NativeHandle handle;
4185 VK_CHECK(vkd.bindImageMemory(*device, *image, *memory, 0u));
4186 getMemoryNative(vkd, *device, *memory, externalMemoryType, handle);
4188 deUint32 ahbFormat = 0;
4189 deUint64 anhUsage = 0;
4190 ahbApi->describe(handle.getAndroidHardwareBuffer(), DE_NULL, DE_NULL, DE_NULL, &ahbFormat, &anhUsage, DE_NULL);
4191 TCU_CHECK(ahbFormat == ahbApi->vkFormatToAhbFormat(format));
4192 TCU_CHECK((anhUsage & requiredAhbUsage) == requiredAhbUsage);
4195 if ((properties.imageFormatProperties.maxArrayLayers > 1u) && enableMaxLayerTest)
4197 const vk::Unique<vk::VkImage> image (createExternalImage(vkd, *device, queueFamilyIndex, externalMemoryType, format, 64u, 64u, tiling, createFlag, usage, 1u, properties.imageFormatProperties.maxArrayLayers));
4198 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *image, externalMemoryType));
4199 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
4200 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, externalMemoryType, *image));
4201 NativeHandle handle;
4203 VK_CHECK(vkd.bindImageMemory(*device, *image, *memory, 0u));
4204 getMemoryNative(vkd, *device, *memory, externalMemoryType, handle);
4206 deUint32 ahbFormat = 0;
4207 deUint64 anhUsage = 0;
4208 ahbApi->describe(handle.getAndroidHardwareBuffer(), DE_NULL, DE_NULL, DE_NULL, &ahbFormat, &anhUsage, DE_NULL);
4209 TCU_CHECK(ahbFormat == ahbApi->vkFormatToAhbFormat(format));
4210 TCU_CHECK((anhUsage & requiredAhbUsage) == requiredAhbUsage);
4214 TCU_CHECK(foundAnyUsableTiling);
4216 return tcu::TestStatus::pass("Pass");
4219 de::MovePtr<tcu::TestCaseGroup> createFenceTests (tcu::TestContext& testCtx)
4221 de::MovePtr<tcu::TestCaseGroup> fenceGroup (new tcu::TestCaseGroup(testCtx, "fence", "Tests for external fences."));
4223 fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT).release());
4224 fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT).release());
4225 fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT).release());
4226 fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT).release());
4231 de::MovePtr<tcu::TestCaseGroup> createSemaphoreTests (tcu::TestContext& testCtx, vk::VkExternalSemaphoreHandleTypeFlagBits externalType)
4235 const char* const name;
4236 const Permanence permanence;
4239 { "temporary", PERMANENCE_TEMPORARY },
4240 { "permanent", PERMANENCE_PERMANENT }
4243 de::MovePtr<tcu::TestCaseGroup> semaphoreGroup (new tcu::TestCaseGroup(testCtx, externalSemaphoreTypeToName(externalType), externalSemaphoreTypeToName(externalType)));
4245 addFunctionCase(semaphoreGroup.get(), "info", "Test external semaphore queries.", testSemaphoreQueries, externalType);
4247 for (size_t permanenceNdx = 0; permanenceNdx < DE_LENGTH_OF_ARRAY(permanences); permanenceNdx++)
4249 const Permanence permanence (permanences[permanenceNdx].permanence);
4250 const char* const permanenceName (permanences[permanenceNdx].name);
4251 const SemaphoreTestConfig config (externalType, permanence);
4253 if (!isSupportedPermanence(externalType, permanence))
4256 if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
4257 || externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
4259 addFunctionCase(semaphoreGroup.get(), std::string("create_win32_") + permanenceName, "Test creating semaphore with win32 properties.", testSemaphoreWin32Create, config);
4262 addFunctionCase(semaphoreGroup.get(), std::string("import_twice_") + permanenceName, "Test importing semaphore twice.", testSemaphoreImportTwice, config);
4263 addFunctionCase(semaphoreGroup.get(), std::string("reimport_") + permanenceName, "Test importing again over previously imported semaphore.", testSemaphoreImportReimport, config);
4264 addFunctionCase(semaphoreGroup.get(), std::string("import_multiple_times_") + permanenceName, "Test importing semaphore multiple times.", testSemaphoreMultipleImports, config);
4265 addFunctionCase(semaphoreGroup.get(), std::string("signal_export_import_wait_") + permanenceName, "Test signaling, exporting, importing and waiting for the sempahore.", testSemaphoreSignalExportImportWait, config);
4266 addFunctionCase(semaphoreGroup.get(), std::string("signal_import_") + permanenceName, "Test signaling and importing the semaphore.", testSemaphoreSignalImport, config);
4267 addFunctionCase(semaphoreGroup.get(), std::string("transference_") + permanenceName, "Test semaphores transference.", testSemaphoreTransference, config);
4269 if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT
4270 || externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT)
4272 // \note Not supported on WIN32 handles
4273 addFunctionCase(semaphoreGroup.get(), std::string("export_multiple_times_") + permanenceName, "Test exporting semaphore multiple times.", testSemaphoreMultipleExports, config);
4275 addFunctionCase(semaphoreGroup.get(), std::string("dup_") + permanenceName, "Test calling dup() on exported semaphore.", testSemaphoreFdDup, config);
4276 addFunctionCase(semaphoreGroup.get(), std::string("dup2_") + permanenceName, "Test calling dup2() on exported semaphore.", testSemaphoreFdDup2, config);
4277 addFunctionCase(semaphoreGroup.get(), std::string("dup3_") + permanenceName, "Test calling dup3() on exported semaphore.", testSemaphoreFdDup3, config);
4278 addFunctionCase(semaphoreGroup.get(), std::string("send_over_socket_") + permanenceName, "Test sending semaphore fd over socket.", testSemaphoreFdSendOverSocket, config);
4281 if (getHandelTypeTransferences(externalType) == TRANSFERENCE_REFERENCE)
4283 addFunctionCase(semaphoreGroup.get(), std::string("signal_wait_import_") + permanenceName, "Test signaling and then waiting for the the sepmahore.", testSemaphoreSignalWaitImport, config);
4284 addFunctionCase(semaphoreGroup.get(), std::string("export_signal_import_wait_") + permanenceName, "Test exporting, signaling, importing and waiting for the semaphore.", testSemaphoreExportSignalImportWait, config);
4285 addFunctionCase(semaphoreGroup.get(), std::string("export_import_signal_wait_") + permanenceName, "Test exporting, importing, signaling and waiting for the semaphore.", testSemaphoreExportImportSignalWait, config);
4289 return semaphoreGroup;
4292 de::MovePtr<tcu::TestCaseGroup> createSemaphoreTests (tcu::TestContext& testCtx)
4294 de::MovePtr<tcu::TestCaseGroup> semaphoreGroup (new tcu::TestCaseGroup(testCtx, "semaphore", "Tests for external semaphores."));
4296 semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT).release());
4297 semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT).release());
4298 semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT).release());
4299 semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT).release());
4301 return semaphoreGroup;
4304 de::MovePtr<tcu::TestCaseGroup> createMemoryTests (tcu::TestContext& testCtx, vk::VkExternalMemoryHandleTypeFlagBits externalType)
4306 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, externalMemoryTypeToName(externalType), "Tests for external memory"));
4308 for (size_t dedicatedNdx = 0; dedicatedNdx < 2; dedicatedNdx++)
4310 const bool dedicated (dedicatedNdx == 1);
4311 de::MovePtr<tcu::TestCaseGroup> dedicatedGroup (new tcu::TestCaseGroup(testCtx, dedicated ? "dedicated" : "suballocated", ""));
4313 for (size_t hostVisibleNdx = 0; hostVisibleNdx < 2; hostVisibleNdx++)
4315 const bool hostVisible (hostVisibleNdx == 1);
4316 de::MovePtr<tcu::TestCaseGroup> hostVisibleGroup (new tcu::TestCaseGroup(testCtx, hostVisible ? "host_visible" : "device_only", ""));
4317 const MemoryTestConfig memoryConfig (externalType, hostVisible, dedicated);
4319 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
4320 || externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
4322 addFunctionCase(hostVisibleGroup.get(), "create_win32", "Test creating memory with win32 properties .", testMemoryWin32Create, memoryConfig);
4325 addFunctionCase(hostVisibleGroup.get(), "import_twice", "Test importing memory object twice.", testMemoryImportTwice, memoryConfig);
4326 addFunctionCase(hostVisibleGroup.get(), "import_multiple_times", "Test importing memory object multiple times.", testMemoryMultipleImports, memoryConfig);
4328 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT
4329 || externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT)
4331 addFunctionCase(hostVisibleGroup.get(), "dup", "Test calling dup() on exported memory.", testMemoryFdDup, memoryConfig);
4332 addFunctionCase(hostVisibleGroup.get(), "dup2", "Test calling dup2() on exported memory.", testMemoryFdDup2, memoryConfig);
4333 addFunctionCase(hostVisibleGroup.get(), "dup3", "Test calling dup3() on exported memory.", testMemoryFdDup3, memoryConfig);
4334 addFunctionCase(hostVisibleGroup.get(), "send_over_socket", "Test sending memory fd over socket.", testMemoryFdSendOverSocket, memoryConfig);
4335 // \note Not supported on WIN32 handles
4336 addFunctionCase(hostVisibleGroup.get(), "export_multiple_times", "Test exporting memory multiple times.", testMemoryMultipleExports, memoryConfig);
4339 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT)
4341 addFunctionCase(hostVisibleGroup.get(), "fd_properties", "Test obtaining the FD memory properties", testMemoryFdProperties, memoryConfig);
4344 dedicatedGroup->addChild(hostVisibleGroup.release());
4348 de::MovePtr<tcu::TestCaseGroup> bufferGroup (new tcu::TestCaseGroup(testCtx, "buffer", ""));
4349 const BufferTestConfig bufferConfig (externalType, dedicated);
4351 addFunctionCase(bufferGroup.get(), "info", "External buffer memory info query.", testBufferQueries, externalType);
4352 addFunctionCase(bufferGroup.get(), "bind_export_import_bind", "Test binding, exporting, importing and binding buffer.", testBufferBindExportImportBind, bufferConfig);
4353 addFunctionCase(bufferGroup.get(), "export_bind_import_bind", "Test exporting, binding, importing and binding buffer.", testBufferExportBindImportBind, bufferConfig);
4354 addFunctionCase(bufferGroup.get(), "export_import_bind_bind", "Test exporting, importing and binding buffer.", testBufferExportImportBindBind, bufferConfig);
4356 dedicatedGroup->addChild(bufferGroup.release());
4360 de::MovePtr<tcu::TestCaseGroup> imageGroup (new tcu::TestCaseGroup(testCtx, "image", ""));
4361 const ImageTestConfig imageConfig (externalType, dedicated);
4363 addFunctionCase(imageGroup.get(), "info", "External image memory info query.", testImageQueries, externalType);
4364 addFunctionCase(imageGroup.get(), "bind_export_import_bind", "Test binding, exporting, importing and binding image.", testImageBindExportImportBind, imageConfig);
4365 addFunctionCase(imageGroup.get(), "export_bind_import_bind", "Test exporting, binding, importing and binding image.", testImageExportBindImportBind, imageConfig);
4366 addFunctionCase(imageGroup.get(), "export_import_bind_bind", "Test exporting, importing and binding image.", testImageExportImportBindBind, imageConfig);
4368 dedicatedGroup->addChild(imageGroup.release());
4371 group->addChild(dedicatedGroup.release());
4374 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
4376 de::MovePtr<tcu::TestCaseGroup> formatGroup (new tcu::TestCaseGroup(testCtx, "image_formats", "Test minimum image format support"));
4378 const vk::VkFormat ahbFormats[] =
4380 vk::VK_FORMAT_R8G8B8_UNORM,
4381 vk::VK_FORMAT_R8G8B8A8_UNORM,
4382 vk::VK_FORMAT_R5G6B5_UNORM_PACK16,
4383 vk::VK_FORMAT_R16G16B16A16_SFLOAT,
4384 vk::VK_FORMAT_A2B10G10R10_UNORM_PACK32,
4385 vk::VK_FORMAT_D16_UNORM,
4386 vk::VK_FORMAT_X8_D24_UNORM_PACK32,
4387 vk::VK_FORMAT_D24_UNORM_S8_UINT,
4388 vk::VK_FORMAT_D32_SFLOAT,
4389 vk::VK_FORMAT_D32_SFLOAT_S8_UINT,
4390 vk::VK_FORMAT_S8_UINT,
4392 const size_t numOfAhbFormats = DE_LENGTH_OF_ARRAY(ahbFormats);
4394 for (size_t ahbFormatNdx = 0; ahbFormatNdx < numOfAhbFormats; ahbFormatNdx++)
4396 const vk::VkFormat format = ahbFormats[ahbFormatNdx];
4397 const std::string testCaseName = getFormatCaseName(format);
4399 addFunctionCase(formatGroup.get(), testCaseName, "", testAndroidHardwareBufferImageFormat, format);
4402 group->addChild(formatGroup.release());
4408 de::MovePtr<tcu::TestCaseGroup> createMemoryTests (tcu::TestContext& testCtx)
4410 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "memory", "Tests for external memory"));
4412 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT).release());
4413 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT).release());
4414 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT).release());
4415 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID).release());
4416 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT).release());
4423 tcu::TestCaseGroup* createExternalMemoryTests (tcu::TestContext& testCtx)
4425 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "external", "Tests for external Vulkan objects"));
4427 group->addChild(createSemaphoreTests(testCtx).release());
4428 group->addChild(createMemoryTests(testCtx).release());
4429 group->addChild(createFenceTests(testCtx).release());
4431 return group.release();