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 if (transference == TRANSFERENCE_COPY)
1453 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphore, config.externalType, handle);
1454 if (handle.getFd() == -1)
1455 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1458 getSemaphoreNative(vkd, *device, *semaphore, config.externalType, handle);
1461 submitEmptySignal(vkd, queue, *semaphore);
1462 submitEmptyWait(vkd, queue, *semaphore);
1464 VK_CHECK(vkd.queueWaitIdle(queue));
1467 return tcu::TestStatus::pass("Pass");
1470 tcu::TestStatus testSemaphoreMultipleImports (Context& context,
1471 const SemaphoreTestConfig config)
1473 const size_t importCount = 4 * 1024;
1474 const Transference transference (getHandelTypeTransferences(config.externalType));
1475 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1476 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1477 const vk::InstanceDriver& vki (instance.getDriver());
1478 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1479 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1481 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1484 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1485 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1486 const vk::DeviceDriver vkd (vkp, instance, *device);
1487 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1488 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1489 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1490 NativeHandle handleA;
1492 if (transference == TRANSFERENCE_COPY)
1494 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, handleA);
1495 if (handleA.getFd() == -1)
1496 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1499 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handleA);
1501 for (size_t importNdx = 0; importNdx < importCount; importNdx++)
1503 NativeHandle handleB (handleA);
1504 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handleB, flags));
1507 if (transference == TRANSFERENCE_COPY)
1509 importSemaphore(vkd, *device, *semaphoreA, config.externalType, handleA, flags);
1510 submitEmptyWait(vkd, queue, *semaphoreA);
1512 else if (transference == TRANSFERENCE_REFERENCE)
1514 submitEmptySignal(vkd, queue, *semaphoreA);
1515 submitEmptyWait(vkd, queue, *semaphoreA);
1518 DE_FATAL("Unknown transference.");
1520 VK_CHECK(vkd.queueWaitIdle(queue));
1523 return tcu::TestStatus::pass("Pass");
1526 tcu::TestStatus testSemaphoreTransference (Context& context,
1527 const SemaphoreTestConfig config)
1529 const Transference transference (getHandelTypeTransferences(config.externalType));
1530 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1531 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1532 const vk::InstanceDriver& vki (instance.getDriver());
1533 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1534 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1536 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1539 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1540 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1541 const vk::DeviceDriver vkd (vkp, instance, *device);
1542 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1543 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1545 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1546 NativeHandle handle;
1548 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
1549 if (transference == TRANSFERENCE_COPY && handle.getFd() == -1)
1550 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1553 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1555 if (config.permanence == PERMANENCE_PERMANENT)
1557 if (transference == TRANSFERENCE_COPY)
1559 submitEmptySignal(vkd, queue, *semaphoreA);
1560 submitEmptyWait(vkd, queue, *semaphoreB);
1561 VK_CHECK(vkd.queueWaitIdle(queue));
1563 submitEmptySignal(vkd, queue, *semaphoreB);
1565 submitEmptyWait(vkd, queue, *semaphoreA);
1566 submitEmptyWait(vkd, queue, *semaphoreB);
1567 VK_CHECK(vkd.queueWaitIdle(queue));
1569 else if (transference== TRANSFERENCE_REFERENCE)
1571 submitEmptyWait(vkd, queue, *semaphoreB);
1572 VK_CHECK(vkd.queueWaitIdle(queue));
1574 submitEmptySignal(vkd, queue, *semaphoreA);
1575 submitEmptyWait(vkd, queue, *semaphoreB);
1577 submitEmptySignal(vkd, queue, *semaphoreB);
1578 submitEmptyWait(vkd, queue, *semaphoreA);
1579 VK_CHECK(vkd.queueWaitIdle(queue));
1582 DE_FATAL("Unknown transference.");
1584 else if (config.permanence == PERMANENCE_TEMPORARY)
1586 if (transference == TRANSFERENCE_COPY)
1588 submitEmptySignal(vkd, queue, *semaphoreA);
1589 submitEmptyWait(vkd, queue, *semaphoreB);
1590 VK_CHECK(vkd.queueWaitIdle(queue));
1592 submitEmptySignal(vkd, queue, *semaphoreB);
1594 submitEmptyWait(vkd, queue, *semaphoreA);
1595 submitEmptyWait(vkd, queue, *semaphoreB);
1596 VK_CHECK(vkd.queueWaitIdle(queue));
1598 else if (transference== TRANSFERENCE_REFERENCE)
1600 submitEmptyWait(vkd, queue, *semaphoreB);
1601 VK_CHECK(vkd.queueWaitIdle(queue));
1603 submitEmptySignal(vkd, queue, *semaphoreA);
1604 submitEmptySignal(vkd, queue, *semaphoreB);
1606 submitEmptyWait(vkd, queue, *semaphoreB);
1607 submitEmptyWait(vkd, queue, *semaphoreA);
1608 VK_CHECK(vkd.queueWaitIdle(queue));
1611 DE_FATAL("Unknown transference.");
1614 DE_FATAL("Unknown permanence.");
1617 return tcu::TestStatus::pass("Pass");
1621 tcu::TestStatus testSemaphoreFdDup (Context& context,
1622 const SemaphoreTestConfig config)
1624 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
1625 const Transference transference (getHandelTypeTransferences(config.externalType));
1626 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1627 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1628 const vk::InstanceDriver& vki (instance.getDriver());
1629 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1630 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1632 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1635 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1636 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1637 const vk::DeviceDriver vkd (vkp, instance, *device);
1638 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1639 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1641 TestLog& log = context.getTestContext().getLog();
1642 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1647 if (transference == TRANSFERENCE_COPY)
1649 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, fd);
1650 if (fd.getFd() == -1)
1651 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1654 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, fd);
1656 NativeHandle newFd (dup(fd.getFd()));
1658 if (newFd.getFd() < 0)
1659 log << TestLog::Message << "dup() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
1661 TCU_CHECK_MSG(newFd.getFd() >= 0, "Failed to call dup() for semaphores fd");
1664 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, newFd, flags));
1666 if (transference == TRANSFERENCE_COPY)
1667 submitEmptyWait(vkd, queue, *semaphoreB);
1668 else if (transference == TRANSFERENCE_REFERENCE)
1670 submitEmptySignal(vkd, queue, *semaphoreA);
1671 submitEmptyWait(vkd, queue, *semaphoreB);
1674 DE_FATAL("Unknown permanence.");
1676 VK_CHECK(vkd.queueWaitIdle(queue));
1680 return tcu::TestStatus::pass("Pass");
1685 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
1689 tcu::TestStatus testSemaphoreFdDup2 (Context& context,
1690 const SemaphoreTestConfig config)
1692 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
1693 const Transference transference (getHandelTypeTransferences(config.externalType));
1694 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1695 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1696 const vk::InstanceDriver& vki (instance.getDriver());
1697 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1698 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1700 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1703 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1704 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1705 const vk::DeviceDriver vkd (vkp, instance, *device);
1706 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1707 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1709 TestLog& log = context.getTestContext().getLog();
1710 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1711 const vk::Unique<vk::VkSemaphore> semaphoreB (createExportableSemaphore(vkd, *device, config.externalType));
1714 NativeHandle fd, secondFd;
1716 if (transference == TRANSFERENCE_COPY)
1718 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, fd);
1719 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreB, config.externalType, secondFd);
1720 if (fd.getFd() == -1 || secondFd.getFd() == -1)
1721 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1725 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, fd);
1726 getSemaphoreNative(vkd, *device, *semaphoreB, config.externalType, secondFd);
1729 int newFd (dup2(fd.getFd(), secondFd.getFd()));
1732 log << TestLog::Message << "dup2() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
1734 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup2() for fences fd");
1737 const vk::Unique<vk::VkSemaphore> semaphoreC (createAndImportSemaphore(vkd, *device, config.externalType, secondFd, flags));
1739 if (transference == TRANSFERENCE_COPY)
1740 submitEmptyWait(vkd, queue, *semaphoreC);
1741 else if (transference == TRANSFERENCE_REFERENCE)
1743 submitEmptySignal(vkd, queue, *semaphoreA);
1744 submitEmptyWait(vkd, queue, *semaphoreC);
1747 DE_FATAL("Unknown permanence.");
1749 VK_CHECK(vkd.queueWaitIdle(queue));
1753 return tcu::TestStatus::pass("Pass");
1758 TCU_THROW(NotSupportedError, "Platform doesn't support dup2()");
1762 tcu::TestStatus testSemaphoreFdDup3 (Context& context,
1763 const SemaphoreTestConfig config)
1765 #if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
1766 const Transference transference (getHandelTypeTransferences(config.externalType));
1767 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1768 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1769 const vk::InstanceDriver& vki (instance.getDriver());
1770 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1771 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1773 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1776 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1777 const vk::DeviceDriver vkd (vkp, instance, *device);
1778 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1779 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1781 TestLog& log = context.getTestContext().getLog();
1782 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1783 const vk::Unique<vk::VkSemaphore> semaphoreB (createExportableSemaphore(vkd, *device, config.externalType));
1786 NativeHandle fd, secondFd;
1788 if (transference == TRANSFERENCE_COPY)
1790 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, fd);
1791 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreB, config.externalType, secondFd);
1792 if (fd.getFd() == -1 || secondFd.getFd() == -1)
1793 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1797 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, fd);
1798 getSemaphoreNative(vkd, *device, *semaphoreB, config.externalType, secondFd);
1801 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1802 const int newFd (dup3(fd.getFd(), secondFd.getFd(), 0));
1805 log << TestLog::Message << "dup3() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
1807 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup3() for fences fd");
1810 const vk::Unique<vk::VkSemaphore> semaphoreC (createAndImportSemaphore(vkd, *device, config.externalType, secondFd, flags));
1812 if (transference == TRANSFERENCE_COPY)
1813 submitEmptyWait(vkd, queue, *semaphoreC);
1814 else if (transference == TRANSFERENCE_REFERENCE)
1816 submitEmptySignal(vkd, queue, *semaphoreA);
1817 submitEmptyWait(vkd, queue, *semaphoreC);
1820 DE_FATAL("Unknown permanence.");
1822 VK_CHECK(vkd.queueWaitIdle(queue));
1826 return tcu::TestStatus::pass("Pass");
1831 TCU_THROW(NotSupportedError, "Platform doesn't support dup3()");
1835 tcu::TestStatus testSemaphoreFdSendOverSocket (Context& context,
1836 const SemaphoreTestConfig config)
1838 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
1839 const Transference transference (getHandelTypeTransferences(config.externalType));
1840 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1841 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1842 const vk::InstanceDriver& vki (instance.getDriver());
1843 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1844 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1846 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1849 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1850 const vk::DeviceDriver vkd (vkp, instance, *device);
1851 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1852 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1854 TestLog& log = context.getTestContext().getLog();
1855 const vk::Unique<vk::VkSemaphore> semaphore (createExportableSemaphore(vkd, *device, config.externalType));
1858 if (transference == TRANSFERENCE_COPY)
1860 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphore, config.externalType, fd);
1861 if (fd.getFd() == -1)
1862 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1865 getSemaphoreNative(vkd, *device, *semaphore, config.externalType, fd);
1870 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
1872 log << TestLog::Message << "Failed to create socket pair: '" << strerror(errno) << "'" << TestLog::EndMessage;
1873 TCU_FAIL("Failed to create socket pair");
1877 const NativeHandle srcSocket (sv[0]);
1878 const NativeHandle dstSocket (sv[1]);
1879 std::string sendData ("deqp");
1883 const int fdRaw (fd.getFd());
1886 char buffer[CMSG_SPACE(sizeof(int))];
1887 iovec iov = { &sendData[0], sendData.length()};
1889 deMemset(&msg, 0, sizeof(msg));
1891 msg.msg_control = buffer;
1892 msg.msg_controllen = sizeof(buffer);
1896 cmsg = CMSG_FIRSTHDR(&msg);
1897 cmsg->cmsg_level = SOL_SOCKET;
1898 cmsg->cmsg_type = SCM_RIGHTS;
1899 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
1901 deMemcpy(CMSG_DATA(cmsg), &fdRaw, sizeof(int));
1902 msg.msg_controllen = cmsg->cmsg_len;
1904 if (sendmsg(srcSocket.getFd(), &msg, 0) < 0)
1906 log << TestLog::Message << "Failed to send fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
1907 TCU_FAIL("Failed to send fd over socket");
1914 char buffer[CMSG_SPACE(sizeof(int))];
1915 std::string recvData (4, '\0');
1916 iovec iov = { &recvData[0], recvData.length() };
1918 deMemset(&msg, 0, sizeof(msg));
1920 msg.msg_control = buffer;
1921 msg.msg_controllen = sizeof(buffer);
1925 const ssize_t bytes = recvmsg(dstSocket.getFd(), &msg, 0);
1929 log << TestLog::Message << "Failed to recv fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
1930 TCU_FAIL("Failed to recv fd over socket");
1933 else if (bytes != (ssize_t)sendData.length())
1935 TCU_FAIL("recvmsg() returned unpexpected number of bytes");
1939 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1940 const cmsghdr* const cmsg = CMSG_FIRSTHDR(&msg);
1942 deMemcpy(&newFd_, CMSG_DATA(cmsg), sizeof(int));
1943 NativeHandle newFd (newFd_);
1945 TCU_CHECK(cmsg->cmsg_level == SOL_SOCKET);
1946 TCU_CHECK(cmsg->cmsg_type == SCM_RIGHTS);
1947 TCU_CHECK(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
1948 TCU_CHECK(recvData == sendData);
1949 TCU_CHECK_MSG(newFd.getFd() >= 0, "Didn't receive valid fd from socket");
1952 const vk::Unique<vk::VkSemaphore> newSemaphore (createAndImportSemaphore(vkd, *device, config.externalType, newFd, flags));
1954 if (transference == TRANSFERENCE_COPY)
1955 submitEmptyWait(vkd, queue, *newSemaphore);
1956 else if (transference == TRANSFERENCE_REFERENCE)
1958 submitEmptySignal(vkd, queue, *newSemaphore);
1959 submitEmptyWait(vkd, queue, *newSemaphore);
1962 DE_FATAL("Unknown permanence.");
1964 VK_CHECK(vkd.queueWaitIdle(queue));
1972 return tcu::TestStatus::pass("Pass");
1976 TCU_THROW(NotSupportedError, "Platform doesn't support sending file descriptors over socket");
1980 tcu::TestStatus testFenceQueries (Context& context, vk::VkExternalFenceHandleTypeFlagBits externalType)
1982 const CustomInstance instance (createTestInstance(context, 0u, 0u, externalType));
1983 const vk::InstanceDriver& vki (instance.getDriver());
1984 const vk::VkPhysicalDevice device (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1986 TestLog& log = context.getTestContext().getLog();
1988 const vk::VkPhysicalDeviceExternalFenceInfo info =
1990 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO,
1994 vk::VkExternalFenceProperties properties =
1996 vk::VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES,
2003 vki.getPhysicalDeviceExternalFenceProperties(device, &info, &properties);
2004 log << TestLog::Message << properties << TestLog::EndMessage;
2006 TCU_CHECK(properties.pNext == DE_NULL);
2007 TCU_CHECK(properties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES);
2009 return tcu::TestStatus::pass("Pass");
2012 struct FenceTestConfig
2014 FenceTestConfig (vk::VkExternalFenceHandleTypeFlagBits externalType_,
2015 Permanence permanence_)
2016 : externalType (externalType_)
2017 , permanence (permanence_)
2021 vk::VkExternalFenceHandleTypeFlagBits externalType;
2022 Permanence permanence;
2025 tcu::TestStatus testFenceWin32Create (Context& context,
2026 const FenceTestConfig config)
2028 #if (DE_OS == DE_OS_WIN32)
2029 const Transference transference (getHandelTypeTransferences(config.externalType));
2030 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2031 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2032 const vk::InstanceDriver& vki (instance.getDriver());
2033 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2034 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2036 checkFenceSupport(vki, physicalDevice, config.externalType);
2039 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2040 const vk::DeviceDriver vkd (vkp, instance, *device);
2041 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2042 const vk::VkExportFenceWin32HandleInfoKHR win32ExportInfo =
2044 vk::VK_STRUCTURE_TYPE_EXPORT_FENCE_WIN32_HANDLE_INFO_KHR,
2047 (vk::pt::Win32SecurityAttributesPtr)DE_NULL,
2048 DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
2049 (vk::pt::Win32LPCWSTR)DE_NULL
2051 const vk::VkExportFenceCreateInfo exportCreateInfo=
2053 vk::VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO,
2055 (vk::VkExternalFenceHandleTypeFlags)config.externalType
2057 const vk::VkFenceCreateInfo createInfo =
2059 vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
2063 const vk::Unique<vk::VkFence> fence (vk::createFence(vkd, *device, &createInfo));
2065 if (transference == TRANSFERENCE_COPY)
2066 submitEmptySignal(vkd, queue, *fence);
2068 NativeHandle handleA;
2069 getFenceNative(vkd, *device, *fence, config.externalType, handleA);
2072 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2073 const vk::Unique<vk::VkFence> fenceA (createAndImportFence(vkd, *device, config.externalType, handleA, flags));
2075 if (transference == TRANSFERENCE_COPY)
2076 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2077 else if (transference == TRANSFERENCE_REFERENCE)
2079 submitEmptySignal(vkd, queue, *fence);
2080 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2083 DE_FATAL("Unknown transference.");
2085 VK_CHECK(vkd.queueWaitIdle(queue));
2088 return tcu::TestStatus::pass("Pass");
2093 TCU_THROW(NotSupportedError, "Platform doesn't support win32 handles");
2097 tcu::TestStatus testFenceImportTwice (Context& context,
2098 const FenceTestConfig config)
2100 const Transference transference (getHandelTypeTransferences(config.externalType));
2101 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2102 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2103 const vk::InstanceDriver& vki (instance.getDriver());
2104 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2105 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2107 checkFenceSupport(vki, physicalDevice, config.externalType);
2110 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2111 const vk::DeviceDriver vkd (vkp, instance, *device);
2112 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2113 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2114 const vk::Unique<vk::VkFence> fence (createExportableFence(vkd, *device, config.externalType));
2115 NativeHandle handleA;
2117 if (transference == TRANSFERENCE_COPY)
2119 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fence, config.externalType, handleA);
2120 if (handleA.getFd() == -1)
2121 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2124 getFenceNative(vkd, *device, *fence, config.externalType, handleA);
2127 NativeHandle handleB (handleA);
2128 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2129 const vk::Unique<vk::VkFence> fenceA (createAndImportFence(vkd, *device, config.externalType, handleA, flags));
2130 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handleB, flags));
2132 if (transference == TRANSFERENCE_COPY)
2133 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2134 else if (transference == TRANSFERENCE_REFERENCE)
2136 submitEmptySignal(vkd, queue, *fenceA);
2137 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2140 DE_FATAL("Unknown transference.");
2142 VK_CHECK(vkd.queueWaitIdle(queue));
2145 return tcu::TestStatus::pass("Pass");
2149 tcu::TestStatus testFenceImportReimport (Context& context,
2150 const FenceTestConfig config)
2152 const Transference transference (getHandelTypeTransferences(config.externalType));
2153 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2154 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2155 const vk::InstanceDriver& vki (instance.getDriver());
2156 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2157 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2159 checkFenceSupport(vki, physicalDevice, config.externalType);
2162 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2163 const vk::DeviceDriver vkd (vkp, instance, *device);
2164 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2165 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2167 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2168 NativeHandle handleA;
2170 if (transference == TRANSFERENCE_COPY)
2172 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, handleA);
2173 if (handleA.getFd() == -1)
2174 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2177 getFenceNative(vkd, *device, *fenceA, config.externalType, handleA);
2179 NativeHandle handleB (handleA);
2180 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2181 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handleA, flags));
2183 importFence(vkd, *device, *fenceB, config.externalType, handleB, flags);
2185 if (transference == TRANSFERENCE_COPY)
2186 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2187 else if (transference == TRANSFERENCE_REFERENCE)
2189 submitEmptySignal(vkd, queue, *fenceA);
2190 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2193 DE_FATAL("Unknown transference.");
2195 VK_CHECK(vkd.queueWaitIdle(queue));
2197 return tcu::TestStatus::pass("Pass");
2201 tcu::TestStatus testFenceSignalExportImportWait (Context& context,
2202 const FenceTestConfig config)
2204 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2205 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2206 const vk::InstanceDriver& vki (instance.getDriver());
2207 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2208 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2210 checkFenceSupport(vki, physicalDevice, config.externalType);
2213 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2214 const vk::DeviceDriver vkd (vkp, instance, *device);
2215 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2216 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2217 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2220 NativeHandle handle;
2222 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2223 if (handle.getFd() == -1)
2224 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2227 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2228 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handle, flags));
2229 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2231 VK_CHECK(vkd.queueWaitIdle(queue));
2235 return tcu::TestStatus::pass("Pass");
2239 tcu::TestStatus testFenceImportSyncFdSignaled (Context& context,
2240 const FenceTestConfig config)
2242 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2243 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2244 const vk::InstanceDriver& vki (instance.getDriver());
2245 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2246 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2247 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2249 checkFenceSupport(vki, physicalDevice, config.externalType);
2252 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2253 const vk::DeviceDriver vkd (vkp, instance, *device);
2254 NativeHandle handle = -1;
2255 const vk::Unique<vk::VkFence> fence (createAndImportFence(vkd, *device, config.externalType, handle, flags));
2257 if (vkd.waitForFences(*device, 1u, &*fence, VK_TRUE, 0) != vk::VK_SUCCESS)
2258 return tcu::TestStatus::pass("Imported -1 sync fd isn't signaled");
2260 return tcu::TestStatus::pass("Pass");
2264 tcu::TestStatus testFenceExportSignalImportWait (Context& context,
2265 const FenceTestConfig config)
2267 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2268 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2269 const vk::InstanceDriver& vki (instance.getDriver());
2270 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2271 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2272 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2274 DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
2275 checkFenceSupport(vki, physicalDevice, config.externalType);
2278 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2279 const vk::DeviceDriver vkd (vkp, instance, *device);
2280 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2282 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2283 NativeHandle handle;
2285 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2287 submitEmptySignal(vkd, queue, *fenceA);
2290 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handle, flags));
2292 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2293 VK_CHECK(vkd.queueWaitIdle(queue));
2297 return tcu::TestStatus::pass("Pass");
2301 tcu::TestStatus testFenceExportImportSignalWait (Context& context,
2302 const FenceTestConfig config)
2304 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2305 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2306 const vk::InstanceDriver& vki (instance.getDriver());
2307 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2308 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2310 DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
2311 checkFenceSupport(vki, physicalDevice, config.externalType);
2314 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2315 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2316 const vk::DeviceDriver vkd (vkp, instance, *device);
2317 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2319 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2320 NativeHandle handle;
2322 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2324 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handle, flags));
2326 submitEmptySignal(vkd, queue, *fenceA);
2327 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2329 VK_CHECK(vkd.queueWaitIdle(queue));
2331 return tcu::TestStatus::pass("Pass");
2335 tcu::TestStatus testFenceSignalImport (Context& context,
2336 const FenceTestConfig config)
2338 const Transference transference (getHandelTypeTransferences(config.externalType));
2339 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2340 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2341 const vk::InstanceDriver& vki (instance.getDriver());
2342 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2343 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2345 checkFenceSupport(vki, physicalDevice, config.externalType);
2348 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2349 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2350 const vk::DeviceDriver vkd (vkp, instance, *device);
2351 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2352 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2354 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2355 const vk::Unique<vk::VkFence> fenceB (createFence(vkd, *device));
2356 NativeHandle handle;
2358 submitEmptySignal(vkd, queue, *fenceB);
2359 VK_CHECK(vkd.queueWaitIdle(queue));
2361 if (transference == TRANSFERENCE_COPY)
2363 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2364 if (handle.getFd() == -1)
2365 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2368 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2370 importFence(vkd, *device, *fenceB, config.externalType, handle, flags);
2372 if (transference == TRANSFERENCE_COPY)
2373 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2374 else if (transference == TRANSFERENCE_REFERENCE)
2376 submitEmptySignal(vkd, queue, *fenceA);
2377 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2380 DE_FATAL("Unknown transference.");
2382 VK_CHECK(vkd.queueWaitIdle(queue));
2384 return tcu::TestStatus::pass("Pass");
2388 tcu::TestStatus testFenceReset (Context& context,
2389 const FenceTestConfig config)
2391 const Transference transference (getHandelTypeTransferences(config.externalType));
2392 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2393 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2394 const vk::InstanceDriver& vki (instance.getDriver());
2395 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2396 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2398 checkFenceSupport(vki, physicalDevice, config.externalType);
2401 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2402 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2403 const vk::DeviceDriver vkd (vkp, instance, *device);
2404 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2405 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2407 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2408 const vk::Unique<vk::VkFence> fenceB (createFence(vkd, *device));
2409 const vk::Unique<vk::VkFence> fenceC (createFence(vkd, *device));
2410 NativeHandle handle;
2412 submitEmptySignal(vkd, queue, *fenceB);
2413 VK_CHECK(vkd.queueWaitIdle(queue));
2415 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2416 if (handle.getFd() == -1)
2417 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2419 NativeHandle handleB (handle);
2420 importFence(vkd, *device, *fenceB, config.externalType, handleB, flags);
2421 importFence(vkd, *device, *fenceC, config.externalType, handle, flags);
2423 VK_CHECK(vkd.queueWaitIdle(queue));
2424 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2426 if (config.permanence == PERMANENCE_TEMPORARY || transference == TRANSFERENCE_COPY)
2428 // vkResetFences() should restore fenceBs prior payload and reset that no affecting fenceCs payload
2429 // or fenceB should be separate copy of the payload and not affect fenceC
2430 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2432 // vkResetFences() should have restored fenceBs prior state and should be now reset
2433 // or fenceB should have it's separate payload
2434 submitEmptySignal(vkd, queue, *fenceB);
2435 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2437 else if (config.permanence == PERMANENCE_PERMANENT)
2439 DE_ASSERT(transference == TRANSFERENCE_REFERENCE);
2441 // Reset fences should have reset all of the fences
2442 submitEmptySignal(vkd, queue, *fenceC);
2444 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2445 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2446 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2449 DE_FATAL("Unknown permanence");
2451 VK_CHECK(vkd.queueWaitIdle(queue));
2453 return tcu::TestStatus::pass("Pass");
2457 tcu::TestStatus testFenceSignalWaitImport (Context& context,
2458 const FenceTestConfig config)
2460 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2461 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2462 const vk::InstanceDriver& vki (instance.getDriver());
2463 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2464 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2466 checkFenceSupport(vki, physicalDevice, config.externalType);
2469 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2470 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2471 const vk::DeviceDriver vkd (vkp, instance, *device);
2472 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2474 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2475 const vk::Unique<vk::VkFence> fenceB (createFence(vkd, *device));
2476 NativeHandle handle;
2478 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2480 submitEmptySignal(vkd, queue, *fenceB);
2481 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2483 VK_CHECK(vkd.queueWaitIdle(queue));
2485 importFence(vkd, *device, *fenceB, config.externalType, handle, flags);
2487 submitEmptySignal(vkd, queue, *fenceA);
2488 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2490 VK_CHECK(vkd.queueWaitIdle(queue));
2492 return tcu::TestStatus::pass("Pass");
2496 tcu::TestStatus testFenceMultipleExports (Context& context,
2497 const FenceTestConfig config)
2499 const size_t exportCount = 1024;
2500 const Transference transference (getHandelTypeTransferences(config.externalType));
2501 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2502 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2503 const vk::InstanceDriver& vki (instance.getDriver());
2504 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2505 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2507 checkFenceSupport(vki, physicalDevice, config.externalType);
2510 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2511 const vk::DeviceDriver vkd (vkp, instance, *device);
2512 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2513 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2514 const vk::Unique<vk::VkFence> fence (createExportableFence(vkd, *device, config.externalType));
2516 for (size_t exportNdx = 0; exportNdx < exportCount; exportNdx++)
2518 NativeHandle handle;
2520 if (transference == TRANSFERENCE_COPY)
2522 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fence, config.externalType, handle, exportNdx == 0 /* expect fence to be signaled after first pass */);
2523 if (handle.getFd() == -1)
2524 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2527 getFenceNative(vkd, *device, *fence, config.externalType, handle, exportNdx == 0 /* expect fence to be signaled after first pass */);
2530 submitEmptySignal(vkd, queue, *fence);
2531 VK_CHECK(vkd.waitForFences(*device, 1u, &*fence, VK_TRUE, ~0ull));
2533 VK_CHECK(vkd.queueWaitIdle(queue));
2536 return tcu::TestStatus::pass("Pass");
2539 tcu::TestStatus testFenceMultipleImports (Context& context,
2540 const FenceTestConfig config)
2542 const size_t importCount = 4 * 1024;
2543 const Transference transference (getHandelTypeTransferences(config.externalType));
2544 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2545 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2546 const vk::InstanceDriver& vki (instance.getDriver());
2547 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2548 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2550 checkFenceSupport(vki, physicalDevice, config.externalType);
2553 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2554 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2555 const vk::DeviceDriver vkd (vkp, instance, *device);
2556 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2557 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2558 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2559 NativeHandle handleA;
2561 if (transference == TRANSFERENCE_COPY)
2563 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, handleA);
2564 if (handleA.getFd() == -1)
2565 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2568 getFenceNative(vkd, *device, *fenceA, config.externalType, handleA);
2570 for (size_t importNdx = 0; importNdx < importCount; importNdx++)
2572 NativeHandle handleB (handleA);
2573 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handleB, flags));
2576 if (transference == TRANSFERENCE_COPY)
2578 importFence(vkd, *device, *fenceA, config.externalType, handleA, flags);
2579 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2581 else if (transference == TRANSFERENCE_REFERENCE)
2583 submitEmptySignal(vkd, queue, *fenceA);
2584 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2587 DE_FATAL("Unknown transference.");
2589 VK_CHECK(vkd.queueWaitIdle(queue));
2592 return tcu::TestStatus::pass("Pass");
2595 tcu::TestStatus testFenceTransference (Context& context,
2596 const FenceTestConfig config)
2598 const Transference transference (getHandelTypeTransferences(config.externalType));
2599 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2600 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2601 const vk::InstanceDriver& vki (instance.getDriver());
2602 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2603 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2605 checkFenceSupport(vki, physicalDevice, config.externalType);
2608 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2609 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2610 const vk::DeviceDriver vkd (vkp, instance, *device);
2611 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2612 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2614 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2615 NativeHandle handle;
2617 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2618 if (handle.getFd() == -1)
2619 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2622 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handle, flags));
2624 if (config.permanence == PERMANENCE_PERMANENT)
2626 if (transference == TRANSFERENCE_COPY)
2628 submitEmptySignal(vkd, queue, *fenceA);
2629 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2630 VK_CHECK(vkd.queueWaitIdle(queue));
2632 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2633 submitEmptySignal(vkd, queue, *fenceB);
2635 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2636 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2637 VK_CHECK(vkd.queueWaitIdle(queue));
2639 else if (transference== TRANSFERENCE_REFERENCE)
2641 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2642 VK_CHECK(vkd.queueWaitIdle(queue));
2644 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2645 submitEmptySignal(vkd, queue, *fenceA);
2646 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2648 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceA));
2649 submitEmptySignal(vkd, queue, *fenceB);
2650 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2651 VK_CHECK(vkd.queueWaitIdle(queue));
2654 DE_FATAL("Unknown transference.");
2656 else if (config.permanence == PERMANENCE_TEMPORARY)
2658 if (transference == TRANSFERENCE_COPY)
2660 submitEmptySignal(vkd, queue, *fenceA);
2661 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2662 VK_CHECK(vkd.queueWaitIdle(queue));
2664 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2665 submitEmptySignal(vkd, queue, *fenceB);
2667 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2668 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2669 VK_CHECK(vkd.queueWaitIdle(queue));
2671 else if (transference == TRANSFERENCE_REFERENCE)
2673 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2674 VK_CHECK(vkd.queueWaitIdle(queue));
2676 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceA));
2677 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2678 submitEmptySignal(vkd, queue, *fenceA);
2679 submitEmptySignal(vkd, queue, *fenceB);
2681 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2682 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2683 VK_CHECK(vkd.queueWaitIdle(queue));
2686 DE_FATAL("Unknown transference.");
2689 DE_FATAL("Unknown permanence.");
2692 return tcu::TestStatus::pass("Pass");
2696 tcu::TestStatus testFenceFdDup (Context& context,
2697 const FenceTestConfig config)
2699 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2700 const Transference transference (getHandelTypeTransferences(config.externalType));
2701 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2702 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2703 const vk::InstanceDriver& vki (instance.getDriver());
2704 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2705 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2707 checkFenceSupport(vki, physicalDevice, config.externalType);
2710 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2711 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2712 const vk::DeviceDriver vkd (vkp, instance, *device);
2713 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2714 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2716 TestLog& log = context.getTestContext().getLog();
2717 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2722 if (transference == TRANSFERENCE_COPY)
2724 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, fd);
2725 if (fd.getFd() == -1)
2726 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2729 getFenceNative(vkd, *device, *fenceA, config.externalType, fd);
2731 NativeHandle newFd (dup(fd.getFd()));
2733 if (newFd.getFd() < 0)
2734 log << TestLog::Message << "dup() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2736 TCU_CHECK_MSG(newFd.getFd() >= 0, "Failed to call dup() for fences fd");
2739 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, newFd, flags));
2741 if (transference == TRANSFERENCE_COPY)
2742 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2743 else if (transference == TRANSFERENCE_REFERENCE)
2745 submitEmptySignal(vkd, queue, *fenceA);
2746 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2749 DE_FATAL("Unknown permanence.");
2751 VK_CHECK(vkd.queueWaitIdle(queue));
2755 return tcu::TestStatus::pass("Pass");
2760 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
2764 tcu::TestStatus testFenceFdDup2 (Context& context,
2765 const FenceTestConfig config)
2767 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2768 const Transference transference (getHandelTypeTransferences(config.externalType));
2769 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2770 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2771 const vk::InstanceDriver& vki (instance.getDriver());
2772 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2773 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2775 checkFenceSupport(vki, physicalDevice, config.externalType);
2778 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2779 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2780 const vk::DeviceDriver vkd (vkp, instance, *device);
2781 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2782 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2784 TestLog& log = context.getTestContext().getLog();
2785 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2786 const vk::Unique<vk::VkFence> fenceB (createExportableFence(vkd, *device, config.externalType));
2789 NativeHandle fd, secondFd;
2791 if (transference == TRANSFERENCE_COPY)
2793 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, fd);
2794 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceB, config.externalType, secondFd);
2795 if (fd.getFd() == -1 || secondFd.getFd() == -1)
2796 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2800 getFenceNative(vkd, *device, *fenceA, config.externalType, fd);
2801 getFenceNative(vkd, *device, *fenceB, config.externalType, secondFd);
2804 int newFd (dup2(fd.getFd(), secondFd.getFd()));
2807 log << TestLog::Message << "dup2() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2809 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup2() for fences fd");
2812 const vk::Unique<vk::VkFence> fenceC (createAndImportFence(vkd, *device, config.externalType, secondFd, flags));
2814 if (transference == TRANSFERENCE_COPY)
2815 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2816 else if (transference == TRANSFERENCE_REFERENCE)
2818 submitEmptySignal(vkd, queue, *fenceA);
2819 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2822 DE_FATAL("Unknown permanence.");
2824 VK_CHECK(vkd.queueWaitIdle(queue));
2828 return tcu::TestStatus::pass("Pass");
2833 TCU_THROW(NotSupportedError, "Platform doesn't support dup2()");
2837 tcu::TestStatus testFenceFdDup3 (Context& context,
2838 const FenceTestConfig config)
2840 #if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
2841 const Transference transference (getHandelTypeTransferences(config.externalType));
2842 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2843 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2844 const vk::InstanceDriver& vki (instance.getDriver());
2845 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2846 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2848 checkFenceSupport(vki, physicalDevice, config.externalType);
2851 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2852 const vk::DeviceDriver vkd (vkp, instance, *device);
2853 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2854 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2856 TestLog& log = context.getTestContext().getLog();
2857 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2858 const vk::Unique<vk::VkFence> fenceB (createExportableFence(vkd, *device, config.externalType));
2861 NativeHandle fd, secondFd;
2863 if (transference == TRANSFERENCE_COPY)
2865 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, fd);
2866 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceB, config.externalType, secondFd);
2867 if (fd.getFd() == -1 || secondFd.getFd() == -1)
2868 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2872 getFenceNative(vkd, *device, *fenceA, config.externalType, fd);
2873 getFenceNative(vkd, *device, *fenceB, config.externalType, secondFd);
2876 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2877 const int newFd (dup3(fd.getFd(), secondFd.getFd(), 0));
2880 log << TestLog::Message << "dup3() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2882 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup3() for fences fd");
2885 const vk::Unique<vk::VkFence> fenceC (createAndImportFence(vkd, *device, config.externalType, secondFd, flags));
2887 if (transference == TRANSFERENCE_COPY)
2888 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2889 else if (transference == TRANSFERENCE_REFERENCE)
2891 submitEmptySignal(vkd, queue, *fenceA);
2892 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2895 DE_FATAL("Unknown permanence.");
2897 VK_CHECK(vkd.queueWaitIdle(queue));
2901 return tcu::TestStatus::pass("Pass");
2906 TCU_THROW(NotSupportedError, "Platform doesn't support dup3()");
2910 tcu::TestStatus testFenceFdSendOverSocket (Context& context,
2911 const FenceTestConfig config)
2913 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2914 const Transference transference (getHandelTypeTransferences(config.externalType));
2915 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2916 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2917 const vk::InstanceDriver& vki (instance.getDriver());
2918 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2919 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2921 checkFenceSupport(vki, physicalDevice, config.externalType);
2924 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2925 const vk::DeviceDriver vkd (vkp, instance, *device);
2926 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2927 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2929 TestLog& log = context.getTestContext().getLog();
2930 const vk::Unique<vk::VkFence> fence (createExportableFence(vkd, *device, config.externalType));
2933 if (transference == TRANSFERENCE_COPY)
2935 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fence, config.externalType, fd);
2936 if (fd.getFd() == -1)
2937 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2940 getFenceNative(vkd, *device, *fence, config.externalType, fd);
2945 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
2947 log << TestLog::Message << "Failed to create socket pair: '" << strerror(errno) << "'" << TestLog::EndMessage;
2948 TCU_FAIL("Failed to create socket pair");
2952 const NativeHandle srcSocket (sv[0]);
2953 const NativeHandle dstSocket (sv[1]);
2954 std::string sendData ("deqp");
2958 const int fdRaw (fd.getFd());
2961 char buffer[CMSG_SPACE(sizeof(int))];
2962 iovec iov = { &sendData[0], sendData.length()};
2964 deMemset(&msg, 0, sizeof(msg));
2966 msg.msg_control = buffer;
2967 msg.msg_controllen = sizeof(buffer);
2971 cmsg = CMSG_FIRSTHDR(&msg);
2972 cmsg->cmsg_level = SOL_SOCKET;
2973 cmsg->cmsg_type = SCM_RIGHTS;
2974 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
2976 deMemcpy(CMSG_DATA(cmsg), &fdRaw, sizeof(int));
2977 msg.msg_controllen = cmsg->cmsg_len;
2979 if (sendmsg(srcSocket.getFd(), &msg, 0) < 0)
2981 log << TestLog::Message << "Failed to send fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
2982 TCU_FAIL("Failed to send fd over socket");
2989 char buffer[CMSG_SPACE(sizeof(int))];
2990 std::string recvData (4, '\0');
2991 iovec iov = { &recvData[0], recvData.length() };
2993 deMemset(&msg, 0, sizeof(msg));
2995 msg.msg_control = buffer;
2996 msg.msg_controllen = sizeof(buffer);
3000 const ssize_t bytes = recvmsg(dstSocket.getFd(), &msg, 0);
3004 log << TestLog::Message << "Failed to recv fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
3005 TCU_FAIL("Failed to recv fd over socket");
3008 else if (bytes != (ssize_t)sendData.length())
3010 TCU_FAIL("recvmsg() returned unpexpected number of bytes");
3014 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
3015 const cmsghdr* const cmsg = CMSG_FIRSTHDR(&msg);
3017 deMemcpy(&newFd_, CMSG_DATA(cmsg), sizeof(int));
3018 NativeHandle newFd (newFd_);
3020 TCU_CHECK(cmsg->cmsg_level == SOL_SOCKET);
3021 TCU_CHECK(cmsg->cmsg_type == SCM_RIGHTS);
3022 TCU_CHECK(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
3023 TCU_CHECK(recvData == sendData);
3024 TCU_CHECK_MSG(newFd.getFd() >= 0, "Didn't receive valid fd from socket");
3027 const vk::Unique<vk::VkFence> newFence (createAndImportFence(vkd, *device, config.externalType, newFd, flags));
3029 if (transference == TRANSFERENCE_COPY)
3030 VK_CHECK(vkd.waitForFences(*device, 1u, &*newFence, VK_TRUE, ~0ull));
3031 else if (transference == TRANSFERENCE_REFERENCE)
3033 submitEmptySignal(vkd, queue, *newFence);
3034 VK_CHECK(vkd.waitForFences(*device, 1u, &*newFence, VK_TRUE, ~0ull));
3037 DE_FATAL("Unknown permanence.");
3039 VK_CHECK(vkd.queueWaitIdle(queue));
3047 return tcu::TestStatus::pass("Pass");
3051 TCU_THROW(NotSupportedError, "Platform doesn't support sending file descriptors over socket");
3055 tcu::TestStatus testBufferQueries (Context& context, vk::VkExternalMemoryHandleTypeFlagBits externalType)
3057 const vk::VkBufferCreateFlags createFlags[] =
3060 vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT,
3061 vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT|vk::VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT,
3062 vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT|vk::VK_BUFFER_CREATE_SPARSE_ALIASED_BIT
3064 const vk::VkBufferUsageFlags usageFlags[] =
3066 vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
3067 vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT,
3068 vk::VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT,
3069 vk::VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT,
3070 vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
3071 vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
3072 vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
3073 vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
3074 vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT
3076 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3077 const CustomInstance instance (createTestInstance(context, 0u, externalType, 0u));
3078 const vk::InstanceDriver& vki (instance.getDriver());
3079 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3080 const vk::VkPhysicalDeviceFeatures deviceFeatures (vk::getPhysicalDeviceFeatures(vki, physicalDevice));
3081 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3083 // VkDevice is only created if physical device claims to support any of these types.
3084 vk::Move<vk::VkDevice> device;
3085 de::MovePtr<vk::DeviceDriver> vkd;
3086 bool deviceHasDedicated = false;
3088 TestLog& log = context.getTestContext().getLog();
3090 for (size_t createFlagNdx = 0; createFlagNdx < DE_LENGTH_OF_ARRAY(createFlags); createFlagNdx++)
3091 for (size_t usageFlagNdx = 0; usageFlagNdx < DE_LENGTH_OF_ARRAY(usageFlags); usageFlagNdx++)
3093 const vk::VkBufferViewCreateFlags createFlag = createFlags[createFlagNdx];
3094 const vk::VkBufferUsageFlags usageFlag = usageFlags[usageFlagNdx];
3095 const vk::VkPhysicalDeviceExternalBufferInfo info =
3097 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO,
3103 vk::VkExternalBufferProperties properties =
3105 vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES,
3110 if (((createFlag & vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT) != 0) &&
3111 (deviceFeatures.sparseBinding == VK_FALSE))
3114 if (((createFlag & vk::VK_BUFFER_CREATE_SPARSE_ALIASED_BIT) != 0) &&
3115 (deviceFeatures.sparseResidencyAliased == VK_FALSE))
3118 if (((createFlag & vk::VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT) != 0) &&
3119 (deviceFeatures.sparseResidencyBuffer == VK_FALSE))
3122 vki.getPhysicalDeviceExternalBufferProperties(physicalDevice, &info, &properties);
3124 log << TestLog::Message << properties << TestLog::EndMessage;
3126 TCU_CHECK(properties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES);
3127 TCU_CHECK(properties.pNext == DE_NULL);
3128 // \todo [2017-06-06 pyry] Can we validate anything else? Compatible types?
3130 if ((properties.externalMemoryProperties.externalMemoryFeatures & (vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT|vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT)) != 0)
3132 const bool requiresDedicated = (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
3134 if (!device || (requiresDedicated && !deviceHasDedicated))
3136 // \note We need to re-create with dedicated mem extensions if previous device instance didn't have them
3139 device = createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, externalType, 0u, queueFamilyIndex, requiresDedicated);
3140 vkd = de::MovePtr<vk::DeviceDriver>(new vk::DeviceDriver(vkp, instance, *device));
3141 deviceHasDedicated = requiresDedicated;
3143 catch (const tcu::NotSupportedError& e)
3146 TCU_FAIL("Physical device claims to support handle type but required extensions are not supported");
3151 if ((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) != 0)
3153 DE_ASSERT(!!device);
3156 if (deviceHasDedicated)
3158 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(*vkd, *device, queueFamilyIndex, externalType, 1024u, createFlag, usageFlag));
3159 const vk::VkMemoryDedicatedRequirements reqs (getMemoryDedicatedRequirements(*vkd, *device, *buffer));
3160 const bool propertiesRequiresDedicated = (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
3161 const bool objectRequiresDedicated = (reqs.requiresDedicatedAllocation != VK_FALSE);
3163 if (propertiesRequiresDedicated != objectRequiresDedicated)
3164 TCU_FAIL("vkGetPhysicalDeviceExternalBufferProperties and vkGetBufferMemoryRequirements2 report different dedicated requirements");
3168 // We can't query whether dedicated memory is required or not on per-object basis.
3169 // This check should be redundant as the code above tries to create device with
3170 // VK_KHR_dedicated_allocation & VK_KHR_get_memory_requirements2 if dedicated memory
3171 // is required. However, checking again doesn't hurt.
3172 TCU_CHECK((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) == 0);
3177 return tcu::TestStatus::pass("Pass");
3180 struct MemoryTestConfig
3182 MemoryTestConfig (vk::VkExternalMemoryHandleTypeFlagBits externalType_,
3185 : externalType (externalType_)
3186 , hostVisible (hostVisible_)
3187 , dedicated (dedicated_)
3191 vk::VkExternalMemoryHandleTypeFlagBits externalType;
3196 #if (DE_OS == DE_OS_WIN32)
3197 deUint32 chooseWin32MemoryType(deUint32 bits)
3200 TCU_THROW(NotSupportedError, "No compatible memory type found");
3202 return deCtz32(bits);
3206 tcu::TestStatus testMemoryWin32Create (Context& context, MemoryTestConfig config)
3208 #if (DE_OS == DE_OS_WIN32)
3209 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3210 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3211 const vk::InstanceDriver& vki (instance.getDriver());
3212 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3213 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3214 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3215 const vk::DeviceDriver vkd (vkp, instance, *device);
3216 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3217 const deUint32 seed = 1261033864u;
3218 const vk::VkDeviceSize bufferSize = 1024;
3219 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
3221 const vk::VkPhysicalDeviceMemoryProperties memoryProps = vk::getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice());
3222 const deUint32 compatibleMemTypes = vk::getCompatibleMemoryTypes(memoryProps, config.hostVisible ? vk::MemoryRequirement::HostVisible : vk::MemoryRequirement::Any);
3224 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3226 // \note Buffer is only allocated to get memory requirements
3227 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3228 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3229 const vk::VkExportMemoryWin32HandleInfoKHR win32Info =
3231 vk::VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR,
3234 (vk::pt::Win32SecurityAttributesPtr)DE_NULL,
3235 DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
3236 (vk::pt::Win32LPCWSTR)DE_NULL
3238 const vk::VkExportMemoryAllocateInfo exportInfo =
3240 vk::VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
3242 (vk::VkExternalMemoryHandleTypeFlags)config.externalType
3245 const deUint32 exportedMemoryTypeIndex = chooseWin32MemoryType(requirements.memoryTypeBits & compatibleMemTypes);
3246 const vk::VkMemoryAllocateInfo info =
3248 vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
3251 exportedMemoryTypeIndex
3253 const vk::Unique<vk::VkDeviceMemory> memory (vk::allocateMemory(vkd, *device, &info));
3254 NativeHandle handleA;
3256 if (config.hostVisible)
3257 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3259 getMemoryNative(vkd, *device, *memory, config.externalType, handleA);
3262 const vk::Unique<vk::VkDeviceMemory> memoryA (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleA));
3264 if (config.hostVisible)
3266 const std::vector<deUint8> testDataA (genTestData(seed ^ 124798807u, (size_t)bufferSize));
3267 const std::vector<deUint8> testDataB (genTestData(seed ^ 970834278u, (size_t)bufferSize));
3269 checkHostMemory(vkd, *device, *memoryA, testData.size(), &testData[0]);
3270 checkHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3272 writeHostMemory(vkd, *device, *memoryA, testDataA.size(), &testDataA[0]);
3273 writeHostMemory(vkd, *device, *memory, testDataA.size(), &testDataB[0]);
3275 checkHostMemory(vkd, *device, *memoryA, testData.size(), &testDataB[0]);
3276 checkHostMemory(vkd, *device, *memory, testData.size(), &testDataB[0]);
3280 return tcu::TestStatus::pass("Pass");
3284 TCU_THROW(NotSupportedError, "Platform doesn't support win32 handles");
3288 deUint32 getExportedMemoryTypeIndex(const vk::InstanceDriver& vki, const vk::VkPhysicalDevice physicalDevice, bool hostVisible, deUint32 memoryBits)
3292 const vk::VkPhysicalDeviceMemoryProperties properties(vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
3293 return chooseHostVisibleMemoryType(memoryBits, properties);
3296 return chooseMemoryType(memoryBits);
3299 tcu::TestStatus testMemoryImportTwice (Context& context, MemoryTestConfig config)
3301 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3302 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3303 const vk::InstanceDriver& vki (instance.getDriver());
3304 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3305 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3306 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3307 const vk::DeviceDriver vkd (vkp, instance, *device);
3308 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3309 const deUint32 seed = 1261033864u;
3310 const vk::VkDeviceSize bufferSize = 1024;
3311 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
3313 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3315 // \note Buffer is only allocated to get memory requirements
3316 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3317 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3318 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3319 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3320 NativeHandle handleA;
3322 if (config.hostVisible)
3323 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3325 getMemoryNative(vkd, *device, *memory, config.externalType, handleA);
3328 const vk::Unique<vk::VkBuffer> bufferA (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3329 const vk::Unique<vk::VkBuffer> bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3330 NativeHandle handleB (handleA);
3331 const vk::Unique<vk::VkDeviceMemory> memoryA (config.dedicated
3332 ? importDedicatedMemory(vkd, *device, *bufferA, requirements, config.externalType, exportedMemoryTypeIndex, handleA)
3333 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleA));
3334 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3335 ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handleB)
3336 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleB));
3338 if (config.hostVisible)
3340 const std::vector<deUint8> testDataA (genTestData(seed ^ 124798807u, (size_t)bufferSize));
3341 const std::vector<deUint8> testDataB (genTestData(seed ^ 970834278u, (size_t)bufferSize));
3343 checkHostMemory(vkd, *device, *memoryA, testData.size(), &testData[0]);
3344 checkHostMemory(vkd, *device, *memoryB, testData.size(), &testData[0]);
3346 writeHostMemory(vkd, *device, *memoryA, testData.size(), &testDataA[0]);
3347 writeHostMemory(vkd, *device, *memoryB, testData.size(), &testDataB[0]);
3349 checkHostMemory(vkd, *device, *memoryA, testData.size(), &testDataB[0]);
3350 checkHostMemory(vkd, *device, *memory, testData.size(), &testDataB[0]);
3354 return tcu::TestStatus::pass("Pass");
3357 tcu::TestStatus testMemoryMultipleImports (Context& context, MemoryTestConfig config)
3359 const size_t count = 4 * 1024;
3360 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3361 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3362 const vk::InstanceDriver& vki (instance.getDriver());
3363 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3364 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3365 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3366 const vk::DeviceDriver vkd (vkp, instance, *device);
3367 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3368 const vk::VkDeviceSize bufferSize = 1024;
3370 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3372 // \note Buffer is only allocated to get memory requirements
3373 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3374 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3375 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3376 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3377 NativeHandle handleA;
3379 getMemoryNative(vkd, *device, *memory, config.externalType, handleA);
3381 for (size_t ndx = 0; ndx < count; ndx++)
3383 const vk::Unique<vk::VkBuffer> bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3384 NativeHandle handleB (handleA);
3385 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3386 ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handleB)
3387 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleB));
3390 return tcu::TestStatus::pass("Pass");
3393 tcu::TestStatus testMemoryMultipleExports (Context& context, MemoryTestConfig config)
3395 const size_t count = 4 * 1024;
3396 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3397 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3398 const vk::InstanceDriver& vki (instance.getDriver());
3399 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3400 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3401 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3402 const vk::DeviceDriver vkd (vkp, instance, *device);
3403 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3404 const vk::VkDeviceSize bufferSize = 1024;
3406 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3408 // \note Buffer is only allocated to get memory requirements
3409 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3410 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3411 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3412 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3414 for (size_t ndx = 0; ndx < count; ndx++)
3416 NativeHandle handle;
3417 getMemoryNative(vkd, *device, *memory, config.externalType, handle);
3420 return tcu::TestStatus::pass("Pass");
3423 tcu::TestStatus testMemoryFdProperties (Context& context, MemoryTestConfig config)
3425 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3426 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3427 const vk::InstanceDriver& vki (instance.getDriver());
3428 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3429 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3430 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3431 const vk::DeviceDriver vkd (vkp, instance, *device);
3432 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3433 const vk::VkDeviceSize bufferSize = 1024;
3435 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3437 // \note Buffer is only allocated to get memory requirements
3438 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3439 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3440 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3441 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3443 vk::VkMemoryFdPropertiesKHR properties;
3444 NativeHandle handle;
3446 getMemoryNative(vkd, *device, *memory, config.externalType, handle);
3447 properties.sType = vk::VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR;
3448 vk::VkResult res = vkd.getMemoryFdPropertiesKHR(*device, config.externalType, handle.getFd(), &properties);
3450 switch (config.externalType)
3452 case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
3453 TCU_CHECK_MSG(res == vk::VK_SUCCESS, "vkGetMemoryFdPropertiesKHR failed for VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT");
3456 // Invalid external memory type for this test.
3461 return tcu::TestStatus::pass("Pass");
3464 tcu::TestStatus testMemoryFdDup (Context& context, MemoryTestConfig config)
3466 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
3467 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3468 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3469 const vk::InstanceDriver& vki (instance.getDriver());
3470 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3471 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3474 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3475 const vk::DeviceDriver vkd (vkp, instance, *device);
3477 TestLog& log = context.getTestContext().getLog();
3478 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3479 const vk::VkDeviceSize bufferSize = 1024;
3480 const deUint32 seed = 851493858u;
3481 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
3483 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3485 // \note Buffer is only allocated to get memory requirements
3486 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3487 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3488 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3489 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3491 if (config.hostVisible)
3492 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3494 const NativeHandle fd (getMemoryFd(vkd, *device, *memory, config.externalType));
3495 NativeHandle newFd (dup(fd.getFd()));
3497 if (newFd.getFd() < 0)
3498 log << TestLog::Message << "dup() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
3500 TCU_CHECK_MSG(newFd.getFd() >= 0, "Failed to call dup() for memorys fd");
3503 const vk::Unique<vk::VkBuffer> newBuffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3504 const vk::Unique<vk::VkDeviceMemory> newMemory (config.dedicated
3505 ? importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType, exportedMemoryTypeIndex, newFd)
3506 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, newFd));
3508 if (config.hostVisible)
3510 const std::vector<deUint8> testDataA (genTestData(seed ^ 672929437u, (size_t)bufferSize));
3512 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3514 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3515 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3519 return tcu::TestStatus::pass("Pass");
3524 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
3528 tcu::TestStatus testMemoryFdDup2 (Context& context, MemoryTestConfig config)
3530 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
3531 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3532 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3533 const vk::InstanceDriver& vki (instance.getDriver());
3534 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3535 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3538 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3539 const vk::DeviceDriver vkd (vkp, instance, *device);
3541 TestLog& log = context.getTestContext().getLog();
3542 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3543 const vk::VkDeviceSize bufferSize = 1024;
3544 const deUint32 seed = 224466865u;
3545 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
3547 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3549 // \note Buffer is only allocated to get memory requirements
3550 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3551 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3552 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3553 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3555 if (config.hostVisible)
3556 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3558 const NativeHandle fd (getMemoryFd(vkd, *device, *memory, config.externalType));
3559 NativeHandle secondFd (getMemoryFd(vkd, *device, *memory, config.externalType));
3560 const int newFd (dup2(fd.getFd(), secondFd.getFd()));
3563 log << TestLog::Message << "dup2() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
3565 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup2() for memorys fd");
3568 const vk::Unique<vk::VkBuffer> newBuffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3569 const vk::Unique<vk::VkDeviceMemory> newMemory (config.dedicated
3570 ? importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType, exportedMemoryTypeIndex, secondFd)
3571 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, secondFd));
3573 if (config.hostVisible)
3575 const std::vector<deUint8> testDataA (genTestData(seed ^ 99012346u, (size_t)bufferSize));
3577 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3579 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3580 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3584 return tcu::TestStatus::pass("Pass");
3589 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
3593 tcu::TestStatus testMemoryFdDup3 (Context& context, MemoryTestConfig config)
3595 #if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
3596 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3597 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3598 const vk::InstanceDriver& vki (instance.getDriver());
3599 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3600 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3603 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3604 const vk::DeviceDriver vkd (vkp, instance, *device);
3606 TestLog& log = context.getTestContext().getLog();
3607 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3608 const vk::VkDeviceSize bufferSize = 1024;
3609 const deUint32 seed = 2554088961u;
3610 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
3612 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3614 // \note Buffer is only allocated to get memory requirements
3615 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3616 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3617 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3618 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3620 if (config.hostVisible)
3621 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3623 const NativeHandle fd (getMemoryFd(vkd, *device, *memory, config.externalType));
3624 NativeHandle secondFd (getMemoryFd(vkd, *device, *memory, config.externalType));
3625 const int newFd (dup3(fd.getFd(), secondFd.getFd(), 0));
3628 log << TestLog::Message << "dup3() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
3630 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup3() for memorys fd");
3633 const vk::Unique<vk::VkBuffer> newBuffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3634 const vk::Unique<vk::VkDeviceMemory> newMemory (config.dedicated
3635 ? importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType, exportedMemoryTypeIndex, secondFd)
3636 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, secondFd));
3638 if (config.hostVisible)
3640 const std::vector<deUint8> testDataA (genTestData(seed ^ 4210342378u, (size_t)bufferSize));
3642 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3644 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3645 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3649 return tcu::TestStatus::pass("Pass");
3654 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
3658 tcu::TestStatus testMemoryFdSendOverSocket (Context& context, MemoryTestConfig config)
3660 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
3661 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3662 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3663 const vk::InstanceDriver& vki (instance.getDriver());
3664 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3665 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3668 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3669 const vk::DeviceDriver vkd (vkp, instance, *device);
3671 TestLog& log = context.getTestContext().getLog();
3672 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3673 const vk::VkDeviceSize bufferSize = 1024;
3674 const deUint32 seed = 3403586456u;
3675 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
3677 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3679 // \note Buffer is only allocated to get memory requirements
3680 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3681 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3682 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3683 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3685 if (config.hostVisible)
3686 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3688 const NativeHandle fd (getMemoryFd(vkd, *device, *memory, config.externalType));
3693 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
3695 log << TestLog::Message << "Failed to create socket pair: '" << strerror(errno) << "'" << TestLog::EndMessage;
3696 TCU_FAIL("Failed to create socket pair");
3700 const NativeHandle srcSocket (sv[0]);
3701 const NativeHandle dstSocket (sv[1]);
3702 std::string sendData ("deqp");
3706 const int fdRaw (fd.getFd());
3709 char tmpBuffer[CMSG_SPACE(sizeof(int))];
3710 iovec iov = { &sendData[0], sendData.length()};
3712 deMemset(&msg, 0, sizeof(msg));
3714 msg.msg_control = tmpBuffer;
3715 msg.msg_controllen = sizeof(tmpBuffer);
3719 cmsg = CMSG_FIRSTHDR(&msg);
3720 cmsg->cmsg_level = SOL_SOCKET;
3721 cmsg->cmsg_type = SCM_RIGHTS;
3722 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
3724 deMemcpy(CMSG_DATA(cmsg), &fdRaw, sizeof(int));
3725 msg.msg_controllen = cmsg->cmsg_len;
3727 if (sendmsg(srcSocket.getFd(), &msg, 0) < 0)
3729 log << TestLog::Message << "Failed to send fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
3730 TCU_FAIL("Failed to send fd over socket");
3737 char tmpBuffer[CMSG_SPACE(sizeof(int))];
3738 std::string recvData (4, '\0');
3739 iovec iov = { &recvData[0], recvData.length() };
3741 deMemset(&msg, 0, sizeof(msg));
3743 msg.msg_control = tmpBuffer;
3744 msg.msg_controllen = sizeof(tmpBuffer);
3748 const ssize_t bytes = recvmsg(dstSocket.getFd(), &msg, 0);
3752 log << TestLog::Message << "Failed to recv fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
3753 TCU_FAIL("Failed to recv fd over socket");
3756 else if (bytes != (ssize_t)sendData.length())
3758 TCU_FAIL("recvmsg() returned unpexpected number of bytes");
3762 const cmsghdr* const cmsg = CMSG_FIRSTHDR(&msg);
3764 deMemcpy(&newFd_, CMSG_DATA(cmsg), sizeof(int));
3765 NativeHandle newFd (newFd_);
3767 TCU_CHECK(cmsg->cmsg_level == SOL_SOCKET);
3768 TCU_CHECK(cmsg->cmsg_type == SCM_RIGHTS);
3769 TCU_CHECK(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
3770 TCU_CHECK(recvData == sendData);
3771 TCU_CHECK_MSG(newFd.getFd() >= 0, "Didn't receive valid fd from socket");
3774 const vk::Unique<vk::VkBuffer> newBuffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3775 const vk::Unique<vk::VkDeviceMemory> newMemory (config.dedicated
3776 ? importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType, exportedMemoryTypeIndex, newFd)
3777 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, newFd));
3779 if (config.hostVisible)
3781 const std::vector<deUint8> testDataA (genTestData(seed ^ 23478978u, (size_t)bufferSize));
3783 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3785 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3786 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3795 return tcu::TestStatus::pass("Pass");
3799 TCU_THROW(NotSupportedError, "Platform doesn't support sending file descriptors over socket");
3803 struct BufferTestConfig
3805 BufferTestConfig (vk::VkExternalMemoryHandleTypeFlagBits externalType_,
3807 : externalType (externalType_)
3808 , dedicated (dedicated_)
3812 vk::VkExternalMemoryHandleTypeFlagBits externalType;
3816 tcu::TestStatus testBufferBindExportImportBind (Context& context,
3817 const BufferTestConfig config)
3819 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3820 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3821 const vk::InstanceDriver& vki (instance.getDriver());
3822 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3823 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3824 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3825 const vk::DeviceDriver vkd (vkp, instance, *device);
3826 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3827 const vk::VkDeviceSize bufferSize = 1024;
3829 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3831 // \note Buffer is only allocated to get memory requirements
3832 const vk::Unique<vk::VkBuffer> bufferA (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3833 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *bufferA));
3834 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
3835 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *bufferA : (vk::VkBuffer)0));
3836 NativeHandle handle;
3838 VK_CHECK(vkd.bindBufferMemory(*device, *bufferA, *memoryA, 0u));
3840 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3843 const vk::Unique<vk::VkBuffer> bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3844 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3845 ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handle)
3846 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3848 VK_CHECK(vkd.bindBufferMemory(*device, *bufferB, *memoryB, 0u));
3851 return tcu::TestStatus::pass("Pass");
3854 tcu::TestStatus testBufferExportBindImportBind (Context& context,
3855 const BufferTestConfig config)
3857 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3858 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3859 const vk::InstanceDriver& vki (instance.getDriver());
3860 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3861 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3862 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3863 const vk::DeviceDriver vkd (vkp, instance, *device);
3864 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3865 const vk::VkDeviceSize bufferSize = 1024;
3867 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3869 // \note Buffer is only allocated to get memory requirements
3870 const vk::Unique<vk::VkBuffer> bufferA (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3871 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *bufferA));
3872 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
3873 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *bufferA : (vk::VkBuffer)0));
3874 NativeHandle handle;
3876 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3877 VK_CHECK(vkd.bindBufferMemory(*device, *bufferA, *memoryA, 0u));
3880 const vk::Unique<vk::VkBuffer> bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3881 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3882 ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handle)
3883 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3885 VK_CHECK(vkd.bindBufferMemory(*device, *bufferB, *memoryB, 0u));
3888 return tcu::TestStatus::pass("Pass");
3891 tcu::TestStatus testBufferExportImportBindBind (Context& context,
3892 const BufferTestConfig config)
3894 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3895 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3896 const vk::InstanceDriver& vki (instance.getDriver());
3897 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3898 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3899 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3900 const vk::DeviceDriver vkd (vkp, instance, *device);
3901 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3902 const vk::VkDeviceSize bufferSize = 1024;
3904 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3906 // \note Buffer is only allocated to get memory requirements
3907 const vk::Unique<vk::VkBuffer> bufferA (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3908 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *bufferA));
3909 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
3910 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *bufferA : (vk::VkBuffer)0));
3911 NativeHandle handle;
3913 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3916 const vk::Unique<vk::VkBuffer> bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3917 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3918 ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handle)
3919 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3921 VK_CHECK(vkd.bindBufferMemory(*device, *bufferA, *memoryA, 0u));
3922 VK_CHECK(vkd.bindBufferMemory(*device, *bufferB, *memoryB, 0u));
3925 return tcu::TestStatus::pass("Pass");
3928 tcu::TestStatus testImageQueries (Context& context, vk::VkExternalMemoryHandleTypeFlagBits externalType)
3930 const vk::VkImageCreateFlags createFlags[] =
3933 vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT,
3934 vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT|vk::VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT,
3935 vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT|vk::VK_IMAGE_CREATE_SPARSE_ALIASED_BIT,
3936 vk::VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT,
3937 vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT
3939 const vk::VkImageUsageFlags usageFlags[] =
3941 vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
3942 vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT,
3943 vk::VK_IMAGE_USAGE_SAMPLED_BIT,
3944 vk::VK_IMAGE_USAGE_STORAGE_BIT,
3945 vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
3946 vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
3947 vk::VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
3948 vk::VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
3949 vk::VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT,
3950 vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT
3952 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3953 const CustomInstance instance (createTestInstance(context, 0u, externalType, 0u));
3954 const vk::InstanceDriver& vki (instance.getDriver());
3955 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3956 const vk::VkPhysicalDeviceFeatures deviceFeatures (vk::getPhysicalDeviceFeatures(vki, physicalDevice));
3957 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3959 // VkDevice is only created if physical device claims to support any of these types.
3960 vk::Move<vk::VkDevice> device;
3961 de::MovePtr<vk::DeviceDriver> vkd;
3962 bool deviceHasDedicated = false;
3964 TestLog& log = context.getTestContext().getLog();
3966 for (size_t createFlagNdx = 0; createFlagNdx < DE_LENGTH_OF_ARRAY(createFlags); createFlagNdx++)
3967 for (size_t usageFlagNdx = 0; usageFlagNdx < DE_LENGTH_OF_ARRAY(usageFlags); usageFlagNdx++)
3969 const vk::VkImageViewCreateFlags createFlag = createFlags[createFlagNdx];
3970 const vk::VkImageUsageFlags usageFlag = usageFlags[usageFlagNdx];
3971 const vk::VkFormat format =
3972 (usageFlags[usageFlagNdx] & vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? vk::VK_FORMAT_D16_UNORM : vk::VK_FORMAT_R8G8B8A8_UNORM;
3973 const vk::VkImageType type = vk::VK_IMAGE_TYPE_2D;
3974 const vk::VkImageTiling tiling = vk::VK_IMAGE_TILING_OPTIMAL;
3975 const vk::VkPhysicalDeviceExternalImageFormatInfo externalInfo =
3977 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
3981 const vk::VkPhysicalDeviceImageFormatInfo2 info =
3983 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
3992 vk::VkExternalImageFormatProperties externalProperties =
3994 vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES,
3998 vk::VkImageFormatProperties2 properties =
4000 vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
4001 &externalProperties,
4011 if (((createFlag & vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT) != 0) &&
4012 (deviceFeatures.sparseBinding == VK_FALSE))
4015 if (((createFlag & vk::VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT) != 0) &&
4016 (deviceFeatures.sparseResidencyImage2D == VK_FALSE))
4019 if (((createFlag & vk::VK_IMAGE_CREATE_SPARSE_ALIASED_BIT) != 0) &&
4020 (deviceFeatures.sparseResidencyAliased == VK_FALSE))
4023 if (vki.getPhysicalDeviceImageFormatProperties2(physicalDevice, &info, &properties) == vk::VK_ERROR_FORMAT_NOT_SUPPORTED) {
4027 log << TestLog::Message << externalProperties << TestLog::EndMessage;
4028 TCU_CHECK(externalProperties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES);
4029 TCU_CHECK(externalProperties.pNext == DE_NULL);
4030 // \todo [2017-06-06 pyry] Can we validate anything else? Compatible types?
4032 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & (vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT|vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT)) != 0)
4034 const bool requiresDedicated = (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
4036 if (!device || (requiresDedicated && !deviceHasDedicated))
4038 // \note We need to re-create with dedicated mem extensions if previous device instance didn't have them
4041 device = createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, externalType, 0u, queueFamilyIndex, requiresDedicated);
4042 vkd = de::MovePtr<vk::DeviceDriver>(new vk::DeviceDriver(vkp, instance, *device));
4043 deviceHasDedicated = requiresDedicated;
4045 catch (const tcu::NotSupportedError& e)
4048 TCU_FAIL("Physical device claims to support handle type but required extensions are not supported");
4053 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) != 0)
4055 DE_ASSERT(!!device);
4058 if (deviceHasDedicated)
4060 // Memory requirements cannot be queried without binding the image.
4061 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
4064 const vk::Unique<vk::VkImage> image (createExternalImage(*vkd, *device, queueFamilyIndex, externalType, format, 16u, 16u, tiling, createFlag, usageFlag));
4065 const vk::VkMemoryDedicatedRequirements reqs (getMemoryDedicatedRequirements(*vkd, *device, *image));
4066 const bool propertiesRequiresDedicated = (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
4067 const bool objectRequiresDedicated = (reqs.requiresDedicatedAllocation != VK_FALSE);
4069 if (propertiesRequiresDedicated != objectRequiresDedicated)
4070 TCU_FAIL("vkGetPhysicalDeviceExternalBufferProperties and vkGetBufferMemoryRequirements2 report different dedicated requirements");
4074 // We can't query whether dedicated memory is required or not on per-object basis.
4075 // This check should be redundant as the code above tries to create device with
4076 // VK_KHR_dedicated_allocation & VK_KHR_get_memory_requirements2 if dedicated memory
4077 // is required. However, checking again doesn't hurt.
4078 TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) == 0);
4083 return tcu::TestStatus::pass("Pass");
4086 struct ImageTestConfig
4088 ImageTestConfig (vk::VkExternalMemoryHandleTypeFlagBits externalType_,
4090 : externalType (externalType_)
4091 , dedicated (dedicated_)
4095 vk::VkExternalMemoryHandleTypeFlagBits externalType;
4099 tcu::TestStatus testImageBindExportImportBind (Context& context,
4100 const ImageTestConfig config)
4102 const vk::PlatformInterface& vkp (context.getPlatformInterface());
4103 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
4104 const vk::InstanceDriver& vki (instance.getDriver());
4105 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
4106 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
4107 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
4108 const vk::DeviceDriver vkd (vkp, instance, *device);
4109 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);
4110 const vk::VkFormat format = vk::VK_FORMAT_R8G8B8A8_UNORM;
4111 const deUint32 width = 64u;
4112 const deUint32 height = 64u;
4113 const vk::VkImageTiling tiling = vk::VK_IMAGE_TILING_OPTIMAL;
4115 checkImageSupport(vki, physicalDevice, config.externalType, 0u, usage, format, tiling, config.dedicated);
4117 const vk::Unique<vk::VkImage> imageA (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
4118 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *imageA, config.externalType));
4119 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
4120 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *imageA : (vk::VkImage)0));
4121 NativeHandle handle;
4123 VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
4125 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
4128 const vk::Unique<vk::VkImage> imageB (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
4129 const deUint32 idx = config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID ? ~0u : exportedMemoryTypeIndex;
4130 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
4131 ? importDedicatedMemory(vkd, *device, *imageB, requirements, config.externalType, idx, handle)
4132 : importMemory(vkd, *device, requirements, config.externalType, idx, handle));
4134 VK_CHECK(vkd.bindImageMemory(*device, *imageB, *memoryB, 0u));
4137 return tcu::TestStatus::pass("Pass");
4140 tcu::TestStatus testImageExportBindImportBind (Context& context,
4141 const ImageTestConfig config)
4143 const vk::PlatformInterface& vkp (context.getPlatformInterface());
4144 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
4145 const vk::InstanceDriver& vki (instance.getDriver());
4146 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
4147 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
4148 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
4149 const vk::DeviceDriver vkd (vkp, instance, *device);
4150 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);
4151 const vk::VkFormat format = vk::VK_FORMAT_R8G8B8A8_UNORM;
4152 const deUint32 width = 64u;
4153 const deUint32 height = 64u;
4154 const vk::VkImageTiling tiling = vk::VK_IMAGE_TILING_OPTIMAL;
4156 checkImageSupport(vki, physicalDevice, config.externalType, 0u, usage, format, tiling, config.dedicated);
4158 const vk::Unique<vk::VkImage> imageA (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
4159 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *imageA, config.externalType));
4160 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
4161 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *imageA : (vk::VkImage)0));
4162 NativeHandle handle;
4164 if (config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID && config.dedicated)
4166 // AHB required the image memory to be bound first.
4167 VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
4168 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
4172 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
4173 VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
4177 const vk::Unique<vk::VkImage> imageB (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
4178 const deUint32 idx = config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID ? ~0u : exportedMemoryTypeIndex;
4179 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
4180 ? importDedicatedMemory(vkd, *device, *imageB, requirements, config.externalType, idx, handle)
4181 : importMemory(vkd, *device, requirements, config.externalType, idx, handle));
4183 VK_CHECK(vkd.bindImageMemory(*device, *imageB, *memoryB, 0u));
4186 return tcu::TestStatus::pass("Pass");
4189 tcu::TestStatus testImageExportImportBindBind (Context& context,
4190 const ImageTestConfig config)
4192 const vk::PlatformInterface& vkp (context.getPlatformInterface());
4193 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
4194 const vk::InstanceDriver& vki (instance.getDriver());
4195 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
4196 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
4197 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
4198 const vk::DeviceDriver vkd (vkp, instance, *device);
4199 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);
4200 const vk::VkFormat format = vk::VK_FORMAT_R8G8B8A8_UNORM;
4201 const deUint32 width = 64u;
4202 const deUint32 height = 64u;
4203 const vk::VkImageTiling tiling = vk::VK_IMAGE_TILING_OPTIMAL;
4205 checkImageSupport(vki, physicalDevice, config.externalType, 0u, usage, format, tiling, config.dedicated);
4207 if (config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID && config.dedicated)
4209 // AHB required the image memory to be bound first, which is not possible in this test.
4210 TCU_THROW(NotSupportedError, "Unsupported for Android Hardware Buffer");
4213 // \note Image is only allocated to get memory requirements
4214 const vk::Unique<vk::VkImage> imageA (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
4215 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *imageA, config.externalType));
4216 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
4217 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *imageA : (vk::VkImage)0));
4218 NativeHandle handle;
4220 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
4223 const vk::Unique<vk::VkImage> imageB (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
4224 const deUint32 idx = config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID ? ~0u : exportedMemoryTypeIndex;
4225 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
4226 ? importDedicatedMemory(vkd, *device, *imageB, requirements, config.externalType, idx, handle)
4227 : importMemory(vkd, *device, requirements, config.externalType, idx, handle));
4229 VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
4230 VK_CHECK(vkd.bindImageMemory(*device, *imageB, *memoryB, 0u));
4233 return tcu::TestStatus::pass("Pass");
4236 template<class TestConfig> void checkEvent (Context& context, const TestConfig)
4238 if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") && !context.getPortabilitySubsetFeatures().events)
4239 TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Events are not supported by this implementation");
4242 template<class TestConfig> void checkSupport (Context& context, const TestConfig config)
4244 const Transference transference (getHandelTypeTransferences(config.externalType));
4245 if (transference == TRANSFERENCE_COPY)
4246 checkEvent(context, config);
4249 de::MovePtr<tcu::TestCaseGroup> createFenceTests (tcu::TestContext& testCtx, vk::VkExternalFenceHandleTypeFlagBits externalType)
4253 const char* const name;
4254 const Permanence permanence;
4257 { "temporary", PERMANENCE_TEMPORARY },
4258 { "permanent", PERMANENCE_PERMANENT }
4261 de::MovePtr<tcu::TestCaseGroup> fenceGroup (new tcu::TestCaseGroup(testCtx, externalFenceTypeToName(externalType), externalFenceTypeToName(externalType)));
4263 addFunctionCase(fenceGroup.get(), "info", "Test external fence queries.", testFenceQueries, externalType);
4265 for (size_t permanenceNdx = 0; permanenceNdx < DE_LENGTH_OF_ARRAY(permanences); permanenceNdx++)
4267 const Permanence permanence (permanences[permanenceNdx].permanence);
4268 const char* const permanenceName (permanences[permanenceNdx].name);
4269 const FenceTestConfig config (externalType, permanence);
4271 if (!isSupportedPermanence(externalType, permanence))
4274 if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT
4275 || externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
4277 addFunctionCase(fenceGroup.get(), std::string("create_win32_") + permanenceName, "Test creating fence with win32 properties.", testFenceWin32Create, config);
4280 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("import_twice_") + permanenceName, "Test importing fence twice.", checkSupport, initProgramsToGetNativeFd, testFenceImportTwice, config);
4281 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("reimport_") + permanenceName, "Test importing again over previously imported fence.", checkSupport, initProgramsToGetNativeFd, testFenceImportReimport, config);
4282 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("import_multiple_times_") + permanenceName, "Test importing fence multiple times.", checkSupport, initProgramsToGetNativeFd, testFenceMultipleImports, config);
4283 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("signal_export_import_wait_") + permanenceName, "Test signaling, exporting, importing and waiting for the sempahore.", checkEvent, initProgramsToGetNativeFd, testFenceSignalExportImportWait, config);
4284 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("signal_import_") + permanenceName, "Test signaling and importing the fence.", checkSupport, initProgramsToGetNativeFd, testFenceSignalImport, config);
4285 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("reset_") + permanenceName, "Test resetting the fence.", checkEvent, initProgramsToGetNativeFd, testFenceReset, config);
4286 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("transference_") + permanenceName, "Test fences transference.", checkEvent, initProgramsToGetNativeFd, testFenceTransference, config);
4288 if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT)
4290 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("import_signaled_") + permanenceName, "Test import signaled fence fd.", initProgramsToGetNativeFd, testFenceImportSyncFdSignaled, config);
4293 if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT
4294 || externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT)
4296 // \note Not supported on WIN32 handles
4297 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("export_multiple_times_") + permanenceName, "Test exporting fence multiple times.", checkSupport, initProgramsToGetNativeFd, testFenceMultipleExports, config);
4299 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("dup_") + permanenceName, "Test calling dup() on exported fence.", checkSupport, initProgramsToGetNativeFd, testFenceFdDup, config);
4300 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("dup2_") + permanenceName, "Test calling dup2() on exported fence.", checkSupport, initProgramsToGetNativeFd, testFenceFdDup2, config);
4301 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("dup3_") + permanenceName, "Test calling dup3() on exported fence.", checkSupport, initProgramsToGetNativeFd, testFenceFdDup3, config);
4302 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("send_over_socket_") + permanenceName, "Test sending fence fd over socket.", checkSupport, initProgramsToGetNativeFd, testFenceFdSendOverSocket, config);
4305 if (getHandelTypeTransferences(externalType) == TRANSFERENCE_REFERENCE)
4307 addFunctionCase(fenceGroup.get(), std::string("signal_wait_import_") + permanenceName, "Test signaling and then waiting for the the sepmahore.", testFenceSignalWaitImport, config);
4308 addFunctionCase(fenceGroup.get(), std::string("export_signal_import_wait_") + permanenceName, "Test exporting, signaling, importing and waiting for the fence.", testFenceExportSignalImportWait, config);
4309 addFunctionCase(fenceGroup.get(), std::string("export_import_signal_wait_") + permanenceName, "Test exporting, importing, signaling and waiting for the fence.", testFenceExportImportSignalWait, config);
4316 bool ValidateAHardwareBuffer(vk::VkFormat format, deUint64 requiredAhbUsage, const vk::DeviceDriver& vkd, const vk::VkDevice& device, vk::VkImageCreateFlags createFlag, deUint32 layerCount, bool& enableMaxLayerTest)
4318 DE_UNREF(createFlag);
4320 AndroidHardwareBufferExternalApi* ahbApi = AndroidHardwareBufferExternalApi::getInstance();
4323 TCU_THROW(NotSupportedError, "Platform doesn't support Android Hardware Buffer handles");
4326 #if (DE_OS == DE_OS_ANDROID)
4327 // If CubeMap create flag is used and AHB doesn't support CubeMap return false.
4328 if(!AndroidHardwareBufferExternalApi::supportsCubeMap() && (createFlag & vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT))
4332 vk::pt::AndroidHardwareBufferPtr ahb = ahbApi->allocate(64u, 64u, layerCount, ahbApi->vkFormatToAhbFormat(format), requiredAhbUsage);
4333 if (ahb.internal == DE_NULL)
4335 enableMaxLayerTest = false;
4336 // try again with layerCount '1'
4337 ahb = ahbApi->allocate(64u, 64u, 1u, ahbApi->vkFormatToAhbFormat(format), requiredAhbUsage);
4338 if (ahb.internal == DE_NULL)
4343 NativeHandle nativeHandle(ahb);
4345 const vk::VkComponentMapping mappingA = { vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY };
4346 const vk::VkComponentMapping mappingB = { vk::VK_COMPONENT_SWIZZLE_R, vk::VK_COMPONENT_SWIZZLE_G, vk::VK_COMPONENT_SWIZZLE_B, vk::VK_COMPONENT_SWIZZLE_A };
4348 for (int variantIdx = 0; variantIdx < 2; ++variantIdx)
4350 // Both mappings should be equivalent and work.
4351 const vk::VkComponentMapping& mapping = ((variantIdx == 0) ? mappingA : mappingB);
4353 vk::VkAndroidHardwareBufferFormatPropertiesANDROID formatProperties =
4355 vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID,
4357 vk::VK_FORMAT_UNDEFINED,
4361 vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY,
4362 vk::VK_SAMPLER_YCBCR_RANGE_ITU_FULL,
4363 vk::VK_CHROMA_LOCATION_COSITED_EVEN,
4364 vk::VK_CHROMA_LOCATION_COSITED_EVEN
4367 vk::VkAndroidHardwareBufferPropertiesANDROID bufferProperties =
4369 vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID,
4375 VK_CHECK(vkd.getAndroidHardwareBufferPropertiesANDROID(device, ahb, &bufferProperties));
4376 TCU_CHECK(formatProperties.format != vk::VK_FORMAT_UNDEFINED);
4377 TCU_CHECK(formatProperties.format == format);
4378 TCU_CHECK(formatProperties.externalFormat != 0u);
4379 TCU_CHECK((formatProperties.formatFeatures & vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) != 0u);
4380 TCU_CHECK((formatProperties.formatFeatures & (vk::VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT | vk::VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT)) != 0u);
4386 tcu::TestStatus testAndroidHardwareBufferImageFormat (Context& context, vk::VkFormat format)
4388 AndroidHardwareBufferExternalApi* ahbApi = AndroidHardwareBufferExternalApi::getInstance();
4391 TCU_THROW(NotSupportedError, "Platform doesn't support Android Hardware Buffer handles");
4394 const vk::VkExternalMemoryHandleTypeFlagBits externalMemoryType = vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
4395 const vk::PlatformInterface& vkp (context.getPlatformInterface());
4396 const CustomInstance instance (createTestInstance(context, 0u, externalMemoryType, 0u));
4397 const vk::InstanceDriver& vki (instance.getDriver());
4398 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
4400 vk::VkPhysicalDeviceProtectedMemoryFeatures protectedFeatures;
4401 protectedFeatures.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES;
4402 protectedFeatures.pNext = DE_NULL;
4403 protectedFeatures.protectedMemory = VK_FALSE;
4405 vk::VkPhysicalDeviceFeatures2 deviceFeatures;
4406 deviceFeatures.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
4407 deviceFeatures.pNext = &protectedFeatures;
4409 vki.getPhysicalDeviceFeatures2(physicalDevice, &deviceFeatures);
4411 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
4412 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, externalMemoryType, 0u, queueFamilyIndex, false, &protectedFeatures));
4413 const vk::DeviceDriver vkd (vkp, instance, *device);
4414 TestLog& log = context.getTestContext().getLog();
4415 const vk::VkPhysicalDeviceLimits limits = getPhysicalDeviceProperties(vki, physicalDevice).limits;
4417 const vk::VkImageUsageFlagBits framebufferUsageFlag = vk::isDepthStencilFormat(format) ? vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
4418 : vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
4420 const vk::VkImageUsageFlagBits usageFlags[] =
4422 vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
4423 vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT,
4424 vk::VK_IMAGE_USAGE_SAMPLED_BIT,
4425 vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT,
4426 framebufferUsageFlag,
4428 const vk::VkImageCreateFlagBits createFlags[] =
4430 vk::VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT,
4431 vk::VK_IMAGE_CREATE_EXTENDED_USAGE_BIT,
4432 vk::VK_IMAGE_CREATE_PROTECTED_BIT,
4433 vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT,
4435 const vk::VkImageTiling tilings[] =
4437 vk::VK_IMAGE_TILING_OPTIMAL,
4438 vk::VK_IMAGE_TILING_LINEAR,
4440 deUint64 mustSupportAhbUsageFlags = ahbApi->mustSupportAhbUsageFlags();
4441 const size_t one = 1u;
4442 const size_t numOfUsageFlags = DE_LENGTH_OF_ARRAY(usageFlags);
4443 const size_t numOfCreateFlags = DE_LENGTH_OF_ARRAY(createFlags);
4444 const size_t numOfFlagCombos = one << (numOfUsageFlags + numOfCreateFlags);
4445 const size_t numOfTilings = DE_LENGTH_OF_ARRAY(tilings);
4447 for (size_t combo = 0; combo < numOfFlagCombos; combo++)
4449 vk::VkImageUsageFlags usage = 0;
4450 vk::VkImageCreateFlags createFlag = 0;
4451 deUint64 requiredAhbUsage = 0;
4452 bool enableMaxLayerTest = true;
4453 for (size_t usageNdx = 0; usageNdx < numOfUsageFlags; usageNdx++)
4455 if ((combo & (one << usageNdx)) == 0)
4457 usage |= usageFlags[usageNdx];
4458 requiredAhbUsage |= ahbApi->vkUsageToAhbUsage(usageFlags[usageNdx]);
4460 for (size_t createFlagNdx = 0; createFlagNdx < numOfCreateFlags; createFlagNdx++)
4462 const size_t bit = numOfUsageFlags + createFlagNdx;
4463 if ((combo & (one << bit)) == 0)
4465 if (((createFlags[createFlagNdx] & vk::VK_IMAGE_CREATE_PROTECTED_BIT) == vk::VK_IMAGE_CREATE_PROTECTED_BIT ) &&
4466 (protectedFeatures.protectedMemory == VK_FALSE))
4469 createFlag |= createFlags[createFlagNdx];
4470 requiredAhbUsage |= ahbApi->vkCreateToAhbUsage(createFlags[createFlagNdx]);
4473 // Only test a combination if the usage flags include at least one of the AHARDWAREBUFFER_USAGE_GPU_* flag.
4474 if ((requiredAhbUsage & mustSupportAhbUsageFlags) == 0u)
4477 // Only test a combination if AHardwareBuffer can be successfully allocated for it.
4478 if (!ValidateAHardwareBuffer(format, requiredAhbUsage, vkd, *device, createFlag, limits.maxImageArrayLayers, enableMaxLayerTest))
4481 bool foundAnyUsableTiling = false;
4482 for (size_t tilingIndex = 0; tilingIndex < numOfTilings; tilingIndex++)
4484 const vk::VkImageTiling tiling = tilings[tilingIndex];
4486 const vk::VkPhysicalDeviceExternalImageFormatInfo externalInfo =
4488 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
4490 vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID
4492 const vk::VkPhysicalDeviceImageFormatInfo2 info =
4494 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
4497 vk::VK_IMAGE_TYPE_2D,
4503 vk::VkAndroidHardwareBufferUsageANDROID ahbUsageProperties =
4505 vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID,
4509 vk::VkExternalImageFormatProperties externalProperties =
4511 vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES,
4512 &ahbUsageProperties,
4515 vk::VkImageFormatProperties2 properties =
4517 vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
4518 &externalProperties,
4528 if (vki.getPhysicalDeviceImageFormatProperties2(physicalDevice, &info, &properties) == vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
4530 log << TestLog::Message << "Tiling " << tiling << " is not supported." << TestLog::EndMessage;
4534 foundAnyUsableTiling = true;
4536 TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) != 0);
4537 TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) != 0);
4538 TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0);
4539 deUint32 maxWidth = properties.imageFormatProperties.maxExtent.width;
4540 deUint32 maxHeight = properties.imageFormatProperties.maxExtent.height;
4541 TCU_CHECK(maxWidth >= 4096);
4542 TCU_CHECK(maxHeight >= 4096);
4543 // Even if not requested, at least one of GPU_* usage flags must be present.
4544 TCU_CHECK((ahbUsageProperties.androidHardwareBufferUsage & mustSupportAhbUsageFlags) != 0u);
4545 // The AHB usage flags corresponding to the create and usage flags used in info must be present.
4546 TCU_CHECK((ahbUsageProperties.androidHardwareBufferUsage & requiredAhbUsage) == requiredAhbUsage);
4548 log << TestLog::Message << "Required flags: " << std::hex << requiredAhbUsage << " Actual flags: " << std::hex << ahbUsageProperties.androidHardwareBufferUsage
4549 << TestLog::EndMessage;
4562 deUint32 exportedMemoryTypeIndex = 0;
4564 if (createFlag & vk::VK_IMAGE_CREATE_PROTECTED_BIT)
4566 const vk::VkPhysicalDeviceMemoryProperties memProperties(vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
4568 for (deUint32 memoryTypeIndex = 0; memoryTypeIndex < VK_MAX_MEMORY_TYPES; memoryTypeIndex++)
4570 if (memProperties.memoryTypes[memoryTypeIndex].propertyFlags & vk::VK_MEMORY_PROPERTY_PROTECTED_BIT)
4572 exportedMemoryTypeIndex = memoryTypeIndex;
4578 for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(sizes); i++)
4580 const vk::Unique<vk::VkImage> image (createExternalImage(vkd, *device, queueFamilyIndex, externalMemoryType, format, sizes[i].width, sizes[i].height, tiling, createFlag, usage));
4581 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *image, externalMemoryType));
4582 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, externalMemoryType, *image));
4583 NativeHandle handle;
4585 VK_CHECK(vkd.bindImageMemory(*device, *image, *memory, 0u));
4586 getMemoryNative(vkd, *device, *memory, externalMemoryType, handle);
4588 deUint32 ahbFormat = 0;
4589 deUint64 anhUsage = 0;
4590 ahbApi->describe(handle.getAndroidHardwareBuffer(), DE_NULL, DE_NULL, DE_NULL, &ahbFormat, &anhUsage, DE_NULL);
4591 TCU_CHECK(ahbFormat == ahbApi->vkFormatToAhbFormat(format));
4592 TCU_CHECK((anhUsage & requiredAhbUsage) == requiredAhbUsage);
4594 // Let watchdog know we're alive
4595 context.getTestContext().touchWatchdog();
4598 if (properties.imageFormatProperties.maxMipLevels >= 7u)
4600 const vk::Unique<vk::VkImage> image (createExternalImage(vkd, *device, queueFamilyIndex, externalMemoryType, format, 64u, 64u, tiling, createFlag, usage, 7u));
4601 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *image, externalMemoryType));
4602 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, externalMemoryType, *image));
4603 NativeHandle handle;
4605 VK_CHECK(vkd.bindImageMemory(*device, *image, *memory, 0u));
4606 getMemoryNative(vkd, *device, *memory, externalMemoryType, handle);
4608 deUint32 ahbFormat = 0;
4609 deUint64 anhUsage = 0;
4610 ahbApi->describe(handle.getAndroidHardwareBuffer(), DE_NULL, DE_NULL, DE_NULL, &ahbFormat, &anhUsage, DE_NULL);
4611 TCU_CHECK(ahbFormat == ahbApi->vkFormatToAhbFormat(format));
4612 TCU_CHECK((anhUsage & requiredAhbUsage) == requiredAhbUsage);
4615 if ((properties.imageFormatProperties.maxArrayLayers > 1u) && enableMaxLayerTest)
4617 const vk::Unique<vk::VkImage> image (createExternalImage(vkd, *device, queueFamilyIndex, externalMemoryType, format, 64u, 64u, tiling, createFlag, usage, 1u, properties.imageFormatProperties.maxArrayLayers));
4618 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *image, externalMemoryType));
4619 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, externalMemoryType, *image));
4620 NativeHandle handle;
4622 VK_CHECK(vkd.bindImageMemory(*device, *image, *memory, 0u));
4623 getMemoryNative(vkd, *device, *memory, externalMemoryType, handle);
4625 deUint32 ahbFormat = 0;
4626 deUint64 anhUsage = 0;
4627 ahbApi->describe(handle.getAndroidHardwareBuffer(), DE_NULL, DE_NULL, DE_NULL, &ahbFormat, &anhUsage, DE_NULL);
4628 TCU_CHECK(ahbFormat == ahbApi->vkFormatToAhbFormat(format));
4629 TCU_CHECK((anhUsage & requiredAhbUsage) == requiredAhbUsage);
4633 TCU_CHECK(foundAnyUsableTiling);
4635 return tcu::TestStatus::pass("Pass");
4638 de::MovePtr<tcu::TestCaseGroup> createFenceTests (tcu::TestContext& testCtx)
4640 de::MovePtr<tcu::TestCaseGroup> fenceGroup (new tcu::TestCaseGroup(testCtx, "fence", "Tests for external fences."));
4642 fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT).release());
4643 fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT).release());
4644 fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT).release());
4645 fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT).release());
4650 de::MovePtr<tcu::TestCaseGroup> createSemaphoreTests (tcu::TestContext& testCtx, vk::VkExternalSemaphoreHandleTypeFlagBits externalType)
4654 const char* const name;
4655 const Permanence permanence;
4658 { "temporary", PERMANENCE_TEMPORARY },
4659 { "permanent", PERMANENCE_PERMANENT }
4663 const char* const name;
4664 vk::VkSemaphoreType type;
4665 } semaphoreTypes[] =
4667 { "binary", vk::VK_SEMAPHORE_TYPE_BINARY },
4668 { "timeline", vk::VK_SEMAPHORE_TYPE_TIMELINE },
4671 de::MovePtr<tcu::TestCaseGroup> semaphoreGroup (new tcu::TestCaseGroup(testCtx, externalSemaphoreTypeToName(externalType), externalSemaphoreTypeToName(externalType)));
4673 for (size_t semaphoreTypeIdx = 0; semaphoreTypeIdx < DE_LENGTH_OF_ARRAY(permanences); semaphoreTypeIdx++)
4675 addFunctionCase(semaphoreGroup.get(), std::string("info_") + semaphoreTypes[semaphoreTypeIdx].name,
4676 "Test external semaphore queries.", testSemaphoreQueries,
4677 TestSemaphoreQueriesParameters(semaphoreTypes[semaphoreTypeIdx].type, externalType));
4680 for (size_t permanenceNdx = 0; permanenceNdx < DE_LENGTH_OF_ARRAY(permanences); permanenceNdx++)
4682 const Permanence permanence (permanences[permanenceNdx].permanence);
4683 const char* const permanenceName (permanences[permanenceNdx].name);
4684 const SemaphoreTestConfig config (externalType, permanence);
4686 if (!isSupportedPermanence(externalType, permanence))
4689 if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
4690 || externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
4692 addFunctionCase(semaphoreGroup.get(), std::string("create_win32_") + permanenceName, "Test creating semaphore with win32 properties.", testSemaphoreWin32Create, config);
4695 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("import_twice_") + permanenceName, "Test importing semaphore twice.", checkSupport, initProgramsToGetNativeFd, testSemaphoreImportTwice, config);
4696 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("reimport_") + permanenceName, "Test importing again over previously imported semaphore.", checkSupport, initProgramsToGetNativeFd, testSemaphoreImportReimport, config);
4697 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("import_multiple_times_") + permanenceName, "Test importing semaphore multiple times.", checkSupport, initProgramsToGetNativeFd, testSemaphoreMultipleImports, config);
4698 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("signal_export_import_wait_") + permanenceName, "Test signaling, exporting, importing and waiting for the sempahore.", checkEvent, initProgramsToGetNativeFd, testSemaphoreSignalExportImportWait, config);
4699 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("signal_import_") + permanenceName, "Test signaling and importing the semaphore.", checkSupport, initProgramsToGetNativeFd, testSemaphoreSignalImport, config);
4700 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("transference_") + permanenceName, "Test semaphores transference.", checkEvent, initProgramsToGetNativeFd, testSemaphoreTransference, config);
4702 if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT)
4704 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("import_signaled_") + permanenceName, "Test import signaled semaphore fd.", initProgramsToGetNativeFd, testSemaphoreImportSyncFdSignaled, config);
4708 if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT
4709 || externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT)
4711 // \note Not supported on WIN32 handles
4712 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("export_multiple_times_") + permanenceName, "Test exporting semaphore multiple times.", checkSupport, initProgramsToGetNativeFd, testSemaphoreMultipleExports, config);
4714 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("dup_") + permanenceName, "Test calling dup() on exported semaphore.", checkSupport, initProgramsToGetNativeFd, testSemaphoreFdDup, config);
4715 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("dup2_") + permanenceName, "Test calling dup2() on exported semaphore.", checkSupport, initProgramsToGetNativeFd, testSemaphoreFdDup2, config);
4716 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("dup3_") + permanenceName, "Test calling dup3() on exported semaphore.", checkSupport, initProgramsToGetNativeFd, testSemaphoreFdDup3, config);
4717 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("send_over_socket_") + permanenceName, "Test sending semaphore fd over socket.", checkSupport, initProgramsToGetNativeFd, testSemaphoreFdSendOverSocket, config);
4720 if (getHandelTypeTransferences(externalType) == TRANSFERENCE_REFERENCE)
4722 addFunctionCase(semaphoreGroup.get(), std::string("signal_wait_import_") + permanenceName, "Test signaling and then waiting for the the sepmahore.", testSemaphoreSignalWaitImport, config);
4723 addFunctionCase(semaphoreGroup.get(), std::string("export_signal_import_wait_") + permanenceName, "Test exporting, signaling, importing and waiting for the semaphore.", testSemaphoreExportSignalImportWait, config);
4724 addFunctionCase(semaphoreGroup.get(), std::string("export_import_signal_wait_") + permanenceName, "Test exporting, importing, signaling and waiting for the semaphore.", checkEvent, testSemaphoreExportImportSignalWait, config);
4728 return semaphoreGroup;
4731 de::MovePtr<tcu::TestCaseGroup> createSemaphoreTests (tcu::TestContext& testCtx)
4733 de::MovePtr<tcu::TestCaseGroup> semaphoreGroup (new tcu::TestCaseGroup(testCtx, "semaphore", "Tests for external semaphores."));
4735 semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT).release());
4736 semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT).release());
4737 semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT).release());
4738 semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT).release());
4740 return semaphoreGroup;
4743 de::MovePtr<tcu::TestCaseGroup> createMemoryTests (tcu::TestContext& testCtx, vk::VkExternalMemoryHandleTypeFlagBits externalType)
4745 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, externalMemoryTypeToName(externalType), "Tests for external memory"));
4747 for (size_t dedicatedNdx = 0; dedicatedNdx < 2; dedicatedNdx++)
4749 const bool dedicated (dedicatedNdx == 1);
4750 de::MovePtr<tcu::TestCaseGroup> dedicatedGroup (new tcu::TestCaseGroup(testCtx, dedicated ? "dedicated" : "suballocated", ""));
4752 for (size_t hostVisibleNdx = 0; hostVisibleNdx < 2; hostVisibleNdx++)
4754 const bool hostVisible (hostVisibleNdx == 1);
4755 de::MovePtr<tcu::TestCaseGroup> hostVisibleGroup (new tcu::TestCaseGroup(testCtx, hostVisible ? "host_visible" : "device_only", ""));
4756 const MemoryTestConfig memoryConfig (externalType, hostVisible, dedicated);
4758 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
4759 || externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
4761 addFunctionCase(hostVisibleGroup.get(), "create_win32", "Test creating memory with win32 properties .", testMemoryWin32Create, memoryConfig);
4764 addFunctionCase(hostVisibleGroup.get(), "import_twice", "Test importing memory object twice.", testMemoryImportTwice, memoryConfig);
4765 addFunctionCase(hostVisibleGroup.get(), "import_multiple_times", "Test importing memory object multiple times.", testMemoryMultipleImports, memoryConfig);
4767 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT
4768 || externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT)
4770 addFunctionCase(hostVisibleGroup.get(), "dup", "Test calling dup() on exported memory.", testMemoryFdDup, memoryConfig);
4771 addFunctionCase(hostVisibleGroup.get(), "dup2", "Test calling dup2() on exported memory.", testMemoryFdDup2, memoryConfig);
4772 addFunctionCase(hostVisibleGroup.get(), "dup3", "Test calling dup3() on exported memory.", testMemoryFdDup3, memoryConfig);
4773 addFunctionCase(hostVisibleGroup.get(), "send_over_socket", "Test sending memory fd over socket.", testMemoryFdSendOverSocket, memoryConfig);
4774 // \note Not supported on WIN32 handles
4775 addFunctionCase(hostVisibleGroup.get(), "export_multiple_times", "Test exporting memory multiple times.", testMemoryMultipleExports, memoryConfig);
4778 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT)
4780 addFunctionCase(hostVisibleGroup.get(), "fd_properties", "Test obtaining the FD memory properties", testMemoryFdProperties, memoryConfig);
4783 dedicatedGroup->addChild(hostVisibleGroup.release());
4787 de::MovePtr<tcu::TestCaseGroup> bufferGroup (new tcu::TestCaseGroup(testCtx, "buffer", ""));
4788 const BufferTestConfig bufferConfig (externalType, dedicated);
4790 addFunctionCase(bufferGroup.get(), "info", "External buffer memory info query.", testBufferQueries, externalType);
4791 addFunctionCase(bufferGroup.get(), "bind_export_import_bind", "Test binding, exporting, importing and binding buffer.", testBufferBindExportImportBind, bufferConfig);
4792 addFunctionCase(bufferGroup.get(), "export_bind_import_bind", "Test exporting, binding, importing and binding buffer.", testBufferExportBindImportBind, bufferConfig);
4793 addFunctionCase(bufferGroup.get(), "export_import_bind_bind", "Test exporting, importing and binding buffer.", testBufferExportImportBindBind, bufferConfig);
4795 dedicatedGroup->addChild(bufferGroup.release());
4799 de::MovePtr<tcu::TestCaseGroup> imageGroup (new tcu::TestCaseGroup(testCtx, "image", ""));
4800 const ImageTestConfig imageConfig (externalType, dedicated);
4802 addFunctionCase(imageGroup.get(), "info", "External image memory info query.", testImageQueries, externalType);
4803 addFunctionCase(imageGroup.get(), "bind_export_import_bind", "Test binding, exporting, importing and binding image.", testImageBindExportImportBind, imageConfig);
4804 addFunctionCase(imageGroup.get(), "export_bind_import_bind", "Test exporting, binding, importing and binding image.", testImageExportBindImportBind, imageConfig);
4805 addFunctionCase(imageGroup.get(), "export_import_bind_bind", "Test exporting, importing and binding image.", testImageExportImportBindBind, imageConfig);
4807 dedicatedGroup->addChild(imageGroup.release());
4810 group->addChild(dedicatedGroup.release());
4813 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
4815 de::MovePtr<tcu::TestCaseGroup> formatGroup (new tcu::TestCaseGroup(testCtx, "image_formats", "Test minimum image format support"));
4817 const vk::VkFormat ahbFormats[] =
4819 vk::VK_FORMAT_R8G8B8_UNORM,
4820 vk::VK_FORMAT_R8G8B8A8_UNORM,
4821 vk::VK_FORMAT_R5G6B5_UNORM_PACK16,
4822 vk::VK_FORMAT_R16G16B16A16_SFLOAT,
4823 vk::VK_FORMAT_A2B10G10R10_UNORM_PACK32,
4824 vk::VK_FORMAT_D16_UNORM,
4825 vk::VK_FORMAT_X8_D24_UNORM_PACK32,
4826 vk::VK_FORMAT_D24_UNORM_S8_UINT,
4827 vk::VK_FORMAT_D32_SFLOAT,
4828 vk::VK_FORMAT_D32_SFLOAT_S8_UINT,
4829 vk::VK_FORMAT_S8_UINT,
4831 const size_t numOfAhbFormats = DE_LENGTH_OF_ARRAY(ahbFormats);
4833 for (size_t ahbFormatNdx = 0; ahbFormatNdx < numOfAhbFormats; ahbFormatNdx++)
4835 const vk::VkFormat format = ahbFormats[ahbFormatNdx];
4836 const std::string testCaseName = getFormatCaseName(format);
4838 addFunctionCase(formatGroup.get(), testCaseName, "", testAndroidHardwareBufferImageFormat, format);
4841 group->addChild(formatGroup.release());
4847 de::MovePtr<tcu::TestCaseGroup> createMemoryTests (tcu::TestContext& testCtx)
4849 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "memory", "Tests for external memory"));
4851 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT).release());
4852 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT).release());
4853 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT).release());
4854 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID).release());
4855 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT).release());
4862 tcu::TestCaseGroup* createExternalMemoryTests (tcu::TestContext& testCtx)
4864 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "external", "Tests for external Vulkan objects"));
4866 group->addChild(createSemaphoreTests(testCtx).release());
4867 group->addChild(createMemoryTests(testCtx).release());
4868 group->addChild(createFenceTests(testCtx).release());
4870 return group.release();