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"
24 #include "../compute/vktComputeTestsUtil.hpp"
26 #include "vktTestCaseUtil.hpp"
27 #include "vkRefUtil.hpp"
28 #include "vkDeviceUtil.hpp"
29 #include "vkQueryUtil.hpp"
30 #include "vkPlatform.hpp"
31 #include "vkMemUtil.hpp"
32 #include "vkApiVersion.hpp"
33 #include "vkImageUtil.hpp"
34 #include "vkObjUtil.hpp"
35 #include "vkBuilderUtil.hpp"
36 #include "vkBarrierUtil.hpp"
37 #include "vkBufferWithMemory.hpp"
39 #include "tcuTestLog.hpp"
40 #include "tcuCommandLine.hpp"
42 #include "deUniquePtr.hpp"
43 #include "deStringUtil.hpp"
44 #include "deRandom.hpp"
48 #include "vktExternalMemoryUtil.hpp"
50 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
54 # include <sys/types.h>
55 # include <sys/socket.h>
58 #if (DE_OS == DE_OS_WIN32)
59 # define WIN32_LEAN_AND_MEAN
67 using namespace vkt::ExternalMemoryUtil;
77 template<typename T, int size>
78 T multiplyComponents (const tcu::Vector<T, size>& v)
81 for (int i = 0; i < size; ++i)
86 std::string getFormatCaseName (vk::VkFormat format)
88 return de::toLower(de::toString(getFormatStr(format)).substr(10));
91 vk::VkMemoryDedicatedRequirements getMemoryDedicatedRequirements (const vk::DeviceInterface& vkd,
95 const vk::VkBufferMemoryRequirementsInfo2 requirementInfo =
97 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2,
101 vk::VkMemoryDedicatedRequirements dedicatedRequirements =
103 vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
108 vk::VkMemoryRequirements2 requirements =
110 vk::VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
111 &dedicatedRequirements,
115 vkd.getBufferMemoryRequirements2(device, &requirementInfo, &requirements);
117 return dedicatedRequirements;
120 vk::VkMemoryDedicatedRequirements getMemoryDedicatedRequirements (const vk::DeviceInterface& vkd,
124 const vk::VkImageMemoryRequirementsInfo2 requirementInfo =
126 vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
130 vk::VkMemoryDedicatedRequirements dedicatedRequirements =
132 vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
137 vk::VkMemoryRequirements2 requirements =
139 vk::VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
140 &dedicatedRequirements,
144 vkd.getImageMemoryRequirements2(device, &requirementInfo, &requirements);
146 return dedicatedRequirements;
149 void writeHostMemory (const vk::DeviceInterface& vkd,
151 vk::VkDeviceMemory memory,
155 void* const ptr = vk::mapMemory(vkd, device, memory, 0, size, 0);
157 deMemcpy(ptr, data, size);
159 flushMappedMemoryRange(vkd, device, memory, 0, VK_WHOLE_SIZE);
161 vkd.unmapMemory(device, memory);
164 void checkHostMemory (const vk::DeviceInterface& vkd,
166 vk::VkDeviceMemory memory,
170 void* const ptr = vk::mapMemory(vkd, device, memory, 0, size, 0);
172 invalidateMappedMemoryRange(vkd, device, memory, 0, VK_WHOLE_SIZE);
174 if (deMemCmp(ptr, data, size) != 0)
175 TCU_FAIL("Memory contents don't match");
177 vkd.unmapMemory(device, memory);
180 std::vector<deUint8> genTestData (deUint32 seed, size_t size)
182 de::Random rng (seed);
183 std::vector<deUint8> data (size);
185 for (size_t ndx = 0; ndx < size; ndx++)
187 data[ndx] = rng.getUint8();
193 deUint32 chooseQueueFamilyIndex (const vk::InstanceInterface& vki,
194 vk::VkPhysicalDevice device,
195 vk::VkQueueFlags requireFlags)
197 const std::vector<vk::VkQueueFamilyProperties> properties (vk::getPhysicalDeviceQueueFamilyProperties(vki, device));
199 for (deUint32 queueFamilyIndex = 0; queueFamilyIndex < (deUint32)properties.size(); queueFamilyIndex++)
201 if ((properties[queueFamilyIndex].queueFlags & requireFlags) == requireFlags)
202 return queueFamilyIndex;
205 TCU_THROW(NotSupportedError, "Queue type not supported");
208 std::vector<std::string> getInstanceExtensions (const deUint32 instanceVersion,
209 const vk::VkExternalSemaphoreHandleTypeFlags externalSemaphoreTypes,
210 const vk::VkExternalMemoryHandleTypeFlags externalMemoryTypes,
211 const vk::VkExternalFenceHandleTypeFlags externalFenceTypes)
213 std::vector<std::string> instanceExtensions;
215 if (!vk::isCoreInstanceExtension(instanceVersion, "VK_KHR_get_physical_device_properties2"))
216 instanceExtensions.push_back("VK_KHR_get_physical_device_properties2");
218 if (externalSemaphoreTypes != 0)
219 if (!vk::isCoreInstanceExtension(instanceVersion, "VK_KHR_external_semaphore_capabilities"))
220 instanceExtensions.push_back("VK_KHR_external_semaphore_capabilities");
222 if (externalMemoryTypes != 0)
223 if (!vk::isCoreInstanceExtension(instanceVersion, "VK_KHR_external_memory_capabilities"))
224 instanceExtensions.push_back("VK_KHR_external_memory_capabilities");
226 if (externalFenceTypes != 0)
227 if (!vk::isCoreInstanceExtension(instanceVersion, "VK_KHR_external_fence_capabilities"))
228 instanceExtensions.push_back("VK_KHR_external_fence_capabilities");
230 return instanceExtensions;
233 CustomInstance createTestInstance (Context& context,
234 const vk::VkExternalSemaphoreHandleTypeFlags externalSemaphoreTypes,
235 const vk::VkExternalMemoryHandleTypeFlags externalMemoryTypes,
236 const vk::VkExternalFenceHandleTypeFlags externalFenceTypes)
240 return vkt::createCustomInstanceWithExtensions(context, getInstanceExtensions(context.getUsedApiVersion(), externalSemaphoreTypes, externalMemoryTypes, externalFenceTypes));
242 catch (const vk::Error& error)
244 if (error.getError() == vk::VK_ERROR_EXTENSION_NOT_PRESENT)
245 TCU_THROW(NotSupportedError, "Required extensions not supported");
251 vk::Move<vk::VkDevice> createTestDevice (const Context& context,
252 const vk::PlatformInterface& vkp,
253 vk::VkInstance instance,
254 const vk::InstanceInterface& vki,
255 vk::VkPhysicalDevice physicalDevice,
256 const vk::VkExternalSemaphoreHandleTypeFlags externalSemaphoreTypes,
257 const vk::VkExternalMemoryHandleTypeFlags externalMemoryTypes,
258 const vk::VkExternalFenceHandleTypeFlags externalFenceTypes,
259 deUint32 queueFamilyIndex,
260 bool useDedicatedAllocs = false,
261 void * protectedFeatures = DE_NULL)
263 const deUint32 apiVersion = context.getUsedApiVersion();
264 bool useExternalSemaphore = false;
265 bool useExternalFence = false;
266 bool useExternalMemory = false;
267 std::vector<const char*> deviceExtensions;
269 if ((externalSemaphoreTypes
270 & (vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT
271 | vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT)) != 0)
273 deviceExtensions.push_back("VK_KHR_external_semaphore_fd");
274 useExternalSemaphore = true;
277 if ((externalFenceTypes
278 & (vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT
279 | vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT)) != 0)
281 deviceExtensions.push_back("VK_KHR_external_fence_fd");
282 useExternalFence = true;
285 if (useDedicatedAllocs)
287 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_dedicated_allocation"))
288 deviceExtensions.push_back("VK_KHR_dedicated_allocation");
289 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_get_memory_requirements2"))
290 deviceExtensions.push_back("VK_KHR_get_memory_requirements2");
293 if ((externalMemoryTypes
294 & (vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT
295 | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT)) != 0)
297 deviceExtensions.push_back("VK_KHR_external_memory_fd");
298 useExternalMemory = true;
301 if ((externalMemoryTypes
302 & vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT) != 0)
304 deviceExtensions.push_back("VK_EXT_external_memory_dma_buf");
305 useExternalMemory = true;
308 if ((externalSemaphoreTypes
309 & (vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
310 | vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)) != 0)
312 deviceExtensions.push_back("VK_KHR_external_semaphore_win32");
313 useExternalSemaphore = true;
316 if ((externalFenceTypes
317 & (vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT
318 | vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)) != 0)
320 deviceExtensions.push_back("VK_KHR_external_fence_win32");
321 useExternalFence = true;
324 if ((externalMemoryTypes
325 & (vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
326 | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT
327 | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT
328 | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT
329 | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT
330 | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT)) != 0)
332 deviceExtensions.push_back("VK_KHR_external_memory_win32");
333 useExternalMemory = true;
336 if ((externalMemoryTypes
337 & vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID) != 0)
339 deviceExtensions.push_back("VK_ANDROID_external_memory_android_hardware_buffer");
340 useExternalMemory = true;
341 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_sampler_ycbcr_conversion"))
342 deviceExtensions.push_back("VK_KHR_sampler_ycbcr_conversion");
343 if (!vk::isCoreDeviceExtension(apiVersion, "VK_EXT_queue_family_foreign"))
344 deviceExtensions.push_back("VK_EXT_queue_family_foreign");
347 if (useExternalSemaphore)
349 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_external_semaphore"))
350 deviceExtensions.push_back("VK_KHR_external_semaphore");
353 if (useExternalFence)
355 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_external_fence"))
356 deviceExtensions.push_back("VK_KHR_external_fence");
359 if (useExternalMemory)
361 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_external_memory"))
362 deviceExtensions.push_back("VK_KHR_external_memory");
365 const float priority = 0.5f;
366 const vk::VkDeviceQueueCreateInfo queues[] =
369 vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
378 const vk::VkDeviceCreateInfo deviceCreateInfo =
380 vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
384 DE_LENGTH_OF_ARRAY(queues),
390 (deUint32)deviceExtensions.size(),
391 deviceExtensions.empty() ? DE_NULL : &deviceExtensions[0],
397 return createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), vkp, instance, vki, physicalDevice, &deviceCreateInfo);
399 catch (const vk::Error& error)
401 if (error.getError() == vk::VK_ERROR_EXTENSION_NOT_PRESENT)
402 TCU_THROW(NotSupportedError, "Required extensions not supported");
408 vk::VkQueue getQueue (const vk::DeviceInterface& vkd,
410 deUint32 queueFamilyIndex)
414 vkd.getDeviceQueue(device, queueFamilyIndex, 0, &queue);
419 uint32_t getMaxInvocations(const Context& context, uint32_t idx)
421 const auto& vki = context.getInstanceInterface();
422 const auto physicalDevice = context.getPhysicalDevice();
423 const auto properties = vk::getPhysicalDeviceProperties(vki, physicalDevice);
425 return properties.limits.maxComputeWorkGroupSize[idx];
428 void checkSemaphoreSupport (const vk::InstanceInterface& vki,
429 vk::VkPhysicalDevice device,
430 vk::VkExternalSemaphoreHandleTypeFlagBits externalType)
432 const vk::VkPhysicalDeviceExternalSemaphoreInfo info =
434 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO,
438 vk::VkExternalSemaphoreProperties properties =
440 vk::VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES,
447 vki.getPhysicalDeviceExternalSemaphoreProperties(device, &info, &properties);
449 if ((properties.externalSemaphoreFeatures & vk::VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT) == 0)
450 TCU_THROW(NotSupportedError, "Semaphore doesn't support exporting in external type");
452 if ((properties.externalSemaphoreFeatures & vk::VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT) == 0)
453 TCU_THROW(NotSupportedError, "Semaphore doesn't support importing in external type");
456 void checkFenceSupport (const vk::InstanceInterface& vki,
457 vk::VkPhysicalDevice device,
458 vk::VkExternalFenceHandleTypeFlagBits externalType)
460 const vk::VkPhysicalDeviceExternalFenceInfo info =
462 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO,
466 vk::VkExternalFenceProperties properties =
468 vk::VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES,
475 vki.getPhysicalDeviceExternalFenceProperties(device, &info, &properties);
477 if ((properties.externalFenceFeatures & vk::VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT) == 0)
478 TCU_THROW(NotSupportedError, "Fence doesn't support exporting in external type");
480 if ((properties.externalFenceFeatures & vk::VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT) == 0)
481 TCU_THROW(NotSupportedError, "Fence doesn't support importing in external type");
484 void checkBufferSupport (const vk::InstanceInterface& vki,
485 vk::VkPhysicalDevice device,
486 vk::VkExternalMemoryHandleTypeFlagBits externalType,
487 vk::VkBufferViewCreateFlags createFlag,
488 vk::VkBufferUsageFlags usageFlag,
491 const vk::VkPhysicalDeviceExternalBufferInfo info =
493 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO,
500 vk::VkExternalBufferProperties properties =
502 vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES,
508 vki.getPhysicalDeviceExternalBufferProperties(device, &info, &properties);
510 if ((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) == 0)
511 TCU_THROW(NotSupportedError, "External handle type doesn't support exporting buffer");
513 if ((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) == 0)
514 TCU_THROW(NotSupportedError, "External handle type doesn't support importing buffer");
516 if (!dedicated && (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0)
517 TCU_THROW(NotSupportedError, "External handle type requires dedicated allocation");
520 void checkImageSupport (const vk::InstanceInterface& vki,
521 vk::VkPhysicalDevice device,
522 vk::VkExternalMemoryHandleTypeFlagBits externalType,
523 vk::VkImageViewCreateFlags createFlag,
524 vk::VkImageUsageFlags usageFlag,
526 vk::VkImageTiling tiling,
529 const vk::VkPhysicalDeviceExternalImageFormatInfo externalInfo =
531 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
535 const vk::VkPhysicalDeviceImageFormatInfo2 info =
537 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
541 vk::VK_IMAGE_TYPE_2D,
546 vk::VkExternalImageFormatProperties externalProperties =
548 vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES,
552 vk::VkImageFormatProperties2 properties =
554 vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
565 vki.getPhysicalDeviceImageFormatProperties2(device, &info, &properties);
567 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) == 0)
568 TCU_THROW(NotSupportedError, "External handle type doesn't support exporting image");
570 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) == 0)
571 TCU_THROW(NotSupportedError, "External handle type doesn't support importing image");
573 if (!dedicated && (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0)
574 TCU_THROW(NotSupportedError, "External handle type requires dedicated allocation");
577 void submitEmptySignal (const vk::DeviceInterface& vkd,
579 vk::VkSemaphore semaphore)
581 const vk::VkSubmitInfo submit =
583 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
597 VK_CHECK(vkd.queueSubmit(queue, 1, &submit, (vk::VkFence)0u));
600 void tuneWorkSizeYAndPrepareCommandBuffer( const Context& context,
601 const vk::DeviceInterface& vk,
604 vk::VkCommandBuffer cmdBuffer,
605 vk::VkDescriptorSet descriptorSet,
606 vk::VkPipelineLayout pipelineLayout,
607 vk::VkPipeline computePipeline,
608 vk::VkBufferMemoryBarrier computeFinishBarrier,
610 tcu::UVec3* maxWorkSize)
614 // Have it be static so we don't need to do tuning every time, especially for "export_multiple_times" tests.
615 static uint32_t yWorkSize = 1;
616 uint64_t timeElapsed = 0;
617 bool bOutLoop = false;
619 const vk::Unique<vk::VkFence> fence(vk::createFence(vk, device));
621 const vk::VkCommandBufferBeginInfo cmdBufferBeginInfo =
623 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
625 vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
630 VK_CHECK(vk.beginCommandBuffer(cmdBuffer, &cmdBufferBeginInfo));
633 * If the handle type is VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR, the spec allowed for implementations to return -1
634 * if the fence is already signaled. Previously, to avoid getting -1 in this case, this test had used vkCmdWaitEvents and
635 * vkSetEvent after submission to get a proper file descriptor before signaling but it's not invalid to call vkSetEvent
636 * after submission. So we just use vkCmdSetEvent and check the state of the event after submission to see if it's already
637 * signaled or an error happens while trying to get a file descriptor.
639 vk.cmdSetEvent(cmdBuffer, event, vk::VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT);
641 // And now we do a simple atomic calculation to avoid signalling instantly right after submit.
642 vk.cmdBindPipeline(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, computePipeline);
643 //vk.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, nullptr);
644 vk.cmdBindDescriptorSets(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &descriptorSet, 0u, nullptr);
645 vk.cmdDispatch(cmdBuffer, maxWorkSize->x(), yWorkSize, maxWorkSize->z());
646 vk.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, 0, 0, nullptr, 1u, &computeFinishBarrier, 0, nullptr);
647 vk.endCommandBuffer(cmdBuffer);
652 const vk::VkSubmitInfo submit =
654 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
668 auto timeStart = std::chrono::high_resolution_clock::now();
670 VK_CHECK(vk.queueSubmit(queue, 1, &submit, (vk::VkFence)*fence));
671 vk.waitForFences(device, 1u, &fence.get(), true, ~0ull);
673 const auto executionTime = std::chrono::high_resolution_clock::now() - timeStart;
674 auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(executionTime);
676 timeElapsed = elapsed.count();
678 // we do loop until we get over 9 miliseconds as an execution time.
679 if (elapsed.count() > 9)
687 if (yWorkSize > maxWorkSize->y())
689 yWorkSize = maxWorkSize->y();
693 vk.resetCommandBuffer(cmdBuffer, 0u);
694 vk.resetFences(device, 1u, &*fence);
697 tcu::TestLog& log = context.getTestContext().getLog();
698 log << tcu::TestLog::Message
699 << "Execution time to get a native file descriptor is " << timeElapsed << "ms with Y WorkSize " << yWorkSize
700 << tcu::TestLog::EndMessage;
705 void submitAtomicCalculationsAndGetSemaphoreNative (const Context& context,
706 const vk::DeviceInterface& vk,
708 vk::Allocator& alloc,
710 deUint32 queueFamilyIndex,
711 vk::VkSemaphore semaphore,
712 vk::VkExternalSemaphoreHandleTypeFlagBits externalType,
713 NativeHandle& nativeHandle)
715 const vk::Unique<vk::VkCommandPool> cmdPool(createCommandPool(vk, device, vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex, nullptr));
716 const vk::Unique<vk::VkCommandBuffer> cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
718 const vk::VkEventCreateInfo eventCreateInfo =
720 vk::VK_STRUCTURE_TYPE_EVENT_CREATE_INFO,
725 const vk::Unique<vk::VkEvent> event(createEvent(vk, device, &eventCreateInfo, nullptr));
727 const uint32_t maxXWorkSize = getMaxInvocations(context, 0);
728 const uint32_t maxYWorkSize = getMaxInvocations(context, 1);
730 tcu::UVec3 workSize = { maxXWorkSize, maxYWorkSize, 1u };
731 const uint32_t workGroupCount = multiplyComponents(workSize);
733 const vk::VkDeviceSize outputBufferSize = sizeof(uint32_t) * workGroupCount;
734 const vk::BufferWithMemory outputBuffer (vk, device, alloc, makeBufferCreateInfo(outputBufferSize, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), vk::MemoryRequirement::Local);
736 // Create a compute shader
737 const vk::Unique<vk::VkShaderModule> compShader(createShaderModule(vk, device, context.getBinaryCollection().get("compute"), 0u));
739 // Create descriptorSetLayout
740 vk::DescriptorSetLayoutBuilder layoutBuilder;
741 layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT);
742 vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout(layoutBuilder.build(vk, device));
744 // Create compute pipeline
745 const vk::Unique<vk::VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout));
746 const vk::Unique<vk::VkPipeline> computePipeline(compute::makeComputePipeline(vk, device, *pipelineLayout, *compShader));
748 // Create descriptor pool
749 const vk::Unique<vk::VkDescriptorPool> descriptorPool(
750 vk::DescriptorPoolBuilder()
751 .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
752 .build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1));
755 const vk::Move<vk::VkDescriptorSet> descriptorSet (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
756 const vk::VkDescriptorBufferInfo outputBufferInfo = makeDescriptorBufferInfo(*outputBuffer, 0ull, outputBufferSize);
757 const vk::VkBufferMemoryBarrier computeFinishBarrier = vk::makeBufferMemoryBarrier(vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_ACCESS_HOST_READ_BIT, *outputBuffer, 0ull, outputBufferSize);
759 vk::DescriptorSetUpdateBuilder()
760 .writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &outputBufferInfo)
763 // Now start tuning work size of Y to have time enough to get a fd at the device.
764 tuneWorkSizeYAndPrepareCommandBuffer(context, vk, device, queue, *cmdBuffer, *descriptorSet, *pipelineLayout, *computePipeline, computeFinishBarrier, *event, &workSize);
766 const vk::VkSubmitInfo submit =
768 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
783 VK_CHECK(vk.queueSubmit(queue, 1, &submit, (vk::VkFence)0u));
785 getSemaphoreNative(vk, device, semaphore, externalType, nativeHandle);
787 // Allow -1, that is valid if signalled properly.
788 if (nativeHandle.getFd() == -1)
789 TCU_CHECK(vk.getEventStatus(device, *event) == vk::VK_EVENT_SET);
791 VK_CHECK(vk.queueWaitIdle(queue));
794 void submitEmptyWait (const vk::DeviceInterface& vkd,
796 vk::VkSemaphore semaphore)
798 const vk::VkPipelineStageFlags stage = vk::VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
799 const vk::VkSubmitInfo submit =
801 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
815 VK_CHECK(vkd.queueSubmit(queue, 1, &submit, (vk::VkFence)0u));
818 void submitEmptySignal (const vk::DeviceInterface& vkd,
822 const vk::VkSubmitInfo submit =
824 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
838 VK_CHECK(vkd.queueSubmit(queue, 1, &submit, fence));
841 void submitAtomicCalculationsAndGetFenceNative (const Context& context,
842 const vk::DeviceInterface& vk,
844 vk::Allocator& alloc,
846 deUint32 queueFamilyIndex,
848 vk::VkExternalFenceHandleTypeFlagBits externalType,
849 NativeHandle& nativeHandle,
850 bool expectFenceUnsignaled = true)
852 const vk::Unique<vk::VkCommandPool> cmdPool(createCommandPool(vk, device, vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex, nullptr));
853 const vk::Unique<vk::VkCommandBuffer> cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
855 const vk::VkEventCreateInfo eventCreateInfo =
857 vk::VK_STRUCTURE_TYPE_EVENT_CREATE_INFO,
862 const vk::Unique<vk::VkEvent> event(createEvent(vk, device, &eventCreateInfo, DE_NULL));
864 const uint32_t maxXWorkSize = getMaxInvocations(context, 0);
865 const uint32_t maxYWorkSize = getMaxInvocations(context, 1);
867 tcu::UVec3 workSize = { maxXWorkSize, maxYWorkSize, 1u };
868 const uint32_t workGroupCount = multiplyComponents(workSize);
870 const vk::VkDeviceSize outputBufferSize = sizeof(uint32_t) * workGroupCount;
871 const vk::BufferWithMemory outputBuffer (vk, device, alloc, makeBufferCreateInfo(outputBufferSize, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), vk::MemoryRequirement::Local);
873 // Create a compute shader
874 const vk::Unique<vk::VkShaderModule> compShader(createShaderModule(vk, device, context.getBinaryCollection().get("compute"), 0u));
876 // Create descriptorSetLayout
877 vk::DescriptorSetLayoutBuilder layoutBuilder;
878 layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT);
879 vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout(layoutBuilder.build(vk, device));
881 // Create compute pipeline
882 const vk::Unique<vk::VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout));
883 const vk::Unique<vk::VkPipeline> computePipeline(compute::makeComputePipeline(vk, device, *pipelineLayout, *compShader));
885 // Create descriptor pool
886 const vk::Unique<vk::VkDescriptorPool> descriptorPool(
887 vk::DescriptorPoolBuilder()
888 .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
889 .build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1));
892 const vk::Move<vk::VkDescriptorSet> descriptorSet (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
893 const vk::VkDescriptorBufferInfo outputBufferInfo = makeDescriptorBufferInfo(*outputBuffer, 0ull, outputBufferSize);
894 const vk::VkBufferMemoryBarrier computeFinishBarrier = vk::makeBufferMemoryBarrier(vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_ACCESS_HOST_READ_BIT, *outputBuffer, 0ull, outputBufferSize);
896 vk::DescriptorSetUpdateBuilder()
897 .writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &outputBufferInfo)
900 // Now start tuning work size of Y to have time enough to get a fd at the device.
901 tuneWorkSizeYAndPrepareCommandBuffer(context, vk, device, queue, *cmdBuffer, *descriptorSet, *pipelineLayout, *computePipeline, computeFinishBarrier, *event, &workSize);
903 const vk::VkSubmitInfo submit =
905 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
919 VK_CHECK(vk.queueSubmit(queue, 1, &submit, fence));
921 getFenceNative(vk, device, fence, externalType, nativeHandle, expectFenceUnsignaled);
922 // Allow -1, that is valid if signalled properly.
923 if (nativeHandle.getFd() == -1)
924 TCU_CHECK(vk.getEventStatus(device, *event) == vk::VK_EVENT_SET);
926 VK_CHECK(vk.queueWaitIdle(queue));
929 struct TestSemaphoreQueriesParameters
931 vk::VkSemaphoreType semaphoreType;
932 vk::VkExternalSemaphoreHandleTypeFlagBits externalType;
934 TestSemaphoreQueriesParameters (vk::VkSemaphoreType semaphoreType_,
935 vk::VkExternalSemaphoreHandleTypeFlagBits externalType_)
936 : semaphoreType (semaphoreType_)
937 , externalType (externalType_)
941 tcu::TestStatus testSemaphoreQueries (Context& context, const TestSemaphoreQueriesParameters params)
943 const CustomInstance instance (createTestInstance(context, params.externalType, 0u, 0u));
944 const vk::InstanceDriver& vki (instance.getDriver());
945 const vk::VkPhysicalDevice device (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
947 TestLog& log = context.getTestContext().getLog();
949 const vk::VkSemaphoreTypeCreateInfo semaphoreTypeInfo =
951 vk::VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO,
953 params.semaphoreType,
956 const vk::VkPhysicalDeviceExternalSemaphoreInfo info =
958 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO,
962 vk::VkExternalSemaphoreProperties properties =
964 vk::VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES,
971 vki.getPhysicalDeviceExternalSemaphoreProperties(device, &info, &properties);
972 log << TestLog::Message << properties << TestLog::EndMessage;
974 TCU_CHECK(properties.pNext == DE_NULL);
975 TCU_CHECK(properties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES);
977 if (params.semaphoreType == vk::VK_SEMAPHORE_TYPE_TIMELINE)
979 context.requireDeviceFunctionality("VK_KHR_timeline_semaphore");
981 if (properties.compatibleHandleTypes & vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT)
982 return tcu::TestStatus::fail("Timeline semaphores are not compatible with SYNC_FD");
984 if (properties.exportFromImportedHandleTypes & vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT)
985 return tcu::TestStatus::fail("Timeline semaphores imported from SYNC_FD");
988 return tcu::TestStatus::pass("Pass");
991 struct SemaphoreTestConfig
993 SemaphoreTestConfig (vk::VkExternalSemaphoreHandleTypeFlagBits externalType_,
994 Permanence permanence_)
995 : externalType (externalType_)
996 , permanence (permanence_)
1000 vk::VkExternalSemaphoreHandleTypeFlagBits externalType;
1001 Permanence permanence;
1004 template<class TestConfig> void initProgramsToGetNativeFd(vk::SourceCollections& dst, const TestConfig)
1006 const tcu::IVec3 localSize = { 64, 1, 1 };
1008 std::ostringstream src;
1009 src << "#version 310 es\n"
1010 << "layout (local_size_x = " << localSize.x() << ", local_size_y = " << localSize.y() << ", local_size_z = " << localSize.z() << ") in;\n"
1011 << "layout(binding = 0) writeonly buffer Output {\n"
1012 << " uint values[];\n"
1015 << "void main (void) {\n"
1016 << " uint offset = gl_NumWorkGroups.x*gl_NumWorkGroups.y*gl_WorkGroupID.z + gl_NumWorkGroups.x*gl_WorkGroupID.y + gl_WorkGroupID.x;\n"
1018 << " atomicAdd(values[offset], 1u);\n"
1021 dst.glslSources.add("compute") << glu::ComputeSource(src.str());
1024 tcu::TestStatus testSemaphoreWin32Create (Context& context,
1025 const SemaphoreTestConfig config)
1027 #if (DE_OS == DE_OS_WIN32)
1028 const Transference transference (getHandelTypeTransferences(config.externalType));
1029 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1030 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1031 const vk::InstanceDriver& vki (instance.getDriver());
1032 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1033 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1035 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1038 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1039 const vk::DeviceDriver vkd (vkp, instance, *device);
1040 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1041 const vk::VkExportSemaphoreWin32HandleInfoKHR win32ExportInfo =
1043 vk::VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR,
1046 (vk::pt::Win32SecurityAttributesPtr)DE_NULL,
1047 DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
1048 (vk::pt::Win32LPCWSTR)DE_NULL
1050 const vk::VkExportSemaphoreCreateInfo exportCreateInfo=
1052 vk::VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO,
1054 (vk::VkExternalMemoryHandleTypeFlags)config.externalType
1056 const vk::VkSemaphoreCreateInfo createInfo =
1058 vk::VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
1062 const vk::Unique<vk::VkSemaphore> semaphore (vk::createSemaphore(vkd, *device, &createInfo));
1064 if (transference == TRANSFERENCE_COPY)
1065 submitEmptySignal(vkd, queue, *semaphore);
1067 NativeHandle handleA;
1068 getSemaphoreNative(vkd, *device, *semaphore, config.externalType, handleA);
1071 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1072 const vk::Unique<vk::VkSemaphore> semaphoreA (createAndImportSemaphore(vkd, *device, config.externalType, handleA, flags));
1074 if (transference == TRANSFERENCE_COPY)
1075 submitEmptyWait(vkd, queue, *semaphoreA);
1076 else if (transference == TRANSFERENCE_REFERENCE)
1078 submitEmptySignal(vkd, queue, *semaphore);
1079 submitEmptyWait(vkd, queue, *semaphoreA);
1082 DE_FATAL("Unknown transference.");
1084 VK_CHECK(vkd.queueWaitIdle(queue));
1087 return tcu::TestStatus::pass("Pass");
1092 TCU_THROW(NotSupportedError, "Platform doesn't support win32 handles");
1096 tcu::TestStatus testSemaphoreImportTwice (Context& context,
1097 const SemaphoreTestConfig config)
1099 const Transference transference (getHandelTypeTransferences(config.externalType));
1100 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1101 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1102 const vk::InstanceDriver& vki (instance.getDriver());
1103 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1104 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1106 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1109 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1110 const vk::DeviceDriver vkd (vkp, instance, *device);
1111 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1112 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1113 const vk::Unique<vk::VkSemaphore> semaphore (createExportableSemaphore(vkd, *device, config.externalType));
1114 NativeHandle handleA;
1116 if (transference == TRANSFERENCE_COPY)
1118 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphore, config.externalType, handleA);
1119 if (handleA.getFd() == -1)
1120 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1123 getSemaphoreNative(vkd, *device, *semaphore, config.externalType, handleA);
1126 NativeHandle handleB (handleA);
1127 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1128 const vk::Unique<vk::VkSemaphore> semaphoreA (createAndImportSemaphore(vkd, *device, config.externalType, handleA, flags));
1129 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handleB, flags));
1131 if (transference == TRANSFERENCE_COPY)
1132 submitEmptyWait(vkd, queue, *semaphoreA);
1133 else if (transference == TRANSFERENCE_REFERENCE)
1135 submitEmptySignal(vkd, queue, *semaphoreA);
1136 submitEmptyWait(vkd, queue, *semaphoreB);
1139 DE_FATAL("Unknown transference.");
1141 VK_CHECK(vkd.queueWaitIdle(queue));
1144 return tcu::TestStatus::pass("Pass");
1148 tcu::TestStatus testSemaphoreImportReimport (Context& context,
1149 const SemaphoreTestConfig config)
1151 const Transference transference (getHandelTypeTransferences(config.externalType));
1152 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1153 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1154 const vk::InstanceDriver& vki (instance.getDriver());
1155 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1156 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1158 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1161 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1162 const vk::DeviceDriver vkd (vkp, instance, *device);
1163 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1164 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1166 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1167 NativeHandle handleA;
1169 if (transference == TRANSFERENCE_COPY)
1171 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, handleA);
1172 if (handleA.getFd() == -1)
1173 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1176 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handleA);
1178 NativeHandle handleB (handleA);
1179 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1180 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handleA, flags));
1182 importSemaphore(vkd, *device, *semaphoreB, config.externalType, handleB, flags);
1184 if (transference == TRANSFERENCE_COPY)
1185 submitEmptyWait(vkd, queue, *semaphoreB);
1186 else if (transference == TRANSFERENCE_REFERENCE)
1188 submitEmptySignal(vkd, queue, *semaphoreA);
1189 submitEmptyWait(vkd, queue, *semaphoreB);
1192 DE_FATAL("Unknown transference.");
1194 VK_CHECK(vkd.queueWaitIdle(queue));
1196 return tcu::TestStatus::pass("Pass");
1200 tcu::TestStatus testSemaphoreSignalExportImportWait (Context& context,
1201 const SemaphoreTestConfig config)
1203 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1204 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1205 const vk::InstanceDriver& vki (instance.getDriver());
1206 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1207 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1208 const Transference transference (getHandelTypeTransferences(config.externalType));
1210 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1213 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1214 const vk::DeviceDriver vkd (vkp, instance, *device);
1215 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1216 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1217 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1219 NativeHandle handle;
1221 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
1222 if (transference == TRANSFERENCE_COPY && handle.getFd() == -1)
1223 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1226 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1227 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1228 submitEmptyWait(vkd, queue, *semaphoreB);
1230 VK_CHECK(vkd.queueWaitIdle(queue));
1234 return tcu::TestStatus::pass("Pass");
1238 tcu::TestStatus testSemaphoreExportSignalImportWait (Context& context,
1239 const SemaphoreTestConfig config)
1241 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1242 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1243 const vk::InstanceDriver& vki (instance.getDriver());
1244 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1245 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1246 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1248 DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
1249 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1252 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1253 const vk::DeviceDriver vkd (vkp, instance, *device);
1254 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1256 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1257 NativeHandle handle;
1259 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
1261 submitEmptySignal(vkd, queue, *semaphoreA);
1264 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1266 submitEmptyWait(vkd, queue, *semaphoreB);
1267 VK_CHECK(vkd.queueWaitIdle(queue));
1271 return tcu::TestStatus::pass("Pass");
1275 tcu::TestStatus testSemaphoreExportImportSignalWait (Context& context,
1276 const SemaphoreTestConfig config)
1278 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1279 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1280 const vk::InstanceDriver& vki (instance.getDriver());
1281 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1282 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1284 DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
1285 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1288 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1289 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1290 const vk::DeviceDriver vkd (vkp, instance, *device);
1291 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1293 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1294 NativeHandle handle;
1296 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
1298 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1300 submitEmptySignal(vkd, queue, *semaphoreA);
1301 submitEmptyWait(vkd, queue, *semaphoreB);
1303 VK_CHECK(vkd.queueWaitIdle(queue));
1305 return tcu::TestStatus::pass("Pass");
1309 tcu::TestStatus testSemaphoreSignalImport (Context& context,
1310 const SemaphoreTestConfig config)
1312 const Transference transference (getHandelTypeTransferences(config.externalType));
1313 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1314 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1315 const vk::InstanceDriver& vki (instance.getDriver());
1316 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1317 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1319 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1322 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1323 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1324 const vk::DeviceDriver vkd (vkp, instance, *device);
1325 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1326 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1328 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1329 const vk::Unique<vk::VkSemaphore> semaphoreB (createSemaphore(vkd, *device));
1330 NativeHandle handle;
1332 submitEmptySignal(vkd, queue, *semaphoreB);
1333 VK_CHECK(vkd.queueWaitIdle(queue));
1335 if (transference == TRANSFERENCE_COPY)
1337 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
1338 if (handle.getFd() == -1)
1339 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1342 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
1344 importSemaphore(vkd, *device, *semaphoreB, config.externalType, handle, flags);
1346 if (transference == TRANSFERENCE_COPY)
1347 submitEmptyWait(vkd, queue, *semaphoreB);
1348 else if (transference == TRANSFERENCE_REFERENCE)
1350 submitEmptySignal(vkd, queue, *semaphoreA);
1351 submitEmptyWait(vkd, queue, *semaphoreB);
1354 DE_FATAL("Unknown transference.");
1356 VK_CHECK(vkd.queueWaitIdle(queue));
1358 return tcu::TestStatus::pass("Pass");
1362 tcu::TestStatus testSemaphoreSignalWaitImport (Context& context,
1363 const SemaphoreTestConfig config)
1365 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1366 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1367 const vk::InstanceDriver& vki (instance.getDriver());
1368 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1369 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1371 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1374 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1375 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1376 const vk::DeviceDriver vkd (vkp, instance, *device);
1377 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1379 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1380 const vk::Unique<vk::VkSemaphore> semaphoreB (createSemaphore(vkd, *device));
1381 NativeHandle handle;
1383 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
1385 submitEmptySignal(vkd, queue, *semaphoreB);
1386 submitEmptyWait(vkd, queue, *semaphoreB);
1388 VK_CHECK(vkd.queueWaitIdle(queue));
1390 importSemaphore(vkd, *device, *semaphoreB, config.externalType, handle, flags);
1392 submitEmptySignal(vkd, queue, *semaphoreA);
1393 submitEmptyWait(vkd, queue, *semaphoreB);
1395 VK_CHECK(vkd.queueWaitIdle(queue));
1397 return tcu::TestStatus::pass("Pass");
1401 tcu::TestStatus testSemaphoreImportSyncFdSignaled (Context& context,
1402 const SemaphoreTestConfig config)
1404 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1405 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1406 const vk::InstanceDriver& vki (instance.getDriver());
1407 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1408 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1409 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1411 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1414 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1415 const vk::DeviceDriver vkd (vkp, instance, *device);
1416 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1417 NativeHandle handle = -1;
1418 const vk::Unique<vk::VkSemaphore> semaphore (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1420 submitEmptyWait(vkd, queue, *semaphore);
1421 VK_CHECK(vkd.queueWaitIdle(queue));
1423 return tcu::TestStatus::pass("Pass");
1427 tcu::TestStatus testSemaphoreMultipleExports (Context& context,
1428 const SemaphoreTestConfig config)
1430 const size_t exportCount = 1024;
1431 const Transference transference (getHandelTypeTransferences(config.externalType));
1432 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1433 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1434 const vk::InstanceDriver& vki (instance.getDriver());
1435 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1436 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1438 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1441 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1442 const vk::DeviceDriver vkd (vkp, instance, *device);
1443 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1444 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1445 const vk::Unique<vk::VkSemaphore> semaphore (createExportableSemaphore(vkd, *device, config.externalType));
1447 for (size_t exportNdx = 0; exportNdx < exportCount; exportNdx++)
1449 NativeHandle handle;
1451 // Need to touch watchdog due to how long one iteration takes
1452 context.getTestContext().touchWatchdog();
1454 if (transference == TRANSFERENCE_COPY)
1456 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphore, config.externalType, handle);
1457 if (handle.getFd() == -1)
1458 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1461 getSemaphoreNative(vkd, *device, *semaphore, config.externalType, handle);
1464 submitEmptySignal(vkd, queue, *semaphore);
1465 submitEmptyWait(vkd, queue, *semaphore);
1467 VK_CHECK(vkd.queueWaitIdle(queue));
1470 return tcu::TestStatus::pass("Pass");
1473 tcu::TestStatus testSemaphoreMultipleImports (Context& context,
1474 const SemaphoreTestConfig config)
1476 const size_t importCount = 4 * 1024;
1477 const Transference transference (getHandelTypeTransferences(config.externalType));
1478 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1479 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1480 const vk::InstanceDriver& vki (instance.getDriver());
1481 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1482 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1484 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1487 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1488 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1489 const vk::DeviceDriver vkd (vkp, instance, *device);
1490 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1491 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1492 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1493 NativeHandle handleA;
1495 if (transference == TRANSFERENCE_COPY)
1497 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, handleA);
1498 if (handleA.getFd() == -1)
1499 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1502 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handleA);
1504 for (size_t importNdx = 0; importNdx < importCount; importNdx++)
1506 NativeHandle handleB (handleA);
1507 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handleB, flags));
1510 if (transference == TRANSFERENCE_COPY)
1512 importSemaphore(vkd, *device, *semaphoreA, config.externalType, handleA, flags);
1513 submitEmptyWait(vkd, queue, *semaphoreA);
1515 else if (transference == TRANSFERENCE_REFERENCE)
1517 submitEmptySignal(vkd, queue, *semaphoreA);
1518 submitEmptyWait(vkd, queue, *semaphoreA);
1521 DE_FATAL("Unknown transference.");
1523 VK_CHECK(vkd.queueWaitIdle(queue));
1526 return tcu::TestStatus::pass("Pass");
1529 tcu::TestStatus testSemaphoreTransference (Context& context,
1530 const SemaphoreTestConfig config)
1532 const Transference transference (getHandelTypeTransferences(config.externalType));
1533 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1534 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1535 const vk::InstanceDriver& vki (instance.getDriver());
1536 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1537 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1539 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1542 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1543 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1544 const vk::DeviceDriver vkd (vkp, instance, *device);
1545 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1546 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1548 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1549 NativeHandle handle;
1551 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
1552 if (transference == TRANSFERENCE_COPY && handle.getFd() == -1)
1553 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1556 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1558 if (config.permanence == PERMANENCE_PERMANENT)
1560 if (transference == TRANSFERENCE_COPY)
1562 submitEmptySignal(vkd, queue, *semaphoreA);
1563 submitEmptyWait(vkd, queue, *semaphoreB);
1564 VK_CHECK(vkd.queueWaitIdle(queue));
1566 submitEmptySignal(vkd, queue, *semaphoreB);
1568 submitEmptyWait(vkd, queue, *semaphoreA);
1569 submitEmptyWait(vkd, queue, *semaphoreB);
1570 VK_CHECK(vkd.queueWaitIdle(queue));
1572 else if (transference== TRANSFERENCE_REFERENCE)
1574 submitEmptyWait(vkd, queue, *semaphoreB);
1575 VK_CHECK(vkd.queueWaitIdle(queue));
1577 submitEmptySignal(vkd, queue, *semaphoreA);
1578 submitEmptyWait(vkd, queue, *semaphoreB);
1580 submitEmptySignal(vkd, queue, *semaphoreB);
1581 submitEmptyWait(vkd, queue, *semaphoreA);
1582 VK_CHECK(vkd.queueWaitIdle(queue));
1585 DE_FATAL("Unknown transference.");
1587 else if (config.permanence == PERMANENCE_TEMPORARY)
1589 if (transference == TRANSFERENCE_COPY)
1591 submitEmptySignal(vkd, queue, *semaphoreA);
1592 submitEmptyWait(vkd, queue, *semaphoreB);
1593 VK_CHECK(vkd.queueWaitIdle(queue));
1595 submitEmptySignal(vkd, queue, *semaphoreB);
1597 submitEmptyWait(vkd, queue, *semaphoreA);
1598 submitEmptyWait(vkd, queue, *semaphoreB);
1599 VK_CHECK(vkd.queueWaitIdle(queue));
1601 else if (transference== TRANSFERENCE_REFERENCE)
1603 submitEmptyWait(vkd, queue, *semaphoreB);
1604 VK_CHECK(vkd.queueWaitIdle(queue));
1606 submitEmptySignal(vkd, queue, *semaphoreA);
1607 submitEmptySignal(vkd, queue, *semaphoreB);
1609 submitEmptyWait(vkd, queue, *semaphoreB);
1610 submitEmptyWait(vkd, queue, *semaphoreA);
1611 VK_CHECK(vkd.queueWaitIdle(queue));
1614 DE_FATAL("Unknown transference.");
1617 DE_FATAL("Unknown permanence.");
1620 return tcu::TestStatus::pass("Pass");
1624 tcu::TestStatus testSemaphoreFdDup (Context& context,
1625 const SemaphoreTestConfig config)
1627 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
1628 const Transference transference (getHandelTypeTransferences(config.externalType));
1629 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1630 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1631 const vk::InstanceDriver& vki (instance.getDriver());
1632 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1633 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1635 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1638 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1639 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1640 const vk::DeviceDriver vkd (vkp, instance, *device);
1641 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1642 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1644 TestLog& log = context.getTestContext().getLog();
1645 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1650 if (transference == TRANSFERENCE_COPY)
1652 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, fd);
1653 if (fd.getFd() == -1)
1654 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1657 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, fd);
1659 NativeHandle newFd (dup(fd.getFd()));
1661 if (newFd.getFd() < 0)
1662 log << TestLog::Message << "dup() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
1664 TCU_CHECK_MSG(newFd.getFd() >= 0, "Failed to call dup() for semaphores fd");
1667 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, newFd, flags));
1669 if (transference == TRANSFERENCE_COPY)
1670 submitEmptyWait(vkd, queue, *semaphoreB);
1671 else if (transference == TRANSFERENCE_REFERENCE)
1673 submitEmptySignal(vkd, queue, *semaphoreA);
1674 submitEmptyWait(vkd, queue, *semaphoreB);
1677 DE_FATAL("Unknown permanence.");
1679 VK_CHECK(vkd.queueWaitIdle(queue));
1683 return tcu::TestStatus::pass("Pass");
1688 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
1692 tcu::TestStatus testSemaphoreFdDup2 (Context& context,
1693 const SemaphoreTestConfig config)
1695 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
1696 const Transference transference (getHandelTypeTransferences(config.externalType));
1697 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1698 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1699 const vk::InstanceDriver& vki (instance.getDriver());
1700 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1701 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1703 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1706 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1707 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1708 const vk::DeviceDriver vkd (vkp, instance, *device);
1709 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1710 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1712 TestLog& log = context.getTestContext().getLog();
1713 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1714 const vk::Unique<vk::VkSemaphore> semaphoreB (createExportableSemaphore(vkd, *device, config.externalType));
1717 NativeHandle fd, secondFd;
1719 if (transference == TRANSFERENCE_COPY)
1721 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, fd);
1722 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreB, config.externalType, secondFd);
1723 if (fd.getFd() == -1 || secondFd.getFd() == -1)
1724 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1728 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, fd);
1729 getSemaphoreNative(vkd, *device, *semaphoreB, config.externalType, secondFd);
1732 int newFd (dup2(fd.getFd(), secondFd.getFd()));
1735 log << TestLog::Message << "dup2() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
1737 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup2() for fences fd");
1740 const vk::Unique<vk::VkSemaphore> semaphoreC (createAndImportSemaphore(vkd, *device, config.externalType, secondFd, flags));
1742 if (transference == TRANSFERENCE_COPY)
1743 submitEmptyWait(vkd, queue, *semaphoreC);
1744 else if (transference == TRANSFERENCE_REFERENCE)
1746 submitEmptySignal(vkd, queue, *semaphoreA);
1747 submitEmptyWait(vkd, queue, *semaphoreC);
1750 DE_FATAL("Unknown permanence.");
1752 VK_CHECK(vkd.queueWaitIdle(queue));
1756 return tcu::TestStatus::pass("Pass");
1761 TCU_THROW(NotSupportedError, "Platform doesn't support dup2()");
1765 tcu::TestStatus testSemaphoreFdDup3 (Context& context,
1766 const SemaphoreTestConfig config)
1768 #if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
1769 const Transference transference (getHandelTypeTransferences(config.externalType));
1770 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1771 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1772 const vk::InstanceDriver& vki (instance.getDriver());
1773 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1774 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1776 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1779 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1780 const vk::DeviceDriver vkd (vkp, instance, *device);
1781 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1782 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1784 TestLog& log = context.getTestContext().getLog();
1785 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1786 const vk::Unique<vk::VkSemaphore> semaphoreB (createExportableSemaphore(vkd, *device, config.externalType));
1789 NativeHandle fd, secondFd;
1791 if (transference == TRANSFERENCE_COPY)
1793 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, fd);
1794 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreB, config.externalType, secondFd);
1795 if (fd.getFd() == -1 || secondFd.getFd() == -1)
1796 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1800 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, fd);
1801 getSemaphoreNative(vkd, *device, *semaphoreB, config.externalType, secondFd);
1804 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1805 const int newFd (dup3(fd.getFd(), secondFd.getFd(), 0));
1808 log << TestLog::Message << "dup3() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
1810 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup3() for fences fd");
1813 const vk::Unique<vk::VkSemaphore> semaphoreC (createAndImportSemaphore(vkd, *device, config.externalType, secondFd, flags));
1815 if (transference == TRANSFERENCE_COPY)
1816 submitEmptyWait(vkd, queue, *semaphoreC);
1817 else if (transference == TRANSFERENCE_REFERENCE)
1819 submitEmptySignal(vkd, queue, *semaphoreA);
1820 submitEmptyWait(vkd, queue, *semaphoreC);
1823 DE_FATAL("Unknown permanence.");
1825 VK_CHECK(vkd.queueWaitIdle(queue));
1829 return tcu::TestStatus::pass("Pass");
1834 TCU_THROW(NotSupportedError, "Platform doesn't support dup3()");
1838 tcu::TestStatus testSemaphoreFdSendOverSocket (Context& context,
1839 const SemaphoreTestConfig config)
1841 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
1842 const Transference transference (getHandelTypeTransferences(config.externalType));
1843 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1844 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1845 const vk::InstanceDriver& vki (instance.getDriver());
1846 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1847 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1849 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1852 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1853 const vk::DeviceDriver vkd (vkp, instance, *device);
1854 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1855 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1857 TestLog& log = context.getTestContext().getLog();
1858 const vk::Unique<vk::VkSemaphore> semaphore (createExportableSemaphore(vkd, *device, config.externalType));
1861 if (transference == TRANSFERENCE_COPY)
1863 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphore, config.externalType, fd);
1864 if (fd.getFd() == -1)
1865 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1868 getSemaphoreNative(vkd, *device, *semaphore, config.externalType, fd);
1873 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
1875 log << TestLog::Message << "Failed to create socket pair: '" << strerror(errno) << "'" << TestLog::EndMessage;
1876 TCU_FAIL("Failed to create socket pair");
1880 const NativeHandle srcSocket (sv[0]);
1881 const NativeHandle dstSocket (sv[1]);
1882 std::string sendData ("deqp");
1886 const int fdRaw (fd.getFd());
1889 char buffer[CMSG_SPACE(sizeof(int))];
1890 iovec iov = { &sendData[0], sendData.length()};
1892 deMemset(&msg, 0, sizeof(msg));
1894 msg.msg_control = buffer;
1895 msg.msg_controllen = sizeof(buffer);
1899 cmsg = CMSG_FIRSTHDR(&msg);
1900 cmsg->cmsg_level = SOL_SOCKET;
1901 cmsg->cmsg_type = SCM_RIGHTS;
1902 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
1904 deMemcpy(CMSG_DATA(cmsg), &fdRaw, sizeof(int));
1905 msg.msg_controllen = cmsg->cmsg_len;
1907 if (sendmsg(srcSocket.getFd(), &msg, 0) < 0)
1909 log << TestLog::Message << "Failed to send fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
1910 TCU_FAIL("Failed to send fd over socket");
1917 char buffer[CMSG_SPACE(sizeof(int))];
1918 std::string recvData (4, '\0');
1919 iovec iov = { &recvData[0], recvData.length() };
1921 deMemset(&msg, 0, sizeof(msg));
1923 msg.msg_control = buffer;
1924 msg.msg_controllen = sizeof(buffer);
1928 const ssize_t bytes = recvmsg(dstSocket.getFd(), &msg, 0);
1932 log << TestLog::Message << "Failed to recv fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
1933 TCU_FAIL("Failed to recv fd over socket");
1936 else if (bytes != (ssize_t)sendData.length())
1938 TCU_FAIL("recvmsg() returned unpexpected number of bytes");
1942 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1943 const cmsghdr* const cmsg = CMSG_FIRSTHDR(&msg);
1945 deMemcpy(&newFd_, CMSG_DATA(cmsg), sizeof(int));
1946 NativeHandle newFd (newFd_);
1948 TCU_CHECK(cmsg->cmsg_level == SOL_SOCKET);
1949 TCU_CHECK(cmsg->cmsg_type == SCM_RIGHTS);
1950 TCU_CHECK(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
1951 TCU_CHECK(recvData == sendData);
1952 TCU_CHECK_MSG(newFd.getFd() >= 0, "Didn't receive valid fd from socket");
1955 const vk::Unique<vk::VkSemaphore> newSemaphore (createAndImportSemaphore(vkd, *device, config.externalType, newFd, flags));
1957 if (transference == TRANSFERENCE_COPY)
1958 submitEmptyWait(vkd, queue, *newSemaphore);
1959 else if (transference == TRANSFERENCE_REFERENCE)
1961 submitEmptySignal(vkd, queue, *newSemaphore);
1962 submitEmptyWait(vkd, queue, *newSemaphore);
1965 DE_FATAL("Unknown permanence.");
1967 VK_CHECK(vkd.queueWaitIdle(queue));
1975 return tcu::TestStatus::pass("Pass");
1979 TCU_THROW(NotSupportedError, "Platform doesn't support sending file descriptors over socket");
1983 tcu::TestStatus testFenceQueries (Context& context, vk::VkExternalFenceHandleTypeFlagBits externalType)
1985 const CustomInstance instance (createTestInstance(context, 0u, 0u, externalType));
1986 const vk::InstanceDriver& vki (instance.getDriver());
1987 const vk::VkPhysicalDevice device (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1989 TestLog& log = context.getTestContext().getLog();
1991 const vk::VkPhysicalDeviceExternalFenceInfo info =
1993 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO,
1997 vk::VkExternalFenceProperties properties =
1999 vk::VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES,
2006 vki.getPhysicalDeviceExternalFenceProperties(device, &info, &properties);
2007 log << TestLog::Message << properties << TestLog::EndMessage;
2009 TCU_CHECK(properties.pNext == DE_NULL);
2010 TCU_CHECK(properties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES);
2012 return tcu::TestStatus::pass("Pass");
2015 struct FenceTestConfig
2017 FenceTestConfig (vk::VkExternalFenceHandleTypeFlagBits externalType_,
2018 Permanence permanence_)
2019 : externalType (externalType_)
2020 , permanence (permanence_)
2024 vk::VkExternalFenceHandleTypeFlagBits externalType;
2025 Permanence permanence;
2028 tcu::TestStatus testFenceWin32Create (Context& context,
2029 const FenceTestConfig config)
2031 #if (DE_OS == DE_OS_WIN32)
2032 const Transference transference (getHandelTypeTransferences(config.externalType));
2033 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2034 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2035 const vk::InstanceDriver& vki (instance.getDriver());
2036 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2037 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2039 checkFenceSupport(vki, physicalDevice, config.externalType);
2042 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2043 const vk::DeviceDriver vkd (vkp, instance, *device);
2044 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2045 const vk::VkExportFenceWin32HandleInfoKHR win32ExportInfo =
2047 vk::VK_STRUCTURE_TYPE_EXPORT_FENCE_WIN32_HANDLE_INFO_KHR,
2050 (vk::pt::Win32SecurityAttributesPtr)DE_NULL,
2051 DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
2052 (vk::pt::Win32LPCWSTR)DE_NULL
2054 const vk::VkExportFenceCreateInfo exportCreateInfo=
2056 vk::VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO,
2058 (vk::VkExternalFenceHandleTypeFlags)config.externalType
2060 const vk::VkFenceCreateInfo createInfo =
2062 vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
2066 const vk::Unique<vk::VkFence> fence (vk::createFence(vkd, *device, &createInfo));
2068 if (transference == TRANSFERENCE_COPY)
2069 submitEmptySignal(vkd, queue, *fence);
2071 NativeHandle handleA;
2072 getFenceNative(vkd, *device, *fence, config.externalType, handleA);
2075 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2076 const vk::Unique<vk::VkFence> fenceA (createAndImportFence(vkd, *device, config.externalType, handleA, flags));
2078 if (transference == TRANSFERENCE_COPY)
2079 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2080 else if (transference == TRANSFERENCE_REFERENCE)
2082 submitEmptySignal(vkd, queue, *fence);
2083 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2086 DE_FATAL("Unknown transference.");
2088 VK_CHECK(vkd.queueWaitIdle(queue));
2091 return tcu::TestStatus::pass("Pass");
2096 TCU_THROW(NotSupportedError, "Platform doesn't support win32 handles");
2100 tcu::TestStatus testFenceImportTwice (Context& context,
2101 const FenceTestConfig config)
2103 const Transference transference (getHandelTypeTransferences(config.externalType));
2104 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2105 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2106 const vk::InstanceDriver& vki (instance.getDriver());
2107 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2108 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2110 checkFenceSupport(vki, physicalDevice, config.externalType);
2113 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2114 const vk::DeviceDriver vkd (vkp, instance, *device);
2115 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2116 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2117 const vk::Unique<vk::VkFence> fence (createExportableFence(vkd, *device, config.externalType));
2118 NativeHandle handleA;
2120 if (transference == TRANSFERENCE_COPY)
2122 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fence, config.externalType, handleA);
2123 if (handleA.getFd() == -1)
2124 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2127 getFenceNative(vkd, *device, *fence, config.externalType, handleA);
2130 NativeHandle handleB (handleA);
2131 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2132 const vk::Unique<vk::VkFence> fenceA (createAndImportFence(vkd, *device, config.externalType, handleA, flags));
2133 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handleB, flags));
2135 if (transference == TRANSFERENCE_COPY)
2136 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2137 else if (transference == TRANSFERENCE_REFERENCE)
2139 submitEmptySignal(vkd, queue, *fenceA);
2140 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2143 DE_FATAL("Unknown transference.");
2145 VK_CHECK(vkd.queueWaitIdle(queue));
2148 return tcu::TestStatus::pass("Pass");
2152 tcu::TestStatus testFenceImportReimport (Context& context,
2153 const FenceTestConfig config)
2155 const Transference transference (getHandelTypeTransferences(config.externalType));
2156 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2157 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2158 const vk::InstanceDriver& vki (instance.getDriver());
2159 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2160 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2162 checkFenceSupport(vki, physicalDevice, config.externalType);
2165 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2166 const vk::DeviceDriver vkd (vkp, instance, *device);
2167 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2168 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2170 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2171 NativeHandle handleA;
2173 if (transference == TRANSFERENCE_COPY)
2175 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, handleA);
2176 if (handleA.getFd() == -1)
2177 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2180 getFenceNative(vkd, *device, *fenceA, config.externalType, handleA);
2182 NativeHandle handleB (handleA);
2183 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2184 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handleA, flags));
2186 importFence(vkd, *device, *fenceB, config.externalType, handleB, flags);
2188 if (transference == TRANSFERENCE_COPY)
2189 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2190 else if (transference == TRANSFERENCE_REFERENCE)
2192 submitEmptySignal(vkd, queue, *fenceA);
2193 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2196 DE_FATAL("Unknown transference.");
2198 VK_CHECK(vkd.queueWaitIdle(queue));
2200 return tcu::TestStatus::pass("Pass");
2204 tcu::TestStatus testFenceSignalExportImportWait (Context& context,
2205 const FenceTestConfig config)
2207 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2208 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2209 const vk::InstanceDriver& vki (instance.getDriver());
2210 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2211 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2213 checkFenceSupport(vki, physicalDevice, config.externalType);
2216 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2217 const vk::DeviceDriver vkd (vkp, instance, *device);
2218 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2219 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2220 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2223 NativeHandle handle;
2225 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2226 if (handle.getFd() == -1)
2227 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2230 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2231 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handle, flags));
2232 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2234 VK_CHECK(vkd.queueWaitIdle(queue));
2238 return tcu::TestStatus::pass("Pass");
2242 tcu::TestStatus testFenceImportSyncFdSignaled (Context& context,
2243 const FenceTestConfig config)
2245 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2246 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2247 const vk::InstanceDriver& vki (instance.getDriver());
2248 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2249 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2250 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2252 checkFenceSupport(vki, physicalDevice, config.externalType);
2255 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2256 const vk::DeviceDriver vkd (vkp, instance, *device);
2257 NativeHandle handle = -1;
2258 const vk::Unique<vk::VkFence> fence (createAndImportFence(vkd, *device, config.externalType, handle, flags));
2260 if (vkd.waitForFences(*device, 1u, &*fence, VK_TRUE, 0) != vk::VK_SUCCESS)
2261 return tcu::TestStatus::pass("Imported -1 sync fd isn't signaled");
2263 return tcu::TestStatus::pass("Pass");
2267 tcu::TestStatus testFenceExportSignalImportWait (Context& context,
2268 const FenceTestConfig config)
2270 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2271 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2272 const vk::InstanceDriver& vki (instance.getDriver());
2273 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2274 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2275 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2277 DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
2278 checkFenceSupport(vki, physicalDevice, config.externalType);
2281 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2282 const vk::DeviceDriver vkd (vkp, instance, *device);
2283 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2285 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2286 NativeHandle handle;
2288 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2290 submitEmptySignal(vkd, queue, *fenceA);
2293 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handle, flags));
2295 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2296 VK_CHECK(vkd.queueWaitIdle(queue));
2300 return tcu::TestStatus::pass("Pass");
2304 tcu::TestStatus testFenceExportImportSignalWait (Context& context,
2305 const FenceTestConfig config)
2307 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2308 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2309 const vk::InstanceDriver& vki (instance.getDriver());
2310 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2311 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2313 DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
2314 checkFenceSupport(vki, physicalDevice, config.externalType);
2317 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2318 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2319 const vk::DeviceDriver vkd (vkp, instance, *device);
2320 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2322 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2323 NativeHandle handle;
2325 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2327 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handle, flags));
2329 submitEmptySignal(vkd, queue, *fenceA);
2330 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2332 VK_CHECK(vkd.queueWaitIdle(queue));
2334 return tcu::TestStatus::pass("Pass");
2338 tcu::TestStatus testFenceSignalImport (Context& context,
2339 const FenceTestConfig config)
2341 const Transference transference (getHandelTypeTransferences(config.externalType));
2342 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2343 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2344 const vk::InstanceDriver& vki (instance.getDriver());
2345 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2346 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2348 checkFenceSupport(vki, physicalDevice, config.externalType);
2351 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2352 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2353 const vk::DeviceDriver vkd (vkp, instance, *device);
2354 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2355 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2357 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2358 const vk::Unique<vk::VkFence> fenceB (createFence(vkd, *device));
2359 NativeHandle handle;
2361 submitEmptySignal(vkd, queue, *fenceB);
2362 VK_CHECK(vkd.queueWaitIdle(queue));
2364 if (transference == TRANSFERENCE_COPY)
2366 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2367 if (handle.getFd() == -1)
2368 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2371 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2373 importFence(vkd, *device, *fenceB, config.externalType, handle, flags);
2375 if (transference == TRANSFERENCE_COPY)
2376 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2377 else if (transference == TRANSFERENCE_REFERENCE)
2379 submitEmptySignal(vkd, queue, *fenceA);
2380 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2383 DE_FATAL("Unknown transference.");
2385 VK_CHECK(vkd.queueWaitIdle(queue));
2387 return tcu::TestStatus::pass("Pass");
2391 tcu::TestStatus testFenceReset (Context& context,
2392 const FenceTestConfig config)
2394 const Transference transference (getHandelTypeTransferences(config.externalType));
2395 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2396 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2397 const vk::InstanceDriver& vki (instance.getDriver());
2398 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2399 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2401 checkFenceSupport(vki, physicalDevice, config.externalType);
2404 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2405 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2406 const vk::DeviceDriver vkd (vkp, instance, *device);
2407 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2408 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2410 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2411 const vk::Unique<vk::VkFence> fenceB (createFence(vkd, *device));
2412 const vk::Unique<vk::VkFence> fenceC (createFence(vkd, *device));
2413 NativeHandle handle;
2415 submitEmptySignal(vkd, queue, *fenceB);
2416 VK_CHECK(vkd.queueWaitIdle(queue));
2418 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2419 if (handle.getFd() == -1)
2420 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2422 NativeHandle handleB (handle);
2423 importFence(vkd, *device, *fenceB, config.externalType, handleB, flags);
2424 importFence(vkd, *device, *fenceC, config.externalType, handle, flags);
2426 VK_CHECK(vkd.queueWaitIdle(queue));
2427 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2429 if (config.permanence == PERMANENCE_TEMPORARY || transference == TRANSFERENCE_COPY)
2431 // vkResetFences() should restore fenceBs prior payload and reset that no affecting fenceCs payload
2432 // or fenceB should be separate copy of the payload and not affect fenceC
2433 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2435 // vkResetFences() should have restored fenceBs prior state and should be now reset
2436 // or fenceB should have it's separate payload
2437 submitEmptySignal(vkd, queue, *fenceB);
2438 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2440 else if (config.permanence == PERMANENCE_PERMANENT)
2442 DE_ASSERT(transference == TRANSFERENCE_REFERENCE);
2444 // Reset fences should have reset all of the fences
2445 submitEmptySignal(vkd, queue, *fenceC);
2447 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2448 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2449 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2452 DE_FATAL("Unknown permanence");
2454 VK_CHECK(vkd.queueWaitIdle(queue));
2456 return tcu::TestStatus::pass("Pass");
2460 tcu::TestStatus testFenceSignalWaitImport (Context& context,
2461 const FenceTestConfig config)
2463 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2464 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2465 const vk::InstanceDriver& vki (instance.getDriver());
2466 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2467 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2469 checkFenceSupport(vki, physicalDevice, config.externalType);
2472 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2473 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2474 const vk::DeviceDriver vkd (vkp, instance, *device);
2475 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2477 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2478 const vk::Unique<vk::VkFence> fenceB (createFence(vkd, *device));
2479 NativeHandle handle;
2481 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2483 submitEmptySignal(vkd, queue, *fenceB);
2484 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2486 VK_CHECK(vkd.queueWaitIdle(queue));
2488 importFence(vkd, *device, *fenceB, config.externalType, handle, flags);
2490 submitEmptySignal(vkd, queue, *fenceA);
2491 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2493 VK_CHECK(vkd.queueWaitIdle(queue));
2495 return tcu::TestStatus::pass("Pass");
2499 tcu::TestStatus testFenceMultipleExports (Context& context,
2500 const FenceTestConfig config)
2502 const size_t exportCount = 1024;
2503 const Transference transference (getHandelTypeTransferences(config.externalType));
2504 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2505 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2506 const vk::InstanceDriver& vki (instance.getDriver());
2507 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2508 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2510 checkFenceSupport(vki, physicalDevice, config.externalType);
2513 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2514 const vk::DeviceDriver vkd (vkp, instance, *device);
2515 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2516 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2517 const vk::Unique<vk::VkFence> fence (createExportableFence(vkd, *device, config.externalType));
2519 for (size_t exportNdx = 0; exportNdx < exportCount; exportNdx++)
2521 NativeHandle handle;
2523 // Need to touch watchdog due to how long one iteration takes
2524 context.getTestContext().touchWatchdog();
2526 if (transference == TRANSFERENCE_COPY)
2528 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fence, config.externalType, handle, exportNdx == 0 /* expect fence to be signaled after first pass */);
2529 if (handle.getFd() == -1)
2530 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2533 getFenceNative(vkd, *device, *fence, config.externalType, handle, exportNdx == 0 /* expect fence to be signaled after first pass */);
2536 submitEmptySignal(vkd, queue, *fence);
2537 VK_CHECK(vkd.waitForFences(*device, 1u, &*fence, VK_TRUE, ~0ull));
2539 VK_CHECK(vkd.queueWaitIdle(queue));
2542 return tcu::TestStatus::pass("Pass");
2545 tcu::TestStatus testFenceMultipleImports (Context& context,
2546 const FenceTestConfig config)
2548 const size_t importCount = 4 * 1024;
2549 const Transference transference (getHandelTypeTransferences(config.externalType));
2550 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2551 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2552 const vk::InstanceDriver& vki (instance.getDriver());
2553 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2554 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2556 checkFenceSupport(vki, physicalDevice, config.externalType);
2559 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2560 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2561 const vk::DeviceDriver vkd (vkp, instance, *device);
2562 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2563 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2564 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2565 NativeHandle handleA;
2567 if (transference == TRANSFERENCE_COPY)
2569 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, handleA);
2570 if (handleA.getFd() == -1)
2571 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2574 getFenceNative(vkd, *device, *fenceA, config.externalType, handleA);
2576 for (size_t importNdx = 0; importNdx < importCount; importNdx++)
2578 NativeHandle handleB (handleA);
2579 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handleB, flags));
2582 if (transference == TRANSFERENCE_COPY)
2584 importFence(vkd, *device, *fenceA, config.externalType, handleA, flags);
2585 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2587 else if (transference == TRANSFERENCE_REFERENCE)
2589 submitEmptySignal(vkd, queue, *fenceA);
2590 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2593 DE_FATAL("Unknown transference.");
2595 VK_CHECK(vkd.queueWaitIdle(queue));
2598 return tcu::TestStatus::pass("Pass");
2601 tcu::TestStatus testFenceTransference (Context& context,
2602 const FenceTestConfig config)
2604 const Transference transference (getHandelTypeTransferences(config.externalType));
2605 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2606 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2607 const vk::InstanceDriver& vki (instance.getDriver());
2608 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2609 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2611 checkFenceSupport(vki, physicalDevice, config.externalType);
2614 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2615 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2616 const vk::DeviceDriver vkd (vkp, instance, *device);
2617 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2618 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2620 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2621 NativeHandle handle;
2623 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2624 if (handle.getFd() == -1)
2625 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2628 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handle, flags));
2630 if (config.permanence == PERMANENCE_PERMANENT)
2632 if (transference == TRANSFERENCE_COPY)
2634 submitEmptySignal(vkd, queue, *fenceA);
2635 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2636 VK_CHECK(vkd.queueWaitIdle(queue));
2638 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2639 submitEmptySignal(vkd, queue, *fenceB);
2641 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2642 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2643 VK_CHECK(vkd.queueWaitIdle(queue));
2645 else if (transference== TRANSFERENCE_REFERENCE)
2647 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2648 VK_CHECK(vkd.queueWaitIdle(queue));
2650 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2651 submitEmptySignal(vkd, queue, *fenceA);
2652 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2654 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceA));
2655 submitEmptySignal(vkd, queue, *fenceB);
2656 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2657 VK_CHECK(vkd.queueWaitIdle(queue));
2660 DE_FATAL("Unknown transference.");
2662 else if (config.permanence == PERMANENCE_TEMPORARY)
2664 if (transference == TRANSFERENCE_COPY)
2666 submitEmptySignal(vkd, queue, *fenceA);
2667 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2668 VK_CHECK(vkd.queueWaitIdle(queue));
2670 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2671 submitEmptySignal(vkd, queue, *fenceB);
2673 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2674 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2675 VK_CHECK(vkd.queueWaitIdle(queue));
2677 else if (transference == TRANSFERENCE_REFERENCE)
2679 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2680 VK_CHECK(vkd.queueWaitIdle(queue));
2682 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceA));
2683 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2684 submitEmptySignal(vkd, queue, *fenceA);
2685 submitEmptySignal(vkd, queue, *fenceB);
2687 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2688 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2689 VK_CHECK(vkd.queueWaitIdle(queue));
2692 DE_FATAL("Unknown transference.");
2695 DE_FATAL("Unknown permanence.");
2698 return tcu::TestStatus::pass("Pass");
2702 tcu::TestStatus testFenceFdDup (Context& context,
2703 const FenceTestConfig config)
2705 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2706 const Transference transference (getHandelTypeTransferences(config.externalType));
2707 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2708 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2709 const vk::InstanceDriver& vki (instance.getDriver());
2710 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2711 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2713 checkFenceSupport(vki, physicalDevice, config.externalType);
2716 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2717 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2718 const vk::DeviceDriver vkd (vkp, instance, *device);
2719 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2720 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2722 TestLog& log = context.getTestContext().getLog();
2723 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2728 if (transference == TRANSFERENCE_COPY)
2730 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, fd);
2731 if (fd.getFd() == -1)
2732 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2735 getFenceNative(vkd, *device, *fenceA, config.externalType, fd);
2737 NativeHandle newFd (dup(fd.getFd()));
2739 if (newFd.getFd() < 0)
2740 log << TestLog::Message << "dup() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2742 TCU_CHECK_MSG(newFd.getFd() >= 0, "Failed to call dup() for fences fd");
2745 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, newFd, flags));
2747 if (transference == TRANSFERENCE_COPY)
2748 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2749 else if (transference == TRANSFERENCE_REFERENCE)
2751 submitEmptySignal(vkd, queue, *fenceA);
2752 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2755 DE_FATAL("Unknown permanence.");
2757 VK_CHECK(vkd.queueWaitIdle(queue));
2761 return tcu::TestStatus::pass("Pass");
2766 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
2770 tcu::TestStatus testFenceFdDup2 (Context& context,
2771 const FenceTestConfig config)
2773 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2774 const Transference transference (getHandelTypeTransferences(config.externalType));
2775 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2776 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2777 const vk::InstanceDriver& vki (instance.getDriver());
2778 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2779 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2781 checkFenceSupport(vki, physicalDevice, config.externalType);
2784 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2785 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2786 const vk::DeviceDriver vkd (vkp, instance, *device);
2787 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2788 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2790 TestLog& log = context.getTestContext().getLog();
2791 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2792 const vk::Unique<vk::VkFence> fenceB (createExportableFence(vkd, *device, config.externalType));
2795 NativeHandle fd, secondFd;
2797 if (transference == TRANSFERENCE_COPY)
2799 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, fd);
2800 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceB, config.externalType, secondFd);
2801 if (fd.getFd() == -1 || secondFd.getFd() == -1)
2802 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2806 getFenceNative(vkd, *device, *fenceA, config.externalType, fd);
2807 getFenceNative(vkd, *device, *fenceB, config.externalType, secondFd);
2810 int newFd (dup2(fd.getFd(), secondFd.getFd()));
2813 log << TestLog::Message << "dup2() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2815 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup2() for fences fd");
2818 const vk::Unique<vk::VkFence> fenceC (createAndImportFence(vkd, *device, config.externalType, secondFd, flags));
2820 if (transference == TRANSFERENCE_COPY)
2821 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2822 else if (transference == TRANSFERENCE_REFERENCE)
2824 submitEmptySignal(vkd, queue, *fenceA);
2825 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2828 DE_FATAL("Unknown permanence.");
2830 VK_CHECK(vkd.queueWaitIdle(queue));
2834 return tcu::TestStatus::pass("Pass");
2839 TCU_THROW(NotSupportedError, "Platform doesn't support dup2()");
2843 tcu::TestStatus testFenceFdDup3 (Context& context,
2844 const FenceTestConfig config)
2846 #if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
2847 const Transference transference (getHandelTypeTransferences(config.externalType));
2848 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2849 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2850 const vk::InstanceDriver& vki (instance.getDriver());
2851 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2852 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2854 checkFenceSupport(vki, physicalDevice, config.externalType);
2857 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2858 const vk::DeviceDriver vkd (vkp, instance, *device);
2859 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2860 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2862 TestLog& log = context.getTestContext().getLog();
2863 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2864 const vk::Unique<vk::VkFence> fenceB (createExportableFence(vkd, *device, config.externalType));
2867 NativeHandle fd, secondFd;
2869 if (transference == TRANSFERENCE_COPY)
2871 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, fd);
2872 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceB, config.externalType, secondFd);
2873 if (fd.getFd() == -1 || secondFd.getFd() == -1)
2874 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2878 getFenceNative(vkd, *device, *fenceA, config.externalType, fd);
2879 getFenceNative(vkd, *device, *fenceB, config.externalType, secondFd);
2882 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2883 const int newFd (dup3(fd.getFd(), secondFd.getFd(), 0));
2886 log << TestLog::Message << "dup3() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2888 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup3() for fences fd");
2891 const vk::Unique<vk::VkFence> fenceC (createAndImportFence(vkd, *device, config.externalType, secondFd, flags));
2893 if (transference == TRANSFERENCE_COPY)
2894 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2895 else if (transference == TRANSFERENCE_REFERENCE)
2897 submitEmptySignal(vkd, queue, *fenceA);
2898 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2901 DE_FATAL("Unknown permanence.");
2903 VK_CHECK(vkd.queueWaitIdle(queue));
2907 return tcu::TestStatus::pass("Pass");
2912 TCU_THROW(NotSupportedError, "Platform doesn't support dup3()");
2916 tcu::TestStatus testFenceFdSendOverSocket (Context& context,
2917 const FenceTestConfig config)
2919 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2920 const Transference transference (getHandelTypeTransferences(config.externalType));
2921 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2922 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2923 const vk::InstanceDriver& vki (instance.getDriver());
2924 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2925 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2927 checkFenceSupport(vki, physicalDevice, config.externalType);
2930 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2931 const vk::DeviceDriver vkd (vkp, instance, *device);
2932 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2933 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2935 TestLog& log = context.getTestContext().getLog();
2936 const vk::Unique<vk::VkFence> fence (createExportableFence(vkd, *device, config.externalType));
2939 if (transference == TRANSFERENCE_COPY)
2941 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fence, config.externalType, fd);
2942 if (fd.getFd() == -1)
2943 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2946 getFenceNative(vkd, *device, *fence, config.externalType, fd);
2951 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
2953 log << TestLog::Message << "Failed to create socket pair: '" << strerror(errno) << "'" << TestLog::EndMessage;
2954 TCU_FAIL("Failed to create socket pair");
2958 const NativeHandle srcSocket (sv[0]);
2959 const NativeHandle dstSocket (sv[1]);
2960 std::string sendData ("deqp");
2964 const int fdRaw (fd.getFd());
2967 char buffer[CMSG_SPACE(sizeof(int))];
2968 iovec iov = { &sendData[0], sendData.length()};
2970 deMemset(&msg, 0, sizeof(msg));
2972 msg.msg_control = buffer;
2973 msg.msg_controllen = sizeof(buffer);
2977 cmsg = CMSG_FIRSTHDR(&msg);
2978 cmsg->cmsg_level = SOL_SOCKET;
2979 cmsg->cmsg_type = SCM_RIGHTS;
2980 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
2982 deMemcpy(CMSG_DATA(cmsg), &fdRaw, sizeof(int));
2983 msg.msg_controllen = cmsg->cmsg_len;
2985 if (sendmsg(srcSocket.getFd(), &msg, 0) < 0)
2987 log << TestLog::Message << "Failed to send fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
2988 TCU_FAIL("Failed to send fd over socket");
2995 char buffer[CMSG_SPACE(sizeof(int))];
2996 std::string recvData (4, '\0');
2997 iovec iov = { &recvData[0], recvData.length() };
2999 deMemset(&msg, 0, sizeof(msg));
3001 msg.msg_control = buffer;
3002 msg.msg_controllen = sizeof(buffer);
3006 const ssize_t bytes = recvmsg(dstSocket.getFd(), &msg, 0);
3010 log << TestLog::Message << "Failed to recv fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
3011 TCU_FAIL("Failed to recv fd over socket");
3014 else if (bytes != (ssize_t)sendData.length())
3016 TCU_FAIL("recvmsg() returned unpexpected number of bytes");
3020 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
3021 const cmsghdr* const cmsg = CMSG_FIRSTHDR(&msg);
3023 deMemcpy(&newFd_, CMSG_DATA(cmsg), sizeof(int));
3024 NativeHandle newFd (newFd_);
3026 TCU_CHECK(cmsg->cmsg_level == SOL_SOCKET);
3027 TCU_CHECK(cmsg->cmsg_type == SCM_RIGHTS);
3028 TCU_CHECK(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
3029 TCU_CHECK(recvData == sendData);
3030 TCU_CHECK_MSG(newFd.getFd() >= 0, "Didn't receive valid fd from socket");
3033 const vk::Unique<vk::VkFence> newFence (createAndImportFence(vkd, *device, config.externalType, newFd, flags));
3035 if (transference == TRANSFERENCE_COPY)
3036 VK_CHECK(vkd.waitForFences(*device, 1u, &*newFence, VK_TRUE, ~0ull));
3037 else if (transference == TRANSFERENCE_REFERENCE)
3039 submitEmptySignal(vkd, queue, *newFence);
3040 VK_CHECK(vkd.waitForFences(*device, 1u, &*newFence, VK_TRUE, ~0ull));
3043 DE_FATAL("Unknown permanence.");
3045 VK_CHECK(vkd.queueWaitIdle(queue));
3053 return tcu::TestStatus::pass("Pass");
3057 TCU_THROW(NotSupportedError, "Platform doesn't support sending file descriptors over socket");
3061 tcu::TestStatus testBufferQueries (Context& context, vk::VkExternalMemoryHandleTypeFlagBits externalType)
3063 const vk::VkBufferCreateFlags createFlags[] =
3066 vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT,
3067 vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT|vk::VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT,
3068 vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT|vk::VK_BUFFER_CREATE_SPARSE_ALIASED_BIT
3070 const vk::VkBufferUsageFlags usageFlags[] =
3072 vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
3073 vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT,
3074 vk::VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT,
3075 vk::VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT,
3076 vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
3077 vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
3078 vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
3079 vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
3080 vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT
3082 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3083 const CustomInstance instance (createTestInstance(context, 0u, externalType, 0u));
3084 const vk::InstanceDriver& vki (instance.getDriver());
3085 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3086 const vk::VkPhysicalDeviceFeatures deviceFeatures (vk::getPhysicalDeviceFeatures(vki, physicalDevice));
3087 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3089 // VkDevice is only created if physical device claims to support any of these types.
3090 vk::Move<vk::VkDevice> device;
3091 de::MovePtr<vk::DeviceDriver> vkd;
3092 bool deviceHasDedicated = false;
3094 TestLog& log = context.getTestContext().getLog();
3096 for (size_t createFlagNdx = 0; createFlagNdx < DE_LENGTH_OF_ARRAY(createFlags); createFlagNdx++)
3097 for (size_t usageFlagNdx = 0; usageFlagNdx < DE_LENGTH_OF_ARRAY(usageFlags); usageFlagNdx++)
3099 const vk::VkBufferViewCreateFlags createFlag = createFlags[createFlagNdx];
3100 const vk::VkBufferUsageFlags usageFlag = usageFlags[usageFlagNdx];
3101 const vk::VkPhysicalDeviceExternalBufferInfo info =
3103 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO,
3109 vk::VkExternalBufferProperties properties =
3111 vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES,
3116 if (((createFlag & vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT) != 0) &&
3117 (deviceFeatures.sparseBinding == VK_FALSE))
3120 if (((createFlag & vk::VK_BUFFER_CREATE_SPARSE_ALIASED_BIT) != 0) &&
3121 (deviceFeatures.sparseResidencyAliased == VK_FALSE))
3124 if (((createFlag & vk::VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT) != 0) &&
3125 (deviceFeatures.sparseResidencyBuffer == VK_FALSE))
3128 vki.getPhysicalDeviceExternalBufferProperties(physicalDevice, &info, &properties);
3130 log << TestLog::Message << properties << TestLog::EndMessage;
3132 TCU_CHECK(properties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES);
3133 TCU_CHECK(properties.pNext == DE_NULL);
3134 // \todo [2017-06-06 pyry] Can we validate anything else? Compatible types?
3136 if ((properties.externalMemoryProperties.externalMemoryFeatures & (vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT|vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT)) != 0)
3138 const bool requiresDedicated = (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
3140 if (!device || (requiresDedicated && !deviceHasDedicated))
3142 // \note We need to re-create with dedicated mem extensions if previous device instance didn't have them
3145 device = createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, externalType, 0u, queueFamilyIndex, requiresDedicated);
3146 vkd = de::MovePtr<vk::DeviceDriver>(new vk::DeviceDriver(vkp, instance, *device));
3147 deviceHasDedicated = requiresDedicated;
3149 catch (const tcu::NotSupportedError& e)
3152 TCU_FAIL("Physical device claims to support handle type but required extensions are not supported");
3157 if ((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) != 0)
3159 DE_ASSERT(!!device);
3162 if (deviceHasDedicated)
3164 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(*vkd, *device, queueFamilyIndex, externalType, 1024u, createFlag, usageFlag));
3165 const vk::VkMemoryDedicatedRequirements reqs (getMemoryDedicatedRequirements(*vkd, *device, *buffer));
3166 const bool propertiesRequiresDedicated = (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
3167 const bool objectRequiresDedicated = (reqs.requiresDedicatedAllocation != VK_FALSE);
3169 if (propertiesRequiresDedicated != objectRequiresDedicated)
3170 TCU_FAIL("vkGetPhysicalDeviceExternalBufferProperties and vkGetBufferMemoryRequirements2 report different dedicated requirements");
3174 // We can't query whether dedicated memory is required or not on per-object basis.
3175 // This check should be redundant as the code above tries to create device with
3176 // VK_KHR_dedicated_allocation & VK_KHR_get_memory_requirements2 if dedicated memory
3177 // is required. However, checking again doesn't hurt.
3178 TCU_CHECK((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) == 0);
3183 return tcu::TestStatus::pass("Pass");
3186 struct MemoryTestConfig
3188 MemoryTestConfig (vk::VkExternalMemoryHandleTypeFlagBits externalType_,
3191 : externalType (externalType_)
3192 , hostVisible (hostVisible_)
3193 , dedicated (dedicated_)
3197 vk::VkExternalMemoryHandleTypeFlagBits externalType;
3202 #if (DE_OS == DE_OS_WIN32)
3203 deUint32 chooseWin32MemoryType(deUint32 bits)
3206 TCU_THROW(NotSupportedError, "No compatible memory type found");
3208 return deCtz32(bits);
3212 tcu::TestStatus testMemoryWin32Create (Context& context, MemoryTestConfig config)
3214 #if (DE_OS == DE_OS_WIN32)
3215 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3216 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3217 const vk::InstanceDriver& vki (instance.getDriver());
3218 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3219 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3220 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3221 const vk::DeviceDriver vkd (vkp, instance, *device);
3222 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3223 const deUint32 seed = 1261033864u;
3224 const vk::VkDeviceSize bufferSize = 1024;
3225 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
3227 const vk::VkPhysicalDeviceMemoryProperties memoryProps = vk::getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice());
3228 const deUint32 compatibleMemTypes = vk::getCompatibleMemoryTypes(memoryProps, config.hostVisible ? vk::MemoryRequirement::HostVisible : vk::MemoryRequirement::Any);
3230 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3232 // \note Buffer is only allocated to get memory requirements
3233 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3234 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3235 const vk::VkExportMemoryWin32HandleInfoKHR win32Info =
3237 vk::VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR,
3240 (vk::pt::Win32SecurityAttributesPtr)DE_NULL,
3241 DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
3242 (vk::pt::Win32LPCWSTR)DE_NULL
3244 const vk::VkExportMemoryAllocateInfo exportInfo =
3246 vk::VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
3248 (vk::VkExternalMemoryHandleTypeFlags)config.externalType
3251 const deUint32 exportedMemoryTypeIndex = chooseWin32MemoryType(requirements.memoryTypeBits & compatibleMemTypes);
3252 const vk::VkMemoryAllocateInfo info =
3254 vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
3257 exportedMemoryTypeIndex
3259 const vk::Unique<vk::VkDeviceMemory> memory (vk::allocateMemory(vkd, *device, &info));
3260 NativeHandle handleA;
3262 if (config.hostVisible)
3263 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3265 getMemoryNative(vkd, *device, *memory, config.externalType, handleA);
3268 const vk::Unique<vk::VkDeviceMemory> memoryA (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleA));
3270 if (config.hostVisible)
3272 const std::vector<deUint8> testDataA (genTestData(seed ^ 124798807u, (size_t)bufferSize));
3273 const std::vector<deUint8> testDataB (genTestData(seed ^ 970834278u, (size_t)bufferSize));
3275 checkHostMemory(vkd, *device, *memoryA, testData.size(), &testData[0]);
3276 checkHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3278 writeHostMemory(vkd, *device, *memoryA, testDataA.size(), &testDataA[0]);
3279 writeHostMemory(vkd, *device, *memory, testDataA.size(), &testDataB[0]);
3281 checkHostMemory(vkd, *device, *memoryA, testData.size(), &testDataB[0]);
3282 checkHostMemory(vkd, *device, *memory, testData.size(), &testDataB[0]);
3286 return tcu::TestStatus::pass("Pass");
3290 TCU_THROW(NotSupportedError, "Platform doesn't support win32 handles");
3294 deUint32 getExportedMemoryTypeIndex(const vk::InstanceDriver& vki, const vk::VkPhysicalDevice physicalDevice, bool hostVisible, deUint32 memoryBits)
3298 const vk::VkPhysicalDeviceMemoryProperties properties(vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
3299 return chooseHostVisibleMemoryType(memoryBits, properties);
3302 return chooseMemoryType(memoryBits);
3305 tcu::TestStatus testMemoryImportTwice (Context& context, MemoryTestConfig config)
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));
3312 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3313 const vk::DeviceDriver vkd (vkp, instance, *device);
3314 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3315 const deUint32 seed = 1261033864u;
3316 const vk::VkDeviceSize bufferSize = 1024;
3317 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
3319 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3321 // \note Buffer is only allocated to get memory requirements
3322 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3323 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3324 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3325 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3326 NativeHandle handleA;
3328 if (config.hostVisible)
3329 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3331 getMemoryNative(vkd, *device, *memory, config.externalType, handleA);
3334 const vk::Unique<vk::VkBuffer> bufferA (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3335 const vk::Unique<vk::VkBuffer> bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3336 NativeHandle handleB (handleA);
3337 const vk::Unique<vk::VkDeviceMemory> memoryA (config.dedicated
3338 ? importDedicatedMemory(vkd, *device, *bufferA, requirements, config.externalType, exportedMemoryTypeIndex, handleA)
3339 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleA));
3340 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3341 ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handleB)
3342 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleB));
3344 if (config.hostVisible)
3346 const std::vector<deUint8> testDataA (genTestData(seed ^ 124798807u, (size_t)bufferSize));
3347 const std::vector<deUint8> testDataB (genTestData(seed ^ 970834278u, (size_t)bufferSize));
3349 checkHostMemory(vkd, *device, *memoryA, testData.size(), &testData[0]);
3350 checkHostMemory(vkd, *device, *memoryB, testData.size(), &testData[0]);
3352 writeHostMemory(vkd, *device, *memoryA, testData.size(), &testDataA[0]);
3353 writeHostMemory(vkd, *device, *memoryB, testData.size(), &testDataB[0]);
3355 checkHostMemory(vkd, *device, *memoryA, testData.size(), &testDataB[0]);
3356 checkHostMemory(vkd, *device, *memory, testData.size(), &testDataB[0]);
3360 return tcu::TestStatus::pass("Pass");
3363 tcu::TestStatus testMemoryMultipleImports (Context& context, MemoryTestConfig config)
3365 const size_t count = 4 * 1024;
3366 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3367 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3368 const vk::InstanceDriver& vki (instance.getDriver());
3369 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3370 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3371 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3372 const vk::DeviceDriver vkd (vkp, instance, *device);
3373 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3374 const vk::VkDeviceSize bufferSize = 1024;
3376 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3378 // \note Buffer is only allocated to get memory requirements
3379 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3380 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3381 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3382 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3383 NativeHandle handleA;
3385 getMemoryNative(vkd, *device, *memory, config.externalType, handleA);
3387 for (size_t ndx = 0; ndx < count; ndx++)
3389 const vk::Unique<vk::VkBuffer> bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3390 NativeHandle handleB (handleA);
3391 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3392 ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handleB)
3393 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleB));
3396 return tcu::TestStatus::pass("Pass");
3399 tcu::TestStatus testMemoryMultipleExports (Context& context, MemoryTestConfig config)
3401 const size_t count = 4 * 1024;
3402 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3403 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3404 const vk::InstanceDriver& vki (instance.getDriver());
3405 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3406 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3407 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3408 const vk::DeviceDriver vkd (vkp, instance, *device);
3409 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3410 const vk::VkDeviceSize bufferSize = 1024;
3412 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3414 // \note Buffer is only allocated to get memory requirements
3415 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3416 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3417 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3418 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3420 for (size_t ndx = 0; ndx < count; ndx++)
3422 NativeHandle handle;
3423 getMemoryNative(vkd, *device, *memory, config.externalType, handle);
3426 return tcu::TestStatus::pass("Pass");
3429 tcu::TestStatus testMemoryFdProperties (Context& context, MemoryTestConfig config)
3431 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3432 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3433 const vk::InstanceDriver& vki (instance.getDriver());
3434 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3435 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3436 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3437 const vk::DeviceDriver vkd (vkp, instance, *device);
3438 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3439 const vk::VkDeviceSize bufferSize = 1024;
3441 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3443 // \note Buffer is only allocated to get memory requirements
3444 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3445 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3446 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3447 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3449 vk::VkMemoryFdPropertiesKHR properties;
3450 NativeHandle handle;
3452 getMemoryNative(vkd, *device, *memory, config.externalType, handle);
3453 properties.sType = vk::VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR;
3454 vk::VkResult res = vkd.getMemoryFdPropertiesKHR(*device, config.externalType, handle.getFd(), &properties);
3456 switch (config.externalType)
3458 case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
3459 TCU_CHECK_MSG(res == vk::VK_SUCCESS, "vkGetMemoryFdPropertiesKHR failed for VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT");
3462 // Invalid external memory type for this test.
3467 return tcu::TestStatus::pass("Pass");
3470 tcu::TestStatus testMemoryFdDup (Context& context, MemoryTestConfig config)
3472 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
3473 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3474 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3475 const vk::InstanceDriver& vki (instance.getDriver());
3476 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3477 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3480 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3481 const vk::DeviceDriver vkd (vkp, instance, *device);
3483 TestLog& log = context.getTestContext().getLog();
3484 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3485 const vk::VkDeviceSize bufferSize = 1024;
3486 const deUint32 seed = 851493858u;
3487 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
3489 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3491 // \note Buffer is only allocated to get memory requirements
3492 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3493 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3494 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3495 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3497 if (config.hostVisible)
3498 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3500 const NativeHandle fd (getMemoryFd(vkd, *device, *memory, config.externalType));
3501 NativeHandle newFd (dup(fd.getFd()));
3503 if (newFd.getFd() < 0)
3504 log << TestLog::Message << "dup() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
3506 TCU_CHECK_MSG(newFd.getFd() >= 0, "Failed to call dup() for memorys fd");
3509 const vk::Unique<vk::VkBuffer> newBuffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3510 const vk::Unique<vk::VkDeviceMemory> newMemory (config.dedicated
3511 ? importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType, exportedMemoryTypeIndex, newFd)
3512 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, newFd));
3514 if (config.hostVisible)
3516 const std::vector<deUint8> testDataA (genTestData(seed ^ 672929437u, (size_t)bufferSize));
3518 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3520 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3521 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3525 return tcu::TestStatus::pass("Pass");
3530 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
3534 tcu::TestStatus testMemoryFdDup2 (Context& context, MemoryTestConfig config)
3536 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
3537 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3538 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3539 const vk::InstanceDriver& vki (instance.getDriver());
3540 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3541 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3544 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3545 const vk::DeviceDriver vkd (vkp, instance, *device);
3547 TestLog& log = context.getTestContext().getLog();
3548 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3549 const vk::VkDeviceSize bufferSize = 1024;
3550 const deUint32 seed = 224466865u;
3551 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
3553 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3555 // \note Buffer is only allocated to get memory requirements
3556 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3557 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3558 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3559 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3561 if (config.hostVisible)
3562 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3564 const NativeHandle fd (getMemoryFd(vkd, *device, *memory, config.externalType));
3565 NativeHandle secondFd (getMemoryFd(vkd, *device, *memory, config.externalType));
3566 const int newFd (dup2(fd.getFd(), secondFd.getFd()));
3569 log << TestLog::Message << "dup2() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
3571 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup2() for memorys fd");
3574 const vk::Unique<vk::VkBuffer> newBuffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3575 const vk::Unique<vk::VkDeviceMemory> newMemory (config.dedicated
3576 ? importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType, exportedMemoryTypeIndex, secondFd)
3577 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, secondFd));
3579 if (config.hostVisible)
3581 const std::vector<deUint8> testDataA (genTestData(seed ^ 99012346u, (size_t)bufferSize));
3583 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3585 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3586 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3590 return tcu::TestStatus::pass("Pass");
3595 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
3599 tcu::TestStatus testMemoryFdDup3 (Context& context, MemoryTestConfig config)
3601 #if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
3602 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3603 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3604 const vk::InstanceDriver& vki (instance.getDriver());
3605 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3606 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3609 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3610 const vk::DeviceDriver vkd (vkp, instance, *device);
3612 TestLog& log = context.getTestContext().getLog();
3613 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3614 const vk::VkDeviceSize bufferSize = 1024;
3615 const deUint32 seed = 2554088961u;
3616 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
3618 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3620 // \note Buffer is only allocated to get memory requirements
3621 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3622 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3623 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3624 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3626 if (config.hostVisible)
3627 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3629 const NativeHandle fd (getMemoryFd(vkd, *device, *memory, config.externalType));
3630 NativeHandle secondFd (getMemoryFd(vkd, *device, *memory, config.externalType));
3631 const int newFd (dup3(fd.getFd(), secondFd.getFd(), 0));
3634 log << TestLog::Message << "dup3() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
3636 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup3() for memorys fd");
3639 const vk::Unique<vk::VkBuffer> newBuffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3640 const vk::Unique<vk::VkDeviceMemory> newMemory (config.dedicated
3641 ? importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType, exportedMemoryTypeIndex, secondFd)
3642 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, secondFd));
3644 if (config.hostVisible)
3646 const std::vector<deUint8> testDataA (genTestData(seed ^ 4210342378u, (size_t)bufferSize));
3648 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3650 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3651 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3655 return tcu::TestStatus::pass("Pass");
3660 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
3664 tcu::TestStatus testMemoryFdSendOverSocket (Context& context, MemoryTestConfig config)
3666 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
3667 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3668 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3669 const vk::InstanceDriver& vki (instance.getDriver());
3670 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3671 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3674 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3675 const vk::DeviceDriver vkd (vkp, instance, *device);
3677 TestLog& log = context.getTestContext().getLog();
3678 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3679 const vk::VkDeviceSize bufferSize = 1024;
3680 const deUint32 seed = 3403586456u;
3681 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
3683 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3685 // \note Buffer is only allocated to get memory requirements
3686 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3687 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3688 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3689 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3691 if (config.hostVisible)
3692 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3694 const NativeHandle fd (getMemoryFd(vkd, *device, *memory, config.externalType));
3699 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
3701 log << TestLog::Message << "Failed to create socket pair: '" << strerror(errno) << "'" << TestLog::EndMessage;
3702 TCU_FAIL("Failed to create socket pair");
3706 const NativeHandle srcSocket (sv[0]);
3707 const NativeHandle dstSocket (sv[1]);
3708 std::string sendData ("deqp");
3712 const int fdRaw (fd.getFd());
3715 char tmpBuffer[CMSG_SPACE(sizeof(int))];
3716 iovec iov = { &sendData[0], sendData.length()};
3718 deMemset(&msg, 0, sizeof(msg));
3720 msg.msg_control = tmpBuffer;
3721 msg.msg_controllen = sizeof(tmpBuffer);
3725 cmsg = CMSG_FIRSTHDR(&msg);
3726 cmsg->cmsg_level = SOL_SOCKET;
3727 cmsg->cmsg_type = SCM_RIGHTS;
3728 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
3730 deMemcpy(CMSG_DATA(cmsg), &fdRaw, sizeof(int));
3731 msg.msg_controllen = cmsg->cmsg_len;
3733 if (sendmsg(srcSocket.getFd(), &msg, 0) < 0)
3735 log << TestLog::Message << "Failed to send fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
3736 TCU_FAIL("Failed to send fd over socket");
3743 char tmpBuffer[CMSG_SPACE(sizeof(int))];
3744 std::string recvData (4, '\0');
3745 iovec iov = { &recvData[0], recvData.length() };
3747 deMemset(&msg, 0, sizeof(msg));
3749 msg.msg_control = tmpBuffer;
3750 msg.msg_controllen = sizeof(tmpBuffer);
3754 const ssize_t bytes = recvmsg(dstSocket.getFd(), &msg, 0);
3758 log << TestLog::Message << "Failed to recv fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
3759 TCU_FAIL("Failed to recv fd over socket");
3762 else if (bytes != (ssize_t)sendData.length())
3764 TCU_FAIL("recvmsg() returned unpexpected number of bytes");
3768 const cmsghdr* const cmsg = CMSG_FIRSTHDR(&msg);
3770 deMemcpy(&newFd_, CMSG_DATA(cmsg), sizeof(int));
3771 NativeHandle newFd (newFd_);
3773 TCU_CHECK(cmsg->cmsg_level == SOL_SOCKET);
3774 TCU_CHECK(cmsg->cmsg_type == SCM_RIGHTS);
3775 TCU_CHECK(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
3776 TCU_CHECK(recvData == sendData);
3777 TCU_CHECK_MSG(newFd.getFd() >= 0, "Didn't receive valid fd from socket");
3780 const vk::Unique<vk::VkBuffer> newBuffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3781 const vk::Unique<vk::VkDeviceMemory> newMemory (config.dedicated
3782 ? importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType, exportedMemoryTypeIndex, newFd)
3783 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, newFd));
3785 if (config.hostVisible)
3787 const std::vector<deUint8> testDataA (genTestData(seed ^ 23478978u, (size_t)bufferSize));
3789 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3791 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3792 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3801 return tcu::TestStatus::pass("Pass");
3805 TCU_THROW(NotSupportedError, "Platform doesn't support sending file descriptors over socket");
3809 struct BufferTestConfig
3811 BufferTestConfig (vk::VkExternalMemoryHandleTypeFlagBits externalType_,
3813 : externalType (externalType_)
3814 , dedicated (dedicated_)
3818 vk::VkExternalMemoryHandleTypeFlagBits externalType;
3822 tcu::TestStatus testBufferBindExportImportBind (Context& context,
3823 const BufferTestConfig config)
3825 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3826 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3827 const vk::InstanceDriver& vki (instance.getDriver());
3828 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3829 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3830 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3831 const vk::DeviceDriver vkd (vkp, instance, *device);
3832 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3833 const vk::VkDeviceSize bufferSize = 1024;
3835 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3837 // \note Buffer is only allocated to get memory requirements
3838 const vk::Unique<vk::VkBuffer> bufferA (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3839 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *bufferA));
3840 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
3841 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *bufferA : (vk::VkBuffer)0));
3842 NativeHandle handle;
3844 VK_CHECK(vkd.bindBufferMemory(*device, *bufferA, *memoryA, 0u));
3846 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3849 const vk::Unique<vk::VkBuffer> bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3850 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3851 ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handle)
3852 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3854 VK_CHECK(vkd.bindBufferMemory(*device, *bufferB, *memoryB, 0u));
3857 return tcu::TestStatus::pass("Pass");
3860 tcu::TestStatus testBufferExportBindImportBind (Context& context,
3861 const BufferTestConfig config)
3863 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3864 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3865 const vk::InstanceDriver& vki (instance.getDriver());
3866 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3867 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3868 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3869 const vk::DeviceDriver vkd (vkp, instance, *device);
3870 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3871 const vk::VkDeviceSize bufferSize = 1024;
3873 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3875 // \note Buffer is only allocated to get memory requirements
3876 const vk::Unique<vk::VkBuffer> bufferA (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3877 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *bufferA));
3878 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
3879 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *bufferA : (vk::VkBuffer)0));
3880 NativeHandle handle;
3882 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3883 VK_CHECK(vkd.bindBufferMemory(*device, *bufferA, *memoryA, 0u));
3886 const vk::Unique<vk::VkBuffer> bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3887 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3888 ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handle)
3889 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3891 VK_CHECK(vkd.bindBufferMemory(*device, *bufferB, *memoryB, 0u));
3894 return tcu::TestStatus::pass("Pass");
3897 tcu::TestStatus testBufferExportImportBindBind (Context& context,
3898 const BufferTestConfig config)
3900 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3901 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3902 const vk::InstanceDriver& vki (instance.getDriver());
3903 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3904 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3905 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3906 const vk::DeviceDriver vkd (vkp, instance, *device);
3907 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3908 const vk::VkDeviceSize bufferSize = 1024;
3910 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3912 // \note Buffer is only allocated to get memory requirements
3913 const vk::Unique<vk::VkBuffer> bufferA (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3914 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *bufferA));
3915 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
3916 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *bufferA : (vk::VkBuffer)0));
3917 NativeHandle handle;
3919 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3922 const vk::Unique<vk::VkBuffer> bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3923 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3924 ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handle)
3925 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3927 VK_CHECK(vkd.bindBufferMemory(*device, *bufferA, *memoryA, 0u));
3928 VK_CHECK(vkd.bindBufferMemory(*device, *bufferB, *memoryB, 0u));
3931 return tcu::TestStatus::pass("Pass");
3934 tcu::TestStatus testImageQueries (Context& context, vk::VkExternalMemoryHandleTypeFlagBits externalType)
3936 const vk::VkImageCreateFlags createFlags[] =
3939 vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT,
3940 vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT|vk::VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT,
3941 vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT|vk::VK_IMAGE_CREATE_SPARSE_ALIASED_BIT,
3942 vk::VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT,
3943 vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT
3945 const vk::VkImageUsageFlags usageFlags[] =
3947 vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
3948 vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT,
3949 vk::VK_IMAGE_USAGE_SAMPLED_BIT,
3950 vk::VK_IMAGE_USAGE_STORAGE_BIT,
3951 vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
3952 vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
3953 vk::VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
3954 vk::VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
3955 vk::VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT,
3956 vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT
3958 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3959 const CustomInstance instance (createTestInstance(context, 0u, externalType, 0u));
3960 const vk::InstanceDriver& vki (instance.getDriver());
3961 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3962 const vk::VkPhysicalDeviceFeatures deviceFeatures (vk::getPhysicalDeviceFeatures(vki, physicalDevice));
3963 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3965 // VkDevice is only created if physical device claims to support any of these types.
3966 vk::Move<vk::VkDevice> device;
3967 de::MovePtr<vk::DeviceDriver> vkd;
3968 bool deviceHasDedicated = false;
3970 TestLog& log = context.getTestContext().getLog();
3972 for (size_t createFlagNdx = 0; createFlagNdx < DE_LENGTH_OF_ARRAY(createFlags); createFlagNdx++)
3973 for (size_t usageFlagNdx = 0; usageFlagNdx < DE_LENGTH_OF_ARRAY(usageFlags); usageFlagNdx++)
3975 const vk::VkImageViewCreateFlags createFlag = createFlags[createFlagNdx];
3976 const vk::VkImageUsageFlags usageFlag = usageFlags[usageFlagNdx];
3977 const vk::VkFormat format =
3978 (usageFlags[usageFlagNdx] & vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? vk::VK_FORMAT_D16_UNORM : vk::VK_FORMAT_R8G8B8A8_UNORM;
3979 const vk::VkImageType type = vk::VK_IMAGE_TYPE_2D;
3980 const vk::VkImageTiling tiling = vk::VK_IMAGE_TILING_OPTIMAL;
3981 const vk::VkPhysicalDeviceExternalImageFormatInfo externalInfo =
3983 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
3987 const vk::VkPhysicalDeviceImageFormatInfo2 info =
3989 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
3998 vk::VkExternalImageFormatProperties externalProperties =
4000 vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES,
4004 vk::VkImageFormatProperties2 properties =
4006 vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
4007 &externalProperties,
4017 if (((createFlag & vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT) != 0) &&
4018 (deviceFeatures.sparseBinding == VK_FALSE))
4021 if (((createFlag & vk::VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT) != 0) &&
4022 (deviceFeatures.sparseResidencyImage2D == VK_FALSE))
4025 if (((createFlag & vk::VK_IMAGE_CREATE_SPARSE_ALIASED_BIT) != 0) &&
4026 (deviceFeatures.sparseResidencyAliased == VK_FALSE))
4029 if (vki.getPhysicalDeviceImageFormatProperties2(physicalDevice, &info, &properties) == vk::VK_ERROR_FORMAT_NOT_SUPPORTED) {
4033 log << TestLog::Message << externalProperties << TestLog::EndMessage;
4034 TCU_CHECK(externalProperties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES);
4035 TCU_CHECK(externalProperties.pNext == DE_NULL);
4036 // \todo [2017-06-06 pyry] Can we validate anything else? Compatible types?
4038 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & (vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT|vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT)) != 0)
4040 const bool requiresDedicated = (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
4042 if (!device || (requiresDedicated && !deviceHasDedicated))
4044 // \note We need to re-create with dedicated mem extensions if previous device instance didn't have them
4047 device = createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, externalType, 0u, queueFamilyIndex, requiresDedicated);
4048 vkd = de::MovePtr<vk::DeviceDriver>(new vk::DeviceDriver(vkp, instance, *device));
4049 deviceHasDedicated = requiresDedicated;
4051 catch (const tcu::NotSupportedError& e)
4054 TCU_FAIL("Physical device claims to support handle type but required extensions are not supported");
4059 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) != 0)
4061 DE_ASSERT(!!device);
4064 if (deviceHasDedicated)
4066 // Memory requirements cannot be queried without binding the image.
4067 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
4070 const vk::Unique<vk::VkImage> image (createExternalImage(*vkd, *device, queueFamilyIndex, externalType, format, 16u, 16u, tiling, createFlag, usageFlag));
4071 const vk::VkMemoryDedicatedRequirements reqs (getMemoryDedicatedRequirements(*vkd, *device, *image));
4072 const bool propertiesRequiresDedicated = (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
4073 const bool objectRequiresDedicated = (reqs.requiresDedicatedAllocation != VK_FALSE);
4075 if (propertiesRequiresDedicated != objectRequiresDedicated)
4076 TCU_FAIL("vkGetPhysicalDeviceExternalBufferProperties and vkGetBufferMemoryRequirements2 report different dedicated requirements");
4080 // We can't query whether dedicated memory is required or not on per-object basis.
4081 // This check should be redundant as the code above tries to create device with
4082 // VK_KHR_dedicated_allocation & VK_KHR_get_memory_requirements2 if dedicated memory
4083 // is required. However, checking again doesn't hurt.
4084 TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) == 0);
4089 return tcu::TestStatus::pass("Pass");
4092 struct ImageTestConfig
4094 ImageTestConfig (vk::VkExternalMemoryHandleTypeFlagBits externalType_,
4096 : externalType (externalType_)
4097 , dedicated (dedicated_)
4101 vk::VkExternalMemoryHandleTypeFlagBits externalType;
4105 tcu::TestStatus testImageBindExportImportBind (Context& context,
4106 const ImageTestConfig config)
4108 const vk::PlatformInterface& vkp (context.getPlatformInterface());
4109 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
4110 const vk::InstanceDriver& vki (instance.getDriver());
4111 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
4112 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
4113 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
4114 const vk::DeviceDriver vkd (vkp, instance, *device);
4115 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);
4116 const vk::VkFormat format = vk::VK_FORMAT_R8G8B8A8_UNORM;
4117 const deUint32 width = 64u;
4118 const deUint32 height = 64u;
4119 const vk::VkImageTiling tiling = vk::VK_IMAGE_TILING_OPTIMAL;
4121 checkImageSupport(vki, physicalDevice, config.externalType, 0u, usage, format, tiling, config.dedicated);
4123 const vk::Unique<vk::VkImage> imageA (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
4124 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *imageA, config.externalType));
4125 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
4126 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *imageA : (vk::VkImage)0));
4127 NativeHandle handle;
4129 VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
4131 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
4134 const vk::Unique<vk::VkImage> imageB (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
4135 const deUint32 idx = config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID ? ~0u : exportedMemoryTypeIndex;
4136 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
4137 ? importDedicatedMemory(vkd, *device, *imageB, requirements, config.externalType, idx, handle)
4138 : importMemory(vkd, *device, requirements, config.externalType, idx, handle));
4140 VK_CHECK(vkd.bindImageMemory(*device, *imageB, *memoryB, 0u));
4143 return tcu::TestStatus::pass("Pass");
4146 tcu::TestStatus testImageExportBindImportBind (Context& context,
4147 const ImageTestConfig config)
4149 const vk::PlatformInterface& vkp (context.getPlatformInterface());
4150 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
4151 const vk::InstanceDriver& vki (instance.getDriver());
4152 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
4153 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
4154 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
4155 const vk::DeviceDriver vkd (vkp, instance, *device);
4156 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);
4157 const vk::VkFormat format = vk::VK_FORMAT_R8G8B8A8_UNORM;
4158 const deUint32 width = 64u;
4159 const deUint32 height = 64u;
4160 const vk::VkImageTiling tiling = vk::VK_IMAGE_TILING_OPTIMAL;
4162 checkImageSupport(vki, physicalDevice, config.externalType, 0u, usage, format, tiling, config.dedicated);
4164 const vk::Unique<vk::VkImage> imageA (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
4165 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *imageA, config.externalType));
4166 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
4167 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *imageA : (vk::VkImage)0));
4168 NativeHandle handle;
4170 if (config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID && config.dedicated)
4172 // AHB required the image memory to be bound first.
4173 VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
4174 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
4178 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
4179 VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
4183 const vk::Unique<vk::VkImage> imageB (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
4184 const deUint32 idx = config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID ? ~0u : exportedMemoryTypeIndex;
4185 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
4186 ? importDedicatedMemory(vkd, *device, *imageB, requirements, config.externalType, idx, handle)
4187 : importMemory(vkd, *device, requirements, config.externalType, idx, handle));
4189 VK_CHECK(vkd.bindImageMemory(*device, *imageB, *memoryB, 0u));
4192 return tcu::TestStatus::pass("Pass");
4195 tcu::TestStatus testImageExportImportBindBind (Context& context,
4196 const ImageTestConfig config)
4198 const vk::PlatformInterface& vkp (context.getPlatformInterface());
4199 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
4200 const vk::InstanceDriver& vki (instance.getDriver());
4201 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
4202 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
4203 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
4204 const vk::DeviceDriver vkd (vkp, instance, *device);
4205 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);
4206 const vk::VkFormat format = vk::VK_FORMAT_R8G8B8A8_UNORM;
4207 const deUint32 width = 64u;
4208 const deUint32 height = 64u;
4209 const vk::VkImageTiling tiling = vk::VK_IMAGE_TILING_OPTIMAL;
4211 checkImageSupport(vki, physicalDevice, config.externalType, 0u, usage, format, tiling, config.dedicated);
4213 if (config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID && config.dedicated)
4215 // AHB required the image memory to be bound first, which is not possible in this test.
4216 TCU_THROW(NotSupportedError, "Unsupported for Android Hardware Buffer");
4219 // \note Image is only allocated to get memory requirements
4220 const vk::Unique<vk::VkImage> imageA (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
4221 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *imageA, config.externalType));
4222 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
4223 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *imageA : (vk::VkImage)0));
4224 NativeHandle handle;
4226 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
4229 const vk::Unique<vk::VkImage> imageB (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
4230 const deUint32 idx = config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID ? ~0u : exportedMemoryTypeIndex;
4231 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
4232 ? importDedicatedMemory(vkd, *device, *imageB, requirements, config.externalType, idx, handle)
4233 : importMemory(vkd, *device, requirements, config.externalType, idx, handle));
4235 VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
4236 VK_CHECK(vkd.bindImageMemory(*device, *imageB, *memoryB, 0u));
4239 return tcu::TestStatus::pass("Pass");
4242 template<class TestConfig> void checkEvent (Context& context, const TestConfig)
4244 if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") && !context.getPortabilitySubsetFeatures().events)
4245 TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Events are not supported by this implementation");
4248 template<class TestConfig> void checkSupport (Context& context, const TestConfig config)
4250 const Transference transference (getHandelTypeTransferences(config.externalType));
4251 if (transference == TRANSFERENCE_COPY)
4252 checkEvent(context, config);
4255 de::MovePtr<tcu::TestCaseGroup> createFenceTests (tcu::TestContext& testCtx, vk::VkExternalFenceHandleTypeFlagBits externalType)
4259 const char* const name;
4260 const Permanence permanence;
4263 { "temporary", PERMANENCE_TEMPORARY },
4264 { "permanent", PERMANENCE_PERMANENT }
4267 de::MovePtr<tcu::TestCaseGroup> fenceGroup (new tcu::TestCaseGroup(testCtx, externalFenceTypeToName(externalType), externalFenceTypeToName(externalType)));
4269 addFunctionCase(fenceGroup.get(), "info", "Test external fence queries.", testFenceQueries, externalType);
4271 for (size_t permanenceNdx = 0; permanenceNdx < DE_LENGTH_OF_ARRAY(permanences); permanenceNdx++)
4273 const Permanence permanence (permanences[permanenceNdx].permanence);
4274 const char* const permanenceName (permanences[permanenceNdx].name);
4275 const FenceTestConfig config (externalType, permanence);
4277 if (!isSupportedPermanence(externalType, permanence))
4280 if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT
4281 || externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
4283 addFunctionCase(fenceGroup.get(), std::string("create_win32_") + permanenceName, "Test creating fence with win32 properties.", testFenceWin32Create, config);
4286 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("import_twice_") + permanenceName, "Test importing fence twice.", checkSupport, initProgramsToGetNativeFd, testFenceImportTwice, config);
4287 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("reimport_") + permanenceName, "Test importing again over previously imported fence.", checkSupport, initProgramsToGetNativeFd, testFenceImportReimport, config);
4288 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("import_multiple_times_") + permanenceName, "Test importing fence multiple times.", checkSupport, initProgramsToGetNativeFd, testFenceMultipleImports, config);
4289 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("signal_export_import_wait_") + permanenceName, "Test signaling, exporting, importing and waiting for the sempahore.", checkEvent, initProgramsToGetNativeFd, testFenceSignalExportImportWait, config);
4290 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("signal_import_") + permanenceName, "Test signaling and importing the fence.", checkSupport, initProgramsToGetNativeFd, testFenceSignalImport, config);
4291 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("reset_") + permanenceName, "Test resetting the fence.", checkEvent, initProgramsToGetNativeFd, testFenceReset, config);
4292 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("transference_") + permanenceName, "Test fences transference.", checkEvent, initProgramsToGetNativeFd, testFenceTransference, config);
4294 if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT)
4296 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("import_signaled_") + permanenceName, "Test import signaled fence fd.", initProgramsToGetNativeFd, testFenceImportSyncFdSignaled, config);
4299 if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT
4300 || externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT)
4302 // \note Not supported on WIN32 handles
4303 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("export_multiple_times_") + permanenceName, "Test exporting fence multiple times.", checkSupport, initProgramsToGetNativeFd, testFenceMultipleExports, config);
4305 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("dup_") + permanenceName, "Test calling dup() on exported fence.", checkSupport, initProgramsToGetNativeFd, testFenceFdDup, config);
4306 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("dup2_") + permanenceName, "Test calling dup2() on exported fence.", checkSupport, initProgramsToGetNativeFd, testFenceFdDup2, config);
4307 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("dup3_") + permanenceName, "Test calling dup3() on exported fence.", checkSupport, initProgramsToGetNativeFd, testFenceFdDup3, config);
4308 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("send_over_socket_") + permanenceName, "Test sending fence fd over socket.", checkSupport, initProgramsToGetNativeFd, testFenceFdSendOverSocket, config);
4311 if (getHandelTypeTransferences(externalType) == TRANSFERENCE_REFERENCE)
4313 addFunctionCase(fenceGroup.get(), std::string("signal_wait_import_") + permanenceName, "Test signaling and then waiting for the the sepmahore.", testFenceSignalWaitImport, config);
4314 addFunctionCase(fenceGroup.get(), std::string("export_signal_import_wait_") + permanenceName, "Test exporting, signaling, importing and waiting for the fence.", testFenceExportSignalImportWait, config);
4315 addFunctionCase(fenceGroup.get(), std::string("export_import_signal_wait_") + permanenceName, "Test exporting, importing, signaling and waiting for the fence.", testFenceExportImportSignalWait, config);
4322 bool ValidateAHardwareBuffer(vk::VkFormat format, deUint64 requiredAhbUsage, const vk::DeviceDriver& vkd, const vk::VkDevice& device, vk::VkImageCreateFlags createFlag, deUint32 layerCount, bool& enableMaxLayerTest)
4324 DE_UNREF(createFlag);
4326 AndroidHardwareBufferExternalApi* ahbApi = AndroidHardwareBufferExternalApi::getInstance();
4329 TCU_THROW(NotSupportedError, "Platform doesn't support Android Hardware Buffer handles");
4332 #if (DE_OS == DE_OS_ANDROID)
4333 // If CubeMap create flag is used and AHB doesn't support CubeMap return false.
4334 if(!AndroidHardwareBufferExternalApi::supportsCubeMap() && (createFlag & vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT))
4338 vk::pt::AndroidHardwareBufferPtr ahb = ahbApi->allocate(64u, 64u, layerCount, ahbApi->vkFormatToAhbFormat(format), requiredAhbUsage);
4339 if (ahb.internal == DE_NULL)
4341 enableMaxLayerTest = false;
4342 // try again with layerCount '1'
4343 ahb = ahbApi->allocate(64u, 64u, 1u, ahbApi->vkFormatToAhbFormat(format), requiredAhbUsage);
4344 if (ahb.internal == DE_NULL)
4349 NativeHandle nativeHandle(ahb);
4351 const vk::VkComponentMapping mappingA = { vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY };
4352 const vk::VkComponentMapping mappingB = { vk::VK_COMPONENT_SWIZZLE_R, vk::VK_COMPONENT_SWIZZLE_G, vk::VK_COMPONENT_SWIZZLE_B, vk::VK_COMPONENT_SWIZZLE_A };
4354 for (int variantIdx = 0; variantIdx < 2; ++variantIdx)
4356 // Both mappings should be equivalent and work.
4357 const vk::VkComponentMapping& mapping = ((variantIdx == 0) ? mappingA : mappingB);
4359 vk::VkAndroidHardwareBufferFormatPropertiesANDROID formatProperties =
4361 vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID,
4363 vk::VK_FORMAT_UNDEFINED,
4367 vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY,
4368 vk::VK_SAMPLER_YCBCR_RANGE_ITU_FULL,
4369 vk::VK_CHROMA_LOCATION_COSITED_EVEN,
4370 vk::VK_CHROMA_LOCATION_COSITED_EVEN
4373 vk::VkAndroidHardwareBufferPropertiesANDROID bufferProperties =
4375 vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID,
4381 VK_CHECK(vkd.getAndroidHardwareBufferPropertiesANDROID(device, ahb, &bufferProperties));
4382 TCU_CHECK(formatProperties.format != vk::VK_FORMAT_UNDEFINED);
4383 TCU_CHECK(formatProperties.format == format);
4384 TCU_CHECK(formatProperties.externalFormat != 0u);
4385 TCU_CHECK((formatProperties.formatFeatures & vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) != 0u);
4386 TCU_CHECK((formatProperties.formatFeatures & (vk::VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT | vk::VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT)) != 0u);
4392 tcu::TestStatus testAndroidHardwareBufferImageFormat (Context& context, vk::VkFormat format)
4394 AndroidHardwareBufferExternalApi* ahbApi = AndroidHardwareBufferExternalApi::getInstance();
4397 TCU_THROW(NotSupportedError, "Platform doesn't support Android Hardware Buffer handles");
4400 const vk::VkExternalMemoryHandleTypeFlagBits externalMemoryType = vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
4401 const vk::PlatformInterface& vkp (context.getPlatformInterface());
4402 const CustomInstance instance (createTestInstance(context, 0u, externalMemoryType, 0u));
4403 const vk::InstanceDriver& vki (instance.getDriver());
4404 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
4406 vk::VkPhysicalDeviceProtectedMemoryFeatures protectedFeatures;
4407 protectedFeatures.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES;
4408 protectedFeatures.pNext = DE_NULL;
4409 protectedFeatures.protectedMemory = VK_FALSE;
4411 vk::VkPhysicalDeviceFeatures2 deviceFeatures;
4412 deviceFeatures.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
4413 deviceFeatures.pNext = &protectedFeatures;
4415 vki.getPhysicalDeviceFeatures2(physicalDevice, &deviceFeatures);
4417 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
4418 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, externalMemoryType, 0u, queueFamilyIndex, false, &protectedFeatures));
4419 const vk::DeviceDriver vkd (vkp, instance, *device);
4420 TestLog& log = context.getTestContext().getLog();
4421 const vk::VkPhysicalDeviceLimits limits = getPhysicalDeviceProperties(vki, physicalDevice).limits;
4423 const vk::VkImageUsageFlagBits framebufferUsageFlag = vk::isDepthStencilFormat(format) ? vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
4424 : vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
4426 const vk::VkImageUsageFlagBits usageFlags[] =
4428 vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
4429 vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT,
4430 vk::VK_IMAGE_USAGE_SAMPLED_BIT,
4431 vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT,
4432 framebufferUsageFlag,
4434 const vk::VkImageCreateFlagBits createFlags[] =
4436 vk::VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT,
4437 vk::VK_IMAGE_CREATE_EXTENDED_USAGE_BIT,
4438 vk::VK_IMAGE_CREATE_PROTECTED_BIT,
4439 vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT,
4441 const vk::VkImageTiling tilings[] =
4443 vk::VK_IMAGE_TILING_OPTIMAL,
4444 vk::VK_IMAGE_TILING_LINEAR,
4446 deUint64 mustSupportAhbUsageFlags = ahbApi->mustSupportAhbUsageFlags();
4447 const size_t one = 1u;
4448 const size_t numOfUsageFlags = DE_LENGTH_OF_ARRAY(usageFlags);
4449 const size_t numOfCreateFlags = DE_LENGTH_OF_ARRAY(createFlags);
4450 const size_t numOfFlagCombos = one << (numOfUsageFlags + numOfCreateFlags);
4451 const size_t numOfTilings = DE_LENGTH_OF_ARRAY(tilings);
4453 for (size_t combo = 0; combo < numOfFlagCombos; combo++)
4455 vk::VkImageUsageFlags usage = 0;
4456 vk::VkImageCreateFlags createFlag = 0;
4457 deUint64 requiredAhbUsage = 0;
4458 bool enableMaxLayerTest = true;
4459 for (size_t usageNdx = 0; usageNdx < numOfUsageFlags; usageNdx++)
4461 if ((combo & (one << usageNdx)) == 0)
4463 usage |= usageFlags[usageNdx];
4464 requiredAhbUsage |= ahbApi->vkUsageToAhbUsage(usageFlags[usageNdx]);
4466 for (size_t createFlagNdx = 0; createFlagNdx < numOfCreateFlags; createFlagNdx++)
4468 const size_t bit = numOfUsageFlags + createFlagNdx;
4469 if ((combo & (one << bit)) == 0)
4471 if (((createFlags[createFlagNdx] & vk::VK_IMAGE_CREATE_PROTECTED_BIT) == vk::VK_IMAGE_CREATE_PROTECTED_BIT ) &&
4472 (protectedFeatures.protectedMemory == VK_FALSE))
4475 createFlag |= createFlags[createFlagNdx];
4476 requiredAhbUsage |= ahbApi->vkCreateToAhbUsage(createFlags[createFlagNdx]);
4479 // Only test a combination if the usage flags include at least one of the AHARDWAREBUFFER_USAGE_GPU_* flag.
4480 if ((requiredAhbUsage & mustSupportAhbUsageFlags) == 0u)
4483 // Only test a combination if AHardwareBuffer can be successfully allocated for it.
4484 if (!ValidateAHardwareBuffer(format, requiredAhbUsage, vkd, *device, createFlag, limits.maxImageArrayLayers, enableMaxLayerTest))
4487 bool foundAnyUsableTiling = false;
4488 for (size_t tilingIndex = 0; tilingIndex < numOfTilings; tilingIndex++)
4490 const vk::VkImageTiling tiling = tilings[tilingIndex];
4492 const vk::VkPhysicalDeviceExternalImageFormatInfo externalInfo =
4494 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
4496 vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID
4498 const vk::VkPhysicalDeviceImageFormatInfo2 info =
4500 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
4503 vk::VK_IMAGE_TYPE_2D,
4509 vk::VkAndroidHardwareBufferUsageANDROID ahbUsageProperties =
4511 vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID,
4515 vk::VkExternalImageFormatProperties externalProperties =
4517 vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES,
4518 &ahbUsageProperties,
4521 vk::VkImageFormatProperties2 properties =
4523 vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
4524 &externalProperties,
4534 if (vki.getPhysicalDeviceImageFormatProperties2(physicalDevice, &info, &properties) == vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
4536 log << TestLog::Message << "Tiling " << tiling << " is not supported." << TestLog::EndMessage;
4540 foundAnyUsableTiling = true;
4542 TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) != 0);
4543 TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) != 0);
4544 TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0);
4545 deUint32 maxWidth = properties.imageFormatProperties.maxExtent.width;
4546 deUint32 maxHeight = properties.imageFormatProperties.maxExtent.height;
4547 TCU_CHECK(maxWidth >= 4096);
4548 TCU_CHECK(maxHeight >= 4096);
4549 // Even if not requested, at least one of GPU_* usage flags must be present.
4550 TCU_CHECK((ahbUsageProperties.androidHardwareBufferUsage & mustSupportAhbUsageFlags) != 0u);
4551 // The AHB usage flags corresponding to the create and usage flags used in info must be present.
4552 TCU_CHECK((ahbUsageProperties.androidHardwareBufferUsage & requiredAhbUsage) == requiredAhbUsage);
4554 log << TestLog::Message << "Required flags: " << std::hex << requiredAhbUsage << " Actual flags: " << std::hex << ahbUsageProperties.androidHardwareBufferUsage
4555 << TestLog::EndMessage;
4568 deUint32 exportedMemoryTypeIndex = 0;
4570 if (createFlag & vk::VK_IMAGE_CREATE_PROTECTED_BIT)
4572 const vk::VkPhysicalDeviceMemoryProperties memProperties(vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
4574 for (deUint32 memoryTypeIndex = 0; memoryTypeIndex < VK_MAX_MEMORY_TYPES; memoryTypeIndex++)
4576 if (memProperties.memoryTypes[memoryTypeIndex].propertyFlags & vk::VK_MEMORY_PROPERTY_PROTECTED_BIT)
4578 exportedMemoryTypeIndex = memoryTypeIndex;
4584 for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(sizes); i++)
4586 const vk::Unique<vk::VkImage> image (createExternalImage(vkd, *device, queueFamilyIndex, externalMemoryType, format, sizes[i].width, sizes[i].height, tiling, createFlag, usage));
4587 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *image, externalMemoryType));
4588 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, externalMemoryType, *image));
4589 NativeHandle handle;
4591 VK_CHECK(vkd.bindImageMemory(*device, *image, *memory, 0u));
4592 getMemoryNative(vkd, *device, *memory, externalMemoryType, handle);
4594 deUint32 ahbFormat = 0;
4595 deUint64 anhUsage = 0;
4596 ahbApi->describe(handle.getAndroidHardwareBuffer(), DE_NULL, DE_NULL, DE_NULL, &ahbFormat, &anhUsage, DE_NULL);
4597 TCU_CHECK(ahbFormat == ahbApi->vkFormatToAhbFormat(format));
4598 TCU_CHECK((anhUsage & requiredAhbUsage) == requiredAhbUsage);
4600 // Let watchdog know we're alive
4601 context.getTestContext().touchWatchdog();
4604 if (properties.imageFormatProperties.maxMipLevels >= 7u)
4606 const vk::Unique<vk::VkImage> image (createExternalImage(vkd, *device, queueFamilyIndex, externalMemoryType, format, 64u, 64u, tiling, createFlag, usage, 7u));
4607 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *image, externalMemoryType));
4608 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, externalMemoryType, *image));
4609 NativeHandle handle;
4611 VK_CHECK(vkd.bindImageMemory(*device, *image, *memory, 0u));
4612 getMemoryNative(vkd, *device, *memory, externalMemoryType, handle);
4614 deUint32 ahbFormat = 0;
4615 deUint64 anhUsage = 0;
4616 ahbApi->describe(handle.getAndroidHardwareBuffer(), DE_NULL, DE_NULL, DE_NULL, &ahbFormat, &anhUsage, DE_NULL);
4617 TCU_CHECK(ahbFormat == ahbApi->vkFormatToAhbFormat(format));
4618 TCU_CHECK((anhUsage & requiredAhbUsage) == requiredAhbUsage);
4621 if ((properties.imageFormatProperties.maxArrayLayers > 1u) && enableMaxLayerTest)
4623 const vk::Unique<vk::VkImage> image (createExternalImage(vkd, *device, queueFamilyIndex, externalMemoryType, format, 64u, 64u, tiling, createFlag, usage, 1u, properties.imageFormatProperties.maxArrayLayers));
4624 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *image, externalMemoryType));
4625 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, externalMemoryType, *image));
4626 NativeHandle handle;
4628 VK_CHECK(vkd.bindImageMemory(*device, *image, *memory, 0u));
4629 getMemoryNative(vkd, *device, *memory, externalMemoryType, handle);
4631 deUint32 ahbFormat = 0;
4632 deUint64 anhUsage = 0;
4633 ahbApi->describe(handle.getAndroidHardwareBuffer(), DE_NULL, DE_NULL, DE_NULL, &ahbFormat, &anhUsage, DE_NULL);
4634 TCU_CHECK(ahbFormat == ahbApi->vkFormatToAhbFormat(format));
4635 TCU_CHECK((anhUsage & requiredAhbUsage) == requiredAhbUsage);
4639 TCU_CHECK(foundAnyUsableTiling);
4641 return tcu::TestStatus::pass("Pass");
4644 de::MovePtr<tcu::TestCaseGroup> createFenceTests (tcu::TestContext& testCtx)
4646 de::MovePtr<tcu::TestCaseGroup> fenceGroup (new tcu::TestCaseGroup(testCtx, "fence", "Tests for external fences."));
4648 fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT).release());
4649 fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT).release());
4650 fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT).release());
4651 fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT).release());
4656 de::MovePtr<tcu::TestCaseGroup> createSemaphoreTests (tcu::TestContext& testCtx, vk::VkExternalSemaphoreHandleTypeFlagBits externalType)
4660 const char* const name;
4661 const Permanence permanence;
4664 { "temporary", PERMANENCE_TEMPORARY },
4665 { "permanent", PERMANENCE_PERMANENT }
4669 const char* const name;
4670 vk::VkSemaphoreType type;
4671 } semaphoreTypes[] =
4673 { "binary", vk::VK_SEMAPHORE_TYPE_BINARY },
4674 { "timeline", vk::VK_SEMAPHORE_TYPE_TIMELINE },
4677 de::MovePtr<tcu::TestCaseGroup> semaphoreGroup (new tcu::TestCaseGroup(testCtx, externalSemaphoreTypeToName(externalType), externalSemaphoreTypeToName(externalType)));
4679 for (size_t semaphoreTypeIdx = 0; semaphoreTypeIdx < DE_LENGTH_OF_ARRAY(permanences); semaphoreTypeIdx++)
4681 addFunctionCase(semaphoreGroup.get(), std::string("info_") + semaphoreTypes[semaphoreTypeIdx].name,
4682 "Test external semaphore queries.", testSemaphoreQueries,
4683 TestSemaphoreQueriesParameters(semaphoreTypes[semaphoreTypeIdx].type, externalType));
4686 for (size_t permanenceNdx = 0; permanenceNdx < DE_LENGTH_OF_ARRAY(permanences); permanenceNdx++)
4688 const Permanence permanence (permanences[permanenceNdx].permanence);
4689 const char* const permanenceName (permanences[permanenceNdx].name);
4690 const SemaphoreTestConfig config (externalType, permanence);
4692 if (!isSupportedPermanence(externalType, permanence))
4695 if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
4696 || externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
4698 addFunctionCase(semaphoreGroup.get(), std::string("create_win32_") + permanenceName, "Test creating semaphore with win32 properties.", testSemaphoreWin32Create, config);
4701 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("import_twice_") + permanenceName, "Test importing semaphore twice.", checkSupport, initProgramsToGetNativeFd, testSemaphoreImportTwice, config);
4702 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("reimport_") + permanenceName, "Test importing again over previously imported semaphore.", checkSupport, initProgramsToGetNativeFd, testSemaphoreImportReimport, config);
4703 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("import_multiple_times_") + permanenceName, "Test importing semaphore multiple times.", checkSupport, initProgramsToGetNativeFd, testSemaphoreMultipleImports, config);
4704 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("signal_export_import_wait_") + permanenceName, "Test signaling, exporting, importing and waiting for the sempahore.", checkEvent, initProgramsToGetNativeFd, testSemaphoreSignalExportImportWait, config);
4705 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("signal_import_") + permanenceName, "Test signaling and importing the semaphore.", checkSupport, initProgramsToGetNativeFd, testSemaphoreSignalImport, config);
4706 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("transference_") + permanenceName, "Test semaphores transference.", checkEvent, initProgramsToGetNativeFd, testSemaphoreTransference, config);
4708 if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT)
4710 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("import_signaled_") + permanenceName, "Test import signaled semaphore fd.", initProgramsToGetNativeFd, testSemaphoreImportSyncFdSignaled, config);
4714 if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT
4715 || externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT)
4717 // \note Not supported on WIN32 handles
4718 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("export_multiple_times_") + permanenceName, "Test exporting semaphore multiple times.", checkSupport, initProgramsToGetNativeFd, testSemaphoreMultipleExports, config);
4720 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("dup_") + permanenceName, "Test calling dup() on exported semaphore.", checkSupport, initProgramsToGetNativeFd, testSemaphoreFdDup, config);
4721 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("dup2_") + permanenceName, "Test calling dup2() on exported semaphore.", checkSupport, initProgramsToGetNativeFd, testSemaphoreFdDup2, config);
4722 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("dup3_") + permanenceName, "Test calling dup3() on exported semaphore.", checkSupport, initProgramsToGetNativeFd, testSemaphoreFdDup3, config);
4723 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("send_over_socket_") + permanenceName, "Test sending semaphore fd over socket.", checkSupport, initProgramsToGetNativeFd, testSemaphoreFdSendOverSocket, config);
4726 if (getHandelTypeTransferences(externalType) == TRANSFERENCE_REFERENCE)
4728 addFunctionCase(semaphoreGroup.get(), std::string("signal_wait_import_") + permanenceName, "Test signaling and then waiting for the the sepmahore.", testSemaphoreSignalWaitImport, config);
4729 addFunctionCase(semaphoreGroup.get(), std::string("export_signal_import_wait_") + permanenceName, "Test exporting, signaling, importing and waiting for the semaphore.", testSemaphoreExportSignalImportWait, config);
4730 addFunctionCase(semaphoreGroup.get(), std::string("export_import_signal_wait_") + permanenceName, "Test exporting, importing, signaling and waiting for the semaphore.", checkEvent, testSemaphoreExportImportSignalWait, config);
4734 return semaphoreGroup;
4737 de::MovePtr<tcu::TestCaseGroup> createSemaphoreTests (tcu::TestContext& testCtx)
4739 de::MovePtr<tcu::TestCaseGroup> semaphoreGroup (new tcu::TestCaseGroup(testCtx, "semaphore", "Tests for external semaphores."));
4741 semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT).release());
4742 semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT).release());
4743 semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT).release());
4744 semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT).release());
4746 return semaphoreGroup;
4749 de::MovePtr<tcu::TestCaseGroup> createMemoryTests (tcu::TestContext& testCtx, vk::VkExternalMemoryHandleTypeFlagBits externalType)
4751 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, externalMemoryTypeToName(externalType), "Tests for external memory"));
4753 for (size_t dedicatedNdx = 0; dedicatedNdx < 2; dedicatedNdx++)
4755 const bool dedicated (dedicatedNdx == 1);
4756 de::MovePtr<tcu::TestCaseGroup> dedicatedGroup (new tcu::TestCaseGroup(testCtx, dedicated ? "dedicated" : "suballocated", ""));
4758 for (size_t hostVisibleNdx = 0; hostVisibleNdx < 2; hostVisibleNdx++)
4760 const bool hostVisible (hostVisibleNdx == 1);
4761 de::MovePtr<tcu::TestCaseGroup> hostVisibleGroup (new tcu::TestCaseGroup(testCtx, hostVisible ? "host_visible" : "device_only", ""));
4762 const MemoryTestConfig memoryConfig (externalType, hostVisible, dedicated);
4764 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
4765 || externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
4767 addFunctionCase(hostVisibleGroup.get(), "create_win32", "Test creating memory with win32 properties .", testMemoryWin32Create, memoryConfig);
4770 addFunctionCase(hostVisibleGroup.get(), "import_twice", "Test importing memory object twice.", testMemoryImportTwice, memoryConfig);
4771 addFunctionCase(hostVisibleGroup.get(), "import_multiple_times", "Test importing memory object multiple times.", testMemoryMultipleImports, memoryConfig);
4773 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT
4774 || externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT)
4776 addFunctionCase(hostVisibleGroup.get(), "dup", "Test calling dup() on exported memory.", testMemoryFdDup, memoryConfig);
4777 addFunctionCase(hostVisibleGroup.get(), "dup2", "Test calling dup2() on exported memory.", testMemoryFdDup2, memoryConfig);
4778 addFunctionCase(hostVisibleGroup.get(), "dup3", "Test calling dup3() on exported memory.", testMemoryFdDup3, memoryConfig);
4779 addFunctionCase(hostVisibleGroup.get(), "send_over_socket", "Test sending memory fd over socket.", testMemoryFdSendOverSocket, memoryConfig);
4780 // \note Not supported on WIN32 handles
4781 addFunctionCase(hostVisibleGroup.get(), "export_multiple_times", "Test exporting memory multiple times.", testMemoryMultipleExports, memoryConfig);
4784 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT)
4786 addFunctionCase(hostVisibleGroup.get(), "fd_properties", "Test obtaining the FD memory properties", testMemoryFdProperties, memoryConfig);
4789 dedicatedGroup->addChild(hostVisibleGroup.release());
4793 de::MovePtr<tcu::TestCaseGroup> bufferGroup (new tcu::TestCaseGroup(testCtx, "buffer", ""));
4794 const BufferTestConfig bufferConfig (externalType, dedicated);
4796 addFunctionCase(bufferGroup.get(), "info", "External buffer memory info query.", testBufferQueries, externalType);
4797 addFunctionCase(bufferGroup.get(), "bind_export_import_bind", "Test binding, exporting, importing and binding buffer.", testBufferBindExportImportBind, bufferConfig);
4798 addFunctionCase(bufferGroup.get(), "export_bind_import_bind", "Test exporting, binding, importing and binding buffer.", testBufferExportBindImportBind, bufferConfig);
4799 addFunctionCase(bufferGroup.get(), "export_import_bind_bind", "Test exporting, importing and binding buffer.", testBufferExportImportBindBind, bufferConfig);
4801 dedicatedGroup->addChild(bufferGroup.release());
4805 de::MovePtr<tcu::TestCaseGroup> imageGroup (new tcu::TestCaseGroup(testCtx, "image", ""));
4806 const ImageTestConfig imageConfig (externalType, dedicated);
4808 addFunctionCase(imageGroup.get(), "info", "External image memory info query.", testImageQueries, externalType);
4809 addFunctionCase(imageGroup.get(), "bind_export_import_bind", "Test binding, exporting, importing and binding image.", testImageBindExportImportBind, imageConfig);
4810 addFunctionCase(imageGroup.get(), "export_bind_import_bind", "Test exporting, binding, importing and binding image.", testImageExportBindImportBind, imageConfig);
4811 addFunctionCase(imageGroup.get(), "export_import_bind_bind", "Test exporting, importing and binding image.", testImageExportImportBindBind, imageConfig);
4813 dedicatedGroup->addChild(imageGroup.release());
4816 group->addChild(dedicatedGroup.release());
4819 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
4821 de::MovePtr<tcu::TestCaseGroup> formatGroup (new tcu::TestCaseGroup(testCtx, "image_formats", "Test minimum image format support"));
4823 const vk::VkFormat ahbFormats[] =
4825 vk::VK_FORMAT_R8G8B8_UNORM,
4826 vk::VK_FORMAT_R8G8B8A8_UNORM,
4827 vk::VK_FORMAT_R5G6B5_UNORM_PACK16,
4828 vk::VK_FORMAT_R16G16B16A16_SFLOAT,
4829 vk::VK_FORMAT_A2B10G10R10_UNORM_PACK32,
4830 vk::VK_FORMAT_D16_UNORM,
4831 vk::VK_FORMAT_X8_D24_UNORM_PACK32,
4832 vk::VK_FORMAT_D24_UNORM_S8_UINT,
4833 vk::VK_FORMAT_D32_SFLOAT,
4834 vk::VK_FORMAT_D32_SFLOAT_S8_UINT,
4835 vk::VK_FORMAT_S8_UINT,
4837 const size_t numOfAhbFormats = DE_LENGTH_OF_ARRAY(ahbFormats);
4839 for (size_t ahbFormatNdx = 0; ahbFormatNdx < numOfAhbFormats; ahbFormatNdx++)
4841 const vk::VkFormat format = ahbFormats[ahbFormatNdx];
4842 const std::string testCaseName = getFormatCaseName(format);
4844 addFunctionCase(formatGroup.get(), testCaseName, "", testAndroidHardwareBufferImageFormat, format);
4847 group->addChild(formatGroup.release());
4853 de::MovePtr<tcu::TestCaseGroup> createMemoryTests (tcu::TestContext& testCtx)
4855 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "memory", "Tests for external memory"));
4857 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT).release());
4858 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT).release());
4859 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT).release());
4860 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID).release());
4861 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT).release());
4868 tcu::TestCaseGroup* createExternalMemoryTests (tcu::TestContext& testCtx)
4870 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "external", "Tests for external Vulkan objects"));
4872 group->addChild(createSemaphoreTests(testCtx).release());
4873 group->addChild(createMemoryTests(testCtx).release());
4874 group->addChild(createFenceTests(testCtx).release());
4876 return group.release();