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 & vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA)
326 deviceExtensions.push_back("VK_FUCHSIA_external_memory");
329 if (externalSemaphoreTypes & vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_ZIRCON_EVENT_BIT_FUCHSIA)
331 deviceExtensions.push_back("VK_FUCHSIA_external_semaphore");
334 if ((externalMemoryTypes
335 & (vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
336 | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT
337 | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT
338 | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT
339 | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT
340 | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT)) != 0)
342 deviceExtensions.push_back("VK_KHR_external_memory_win32");
343 useExternalMemory = true;
346 if ((externalMemoryTypes
347 & vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID) != 0)
349 deviceExtensions.push_back("VK_ANDROID_external_memory_android_hardware_buffer");
350 useExternalMemory = true;
351 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_sampler_ycbcr_conversion"))
352 deviceExtensions.push_back("VK_KHR_sampler_ycbcr_conversion");
353 if (!vk::isCoreDeviceExtension(apiVersion, "VK_EXT_queue_family_foreign"))
354 deviceExtensions.push_back("VK_EXT_queue_family_foreign");
357 if (useExternalSemaphore)
359 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_external_semaphore"))
360 deviceExtensions.push_back("VK_KHR_external_semaphore");
363 if (useExternalFence)
365 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_external_fence"))
366 deviceExtensions.push_back("VK_KHR_external_fence");
369 if (useExternalMemory)
371 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_external_memory"))
372 deviceExtensions.push_back("VK_KHR_external_memory");
375 const float priority = 0.5f;
376 const vk::VkDeviceQueueCreateInfo queues[] =
379 vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
388 const vk::VkDeviceCreateInfo deviceCreateInfo =
390 vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
394 DE_LENGTH_OF_ARRAY(queues),
400 (deUint32)deviceExtensions.size(),
401 deviceExtensions.empty() ? DE_NULL : &deviceExtensions[0],
407 return createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), vkp, instance, vki, physicalDevice, &deviceCreateInfo);
409 catch (const vk::Error& error)
411 if (error.getError() == vk::VK_ERROR_EXTENSION_NOT_PRESENT)
412 TCU_THROW(NotSupportedError, "Required extensions not supported");
418 vk::VkQueue getQueue (const vk::DeviceInterface& vkd,
420 deUint32 queueFamilyIndex)
424 vkd.getDeviceQueue(device, queueFamilyIndex, 0, &queue);
429 uint32_t getMaxInvocations(const Context& context, uint32_t idx)
431 const auto& vki = context.getInstanceInterface();
432 const auto physicalDevice = context.getPhysicalDevice();
433 const auto properties = vk::getPhysicalDeviceProperties(vki, physicalDevice);
435 return properties.limits.maxComputeWorkGroupSize[idx];
438 void checkSemaphoreSupport (const vk::InstanceInterface& vki,
439 vk::VkPhysicalDevice device,
440 vk::VkExternalSemaphoreHandleTypeFlagBits externalType)
442 const vk::VkPhysicalDeviceExternalSemaphoreInfo info =
444 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO,
448 vk::VkExternalSemaphoreProperties properties =
450 vk::VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES,
457 vki.getPhysicalDeviceExternalSemaphoreProperties(device, &info, &properties);
459 if ((properties.externalSemaphoreFeatures & vk::VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT) == 0)
460 TCU_THROW(NotSupportedError, "Semaphore doesn't support exporting in external type");
462 if ((properties.externalSemaphoreFeatures & vk::VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT) == 0)
463 TCU_THROW(NotSupportedError, "Semaphore doesn't support importing in external type");
466 void checkFenceSupport (const vk::InstanceInterface& vki,
467 vk::VkPhysicalDevice device,
468 vk::VkExternalFenceHandleTypeFlagBits externalType)
470 const vk::VkPhysicalDeviceExternalFenceInfo info =
472 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO,
476 vk::VkExternalFenceProperties properties =
478 vk::VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES,
485 vki.getPhysicalDeviceExternalFenceProperties(device, &info, &properties);
487 if ((properties.externalFenceFeatures & vk::VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT) == 0)
488 TCU_THROW(NotSupportedError, "Fence doesn't support exporting in external type");
490 if ((properties.externalFenceFeatures & vk::VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT) == 0)
491 TCU_THROW(NotSupportedError, "Fence doesn't support importing in external type");
494 void checkBufferSupport (const vk::InstanceInterface& vki,
495 vk::VkPhysicalDevice device,
496 vk::VkExternalMemoryHandleTypeFlagBits externalType,
497 vk::VkBufferViewCreateFlags createFlag,
498 vk::VkBufferUsageFlags usageFlag,
501 const vk::VkPhysicalDeviceExternalBufferInfo info =
503 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO,
510 vk::VkExternalBufferProperties properties =
512 vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES,
518 vki.getPhysicalDeviceExternalBufferProperties(device, &info, &properties);
520 if ((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) == 0)
521 TCU_THROW(NotSupportedError, "External handle type doesn't support exporting buffer");
523 if ((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) == 0)
524 TCU_THROW(NotSupportedError, "External handle type doesn't support importing buffer");
526 if (!dedicated && (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0)
527 TCU_THROW(NotSupportedError, "External handle type requires dedicated allocation");
530 void checkImageSupport (const vk::InstanceInterface& vki,
531 vk::VkPhysicalDevice device,
532 vk::VkExternalMemoryHandleTypeFlagBits externalType,
533 vk::VkImageViewCreateFlags createFlag,
534 vk::VkImageUsageFlags usageFlag,
536 vk::VkImageTiling tiling,
539 const vk::VkPhysicalDeviceExternalImageFormatInfo externalInfo =
541 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
545 const vk::VkPhysicalDeviceImageFormatInfo2 info =
547 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
551 vk::VK_IMAGE_TYPE_2D,
556 vk::VkExternalImageFormatProperties externalProperties =
558 vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES,
562 vk::VkImageFormatProperties2 properties =
564 vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
575 vki.getPhysicalDeviceImageFormatProperties2(device, &info, &properties);
577 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) == 0)
578 TCU_THROW(NotSupportedError, "External handle type doesn't support exporting image");
580 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) == 0)
581 TCU_THROW(NotSupportedError, "External handle type doesn't support importing image");
583 if (!dedicated && (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0)
584 TCU_THROW(NotSupportedError, "External handle type requires dedicated allocation");
587 void submitEmptySignal (const vk::DeviceInterface& vkd,
589 vk::VkSemaphore semaphore)
591 const vk::VkSubmitInfo submit =
593 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
607 VK_CHECK(vkd.queueSubmit(queue, 1, &submit, (vk::VkFence)0u));
610 void tuneWorkSizeYAndPrepareCommandBuffer( const Context& context,
611 const vk::DeviceInterface& vk,
614 vk::VkCommandBuffer cmdBuffer,
615 vk::VkDescriptorSet descriptorSet,
616 vk::VkPipelineLayout pipelineLayout,
617 vk::VkPipeline computePipeline,
618 vk::VkBufferMemoryBarrier computeFinishBarrier,
620 tcu::UVec3* maxWorkSize)
624 // Have it be static so we don't need to do tuning every time, especially for "export_multiple_times" tests.
625 static uint32_t yWorkSize = 1;
626 uint64_t timeElapsed = 0;
627 bool bOutLoop = false;
629 const vk::Unique<vk::VkFence> fence(vk::createFence(vk, device));
631 const vk::VkCommandBufferBeginInfo cmdBufferBeginInfo =
633 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
635 vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
640 VK_CHECK(vk.beginCommandBuffer(cmdBuffer, &cmdBufferBeginInfo));
643 * If the handle type is VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR, the spec allowed for implementations to return -1
644 * if the fence is already signaled. Previously, to avoid getting -1 in this case, this test had used vkCmdWaitEvents and
645 * vkSetEvent after submission to get a proper file descriptor before signaling but it's not invalid to call vkSetEvent
646 * after submission. So we just use vkCmdSetEvent and check the state of the event after submission to see if it's already
647 * signaled or an error happens while trying to get a file descriptor.
649 vk.cmdSetEvent(cmdBuffer, event, vk::VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT);
651 // And now we do a simple atomic calculation to avoid signalling instantly right after submit.
652 vk.cmdBindPipeline(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, computePipeline);
653 //vk.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, nullptr);
654 vk.cmdBindDescriptorSets(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &descriptorSet, 0u, nullptr);
655 vk.cmdDispatch(cmdBuffer, maxWorkSize->x(), yWorkSize, maxWorkSize->z());
656 vk.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, 0, 0, nullptr, 1u, &computeFinishBarrier, 0, nullptr);
657 vk.endCommandBuffer(cmdBuffer);
662 const vk::VkSubmitInfo submit =
664 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
678 auto timeStart = std::chrono::high_resolution_clock::now();
680 VK_CHECK(vk.queueSubmit(queue, 1, &submit, (vk::VkFence)*fence));
681 vk.waitForFences(device, 1u, &fence.get(), true, ~0ull);
683 const auto executionTime = std::chrono::high_resolution_clock::now() - timeStart;
684 auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(executionTime);
686 timeElapsed = elapsed.count();
688 // we do loop until we get over 9 miliseconds as an execution time.
689 if (elapsed.count() > 9)
697 if (yWorkSize > maxWorkSize->y())
699 yWorkSize = maxWorkSize->y();
703 vk.resetCommandBuffer(cmdBuffer, 0u);
704 vk.resetFences(device, 1u, &*fence);
707 tcu::TestLog& log = context.getTestContext().getLog();
708 log << tcu::TestLog::Message
709 << "Execution time to get a native file descriptor is " << timeElapsed << "ms with Y WorkSize " << yWorkSize
710 << tcu::TestLog::EndMessage;
715 void submitAtomicCalculationsAndGetSemaphoreNative (const Context& context,
716 const vk::DeviceInterface& vk,
718 vk::Allocator& alloc,
720 deUint32 queueFamilyIndex,
721 vk::VkSemaphore semaphore,
722 vk::VkExternalSemaphoreHandleTypeFlagBits externalType,
723 NativeHandle& nativeHandle)
725 const vk::Unique<vk::VkCommandPool> cmdPool(createCommandPool(vk, device, vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex, nullptr));
726 const vk::Unique<vk::VkCommandBuffer> cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
728 const vk::VkEventCreateInfo eventCreateInfo =
730 vk::VK_STRUCTURE_TYPE_EVENT_CREATE_INFO,
735 const vk::Unique<vk::VkEvent> event(createEvent(vk, device, &eventCreateInfo, nullptr));
737 const uint32_t maxXWorkSize = getMaxInvocations(context, 0);
738 const uint32_t maxYWorkSize = getMaxInvocations(context, 1);
740 tcu::UVec3 workSize = { maxXWorkSize, maxYWorkSize, 1u };
741 const uint32_t workGroupCount = multiplyComponents(workSize);
743 const vk::VkDeviceSize outputBufferSize = sizeof(uint32_t) * workGroupCount;
744 const vk::BufferWithMemory outputBuffer (vk, device, alloc, makeBufferCreateInfo(outputBufferSize, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), vk::MemoryRequirement::Local);
746 // Create a compute shader
747 const vk::Unique<vk::VkShaderModule> compShader(createShaderModule(vk, device, context.getBinaryCollection().get("compute"), 0u));
749 // Create descriptorSetLayout
750 vk::DescriptorSetLayoutBuilder layoutBuilder;
751 layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT);
752 vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout(layoutBuilder.build(vk, device));
754 // Create compute pipeline
755 const vk::Unique<vk::VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout));
756 const vk::Unique<vk::VkPipeline> computePipeline(makeComputePipeline(vk, device, *pipelineLayout, *compShader));
758 // Create descriptor pool
759 const vk::Unique<vk::VkDescriptorPool> descriptorPool(
760 vk::DescriptorPoolBuilder()
761 .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
762 .build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1));
765 const vk::Move<vk::VkDescriptorSet> descriptorSet (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
766 const vk::VkDescriptorBufferInfo outputBufferInfo = makeDescriptorBufferInfo(*outputBuffer, 0ull, outputBufferSize);
767 const vk::VkBufferMemoryBarrier computeFinishBarrier = vk::makeBufferMemoryBarrier(vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_ACCESS_HOST_READ_BIT, *outputBuffer, 0ull, outputBufferSize);
769 vk::DescriptorSetUpdateBuilder()
770 .writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &outputBufferInfo)
773 // Now start tuning work size of Y to have time enough to get a fd at the device.
774 tuneWorkSizeYAndPrepareCommandBuffer(context, vk, device, queue, *cmdBuffer, *descriptorSet, *pipelineLayout, *computePipeline, computeFinishBarrier, *event, &workSize);
776 const vk::VkSubmitInfo submit =
778 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
793 VK_CHECK(vk.queueSubmit(queue, 1, &submit, (vk::VkFence)0u));
795 getSemaphoreNative(vk, device, semaphore, externalType, nativeHandle);
797 // Allow -1, that is valid if signalled properly.
798 if (nativeHandle.getFd() == -1)
799 TCU_CHECK(vk.getEventStatus(device, *event) == vk::VK_EVENT_SET);
801 VK_CHECK(vk.queueWaitIdle(queue));
804 void submitEmptyWait (const vk::DeviceInterface& vkd,
806 vk::VkSemaphore semaphore)
808 const vk::VkPipelineStageFlags stage = vk::VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
809 const vk::VkSubmitInfo submit =
811 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
825 VK_CHECK(vkd.queueSubmit(queue, 1, &submit, (vk::VkFence)0u));
828 void submitEmptySignal (const vk::DeviceInterface& vkd,
832 const vk::VkSubmitInfo submit =
834 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
848 VK_CHECK(vkd.queueSubmit(queue, 1, &submit, fence));
851 void submitAtomicCalculationsAndGetFenceNative (const Context& context,
852 const vk::DeviceInterface& vk,
854 vk::Allocator& alloc,
856 deUint32 queueFamilyIndex,
858 vk::VkExternalFenceHandleTypeFlagBits externalType,
859 NativeHandle& nativeHandle,
860 bool expectFenceUnsignaled = true)
862 const vk::Unique<vk::VkCommandPool> cmdPool(createCommandPool(vk, device, vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex, nullptr));
863 const vk::Unique<vk::VkCommandBuffer> cmdBuffer(allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
865 const vk::VkEventCreateInfo eventCreateInfo =
867 vk::VK_STRUCTURE_TYPE_EVENT_CREATE_INFO,
872 const vk::Unique<vk::VkEvent> event(createEvent(vk, device, &eventCreateInfo, DE_NULL));
874 const uint32_t maxXWorkSize = getMaxInvocations(context, 0);
875 const uint32_t maxYWorkSize = getMaxInvocations(context, 1);
877 tcu::UVec3 workSize = { maxXWorkSize, maxYWorkSize, 1u };
878 const uint32_t workGroupCount = multiplyComponents(workSize);
880 const vk::VkDeviceSize outputBufferSize = sizeof(uint32_t) * workGroupCount;
881 const vk::BufferWithMemory outputBuffer (vk, device, alloc, makeBufferCreateInfo(outputBufferSize, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), vk::MemoryRequirement::Local);
883 // Create a compute shader
884 const vk::Unique<vk::VkShaderModule> compShader(createShaderModule(vk, device, context.getBinaryCollection().get("compute"), 0u));
886 // Create descriptorSetLayout
887 vk::DescriptorSetLayoutBuilder layoutBuilder;
888 layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT);
889 vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout(layoutBuilder.build(vk, device));
891 // Create compute pipeline
892 const vk::Unique<vk::VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout));
893 const vk::Unique<vk::VkPipeline> computePipeline(makeComputePipeline(vk, device, *pipelineLayout, *compShader));
895 // Create descriptor pool
896 const vk::Unique<vk::VkDescriptorPool> descriptorPool(
897 vk::DescriptorPoolBuilder()
898 .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
899 .build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1));
902 const vk::Move<vk::VkDescriptorSet> descriptorSet (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
903 const vk::VkDescriptorBufferInfo outputBufferInfo = makeDescriptorBufferInfo(*outputBuffer, 0ull, outputBufferSize);
904 const vk::VkBufferMemoryBarrier computeFinishBarrier = vk::makeBufferMemoryBarrier(vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_ACCESS_HOST_READ_BIT, *outputBuffer, 0ull, outputBufferSize);
906 vk::DescriptorSetUpdateBuilder()
907 .writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &outputBufferInfo)
910 // Now start tuning work size of Y to have time enough to get a fd at the device.
911 tuneWorkSizeYAndPrepareCommandBuffer(context, vk, device, queue, *cmdBuffer, *descriptorSet, *pipelineLayout, *computePipeline, computeFinishBarrier, *event, &workSize);
913 const vk::VkSubmitInfo submit =
915 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
929 VK_CHECK(vk.queueSubmit(queue, 1, &submit, fence));
931 getFenceNative(vk, device, fence, externalType, nativeHandle, expectFenceUnsignaled);
932 // Allow -1, that is valid if signalled properly.
933 if (nativeHandle.getFd() == -1)
934 TCU_CHECK(vk.getEventStatus(device, *event) == vk::VK_EVENT_SET);
936 VK_CHECK(vk.queueWaitIdle(queue));
939 struct TestSemaphoreQueriesParameters
941 vk::VkSemaphoreType semaphoreType;
942 vk::VkExternalSemaphoreHandleTypeFlagBits externalType;
944 TestSemaphoreQueriesParameters (vk::VkSemaphoreType semaphoreType_,
945 vk::VkExternalSemaphoreHandleTypeFlagBits externalType_)
946 : semaphoreType (semaphoreType_)
947 , externalType (externalType_)
951 tcu::TestStatus testSemaphoreQueries (Context& context, const TestSemaphoreQueriesParameters params)
953 const CustomInstance instance (createTestInstance(context, params.externalType, 0u, 0u));
954 const vk::InstanceDriver& vki (instance.getDriver());
955 const vk::VkPhysicalDevice device (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
957 TestLog& log = context.getTestContext().getLog();
959 const vk::VkSemaphoreTypeCreateInfo semaphoreTypeInfo =
961 vk::VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO,
963 params.semaphoreType,
966 const vk::VkPhysicalDeviceExternalSemaphoreInfo info =
968 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO,
972 vk::VkExternalSemaphoreProperties properties =
974 vk::VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES,
981 vki.getPhysicalDeviceExternalSemaphoreProperties(device, &info, &properties);
982 log << TestLog::Message << properties << TestLog::EndMessage;
984 TCU_CHECK(properties.pNext == DE_NULL);
985 TCU_CHECK(properties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES);
987 if (params.semaphoreType == vk::VK_SEMAPHORE_TYPE_TIMELINE)
989 context.requireDeviceFunctionality("VK_KHR_timeline_semaphore");
991 if (properties.compatibleHandleTypes & vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT)
992 return tcu::TestStatus::fail("Timeline semaphores are not compatible with SYNC_FD");
994 if (properties.exportFromImportedHandleTypes & vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT)
995 return tcu::TestStatus::fail("Timeline semaphores imported from SYNC_FD");
998 return tcu::TestStatus::pass("Pass");
1001 struct SemaphoreTestConfig
1003 SemaphoreTestConfig (vk::VkExternalSemaphoreHandleTypeFlagBits externalType_,
1004 Permanence permanence_)
1005 : externalType (externalType_)
1006 , permanence (permanence_)
1010 vk::VkExternalSemaphoreHandleTypeFlagBits externalType;
1011 Permanence permanence;
1014 template<class TestConfig> void initProgramsToGetNativeFd(vk::SourceCollections& dst, const TestConfig)
1016 const tcu::IVec3 localSize = { 64, 1, 1 };
1018 std::ostringstream src;
1019 src << "#version 310 es\n"
1020 << "layout (local_size_x = " << localSize.x() << ", local_size_y = " << localSize.y() << ", local_size_z = " << localSize.z() << ") in;\n"
1021 << "layout(binding = 0) writeonly buffer Output {\n"
1022 << " uint values[];\n"
1025 << "void main (void) {\n"
1026 << " uint offset = gl_NumWorkGroups.x*gl_NumWorkGroups.y*gl_WorkGroupID.z + gl_NumWorkGroups.x*gl_WorkGroupID.y + gl_WorkGroupID.x;\n"
1028 << " atomicAdd(values[offset], 1u);\n"
1031 dst.glslSources.add("compute") << glu::ComputeSource(src.str());
1034 tcu::TestStatus testSemaphoreWin32Create (Context& context,
1035 const SemaphoreTestConfig config)
1037 #if (DE_OS == DE_OS_WIN32)
1038 const Transference transference (getHandelTypeTransferences(config.externalType));
1039 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1040 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1041 const vk::InstanceDriver& vki (instance.getDriver());
1042 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1043 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1045 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1048 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1049 const vk::DeviceDriver vkd (vkp, instance, *device);
1050 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1051 const vk::VkExportSemaphoreWin32HandleInfoKHR win32ExportInfo =
1053 vk::VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR,
1056 (vk::pt::Win32SecurityAttributesPtr)DE_NULL,
1057 DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
1058 (vk::pt::Win32LPCWSTR)DE_NULL
1060 const vk::VkExportSemaphoreCreateInfo exportCreateInfo=
1062 vk::VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO,
1064 (vk::VkExternalMemoryHandleTypeFlags)config.externalType
1066 const vk::VkSemaphoreCreateInfo createInfo =
1068 vk::VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
1072 const vk::Unique<vk::VkSemaphore> semaphore (vk::createSemaphore(vkd, *device, &createInfo));
1074 if (transference == TRANSFERENCE_COPY)
1075 submitEmptySignal(vkd, queue, *semaphore);
1077 NativeHandle handleA;
1078 getSemaphoreNative(vkd, *device, *semaphore, config.externalType, handleA);
1081 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1082 const vk::Unique<vk::VkSemaphore> semaphoreA (createAndImportSemaphore(vkd, *device, config.externalType, handleA, flags));
1084 if (transference == TRANSFERENCE_COPY)
1085 submitEmptyWait(vkd, queue, *semaphoreA);
1086 else if (transference == TRANSFERENCE_REFERENCE)
1088 submitEmptySignal(vkd, queue, *semaphore);
1089 submitEmptyWait(vkd, queue, *semaphoreA);
1092 DE_FATAL("Unknown transference.");
1094 VK_CHECK(vkd.queueWaitIdle(queue));
1097 return tcu::TestStatus::pass("Pass");
1102 TCU_THROW(NotSupportedError, "Platform doesn't support win32 handles");
1106 tcu::TestStatus testSemaphoreImportTwice (Context& context,
1107 const SemaphoreTestConfig config)
1109 const Transference transference (getHandelTypeTransferences(config.externalType));
1110 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1111 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1112 const vk::InstanceDriver& vki (instance.getDriver());
1113 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1114 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1116 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1119 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1120 const vk::DeviceDriver vkd (vkp, instance, *device);
1121 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1122 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1123 const vk::Unique<vk::VkSemaphore> semaphore (createExportableSemaphore(vkd, *device, config.externalType));
1124 NativeHandle handleA;
1126 if (transference == TRANSFERENCE_COPY)
1128 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphore, config.externalType, handleA);
1129 if (handleA.getFd() == -1)
1130 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1133 getSemaphoreNative(vkd, *device, *semaphore, config.externalType, handleA);
1136 NativeHandle handleB (handleA);
1137 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1138 const vk::Unique<vk::VkSemaphore> semaphoreA (createAndImportSemaphore(vkd, *device, config.externalType, handleA, flags));
1139 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handleB, flags));
1141 if (transference == TRANSFERENCE_COPY)
1142 submitEmptyWait(vkd, queue, *semaphoreA);
1143 else if (transference == TRANSFERENCE_REFERENCE)
1145 submitEmptySignal(vkd, queue, *semaphoreA);
1146 submitEmptyWait(vkd, queue, *semaphoreB);
1149 DE_FATAL("Unknown transference.");
1151 VK_CHECK(vkd.queueWaitIdle(queue));
1154 return tcu::TestStatus::pass("Pass");
1158 tcu::TestStatus testSemaphoreImportReimport (Context& context,
1159 const SemaphoreTestConfig config)
1161 const Transference transference (getHandelTypeTransferences(config.externalType));
1162 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1163 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1164 const vk::InstanceDriver& vki (instance.getDriver());
1165 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1166 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1168 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1171 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1172 const vk::DeviceDriver vkd (vkp, instance, *device);
1173 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1174 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1176 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1177 NativeHandle handleA;
1179 if (transference == TRANSFERENCE_COPY)
1181 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, handleA);
1182 if (handleA.getFd() == -1)
1183 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1186 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handleA);
1188 NativeHandle handleB (handleA);
1189 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1190 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handleA, flags));
1192 importSemaphore(vkd, *device, *semaphoreB, config.externalType, handleB, flags);
1194 if (transference == TRANSFERENCE_COPY)
1195 submitEmptyWait(vkd, queue, *semaphoreB);
1196 else if (transference == TRANSFERENCE_REFERENCE)
1198 submitEmptySignal(vkd, queue, *semaphoreA);
1199 submitEmptyWait(vkd, queue, *semaphoreB);
1202 DE_FATAL("Unknown transference.");
1204 VK_CHECK(vkd.queueWaitIdle(queue));
1206 return tcu::TestStatus::pass("Pass");
1210 tcu::TestStatus testSemaphoreSignalExportImportWait (Context& context,
1211 const SemaphoreTestConfig config)
1213 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1214 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1215 const vk::InstanceDriver& vki (instance.getDriver());
1216 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1217 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1218 const Transference transference (getHandelTypeTransferences(config.externalType));
1220 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1223 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1224 const vk::DeviceDriver vkd (vkp, instance, *device);
1225 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1226 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1227 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1229 NativeHandle handle;
1231 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
1232 if (transference == TRANSFERENCE_COPY && handle.getFd() == -1)
1233 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1236 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1237 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1238 submitEmptyWait(vkd, queue, *semaphoreB);
1240 VK_CHECK(vkd.queueWaitIdle(queue));
1244 return tcu::TestStatus::pass("Pass");
1248 tcu::TestStatus testSemaphoreExportSignalImportWait (Context& context,
1249 const SemaphoreTestConfig config)
1251 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1252 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1253 const vk::InstanceDriver& vki (instance.getDriver());
1254 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1255 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1256 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1258 DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
1259 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1262 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1263 const vk::DeviceDriver vkd (vkp, instance, *device);
1264 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1266 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1267 NativeHandle handle;
1269 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
1271 submitEmptySignal(vkd, queue, *semaphoreA);
1274 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1276 submitEmptyWait(vkd, queue, *semaphoreB);
1277 VK_CHECK(vkd.queueWaitIdle(queue));
1281 return tcu::TestStatus::pass("Pass");
1285 tcu::TestStatus testSemaphoreExportImportSignalWait (Context& context,
1286 const SemaphoreTestConfig config)
1288 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1289 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1290 const vk::InstanceDriver& vki (instance.getDriver());
1291 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1292 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1294 DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
1295 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1298 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1299 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1300 const vk::DeviceDriver vkd (vkp, instance, *device);
1301 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1303 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1304 NativeHandle handle;
1306 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
1308 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1310 submitEmptySignal(vkd, queue, *semaphoreA);
1311 submitEmptyWait(vkd, queue, *semaphoreB);
1313 VK_CHECK(vkd.queueWaitIdle(queue));
1315 return tcu::TestStatus::pass("Pass");
1319 tcu::TestStatus testSemaphoreSignalImport (Context& context,
1320 const SemaphoreTestConfig config)
1322 const Transference transference (getHandelTypeTransferences(config.externalType));
1323 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1324 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1325 const vk::InstanceDriver& vki (instance.getDriver());
1326 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1327 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1329 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1332 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1333 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1334 const vk::DeviceDriver vkd (vkp, instance, *device);
1335 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1336 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1338 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1339 const vk::Unique<vk::VkSemaphore> semaphoreB (createSemaphore(vkd, *device));
1340 NativeHandle handle;
1342 submitEmptySignal(vkd, queue, *semaphoreB);
1343 VK_CHECK(vkd.queueWaitIdle(queue));
1345 if (transference == TRANSFERENCE_COPY)
1347 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
1348 if (handle.getFd() == -1)
1349 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1352 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
1354 importSemaphore(vkd, *device, *semaphoreB, config.externalType, handle, flags);
1356 if (transference == TRANSFERENCE_COPY)
1357 submitEmptyWait(vkd, queue, *semaphoreB);
1358 else if (transference == TRANSFERENCE_REFERENCE)
1360 submitEmptySignal(vkd, queue, *semaphoreA);
1361 submitEmptyWait(vkd, queue, *semaphoreB);
1364 DE_FATAL("Unknown transference.");
1366 VK_CHECK(vkd.queueWaitIdle(queue));
1368 return tcu::TestStatus::pass("Pass");
1372 tcu::TestStatus testSemaphoreSignalWaitImport (Context& context,
1373 const SemaphoreTestConfig config)
1375 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1376 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1377 const vk::InstanceDriver& vki (instance.getDriver());
1378 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1379 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1381 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1384 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1385 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1386 const vk::DeviceDriver vkd (vkp, instance, *device);
1387 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1389 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1390 const vk::Unique<vk::VkSemaphore> semaphoreB (createSemaphore(vkd, *device));
1391 NativeHandle handle;
1393 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
1395 submitEmptySignal(vkd, queue, *semaphoreB);
1396 submitEmptyWait(vkd, queue, *semaphoreB);
1398 VK_CHECK(vkd.queueWaitIdle(queue));
1400 importSemaphore(vkd, *device, *semaphoreB, config.externalType, handle, flags);
1402 submitEmptySignal(vkd, queue, *semaphoreA);
1403 submitEmptyWait(vkd, queue, *semaphoreB);
1405 VK_CHECK(vkd.queueWaitIdle(queue));
1407 return tcu::TestStatus::pass("Pass");
1411 tcu::TestStatus testSemaphoreImportSyncFdSignaled (Context& context,
1412 const SemaphoreTestConfig config)
1414 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1415 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1416 const vk::InstanceDriver& vki (instance.getDriver());
1417 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1418 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1419 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1421 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1424 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1425 const vk::DeviceDriver vkd (vkp, instance, *device);
1426 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1427 NativeHandle handle = -1;
1428 const vk::Unique<vk::VkSemaphore> semaphore (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1430 submitEmptyWait(vkd, queue, *semaphore);
1431 VK_CHECK(vkd.queueWaitIdle(queue));
1433 return tcu::TestStatus::pass("Pass");
1437 tcu::TestStatus testSemaphoreMultipleExports (Context& context,
1438 const SemaphoreTestConfig config)
1440 const size_t exportCount = 1024;
1441 const Transference transference (getHandelTypeTransferences(config.externalType));
1442 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1443 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1444 const vk::InstanceDriver& vki (instance.getDriver());
1445 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1446 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1448 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1451 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1452 const vk::DeviceDriver vkd (vkp, instance, *device);
1453 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1454 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1455 const vk::Unique<vk::VkSemaphore> semaphore (createExportableSemaphore(vkd, *device, config.externalType));
1457 for (size_t exportNdx = 0; exportNdx < exportCount; exportNdx++)
1459 NativeHandle handle;
1461 // Need to touch watchdog due to how long one iteration takes
1462 context.getTestContext().touchWatchdog();
1464 if (transference == TRANSFERENCE_COPY)
1466 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphore, config.externalType, handle);
1467 if (handle.getFd() == -1)
1468 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1471 getSemaphoreNative(vkd, *device, *semaphore, config.externalType, handle);
1474 submitEmptySignal(vkd, queue, *semaphore);
1475 submitEmptyWait(vkd, queue, *semaphore);
1477 VK_CHECK(vkd.queueWaitIdle(queue));
1480 return tcu::TestStatus::pass("Pass");
1483 tcu::TestStatus testSemaphoreMultipleImports (Context& context,
1484 const SemaphoreTestConfig config)
1486 const size_t importCount = 4 * 1024;
1487 const Transference transference (getHandelTypeTransferences(config.externalType));
1488 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1489 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1490 const vk::InstanceDriver& vki (instance.getDriver());
1491 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1492 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1494 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1497 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1498 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1499 const vk::DeviceDriver vkd (vkp, instance, *device);
1500 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1501 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1502 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1503 NativeHandle handleA;
1505 if (transference == TRANSFERENCE_COPY)
1507 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, handleA);
1508 if (handleA.getFd() == -1)
1509 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1512 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handleA);
1514 for (size_t importNdx = 0; importNdx < importCount; importNdx++)
1516 NativeHandle handleB (handleA);
1517 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handleB, flags));
1520 if (transference == TRANSFERENCE_COPY)
1522 importSemaphore(vkd, *device, *semaphoreA, config.externalType, handleA, flags);
1523 submitEmptyWait(vkd, queue, *semaphoreA);
1525 else if (transference == TRANSFERENCE_REFERENCE)
1527 submitEmptySignal(vkd, queue, *semaphoreA);
1528 submitEmptyWait(vkd, queue, *semaphoreA);
1531 DE_FATAL("Unknown transference.");
1533 VK_CHECK(vkd.queueWaitIdle(queue));
1536 return tcu::TestStatus::pass("Pass");
1539 tcu::TestStatus testSemaphoreTransference (Context& context,
1540 const SemaphoreTestConfig config)
1542 const Transference transference (getHandelTypeTransferences(config.externalType));
1543 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1544 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1545 const vk::InstanceDriver& vki (instance.getDriver());
1546 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1547 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1549 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1552 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1553 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1554 const vk::DeviceDriver vkd (vkp, instance, *device);
1555 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1556 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1558 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1559 NativeHandle handle;
1561 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, handle);
1562 if (transference == TRANSFERENCE_COPY && handle.getFd() == -1)
1563 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1566 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1568 if (config.permanence == PERMANENCE_PERMANENT)
1570 if (transference == TRANSFERENCE_COPY)
1572 submitEmptySignal(vkd, queue, *semaphoreA);
1573 submitEmptyWait(vkd, queue, *semaphoreB);
1574 VK_CHECK(vkd.queueWaitIdle(queue));
1576 submitEmptySignal(vkd, queue, *semaphoreB);
1578 submitEmptyWait(vkd, queue, *semaphoreA);
1579 submitEmptyWait(vkd, queue, *semaphoreB);
1580 VK_CHECK(vkd.queueWaitIdle(queue));
1582 else if (transference== TRANSFERENCE_REFERENCE)
1584 submitEmptyWait(vkd, queue, *semaphoreB);
1585 VK_CHECK(vkd.queueWaitIdle(queue));
1587 submitEmptySignal(vkd, queue, *semaphoreA);
1588 submitEmptyWait(vkd, queue, *semaphoreB);
1590 submitEmptySignal(vkd, queue, *semaphoreB);
1591 submitEmptyWait(vkd, queue, *semaphoreA);
1592 VK_CHECK(vkd.queueWaitIdle(queue));
1595 DE_FATAL("Unknown transference.");
1597 else if (config.permanence == PERMANENCE_TEMPORARY)
1599 if (transference == TRANSFERENCE_COPY)
1601 submitEmptySignal(vkd, queue, *semaphoreA);
1602 submitEmptyWait(vkd, queue, *semaphoreB);
1603 VK_CHECK(vkd.queueWaitIdle(queue));
1605 submitEmptySignal(vkd, queue, *semaphoreB);
1607 submitEmptyWait(vkd, queue, *semaphoreA);
1608 submitEmptyWait(vkd, queue, *semaphoreB);
1609 VK_CHECK(vkd.queueWaitIdle(queue));
1611 else if (transference== TRANSFERENCE_REFERENCE)
1613 submitEmptyWait(vkd, queue, *semaphoreB);
1614 VK_CHECK(vkd.queueWaitIdle(queue));
1616 submitEmptySignal(vkd, queue, *semaphoreA);
1617 submitEmptySignal(vkd, queue, *semaphoreB);
1619 submitEmptyWait(vkd, queue, *semaphoreB);
1620 submitEmptyWait(vkd, queue, *semaphoreA);
1621 VK_CHECK(vkd.queueWaitIdle(queue));
1624 DE_FATAL("Unknown transference.");
1627 DE_FATAL("Unknown permanence.");
1630 return tcu::TestStatus::pass("Pass");
1634 tcu::TestStatus testSemaphoreFdDup (Context& context,
1635 const SemaphoreTestConfig config)
1637 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
1638 const Transference transference (getHandelTypeTransferences(config.externalType));
1639 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1640 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1641 const vk::InstanceDriver& vki (instance.getDriver());
1642 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1643 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1645 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1648 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1649 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1650 const vk::DeviceDriver vkd (vkp, instance, *device);
1651 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1652 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1654 TestLog& log = context.getTestContext().getLog();
1655 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1660 if (transference == TRANSFERENCE_COPY)
1662 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, fd);
1663 if (fd.getFd() == -1)
1664 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1667 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, fd);
1669 NativeHandle newFd (dup(fd.getFd()));
1671 if (newFd.getFd() < 0)
1672 log << TestLog::Message << "dup() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
1674 TCU_CHECK_MSG(newFd.getFd() >= 0, "Failed to call dup() for semaphores fd");
1677 const vk::Unique<vk::VkSemaphore> semaphoreB (createAndImportSemaphore(vkd, *device, config.externalType, newFd, flags));
1679 if (transference == TRANSFERENCE_COPY)
1680 submitEmptyWait(vkd, queue, *semaphoreB);
1681 else if (transference == TRANSFERENCE_REFERENCE)
1683 submitEmptySignal(vkd, queue, *semaphoreA);
1684 submitEmptyWait(vkd, queue, *semaphoreB);
1687 DE_FATAL("Unknown permanence.");
1689 VK_CHECK(vkd.queueWaitIdle(queue));
1693 return tcu::TestStatus::pass("Pass");
1698 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
1702 tcu::TestStatus testSemaphoreFdDup2 (Context& context,
1703 const SemaphoreTestConfig config)
1705 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
1706 const Transference transference (getHandelTypeTransferences(config.externalType));
1707 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1708 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1709 const vk::InstanceDriver& vki (instance.getDriver());
1710 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1711 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1713 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1716 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1717 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1718 const vk::DeviceDriver vkd (vkp, instance, *device);
1719 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1720 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1722 TestLog& log = context.getTestContext().getLog();
1723 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1724 const vk::Unique<vk::VkSemaphore> semaphoreB (createExportableSemaphore(vkd, *device, config.externalType));
1727 NativeHandle fd, secondFd;
1729 if (transference == TRANSFERENCE_COPY)
1731 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, fd);
1732 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreB, config.externalType, secondFd);
1733 if (fd.getFd() == -1 || secondFd.getFd() == -1)
1734 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1738 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, fd);
1739 getSemaphoreNative(vkd, *device, *semaphoreB, config.externalType, secondFd);
1742 int newFd (dup2(fd.getFd(), secondFd.getFd()));
1745 log << TestLog::Message << "dup2() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
1747 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup2() for fences fd");
1750 const vk::Unique<vk::VkSemaphore> semaphoreC (createAndImportSemaphore(vkd, *device, config.externalType, secondFd, flags));
1752 if (transference == TRANSFERENCE_COPY)
1753 submitEmptyWait(vkd, queue, *semaphoreC);
1754 else if (transference == TRANSFERENCE_REFERENCE)
1756 submitEmptySignal(vkd, queue, *semaphoreA);
1757 submitEmptyWait(vkd, queue, *semaphoreC);
1760 DE_FATAL("Unknown permanence.");
1762 VK_CHECK(vkd.queueWaitIdle(queue));
1766 return tcu::TestStatus::pass("Pass");
1771 TCU_THROW(NotSupportedError, "Platform doesn't support dup2()");
1775 tcu::TestStatus testSemaphoreFdDup3 (Context& context,
1776 const SemaphoreTestConfig config)
1778 #if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
1779 const Transference transference (getHandelTypeTransferences(config.externalType));
1780 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1781 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1782 const vk::InstanceDriver& vki (instance.getDriver());
1783 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1784 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1786 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1789 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1790 const vk::DeviceDriver vkd (vkp, instance, *device);
1791 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1792 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1794 TestLog& log = context.getTestContext().getLog();
1795 const vk::Unique<vk::VkSemaphore> semaphoreA (createExportableSemaphore(vkd, *device, config.externalType));
1796 const vk::Unique<vk::VkSemaphore> semaphoreB (createExportableSemaphore(vkd, *device, config.externalType));
1799 NativeHandle fd, secondFd;
1801 if (transference == TRANSFERENCE_COPY)
1803 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreA, config.externalType, fd);
1804 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphoreB, config.externalType, secondFd);
1805 if (fd.getFd() == -1 || secondFd.getFd() == -1)
1806 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1810 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, fd);
1811 getSemaphoreNative(vkd, *device, *semaphoreB, config.externalType, secondFd);
1814 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1815 const int newFd (dup3(fd.getFd(), secondFd.getFd(), 0));
1818 log << TestLog::Message << "dup3() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
1820 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup3() for fences fd");
1823 const vk::Unique<vk::VkSemaphore> semaphoreC (createAndImportSemaphore(vkd, *device, config.externalType, secondFd, flags));
1825 if (transference == TRANSFERENCE_COPY)
1826 submitEmptyWait(vkd, queue, *semaphoreC);
1827 else if (transference == TRANSFERENCE_REFERENCE)
1829 submitEmptySignal(vkd, queue, *semaphoreA);
1830 submitEmptyWait(vkd, queue, *semaphoreC);
1833 DE_FATAL("Unknown permanence.");
1835 VK_CHECK(vkd.queueWaitIdle(queue));
1839 return tcu::TestStatus::pass("Pass");
1844 TCU_THROW(NotSupportedError, "Platform doesn't support dup3()");
1848 tcu::TestStatus testSemaphoreFdSendOverSocket (Context& context,
1849 const SemaphoreTestConfig config)
1851 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
1852 const Transference transference (getHandelTypeTransferences(config.externalType));
1853 const vk::PlatformInterface& vkp (context.getPlatformInterface());
1854 const CustomInstance instance (createTestInstance(context, config.externalType, 0u, 0u));
1855 const vk::InstanceDriver& vki (instance.getDriver());
1856 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1857 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1859 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1862 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, config.externalType, 0u, 0u, queueFamilyIndex));
1863 const vk::DeviceDriver vkd (vkp, instance, *device);
1864 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1865 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
1867 TestLog& log = context.getTestContext().getLog();
1868 const vk::Unique<vk::VkSemaphore> semaphore (createExportableSemaphore(vkd, *device, config.externalType));
1871 if (transference == TRANSFERENCE_COPY)
1873 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *semaphore, config.externalType, fd);
1874 if (fd.getFd() == -1)
1875 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1878 getSemaphoreNative(vkd, *device, *semaphore, config.externalType, fd);
1883 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
1885 log << TestLog::Message << "Failed to create socket pair: '" << strerror(errno) << "'" << TestLog::EndMessage;
1886 TCU_FAIL("Failed to create socket pair");
1890 const NativeHandle srcSocket (sv[0]);
1891 const NativeHandle dstSocket (sv[1]);
1892 std::string sendData ("deqp");
1896 const int fdRaw (fd.getFd());
1899 char buffer[CMSG_SPACE(sizeof(int))];
1900 iovec iov = { &sendData[0], sendData.length()};
1902 deMemset(&msg, 0, sizeof(msg));
1904 msg.msg_control = buffer;
1905 msg.msg_controllen = sizeof(buffer);
1909 cmsg = CMSG_FIRSTHDR(&msg);
1910 cmsg->cmsg_level = SOL_SOCKET;
1911 cmsg->cmsg_type = SCM_RIGHTS;
1912 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
1914 deMemcpy(CMSG_DATA(cmsg), &fdRaw, sizeof(int));
1915 msg.msg_controllen = cmsg->cmsg_len;
1917 if (sendmsg(srcSocket.getFd(), &msg, 0) < 0)
1919 log << TestLog::Message << "Failed to send fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
1920 TCU_FAIL("Failed to send fd over socket");
1927 char buffer[CMSG_SPACE(sizeof(int))];
1928 std::string recvData (4, '\0');
1929 iovec iov = { &recvData[0], recvData.length() };
1931 deMemset(&msg, 0, sizeof(msg));
1933 msg.msg_control = buffer;
1934 msg.msg_controllen = sizeof(buffer);
1938 const ssize_t bytes = recvmsg(dstSocket.getFd(), &msg, 0);
1942 log << TestLog::Message << "Failed to recv fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
1943 TCU_FAIL("Failed to recv fd over socket");
1946 else if (bytes != (ssize_t)sendData.length())
1948 TCU_FAIL("recvmsg() returned unpexpected number of bytes");
1952 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT : (vk::VkSemaphoreImportFlagBits)0u;
1953 const cmsghdr* const cmsg = CMSG_FIRSTHDR(&msg);
1955 deMemcpy(&newFd_, CMSG_DATA(cmsg), sizeof(int));
1956 NativeHandle newFd (newFd_);
1958 TCU_CHECK(cmsg->cmsg_level == SOL_SOCKET);
1959 TCU_CHECK(cmsg->cmsg_type == SCM_RIGHTS);
1960 TCU_CHECK(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
1961 TCU_CHECK(recvData == sendData);
1962 TCU_CHECK_MSG(newFd.getFd() >= 0, "Didn't receive valid fd from socket");
1965 const vk::Unique<vk::VkSemaphore> newSemaphore (createAndImportSemaphore(vkd, *device, config.externalType, newFd, flags));
1967 if (transference == TRANSFERENCE_COPY)
1968 submitEmptyWait(vkd, queue, *newSemaphore);
1969 else if (transference == TRANSFERENCE_REFERENCE)
1971 submitEmptySignal(vkd, queue, *newSemaphore);
1972 submitEmptyWait(vkd, queue, *newSemaphore);
1975 DE_FATAL("Unknown permanence.");
1977 VK_CHECK(vkd.queueWaitIdle(queue));
1985 return tcu::TestStatus::pass("Pass");
1989 TCU_THROW(NotSupportedError, "Platform doesn't support sending file descriptors over socket");
1993 tcu::TestStatus testFenceQueries (Context& context, vk::VkExternalFenceHandleTypeFlagBits externalType)
1995 const CustomInstance instance (createTestInstance(context, 0u, 0u, externalType));
1996 const vk::InstanceDriver& vki (instance.getDriver());
1997 const vk::VkPhysicalDevice device (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1999 TestLog& log = context.getTestContext().getLog();
2001 const vk::VkPhysicalDeviceExternalFenceInfo info =
2003 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO,
2007 vk::VkExternalFenceProperties properties =
2009 vk::VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES,
2016 vki.getPhysicalDeviceExternalFenceProperties(device, &info, &properties);
2017 log << TestLog::Message << properties << TestLog::EndMessage;
2019 TCU_CHECK(properties.pNext == DE_NULL);
2020 TCU_CHECK(properties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES);
2022 return tcu::TestStatus::pass("Pass");
2025 struct FenceTestConfig
2027 FenceTestConfig (vk::VkExternalFenceHandleTypeFlagBits externalType_,
2028 Permanence permanence_)
2029 : externalType (externalType_)
2030 , permanence (permanence_)
2034 vk::VkExternalFenceHandleTypeFlagBits externalType;
2035 Permanence permanence;
2038 tcu::TestStatus testFenceWin32Create (Context& context,
2039 const FenceTestConfig config)
2041 #if (DE_OS == DE_OS_WIN32)
2042 const Transference transference (getHandelTypeTransferences(config.externalType));
2043 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2044 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2045 const vk::InstanceDriver& vki (instance.getDriver());
2046 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2047 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2049 checkFenceSupport(vki, physicalDevice, config.externalType);
2052 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2053 const vk::DeviceDriver vkd (vkp, instance, *device);
2054 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2055 const vk::VkExportFenceWin32HandleInfoKHR win32ExportInfo =
2057 vk::VK_STRUCTURE_TYPE_EXPORT_FENCE_WIN32_HANDLE_INFO_KHR,
2060 (vk::pt::Win32SecurityAttributesPtr)DE_NULL,
2061 DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
2062 (vk::pt::Win32LPCWSTR)DE_NULL
2064 const vk::VkExportFenceCreateInfo exportCreateInfo=
2066 vk::VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO,
2068 (vk::VkExternalFenceHandleTypeFlags)config.externalType
2070 const vk::VkFenceCreateInfo createInfo =
2072 vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
2076 const vk::Unique<vk::VkFence> fence (vk::createFence(vkd, *device, &createInfo));
2078 if (transference == TRANSFERENCE_COPY)
2079 submitEmptySignal(vkd, queue, *fence);
2081 NativeHandle handleA;
2082 getFenceNative(vkd, *device, *fence, config.externalType, handleA);
2085 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2086 const vk::Unique<vk::VkFence> fenceA (createAndImportFence(vkd, *device, config.externalType, handleA, flags));
2088 if (transference == TRANSFERENCE_COPY)
2089 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2090 else if (transference == TRANSFERENCE_REFERENCE)
2092 submitEmptySignal(vkd, queue, *fence);
2093 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2096 DE_FATAL("Unknown transference.");
2098 VK_CHECK(vkd.queueWaitIdle(queue));
2101 return tcu::TestStatus::pass("Pass");
2106 TCU_THROW(NotSupportedError, "Platform doesn't support win32 handles");
2110 tcu::TestStatus testFenceImportTwice (Context& context,
2111 const FenceTestConfig config)
2113 const Transference transference (getHandelTypeTransferences(config.externalType));
2114 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2115 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2116 const vk::InstanceDriver& vki (instance.getDriver());
2117 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2118 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2120 checkFenceSupport(vki, physicalDevice, config.externalType);
2123 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2124 const vk::DeviceDriver vkd (vkp, instance, *device);
2125 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2126 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2127 const vk::Unique<vk::VkFence> fence (createExportableFence(vkd, *device, config.externalType));
2128 NativeHandle handleA;
2130 if (transference == TRANSFERENCE_COPY)
2132 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fence, config.externalType, handleA);
2133 if (handleA.getFd() == -1)
2134 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2137 getFenceNative(vkd, *device, *fence, config.externalType, handleA);
2140 NativeHandle handleB (handleA);
2141 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2142 const vk::Unique<vk::VkFence> fenceA (createAndImportFence(vkd, *device, config.externalType, handleA, flags));
2143 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handleB, flags));
2145 if (transference == TRANSFERENCE_COPY)
2146 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2147 else if (transference == TRANSFERENCE_REFERENCE)
2149 submitEmptySignal(vkd, queue, *fenceA);
2150 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2153 DE_FATAL("Unknown transference.");
2155 VK_CHECK(vkd.queueWaitIdle(queue));
2158 return tcu::TestStatus::pass("Pass");
2162 tcu::TestStatus testFenceImportReimport (Context& context,
2163 const FenceTestConfig config)
2165 const Transference transference (getHandelTypeTransferences(config.externalType));
2166 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2167 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2168 const vk::InstanceDriver& vki (instance.getDriver());
2169 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2170 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2172 checkFenceSupport(vki, physicalDevice, config.externalType);
2175 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2176 const vk::DeviceDriver vkd (vkp, instance, *device);
2177 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2178 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2180 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2181 NativeHandle handleA;
2183 if (transference == TRANSFERENCE_COPY)
2185 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, handleA);
2186 if (handleA.getFd() == -1)
2187 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2190 getFenceNative(vkd, *device, *fenceA, config.externalType, handleA);
2192 NativeHandle handleB (handleA);
2193 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2194 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handleA, flags));
2196 importFence(vkd, *device, *fenceB, config.externalType, handleB, flags);
2198 if (transference == TRANSFERENCE_COPY)
2199 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2200 else if (transference == TRANSFERENCE_REFERENCE)
2202 submitEmptySignal(vkd, queue, *fenceA);
2203 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2206 DE_FATAL("Unknown transference.");
2208 VK_CHECK(vkd.queueWaitIdle(queue));
2210 return tcu::TestStatus::pass("Pass");
2214 tcu::TestStatus testFenceSignalExportImportWait (Context& context,
2215 const FenceTestConfig config)
2217 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2218 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2219 const vk::InstanceDriver& vki (instance.getDriver());
2220 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2221 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2223 checkFenceSupport(vki, physicalDevice, config.externalType);
2226 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2227 const vk::DeviceDriver vkd (vkp, instance, *device);
2228 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2229 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2230 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2233 NativeHandle handle;
2235 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2236 if (handle.getFd() == -1)
2237 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2240 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2241 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handle, flags));
2242 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2244 VK_CHECK(vkd.queueWaitIdle(queue));
2248 return tcu::TestStatus::pass("Pass");
2252 tcu::TestStatus testFenceImportSyncFdSignaled (Context& context,
2253 const FenceTestConfig config)
2255 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2256 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2257 const vk::InstanceDriver& vki (instance.getDriver());
2258 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2259 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2260 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2262 checkFenceSupport(vki, physicalDevice, config.externalType);
2265 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2266 const vk::DeviceDriver vkd (vkp, instance, *device);
2267 NativeHandle handle = -1;
2268 const vk::Unique<vk::VkFence> fence (createAndImportFence(vkd, *device, config.externalType, handle, flags));
2270 if (vkd.waitForFences(*device, 1u, &*fence, VK_TRUE, 0) != vk::VK_SUCCESS)
2271 return tcu::TestStatus::pass("Imported -1 sync fd isn't signaled");
2273 return tcu::TestStatus::pass("Pass");
2277 tcu::TestStatus testFenceExportSignalImportWait (Context& context,
2278 const FenceTestConfig config)
2280 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2281 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2282 const vk::InstanceDriver& vki (instance.getDriver());
2283 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2284 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2285 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2287 DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
2288 checkFenceSupport(vki, physicalDevice, config.externalType);
2291 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2292 const vk::DeviceDriver vkd (vkp, instance, *device);
2293 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2295 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2296 NativeHandle handle;
2298 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2300 submitEmptySignal(vkd, queue, *fenceA);
2303 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handle, flags));
2305 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2306 VK_CHECK(vkd.queueWaitIdle(queue));
2310 return tcu::TestStatus::pass("Pass");
2314 tcu::TestStatus testFenceExportImportSignalWait (Context& context,
2315 const FenceTestConfig config)
2317 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2318 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2319 const vk::InstanceDriver& vki (instance.getDriver());
2320 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2321 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2323 DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
2324 checkFenceSupport(vki, physicalDevice, config.externalType);
2327 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2328 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2329 const vk::DeviceDriver vkd (vkp, instance, *device);
2330 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2332 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2333 NativeHandle handle;
2335 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2337 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handle, flags));
2339 submitEmptySignal(vkd, queue, *fenceA);
2340 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2342 VK_CHECK(vkd.queueWaitIdle(queue));
2344 return tcu::TestStatus::pass("Pass");
2348 tcu::TestStatus testFenceSignalImport (Context& context,
2349 const FenceTestConfig config)
2351 const Transference transference (getHandelTypeTransferences(config.externalType));
2352 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2353 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2354 const vk::InstanceDriver& vki (instance.getDriver());
2355 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2356 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2358 checkFenceSupport(vki, physicalDevice, config.externalType);
2361 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2362 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2363 const vk::DeviceDriver vkd (vkp, instance, *device);
2364 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2365 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2367 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2368 const vk::Unique<vk::VkFence> fenceB (createFence(vkd, *device));
2369 NativeHandle handle;
2371 submitEmptySignal(vkd, queue, *fenceB);
2372 VK_CHECK(vkd.queueWaitIdle(queue));
2374 if (transference == TRANSFERENCE_COPY)
2376 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2377 if (handle.getFd() == -1)
2378 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2381 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2383 importFence(vkd, *device, *fenceB, config.externalType, handle, flags);
2385 if (transference == TRANSFERENCE_COPY)
2386 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2387 else if (transference == TRANSFERENCE_REFERENCE)
2389 submitEmptySignal(vkd, queue, *fenceA);
2390 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2393 DE_FATAL("Unknown transference.");
2395 VK_CHECK(vkd.queueWaitIdle(queue));
2397 return tcu::TestStatus::pass("Pass");
2401 tcu::TestStatus testFenceReset (Context& context,
2402 const FenceTestConfig config)
2404 const Transference transference (getHandelTypeTransferences(config.externalType));
2405 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2406 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2407 const vk::InstanceDriver& vki (instance.getDriver());
2408 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2409 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2411 checkFenceSupport(vki, physicalDevice, config.externalType);
2414 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2415 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2416 const vk::DeviceDriver vkd (vkp, instance, *device);
2417 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2418 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2420 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2421 const vk::Unique<vk::VkFence> fenceB (createFence(vkd, *device));
2422 const vk::Unique<vk::VkFence> fenceC (createFence(vkd, *device));
2423 NativeHandle handle;
2425 submitEmptySignal(vkd, queue, *fenceB);
2426 VK_CHECK(vkd.queueWaitIdle(queue));
2428 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2429 if (handle.getFd() == -1)
2430 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2432 NativeHandle handleB (handle);
2433 importFence(vkd, *device, *fenceB, config.externalType, handleB, flags);
2434 importFence(vkd, *device, *fenceC, config.externalType, handle, flags);
2436 VK_CHECK(vkd.queueWaitIdle(queue));
2437 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2439 if (config.permanence == PERMANENCE_TEMPORARY || transference == TRANSFERENCE_COPY)
2441 // vkResetFences() should restore fenceBs prior payload and reset that no affecting fenceCs payload
2442 // or fenceB should be separate copy of the payload and not affect fenceC
2443 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2445 // vkResetFences() should have restored fenceBs prior state and should be now reset
2446 // or fenceB should have it's separate payload
2447 submitEmptySignal(vkd, queue, *fenceB);
2448 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2450 else if (config.permanence == PERMANENCE_PERMANENT)
2452 DE_ASSERT(transference == TRANSFERENCE_REFERENCE);
2454 // Reset fences should have reset all of the fences
2455 submitEmptySignal(vkd, queue, *fenceC);
2457 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2458 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2459 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2462 DE_FATAL("Unknown permanence");
2464 VK_CHECK(vkd.queueWaitIdle(queue));
2466 return tcu::TestStatus::pass("Pass");
2470 tcu::TestStatus testFenceSignalWaitImport (Context& context,
2471 const FenceTestConfig config)
2473 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2474 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2475 const vk::InstanceDriver& vki (instance.getDriver());
2476 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2477 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2479 checkFenceSupport(vki, physicalDevice, config.externalType);
2482 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2483 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2484 const vk::DeviceDriver vkd (vkp, instance, *device);
2485 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2487 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2488 const vk::Unique<vk::VkFence> fenceB (createFence(vkd, *device));
2489 NativeHandle handle;
2491 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2493 submitEmptySignal(vkd, queue, *fenceB);
2494 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2496 VK_CHECK(vkd.queueWaitIdle(queue));
2498 importFence(vkd, *device, *fenceB, config.externalType, handle, flags);
2500 submitEmptySignal(vkd, queue, *fenceA);
2501 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2503 VK_CHECK(vkd.queueWaitIdle(queue));
2505 return tcu::TestStatus::pass("Pass");
2509 tcu::TestStatus testFenceMultipleExports (Context& context,
2510 const FenceTestConfig config)
2512 const size_t exportCount = 1024;
2513 const Transference transference (getHandelTypeTransferences(config.externalType));
2514 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2515 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2516 const vk::InstanceDriver& vki (instance.getDriver());
2517 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2518 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2520 checkFenceSupport(vki, physicalDevice, config.externalType);
2523 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2524 const vk::DeviceDriver vkd (vkp, instance, *device);
2525 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2526 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2527 const vk::Unique<vk::VkFence> fence (createExportableFence(vkd, *device, config.externalType));
2529 for (size_t exportNdx = 0; exportNdx < exportCount; exportNdx++)
2531 NativeHandle handle;
2533 // Need to touch watchdog due to how long one iteration takes
2534 context.getTestContext().touchWatchdog();
2536 if (transference == TRANSFERENCE_COPY)
2538 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fence, config.externalType, handle, exportNdx == 0 /* expect fence to be signaled after first pass */);
2539 if (handle.getFd() == -1)
2540 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2543 getFenceNative(vkd, *device, *fence, config.externalType, handle, exportNdx == 0 /* expect fence to be signaled after first pass */);
2546 submitEmptySignal(vkd, queue, *fence);
2547 VK_CHECK(vkd.waitForFences(*device, 1u, &*fence, VK_TRUE, ~0ull));
2549 VK_CHECK(vkd.queueWaitIdle(queue));
2552 return tcu::TestStatus::pass("Pass");
2555 tcu::TestStatus testFenceMultipleImports (Context& context,
2556 const FenceTestConfig config)
2558 const size_t importCount = 4 * 1024;
2559 const Transference transference (getHandelTypeTransferences(config.externalType));
2560 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2561 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2562 const vk::InstanceDriver& vki (instance.getDriver());
2563 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2564 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2566 checkFenceSupport(vki, physicalDevice, config.externalType);
2569 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2570 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2571 const vk::DeviceDriver vkd (vkp, instance, *device);
2572 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2573 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2574 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2575 NativeHandle handleA;
2577 if (transference == TRANSFERENCE_COPY)
2579 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, handleA);
2580 if (handleA.getFd() == -1)
2581 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2584 getFenceNative(vkd, *device, *fenceA, config.externalType, handleA);
2586 for (size_t importNdx = 0; importNdx < importCount; importNdx++)
2588 NativeHandle handleB (handleA);
2589 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handleB, flags));
2592 if (transference == TRANSFERENCE_COPY)
2594 importFence(vkd, *device, *fenceA, config.externalType, handleA, flags);
2595 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2597 else if (transference == TRANSFERENCE_REFERENCE)
2599 submitEmptySignal(vkd, queue, *fenceA);
2600 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2603 DE_FATAL("Unknown transference.");
2605 VK_CHECK(vkd.queueWaitIdle(queue));
2608 return tcu::TestStatus::pass("Pass");
2611 tcu::TestStatus testFenceTransference (Context& context,
2612 const FenceTestConfig config)
2614 const Transference transference (getHandelTypeTransferences(config.externalType));
2615 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2616 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2617 const vk::InstanceDriver& vki (instance.getDriver());
2618 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2619 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2621 checkFenceSupport(vki, physicalDevice, config.externalType);
2624 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2625 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2626 const vk::DeviceDriver vkd (vkp, instance, *device);
2627 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2628 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2630 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2631 NativeHandle handle;
2633 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, handle);
2634 if (handle.getFd() == -1)
2635 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2638 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, handle, flags));
2640 if (config.permanence == PERMANENCE_PERMANENT)
2642 if (transference == TRANSFERENCE_COPY)
2644 submitEmptySignal(vkd, queue, *fenceA);
2645 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2646 VK_CHECK(vkd.queueWaitIdle(queue));
2648 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2649 submitEmptySignal(vkd, queue, *fenceB);
2651 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2652 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2653 VK_CHECK(vkd.queueWaitIdle(queue));
2655 else if (transference== TRANSFERENCE_REFERENCE)
2657 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2658 VK_CHECK(vkd.queueWaitIdle(queue));
2660 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2661 submitEmptySignal(vkd, queue, *fenceA);
2662 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2664 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceA));
2665 submitEmptySignal(vkd, queue, *fenceB);
2666 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2667 VK_CHECK(vkd.queueWaitIdle(queue));
2670 DE_FATAL("Unknown transference.");
2672 else if (config.permanence == PERMANENCE_TEMPORARY)
2674 if (transference == TRANSFERENCE_COPY)
2676 submitEmptySignal(vkd, queue, *fenceA);
2677 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2678 VK_CHECK(vkd.queueWaitIdle(queue));
2680 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2681 submitEmptySignal(vkd, queue, *fenceB);
2683 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2684 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2685 VK_CHECK(vkd.queueWaitIdle(queue));
2687 else if (transference == TRANSFERENCE_REFERENCE)
2689 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2690 VK_CHECK(vkd.queueWaitIdle(queue));
2692 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceA));
2693 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2694 submitEmptySignal(vkd, queue, *fenceA);
2695 submitEmptySignal(vkd, queue, *fenceB);
2697 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2698 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2699 VK_CHECK(vkd.queueWaitIdle(queue));
2702 DE_FATAL("Unknown transference.");
2705 DE_FATAL("Unknown permanence.");
2708 return tcu::TestStatus::pass("Pass");
2712 tcu::TestStatus testFenceFdDup (Context& context,
2713 const FenceTestConfig config)
2715 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2716 const Transference transference (getHandelTypeTransferences(config.externalType));
2717 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2718 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2719 const vk::InstanceDriver& vki (instance.getDriver());
2720 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2721 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2723 checkFenceSupport(vki, physicalDevice, config.externalType);
2726 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2727 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2728 const vk::DeviceDriver vkd (vkp, instance, *device);
2729 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2730 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2732 TestLog& log = context.getTestContext().getLog();
2733 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2738 if (transference == TRANSFERENCE_COPY)
2740 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, fd);
2741 if (fd.getFd() == -1)
2742 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2745 getFenceNative(vkd, *device, *fenceA, config.externalType, fd);
2747 NativeHandle newFd (dup(fd.getFd()));
2749 if (newFd.getFd() < 0)
2750 log << TestLog::Message << "dup() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2752 TCU_CHECK_MSG(newFd.getFd() >= 0, "Failed to call dup() for fences fd");
2755 const vk::Unique<vk::VkFence> fenceB (createAndImportFence(vkd, *device, config.externalType, newFd, flags));
2757 if (transference == TRANSFERENCE_COPY)
2758 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2759 else if (transference == TRANSFERENCE_REFERENCE)
2761 submitEmptySignal(vkd, queue, *fenceA);
2762 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2765 DE_FATAL("Unknown permanence.");
2767 VK_CHECK(vkd.queueWaitIdle(queue));
2771 return tcu::TestStatus::pass("Pass");
2776 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
2780 tcu::TestStatus testFenceFdDup2 (Context& context,
2781 const FenceTestConfig config)
2783 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2784 const Transference transference (getHandelTypeTransferences(config.externalType));
2785 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2786 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2787 const vk::InstanceDriver& vki (instance.getDriver());
2788 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2789 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2791 checkFenceSupport(vki, physicalDevice, config.externalType);
2794 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2795 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2796 const vk::DeviceDriver vkd (vkp, instance, *device);
2797 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2798 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2800 TestLog& log = context.getTestContext().getLog();
2801 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2802 const vk::Unique<vk::VkFence> fenceB (createExportableFence(vkd, *device, config.externalType));
2805 NativeHandle fd, secondFd;
2807 if (transference == TRANSFERENCE_COPY)
2809 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, fd);
2810 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceB, config.externalType, secondFd);
2811 if (fd.getFd() == -1 || secondFd.getFd() == -1)
2812 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2816 getFenceNative(vkd, *device, *fenceA, config.externalType, fd);
2817 getFenceNative(vkd, *device, *fenceB, config.externalType, secondFd);
2820 int newFd (dup2(fd.getFd(), secondFd.getFd()));
2823 log << TestLog::Message << "dup2() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2825 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup2() for fences fd");
2828 const vk::Unique<vk::VkFence> fenceC (createAndImportFence(vkd, *device, config.externalType, secondFd, flags));
2830 if (transference == TRANSFERENCE_COPY)
2831 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2832 else if (transference == TRANSFERENCE_REFERENCE)
2834 submitEmptySignal(vkd, queue, *fenceA);
2835 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2838 DE_FATAL("Unknown permanence.");
2840 VK_CHECK(vkd.queueWaitIdle(queue));
2844 return tcu::TestStatus::pass("Pass");
2849 TCU_THROW(NotSupportedError, "Platform doesn't support dup2()");
2853 tcu::TestStatus testFenceFdDup3 (Context& context,
2854 const FenceTestConfig config)
2856 #if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
2857 const Transference transference (getHandelTypeTransferences(config.externalType));
2858 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2859 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2860 const vk::InstanceDriver& vki (instance.getDriver());
2861 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2862 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2864 checkFenceSupport(vki, physicalDevice, config.externalType);
2867 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2868 const vk::DeviceDriver vkd (vkp, instance, *device);
2869 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2870 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2872 TestLog& log = context.getTestContext().getLog();
2873 const vk::Unique<vk::VkFence> fenceA (createExportableFence(vkd, *device, config.externalType));
2874 const vk::Unique<vk::VkFence> fenceB (createExportableFence(vkd, *device, config.externalType));
2877 NativeHandle fd, secondFd;
2879 if (transference == TRANSFERENCE_COPY)
2881 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA, config.externalType, fd);
2882 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceB, config.externalType, secondFd);
2883 if (fd.getFd() == -1 || secondFd.getFd() == -1)
2884 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2888 getFenceNative(vkd, *device, *fenceA, config.externalType, fd);
2889 getFenceNative(vkd, *device, *fenceB, config.externalType, secondFd);
2892 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2893 const int newFd (dup3(fd.getFd(), secondFd.getFd(), 0));
2896 log << TestLog::Message << "dup3() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2898 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup3() for fences fd");
2901 const vk::Unique<vk::VkFence> fenceC (createAndImportFence(vkd, *device, config.externalType, secondFd, flags));
2903 if (transference == TRANSFERENCE_COPY)
2904 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2905 else if (transference == TRANSFERENCE_REFERENCE)
2907 submitEmptySignal(vkd, queue, *fenceA);
2908 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2911 DE_FATAL("Unknown permanence.");
2913 VK_CHECK(vkd.queueWaitIdle(queue));
2917 return tcu::TestStatus::pass("Pass");
2922 TCU_THROW(NotSupportedError, "Platform doesn't support dup3()");
2926 tcu::TestStatus testFenceFdSendOverSocket (Context& context,
2927 const FenceTestConfig config)
2929 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2930 const Transference transference (getHandelTypeTransferences(config.externalType));
2931 const vk::PlatformInterface& vkp (context.getPlatformInterface());
2932 const CustomInstance instance (createTestInstance(context, 0u, 0u, config.externalType));
2933 const vk::InstanceDriver& vki (instance.getDriver());
2934 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2935 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2937 checkFenceSupport(vki, physicalDevice, config.externalType);
2940 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u, config.externalType, queueFamilyIndex));
2941 const vk::DeviceDriver vkd (vkp, instance, *device);
2942 vk::SimpleAllocator alloc (vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2943 const vk::VkQueue queue (getQueue(vkd, *device, queueFamilyIndex));
2945 TestLog& log = context.getTestContext().getLog();
2946 const vk::Unique<vk::VkFence> fence (createExportableFence(vkd, *device, config.externalType));
2949 if (transference == TRANSFERENCE_COPY)
2951 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fence, config.externalType, fd);
2952 if (fd.getFd() == -1)
2953 return tcu::TestStatus::pass("Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2956 getFenceNative(vkd, *device, *fence, config.externalType, fd);
2961 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
2963 log << TestLog::Message << "Failed to create socket pair: '" << strerror(errno) << "'" << TestLog::EndMessage;
2964 TCU_FAIL("Failed to create socket pair");
2968 const NativeHandle srcSocket (sv[0]);
2969 const NativeHandle dstSocket (sv[1]);
2970 std::string sendData ("deqp");
2974 const int fdRaw (fd.getFd());
2977 char buffer[CMSG_SPACE(sizeof(int))];
2978 iovec iov = { &sendData[0], sendData.length()};
2980 deMemset(&msg, 0, sizeof(msg));
2982 msg.msg_control = buffer;
2983 msg.msg_controllen = sizeof(buffer);
2987 cmsg = CMSG_FIRSTHDR(&msg);
2988 cmsg->cmsg_level = SOL_SOCKET;
2989 cmsg->cmsg_type = SCM_RIGHTS;
2990 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
2992 deMemcpy(CMSG_DATA(cmsg), &fdRaw, sizeof(int));
2993 msg.msg_controllen = cmsg->cmsg_len;
2995 if (sendmsg(srcSocket.getFd(), &msg, 0) < 0)
2997 log << TestLog::Message << "Failed to send fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
2998 TCU_FAIL("Failed to send fd over socket");
3005 char buffer[CMSG_SPACE(sizeof(int))];
3006 std::string recvData (4, '\0');
3007 iovec iov = { &recvData[0], recvData.length() };
3009 deMemset(&msg, 0, sizeof(msg));
3011 msg.msg_control = buffer;
3012 msg.msg_controllen = sizeof(buffer);
3016 const ssize_t bytes = recvmsg(dstSocket.getFd(), &msg, 0);
3020 log << TestLog::Message << "Failed to recv fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
3021 TCU_FAIL("Failed to recv fd over socket");
3024 else if (bytes != (ssize_t)sendData.length())
3026 TCU_FAIL("recvmsg() returned unpexpected number of bytes");
3030 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
3031 const cmsghdr* const cmsg = CMSG_FIRSTHDR(&msg);
3033 deMemcpy(&newFd_, CMSG_DATA(cmsg), sizeof(int));
3034 NativeHandle newFd (newFd_);
3036 TCU_CHECK(cmsg->cmsg_level == SOL_SOCKET);
3037 TCU_CHECK(cmsg->cmsg_type == SCM_RIGHTS);
3038 TCU_CHECK(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
3039 TCU_CHECK(recvData == sendData);
3040 TCU_CHECK_MSG(newFd.getFd() >= 0, "Didn't receive valid fd from socket");
3043 const vk::Unique<vk::VkFence> newFence (createAndImportFence(vkd, *device, config.externalType, newFd, flags));
3045 if (transference == TRANSFERENCE_COPY)
3046 VK_CHECK(vkd.waitForFences(*device, 1u, &*newFence, VK_TRUE, ~0ull));
3047 else if (transference == TRANSFERENCE_REFERENCE)
3049 submitEmptySignal(vkd, queue, *newFence);
3050 VK_CHECK(vkd.waitForFences(*device, 1u, &*newFence, VK_TRUE, ~0ull));
3053 DE_FATAL("Unknown permanence.");
3055 VK_CHECK(vkd.queueWaitIdle(queue));
3063 return tcu::TestStatus::pass("Pass");
3067 TCU_THROW(NotSupportedError, "Platform doesn't support sending file descriptors over socket");
3071 tcu::TestStatus testBufferQueries (Context& context, vk::VkExternalMemoryHandleTypeFlagBits externalType)
3073 const vk::VkBufferCreateFlags createFlags[] =
3076 vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT,
3077 vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT|vk::VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT,
3078 vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT|vk::VK_BUFFER_CREATE_SPARSE_ALIASED_BIT
3080 const vk::VkBufferUsageFlags usageFlags[] =
3082 vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
3083 vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT,
3084 vk::VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT,
3085 vk::VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT,
3086 vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
3087 vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
3088 vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT,
3089 vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
3090 vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT
3092 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3093 const CustomInstance instance (createTestInstance(context, 0u, externalType, 0u));
3094 const vk::InstanceDriver& vki (instance.getDriver());
3095 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3096 const vk::VkPhysicalDeviceFeatures deviceFeatures (vk::getPhysicalDeviceFeatures(vki, physicalDevice));
3097 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3099 // VkDevice is only created if physical device claims to support any of these types.
3100 vk::Move<vk::VkDevice> device;
3101 de::MovePtr<vk::DeviceDriver> vkd;
3102 bool deviceHasDedicated = false;
3104 TestLog& log = context.getTestContext().getLog();
3106 for (size_t createFlagNdx = 0; createFlagNdx < DE_LENGTH_OF_ARRAY(createFlags); createFlagNdx++)
3107 for (size_t usageFlagNdx = 0; usageFlagNdx < DE_LENGTH_OF_ARRAY(usageFlags); usageFlagNdx++)
3109 const vk::VkBufferViewCreateFlags createFlag = createFlags[createFlagNdx];
3110 const vk::VkBufferUsageFlags usageFlag = usageFlags[usageFlagNdx];
3111 const vk::VkPhysicalDeviceExternalBufferInfo info =
3113 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO,
3119 vk::VkExternalBufferProperties properties =
3121 vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES,
3126 if (((createFlag & vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT) != 0) &&
3127 (deviceFeatures.sparseBinding == VK_FALSE))
3130 if (((createFlag & vk::VK_BUFFER_CREATE_SPARSE_ALIASED_BIT) != 0) &&
3131 (deviceFeatures.sparseResidencyAliased == VK_FALSE))
3134 if (((createFlag & vk::VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT) != 0) &&
3135 (deviceFeatures.sparseResidencyBuffer == VK_FALSE))
3138 vki.getPhysicalDeviceExternalBufferProperties(physicalDevice, &info, &properties);
3140 log << TestLog::Message << properties << TestLog::EndMessage;
3142 TCU_CHECK(properties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES);
3143 TCU_CHECK(properties.pNext == DE_NULL);
3144 // \todo [2017-06-06 pyry] Can we validate anything else? Compatible types?
3146 if ((properties.externalMemoryProperties.externalMemoryFeatures & (vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT|vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT)) != 0)
3148 const bool requiresDedicated = (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
3150 if (!device || (requiresDedicated && !deviceHasDedicated))
3152 // \note We need to re-create with dedicated mem extensions if previous device instance didn't have them
3155 device = createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, externalType, 0u, queueFamilyIndex, requiresDedicated);
3156 vkd = de::MovePtr<vk::DeviceDriver>(new vk::DeviceDriver(vkp, instance, *device));
3157 deviceHasDedicated = requiresDedicated;
3159 catch (const tcu::NotSupportedError& e)
3162 TCU_FAIL("Physical device claims to support handle type but required extensions are not supported");
3167 if ((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) != 0)
3169 DE_ASSERT(!!device);
3172 if (deviceHasDedicated)
3174 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(*vkd, *device, queueFamilyIndex, externalType, 1024u, createFlag, usageFlag));
3175 const vk::VkMemoryDedicatedRequirements reqs (getMemoryDedicatedRequirements(*vkd, *device, *buffer));
3176 const bool propertiesRequiresDedicated = (properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
3177 const bool objectRequiresDedicated = (reqs.requiresDedicatedAllocation != VK_FALSE);
3179 if (propertiesRequiresDedicated != objectRequiresDedicated)
3180 TCU_FAIL("vkGetPhysicalDeviceExternalBufferProperties and vkGetBufferMemoryRequirements2 report different dedicated requirements");
3184 // We can't query whether dedicated memory is required or not on per-object basis.
3185 // This check should be redundant as the code above tries to create device with
3186 // VK_KHR_dedicated_allocation & VK_KHR_get_memory_requirements2 if dedicated memory
3187 // is required. However, checking again doesn't hurt.
3188 TCU_CHECK((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) == 0);
3193 return tcu::TestStatus::pass("Pass");
3196 struct MemoryTestConfig
3198 MemoryTestConfig (vk::VkExternalMemoryHandleTypeFlagBits externalType_,
3201 : externalType (externalType_)
3202 , hostVisible (hostVisible_)
3203 , dedicated (dedicated_)
3207 vk::VkExternalMemoryHandleTypeFlagBits externalType;
3212 #if (DE_OS == DE_OS_WIN32)
3213 deUint32 chooseWin32MemoryType(deUint32 bits)
3216 TCU_THROW(NotSupportedError, "No compatible memory type found");
3218 return deCtz32(bits);
3222 tcu::TestStatus testMemoryWin32Create (Context& context, MemoryTestConfig config)
3224 #if (DE_OS == DE_OS_WIN32)
3225 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3226 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3227 const vk::InstanceDriver& vki (instance.getDriver());
3228 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3229 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3230 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3231 const vk::DeviceDriver vkd (vkp, instance, *device);
3232 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3233 const deUint32 seed = 1261033864u;
3234 const vk::VkDeviceSize bufferSize = 1024;
3235 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
3237 const vk::VkPhysicalDeviceMemoryProperties memoryProps = vk::getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice());
3238 const deUint32 compatibleMemTypes = vk::getCompatibleMemoryTypes(memoryProps, config.hostVisible ? vk::MemoryRequirement::HostVisible : vk::MemoryRequirement::Any);
3240 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3242 // \note Buffer is only allocated to get memory requirements
3243 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3244 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3245 const vk::VkExportMemoryWin32HandleInfoKHR win32Info =
3247 vk::VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR,
3250 (vk::pt::Win32SecurityAttributesPtr)DE_NULL,
3251 DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
3252 (vk::pt::Win32LPCWSTR)DE_NULL
3254 const vk::VkExportMemoryAllocateInfo exportInfo =
3256 vk::VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
3258 (vk::VkExternalMemoryHandleTypeFlags)config.externalType
3261 const deUint32 exportedMemoryTypeIndex = chooseWin32MemoryType(requirements.memoryTypeBits & compatibleMemTypes);
3262 const vk::VkMemoryAllocateInfo info =
3264 vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
3267 exportedMemoryTypeIndex
3269 const vk::Unique<vk::VkDeviceMemory> memory (vk::allocateMemory(vkd, *device, &info));
3270 NativeHandle handleA;
3272 if (config.hostVisible)
3273 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3275 getMemoryNative(vkd, *device, *memory, config.externalType, handleA);
3278 const vk::Unique<vk::VkDeviceMemory> memoryA (importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleA));
3280 if (config.hostVisible)
3282 const std::vector<deUint8> testDataA (genTestData(seed ^ 124798807u, (size_t)bufferSize));
3283 const std::vector<deUint8> testDataB (genTestData(seed ^ 970834278u, (size_t)bufferSize));
3285 checkHostMemory(vkd, *device, *memoryA, testData.size(), &testData[0]);
3286 checkHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3288 writeHostMemory(vkd, *device, *memoryA, testDataA.size(), &testDataA[0]);
3289 writeHostMemory(vkd, *device, *memory, testDataA.size(), &testDataB[0]);
3291 checkHostMemory(vkd, *device, *memoryA, testData.size(), &testDataB[0]);
3292 checkHostMemory(vkd, *device, *memory, testData.size(), &testDataB[0]);
3296 return tcu::TestStatus::pass("Pass");
3300 TCU_THROW(NotSupportedError, "Platform doesn't support win32 handles");
3304 deUint32 getExportedMemoryTypeIndex(const vk::InstanceDriver& vki, const vk::VkPhysicalDevice physicalDevice, bool hostVisible, deUint32 memoryBits)
3308 const vk::VkPhysicalDeviceMemoryProperties properties(vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
3309 return chooseHostVisibleMemoryType(memoryBits, properties);
3312 return chooseMemoryType(memoryBits);
3315 tcu::TestStatus testMemoryImportTwice (Context& context, MemoryTestConfig config)
3317 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3318 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3319 const vk::InstanceDriver& vki (instance.getDriver());
3320 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3321 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3322 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3323 const vk::DeviceDriver vkd (vkp, instance, *device);
3324 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3325 const deUint32 seed = 1261033864u;
3326 const vk::VkDeviceSize bufferSize = 1024;
3327 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
3329 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3331 // \note Buffer is only allocated to get memory requirements
3332 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3333 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3334 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3335 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3336 NativeHandle handleA;
3338 if (config.hostVisible)
3339 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3341 getMemoryNative(vkd, *device, *memory, config.externalType, handleA);
3344 const vk::Unique<vk::VkBuffer> bufferA (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3345 const vk::Unique<vk::VkBuffer> bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3346 NativeHandle handleB (handleA);
3347 const vk::Unique<vk::VkDeviceMemory> memoryA (config.dedicated
3348 ? importDedicatedMemory(vkd, *device, *bufferA, requirements, config.externalType, exportedMemoryTypeIndex, handleA)
3349 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleA));
3350 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3351 ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handleB)
3352 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleB));
3354 if (config.hostVisible)
3356 const std::vector<deUint8> testDataA (genTestData(seed ^ 124798807u, (size_t)bufferSize));
3357 const std::vector<deUint8> testDataB (genTestData(seed ^ 970834278u, (size_t)bufferSize));
3359 checkHostMemory(vkd, *device, *memoryA, testData.size(), &testData[0]);
3360 checkHostMemory(vkd, *device, *memoryB, testData.size(), &testData[0]);
3362 writeHostMemory(vkd, *device, *memoryA, testData.size(), &testDataA[0]);
3363 writeHostMemory(vkd, *device, *memoryB, testData.size(), &testDataB[0]);
3365 checkHostMemory(vkd, *device, *memoryA, testData.size(), &testDataB[0]);
3366 checkHostMemory(vkd, *device, *memory, testData.size(), &testDataB[0]);
3370 return tcu::TestStatus::pass("Pass");
3373 tcu::TestStatus testMemoryMultipleImports (Context& context, MemoryTestConfig config)
3375 const size_t count = 4 * 1024;
3376 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3377 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3378 const vk::InstanceDriver& vki (instance.getDriver());
3379 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3380 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3381 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3382 const vk::DeviceDriver vkd (vkp, instance, *device);
3383 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3384 const vk::VkDeviceSize bufferSize = 1024;
3386 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3388 // \note Buffer is only allocated to get memory requirements
3389 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3390 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3391 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3392 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3393 NativeHandle handleA;
3395 getMemoryNative(vkd, *device, *memory, config.externalType, handleA);
3397 for (size_t ndx = 0; ndx < count; ndx++)
3399 const vk::Unique<vk::VkBuffer> bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3400 NativeHandle handleB (handleA);
3401 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3402 ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handleB)
3403 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleB));
3406 return tcu::TestStatus::pass("Pass");
3409 tcu::TestStatus testMemoryMultipleExports (Context& context, MemoryTestConfig config)
3411 const size_t count = 4 * 1024;
3412 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3413 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3414 const vk::InstanceDriver& vki (instance.getDriver());
3415 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3416 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3417 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3418 const vk::DeviceDriver vkd (vkp, instance, *device);
3419 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3420 const vk::VkDeviceSize bufferSize = 1024;
3422 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3424 // \note Buffer is only allocated to get memory requirements
3425 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3426 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3427 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3428 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3430 for (size_t ndx = 0; ndx < count; ndx++)
3432 NativeHandle handle;
3433 getMemoryNative(vkd, *device, *memory, config.externalType, handle);
3436 return tcu::TestStatus::pass("Pass");
3439 tcu::TestStatus testMemoryFdProperties (Context& context, MemoryTestConfig config)
3441 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3442 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3443 const vk::InstanceDriver& vki (instance.getDriver());
3444 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3445 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3446 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3447 const vk::DeviceDriver vkd (vkp, instance, *device);
3448 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3449 const vk::VkDeviceSize bufferSize = 1024;
3451 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3453 // \note Buffer is only allocated to get memory requirements
3454 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3455 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3456 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3457 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3459 vk::VkMemoryFdPropertiesKHR properties;
3460 NativeHandle handle;
3462 getMemoryNative(vkd, *device, *memory, config.externalType, handle);
3463 properties.sType = vk::VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR;
3464 vk::VkResult res = vkd.getMemoryFdPropertiesKHR(*device, config.externalType, handle.getFd(), &properties);
3466 switch (config.externalType)
3468 case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
3469 TCU_CHECK_MSG(res == vk::VK_SUCCESS, "vkGetMemoryFdPropertiesKHR failed for VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT");
3472 // Invalid external memory type for this test.
3477 return tcu::TestStatus::pass("Pass");
3480 tcu::TestStatus testMemoryFdDup (Context& context, MemoryTestConfig config)
3482 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
3483 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3484 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3485 const vk::InstanceDriver& vki (instance.getDriver());
3486 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3487 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3490 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3491 const vk::DeviceDriver vkd (vkp, instance, *device);
3493 TestLog& log = context.getTestContext().getLog();
3494 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3495 const vk::VkDeviceSize bufferSize = 1024;
3496 const deUint32 seed = 851493858u;
3497 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
3499 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3501 // \note Buffer is only allocated to get memory requirements
3502 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3503 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3504 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3505 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3507 if (config.hostVisible)
3508 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3510 const NativeHandle fd (getMemoryFd(vkd, *device, *memory, config.externalType));
3511 NativeHandle newFd (dup(fd.getFd()));
3513 if (newFd.getFd() < 0)
3514 log << TestLog::Message << "dup() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
3516 TCU_CHECK_MSG(newFd.getFd() >= 0, "Failed to call dup() for memorys fd");
3519 const vk::Unique<vk::VkBuffer> newBuffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3520 const vk::Unique<vk::VkDeviceMemory> newMemory (config.dedicated
3521 ? importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType, exportedMemoryTypeIndex, newFd)
3522 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, newFd));
3524 if (config.hostVisible)
3526 const std::vector<deUint8> testDataA (genTestData(seed ^ 672929437u, (size_t)bufferSize));
3528 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3530 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3531 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3535 return tcu::TestStatus::pass("Pass");
3540 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
3544 tcu::TestStatus testMemoryFdDup2 (Context& context, MemoryTestConfig config)
3546 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
3547 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3548 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3549 const vk::InstanceDriver& vki (instance.getDriver());
3550 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3551 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3554 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3555 const vk::DeviceDriver vkd (vkp, instance, *device);
3557 TestLog& log = context.getTestContext().getLog();
3558 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3559 const vk::VkDeviceSize bufferSize = 1024;
3560 const deUint32 seed = 224466865u;
3561 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
3563 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3565 // \note Buffer is only allocated to get memory requirements
3566 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3567 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3568 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3569 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3571 if (config.hostVisible)
3572 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3574 const NativeHandle fd (getMemoryFd(vkd, *device, *memory, config.externalType));
3575 NativeHandle secondFd (getMemoryFd(vkd, *device, *memory, config.externalType));
3576 const int newFd (dup2(fd.getFd(), secondFd.getFd()));
3579 log << TestLog::Message << "dup2() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
3581 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup2() for memorys fd");
3584 const vk::Unique<vk::VkBuffer> newBuffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3585 const vk::Unique<vk::VkDeviceMemory> newMemory (config.dedicated
3586 ? importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType, exportedMemoryTypeIndex, secondFd)
3587 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, secondFd));
3589 if (config.hostVisible)
3591 const std::vector<deUint8> testDataA (genTestData(seed ^ 99012346u, (size_t)bufferSize));
3593 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3595 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3596 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3600 return tcu::TestStatus::pass("Pass");
3605 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
3609 tcu::TestStatus testMemoryFdDup3 (Context& context, MemoryTestConfig config)
3611 #if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
3612 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3613 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3614 const vk::InstanceDriver& vki (instance.getDriver());
3615 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3616 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3619 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3620 const vk::DeviceDriver vkd (vkp, instance, *device);
3622 TestLog& log = context.getTestContext().getLog();
3623 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3624 const vk::VkDeviceSize bufferSize = 1024;
3625 const deUint32 seed = 2554088961u;
3626 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
3628 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3630 // \note Buffer is only allocated to get memory requirements
3631 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3632 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3633 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3634 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3636 if (config.hostVisible)
3637 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3639 const NativeHandle fd (getMemoryFd(vkd, *device, *memory, config.externalType));
3640 NativeHandle secondFd (getMemoryFd(vkd, *device, *memory, config.externalType));
3641 const int newFd (dup3(fd.getFd(), secondFd.getFd(), 0));
3644 log << TestLog::Message << "dup3() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
3646 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup3() for memorys fd");
3649 const vk::Unique<vk::VkBuffer> newBuffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3650 const vk::Unique<vk::VkDeviceMemory> newMemory (config.dedicated
3651 ? importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType, exportedMemoryTypeIndex, secondFd)
3652 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, secondFd));
3654 if (config.hostVisible)
3656 const std::vector<deUint8> testDataA (genTestData(seed ^ 4210342378u, (size_t)bufferSize));
3658 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3660 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3661 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3665 return tcu::TestStatus::pass("Pass");
3670 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
3674 tcu::TestStatus testMemoryFdSendOverSocket (Context& context, MemoryTestConfig config)
3676 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
3677 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3678 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3679 const vk::InstanceDriver& vki (instance.getDriver());
3680 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3681 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3684 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3685 const vk::DeviceDriver vkd (vkp, instance, *device);
3687 TestLog& log = context.getTestContext().getLog();
3688 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3689 const vk::VkDeviceSize bufferSize = 1024;
3690 const deUint32 seed = 3403586456u;
3691 const std::vector<deUint8> testData (genTestData(seed, (size_t)bufferSize));
3693 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3695 // \note Buffer is only allocated to get memory requirements
3696 const vk::Unique<vk::VkBuffer> buffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3697 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *buffer));
3698 const deUint32 exportedMemoryTypeIndex (getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3699 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *buffer : (vk::VkBuffer)0));
3701 if (config.hostVisible)
3702 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3704 const NativeHandle fd (getMemoryFd(vkd, *device, *memory, config.externalType));
3709 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
3711 log << TestLog::Message << "Failed to create socket pair: '" << strerror(errno) << "'" << TestLog::EndMessage;
3712 TCU_FAIL("Failed to create socket pair");
3716 const NativeHandle srcSocket (sv[0]);
3717 const NativeHandle dstSocket (sv[1]);
3718 std::string sendData ("deqp");
3722 const int fdRaw (fd.getFd());
3725 char tmpBuffer[CMSG_SPACE(sizeof(int))];
3726 iovec iov = { &sendData[0], sendData.length()};
3728 deMemset(&msg, 0, sizeof(msg));
3730 msg.msg_control = tmpBuffer;
3731 msg.msg_controllen = sizeof(tmpBuffer);
3735 cmsg = CMSG_FIRSTHDR(&msg);
3736 cmsg->cmsg_level = SOL_SOCKET;
3737 cmsg->cmsg_type = SCM_RIGHTS;
3738 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
3740 deMemcpy(CMSG_DATA(cmsg), &fdRaw, sizeof(int));
3741 msg.msg_controllen = cmsg->cmsg_len;
3743 if (sendmsg(srcSocket.getFd(), &msg, 0) < 0)
3745 log << TestLog::Message << "Failed to send fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
3746 TCU_FAIL("Failed to send fd over socket");
3753 char tmpBuffer[CMSG_SPACE(sizeof(int))];
3754 std::string recvData (4, '\0');
3755 iovec iov = { &recvData[0], recvData.length() };
3757 deMemset(&msg, 0, sizeof(msg));
3759 msg.msg_control = tmpBuffer;
3760 msg.msg_controllen = sizeof(tmpBuffer);
3764 const ssize_t bytes = recvmsg(dstSocket.getFd(), &msg, 0);
3768 log << TestLog::Message << "Failed to recv fd over socket: '" << strerror(errno) << "'" << TestLog::EndMessage;
3769 TCU_FAIL("Failed to recv fd over socket");
3772 else if (bytes != (ssize_t)sendData.length())
3774 TCU_FAIL("recvmsg() returned unpexpected number of bytes");
3778 const cmsghdr* const cmsg = CMSG_FIRSTHDR(&msg);
3780 deMemcpy(&newFd_, CMSG_DATA(cmsg), sizeof(int));
3781 NativeHandle newFd (newFd_);
3783 TCU_CHECK(cmsg->cmsg_level == SOL_SOCKET);
3784 TCU_CHECK(cmsg->cmsg_type == SCM_RIGHTS);
3785 TCU_CHECK(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
3786 TCU_CHECK(recvData == sendData);
3787 TCU_CHECK_MSG(newFd.getFd() >= 0, "Didn't receive valid fd from socket");
3790 const vk::Unique<vk::VkBuffer> newBuffer (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3791 const vk::Unique<vk::VkDeviceMemory> newMemory (config.dedicated
3792 ? importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType, exportedMemoryTypeIndex, newFd)
3793 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, newFd));
3795 if (config.hostVisible)
3797 const std::vector<deUint8> testDataA (genTestData(seed ^ 23478978u, (size_t)bufferSize));
3799 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3801 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3802 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3811 return tcu::TestStatus::pass("Pass");
3815 TCU_THROW(NotSupportedError, "Platform doesn't support sending file descriptors over socket");
3819 struct BufferTestConfig
3821 BufferTestConfig (vk::VkExternalMemoryHandleTypeFlagBits externalType_,
3823 : externalType (externalType_)
3824 , dedicated (dedicated_)
3828 vk::VkExternalMemoryHandleTypeFlagBits externalType;
3832 tcu::TestStatus testBufferBindExportImportBind (Context& context,
3833 const BufferTestConfig config)
3835 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3836 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3837 const vk::InstanceDriver& vki (instance.getDriver());
3838 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3839 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3840 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3841 const vk::DeviceDriver vkd (vkp, instance, *device);
3842 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3843 const vk::VkDeviceSize bufferSize = 1024;
3845 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3847 // \note Buffer is only allocated to get memory requirements
3848 const vk::Unique<vk::VkBuffer> bufferA (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3849 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *bufferA));
3850 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
3851 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *bufferA : (vk::VkBuffer)0));
3852 NativeHandle handle;
3854 VK_CHECK(vkd.bindBufferMemory(*device, *bufferA, *memoryA, 0u));
3856 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3859 const vk::Unique<vk::VkBuffer> bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3860 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3861 ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handle)
3862 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3864 VK_CHECK(vkd.bindBufferMemory(*device, *bufferB, *memoryB, 0u));
3867 return tcu::TestStatus::pass("Pass");
3870 tcu::TestStatus testBufferExportBindImportBind (Context& context,
3871 const BufferTestConfig config)
3873 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3874 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3875 const vk::InstanceDriver& vki (instance.getDriver());
3876 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3877 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3878 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3879 const vk::DeviceDriver vkd (vkp, instance, *device);
3880 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3881 const vk::VkDeviceSize bufferSize = 1024;
3883 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3885 // \note Buffer is only allocated to get memory requirements
3886 const vk::Unique<vk::VkBuffer> bufferA (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3887 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *bufferA));
3888 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
3889 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *bufferA : (vk::VkBuffer)0));
3890 NativeHandle handle;
3892 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3893 VK_CHECK(vkd.bindBufferMemory(*device, *bufferA, *memoryA, 0u));
3896 const vk::Unique<vk::VkBuffer> bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3897 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3898 ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handle)
3899 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3901 VK_CHECK(vkd.bindBufferMemory(*device, *bufferB, *memoryB, 0u));
3904 return tcu::TestStatus::pass("Pass");
3907 tcu::TestStatus testBufferExportImportBindBind (Context& context,
3908 const BufferTestConfig config)
3910 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3911 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
3912 const vk::InstanceDriver& vki (instance.getDriver());
3913 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3914 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3915 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
3916 const vk::DeviceDriver vkd (vkp, instance, *device);
3917 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT|vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3918 const vk::VkDeviceSize bufferSize = 1024;
3920 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3922 // \note Buffer is only allocated to get memory requirements
3923 const vk::Unique<vk::VkBuffer> bufferA (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3924 const vk::VkMemoryRequirements requirements (getBufferMemoryRequirements(vkd, *device, *bufferA));
3925 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
3926 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *bufferA : (vk::VkBuffer)0));
3927 NativeHandle handle;
3929 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
3932 const vk::Unique<vk::VkBuffer> bufferB (createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3933 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
3934 ? importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType, exportedMemoryTypeIndex, handle)
3935 : importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
3937 VK_CHECK(vkd.bindBufferMemory(*device, *bufferA, *memoryA, 0u));
3938 VK_CHECK(vkd.bindBufferMemory(*device, *bufferB, *memoryB, 0u));
3941 return tcu::TestStatus::pass("Pass");
3944 tcu::TestStatus testImageQueries (Context& context, vk::VkExternalMemoryHandleTypeFlagBits externalType)
3946 const vk::VkImageCreateFlags createFlags[] =
3949 vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT,
3950 vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT|vk::VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT,
3951 vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT|vk::VK_IMAGE_CREATE_SPARSE_ALIASED_BIT,
3952 vk::VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT,
3953 vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT
3955 const vk::VkImageUsageFlags usageFlags[] =
3957 vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
3958 vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT,
3959 vk::VK_IMAGE_USAGE_SAMPLED_BIT,
3960 vk::VK_IMAGE_USAGE_STORAGE_BIT,
3961 vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
3962 vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
3963 vk::VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
3964 vk::VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
3965 vk::VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT,
3966 vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT
3968 const vk::PlatformInterface& vkp (context.getPlatformInterface());
3969 const CustomInstance instance (createTestInstance(context, 0u, externalType, 0u));
3970 const vk::InstanceDriver& vki (instance.getDriver());
3971 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3972 const vk::VkPhysicalDeviceFeatures deviceFeatures (vk::getPhysicalDeviceFeatures(vki, physicalDevice));
3973 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3975 // VkDevice is only created if physical device claims to support any of these types.
3976 vk::Move<vk::VkDevice> device;
3977 de::MovePtr<vk::DeviceDriver> vkd;
3978 bool deviceHasDedicated = false;
3980 TestLog& log = context.getTestContext().getLog();
3982 for (size_t createFlagNdx = 0; createFlagNdx < DE_LENGTH_OF_ARRAY(createFlags); createFlagNdx++)
3983 for (size_t usageFlagNdx = 0; usageFlagNdx < DE_LENGTH_OF_ARRAY(usageFlags); usageFlagNdx++)
3985 const vk::VkImageViewCreateFlags createFlag = createFlags[createFlagNdx];
3986 const vk::VkImageUsageFlags usageFlag = usageFlags[usageFlagNdx];
3987 const vk::VkFormat format =
3988 (usageFlags[usageFlagNdx] & vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? vk::VK_FORMAT_D16_UNORM : vk::VK_FORMAT_R8G8B8A8_UNORM;
3989 const vk::VkImageType type = vk::VK_IMAGE_TYPE_2D;
3990 const vk::VkImageTiling tiling = vk::VK_IMAGE_TILING_OPTIMAL;
3991 const vk::VkPhysicalDeviceExternalImageFormatInfo externalInfo =
3993 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
3997 const vk::VkPhysicalDeviceImageFormatInfo2 info =
3999 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
4008 vk::VkExternalImageFormatProperties externalProperties =
4010 vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES,
4014 vk::VkImageFormatProperties2 properties =
4016 vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
4017 &externalProperties,
4027 if (((createFlag & vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT) != 0) &&
4028 (deviceFeatures.sparseBinding == VK_FALSE))
4031 if (((createFlag & vk::VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT) != 0) &&
4032 (deviceFeatures.sparseResidencyImage2D == VK_FALSE))
4035 if (((createFlag & vk::VK_IMAGE_CREATE_SPARSE_ALIASED_BIT) != 0) &&
4036 (deviceFeatures.sparseResidencyAliased == VK_FALSE))
4039 if (vki.getPhysicalDeviceImageFormatProperties2(physicalDevice, &info, &properties) == vk::VK_ERROR_FORMAT_NOT_SUPPORTED) {
4043 log << TestLog::Message << externalProperties << TestLog::EndMessage;
4044 TCU_CHECK(externalProperties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES);
4045 TCU_CHECK(externalProperties.pNext == DE_NULL);
4046 // \todo [2017-06-06 pyry] Can we validate anything else? Compatible types?
4048 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & (vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT|vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT)) != 0)
4050 const bool requiresDedicated = (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
4052 if (!device || (requiresDedicated && !deviceHasDedicated))
4054 // \note We need to re-create with dedicated mem extensions if previous device instance didn't have them
4057 device = createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, externalType, 0u, queueFamilyIndex, requiresDedicated);
4058 vkd = de::MovePtr<vk::DeviceDriver>(new vk::DeviceDriver(vkp, instance, *device));
4059 deviceHasDedicated = requiresDedicated;
4061 catch (const tcu::NotSupportedError& e)
4064 TCU_FAIL("Physical device claims to support handle type but required extensions are not supported");
4069 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) != 0)
4071 DE_ASSERT(!!device);
4074 if (deviceHasDedicated)
4076 // Memory requirements cannot be queried without binding the image.
4077 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
4080 const vk::Unique<vk::VkImage> image (createExternalImage(*vkd, *device, queueFamilyIndex, externalType, format, 16u, 16u, tiling, createFlag, usageFlag));
4081 const vk::VkMemoryDedicatedRequirements reqs (getMemoryDedicatedRequirements(*vkd, *device, *image));
4082 const bool propertiesRequiresDedicated = (externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
4083 const bool objectRequiresDedicated = (reqs.requiresDedicatedAllocation != VK_FALSE);
4085 if (propertiesRequiresDedicated != objectRequiresDedicated)
4086 TCU_FAIL("vkGetPhysicalDeviceExternalBufferProperties and vkGetBufferMemoryRequirements2 report different dedicated requirements");
4090 // We can't query whether dedicated memory is required or not on per-object basis.
4091 // This check should be redundant as the code above tries to create device with
4092 // VK_KHR_dedicated_allocation & VK_KHR_get_memory_requirements2 if dedicated memory
4093 // is required. However, checking again doesn't hurt.
4094 TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) == 0);
4099 return tcu::TestStatus::pass("Pass");
4102 struct ImageTestConfig
4104 ImageTestConfig (vk::VkExternalMemoryHandleTypeFlagBits externalType_,
4106 : externalType (externalType_)
4107 , dedicated (dedicated_)
4111 vk::VkExternalMemoryHandleTypeFlagBits externalType;
4115 tcu::TestStatus testImageBindExportImportBind (Context& context,
4116 const ImageTestConfig config)
4118 const vk::PlatformInterface& vkp (context.getPlatformInterface());
4119 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
4120 const vk::InstanceDriver& vki (instance.getDriver());
4121 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
4122 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
4123 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
4124 const vk::DeviceDriver vkd (vkp, instance, *device);
4125 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);
4126 const vk::VkFormat format = vk::VK_FORMAT_R8G8B8A8_UNORM;
4127 const deUint32 width = 64u;
4128 const deUint32 height = 64u;
4129 const vk::VkImageTiling tiling = vk::VK_IMAGE_TILING_OPTIMAL;
4131 checkImageSupport(vki, physicalDevice, config.externalType, 0u, usage, format, tiling, config.dedicated);
4133 const vk::Unique<vk::VkImage> imageA (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
4134 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *imageA, config.externalType));
4135 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
4136 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *imageA : (vk::VkImage)0));
4137 NativeHandle handle;
4139 VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
4141 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
4144 const vk::Unique<vk::VkImage> imageB (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
4145 const deUint32 idx = config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID ? ~0u : exportedMemoryTypeIndex;
4146 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
4147 ? importDedicatedMemory(vkd, *device, *imageB, requirements, config.externalType, idx, handle)
4148 : importMemory(vkd, *device, requirements, config.externalType, idx, handle));
4150 VK_CHECK(vkd.bindImageMemory(*device, *imageB, *memoryB, 0u));
4153 return tcu::TestStatus::pass("Pass");
4156 tcu::TestStatus testImageExportBindImportBind (Context& context,
4157 const ImageTestConfig config)
4159 const vk::PlatformInterface& vkp (context.getPlatformInterface());
4160 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
4161 const vk::InstanceDriver& vki (instance.getDriver());
4162 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
4163 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
4164 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
4165 const vk::DeviceDriver vkd (vkp, instance, *device);
4166 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);
4167 const vk::VkFormat format = vk::VK_FORMAT_R8G8B8A8_UNORM;
4168 const deUint32 width = 64u;
4169 const deUint32 height = 64u;
4170 const vk::VkImageTiling tiling = vk::VK_IMAGE_TILING_OPTIMAL;
4172 checkImageSupport(vki, physicalDevice, config.externalType, 0u, usage, format, tiling, config.dedicated);
4174 const vk::Unique<vk::VkImage> imageA (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
4175 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *imageA, config.externalType));
4176 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
4177 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *imageA : (vk::VkImage)0));
4178 NativeHandle handle;
4180 if (config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID && config.dedicated)
4182 // AHB required the image memory to be bound first.
4183 VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
4184 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
4188 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
4189 VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
4193 const vk::Unique<vk::VkImage> imageB (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
4194 const deUint32 idx = config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID ? ~0u : exportedMemoryTypeIndex;
4195 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
4196 ? importDedicatedMemory(vkd, *device, *imageB, requirements, config.externalType, idx, handle)
4197 : importMemory(vkd, *device, requirements, config.externalType, idx, handle));
4199 VK_CHECK(vkd.bindImageMemory(*device, *imageB, *memoryB, 0u));
4202 return tcu::TestStatus::pass("Pass");
4205 tcu::TestStatus testImageExportImportBindBind (Context& context,
4206 const ImageTestConfig config)
4208 const vk::PlatformInterface& vkp (context.getPlatformInterface());
4209 const CustomInstance instance (createTestInstance(context, 0u, config.externalType, 0u));
4210 const vk::InstanceDriver& vki (instance.getDriver());
4211 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
4212 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
4213 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
4214 const vk::DeviceDriver vkd (vkp, instance, *device);
4215 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);
4216 const vk::VkFormat format = vk::VK_FORMAT_R8G8B8A8_UNORM;
4217 const deUint32 width = 64u;
4218 const deUint32 height = 64u;
4219 const vk::VkImageTiling tiling = vk::VK_IMAGE_TILING_OPTIMAL;
4221 checkImageSupport(vki, physicalDevice, config.externalType, 0u, usage, format, tiling, config.dedicated);
4223 if (config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID && config.dedicated)
4225 // AHB required the image memory to be bound first, which is not possible in this test.
4226 TCU_THROW(NotSupportedError, "Unsupported for Android Hardware Buffer");
4229 // \note Image is only allocated to get memory requirements
4230 const vk::Unique<vk::VkImage> imageA (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
4231 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *imageA, config.externalType));
4232 const deUint32 exportedMemoryTypeIndex (chooseMemoryType(requirements.memoryTypeBits));
4233 const vk::Unique<vk::VkDeviceMemory> memoryA (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType, config.dedicated ? *imageA : (vk::VkImage)0));
4234 NativeHandle handle;
4236 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
4239 const vk::Unique<vk::VkImage> imageB (createExternalImage(vkd, *device, queueFamilyIndex, config.externalType, format, width, height, tiling, 0u, usage));
4240 const deUint32 idx = config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID ? ~0u : exportedMemoryTypeIndex;
4241 const vk::Unique<vk::VkDeviceMemory> memoryB (config.dedicated
4242 ? importDedicatedMemory(vkd, *device, *imageB, requirements, config.externalType, idx, handle)
4243 : importMemory(vkd, *device, requirements, config.externalType, idx, handle));
4245 VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
4246 VK_CHECK(vkd.bindImageMemory(*device, *imageB, *memoryB, 0u));
4249 return tcu::TestStatus::pass("Pass");
4252 template<class TestConfig> void checkEvent (Context& context, const TestConfig)
4254 if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") && !context.getPortabilitySubsetFeatures().events)
4255 TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Events are not supported by this implementation");
4258 template<class TestConfig> void checkSupport (Context& context, const TestConfig config)
4260 const Transference transference (getHandelTypeTransferences(config.externalType));
4261 if (transference == TRANSFERENCE_COPY)
4262 checkEvent(context, config);
4265 de::MovePtr<tcu::TestCaseGroup> createFenceTests (tcu::TestContext& testCtx, vk::VkExternalFenceHandleTypeFlagBits externalType)
4269 const char* const name;
4270 const Permanence permanence;
4273 { "temporary", PERMANENCE_TEMPORARY },
4274 { "permanent", PERMANENCE_PERMANENT }
4277 de::MovePtr<tcu::TestCaseGroup> fenceGroup (new tcu::TestCaseGroup(testCtx, externalFenceTypeToName(externalType), externalFenceTypeToName(externalType)));
4279 addFunctionCase(fenceGroup.get(), "info", "Test external fence queries.", testFenceQueries, externalType);
4281 for (size_t permanenceNdx = 0; permanenceNdx < DE_LENGTH_OF_ARRAY(permanences); permanenceNdx++)
4283 const Permanence permanence (permanences[permanenceNdx].permanence);
4284 const char* const permanenceName (permanences[permanenceNdx].name);
4285 const FenceTestConfig config (externalType, permanence);
4287 if (!isSupportedPermanence(externalType, permanence))
4290 if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT
4291 || externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
4293 addFunctionCase(fenceGroup.get(), std::string("create_win32_") + permanenceName, "Test creating fence with win32 properties.", testFenceWin32Create, config);
4296 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("import_twice_") + permanenceName, "Test importing fence twice.", checkSupport, initProgramsToGetNativeFd, testFenceImportTwice, config);
4297 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("reimport_") + permanenceName, "Test importing again over previously imported fence.", checkSupport, initProgramsToGetNativeFd, testFenceImportReimport, config);
4298 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("import_multiple_times_") + permanenceName, "Test importing fence multiple times.", checkSupport, initProgramsToGetNativeFd, testFenceMultipleImports, config);
4299 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("signal_export_import_wait_") + permanenceName, "Test signaling, exporting, importing and waiting for the sempahore.", checkEvent, initProgramsToGetNativeFd, testFenceSignalExportImportWait, config);
4300 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("signal_import_") + permanenceName, "Test signaling and importing the fence.", checkSupport, initProgramsToGetNativeFd, testFenceSignalImport, config);
4301 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("reset_") + permanenceName, "Test resetting the fence.", checkEvent, initProgramsToGetNativeFd, testFenceReset, config);
4302 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("transference_") + permanenceName, "Test fences transference.", checkEvent, initProgramsToGetNativeFd, testFenceTransference, config);
4304 if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT)
4306 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("import_signaled_") + permanenceName, "Test import signaled fence fd.", initProgramsToGetNativeFd, testFenceImportSyncFdSignaled, config);
4309 if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT
4310 || externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT)
4312 // \note Not supported on WIN32 handles
4313 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("export_multiple_times_") + permanenceName, "Test exporting fence multiple times.", checkSupport, initProgramsToGetNativeFd, testFenceMultipleExports, config);
4315 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("dup_") + permanenceName, "Test calling dup() on exported fence.", checkSupport, initProgramsToGetNativeFd, testFenceFdDup, config);
4316 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("dup2_") + permanenceName, "Test calling dup2() on exported fence.", checkSupport, initProgramsToGetNativeFd, testFenceFdDup2, config);
4317 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("dup3_") + permanenceName, "Test calling dup3() on exported fence.", checkSupport, initProgramsToGetNativeFd, testFenceFdDup3, config);
4318 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("send_over_socket_") + permanenceName, "Test sending fence fd over socket.", checkSupport, initProgramsToGetNativeFd, testFenceFdSendOverSocket, config);
4321 if (getHandelTypeTransferences(externalType) == TRANSFERENCE_REFERENCE)
4323 addFunctionCase(fenceGroup.get(), std::string("signal_wait_import_") + permanenceName, "Test signaling and then waiting for the the sepmahore.", testFenceSignalWaitImport, config);
4324 addFunctionCase(fenceGroup.get(), std::string("export_signal_import_wait_") + permanenceName, "Test exporting, signaling, importing and waiting for the fence.", testFenceExportSignalImportWait, config);
4325 addFunctionCase(fenceGroup.get(), std::string("export_import_signal_wait_") + permanenceName, "Test exporting, importing, signaling and waiting for the fence.", testFenceExportImportSignalWait, config);
4332 void generateFailureText (TestLog& log, vk::VkFormat format, vk::VkImageUsageFlags usage, vk::VkImageCreateFlags create, vk::VkImageTiling tiling = static_cast<vk::VkImageTiling>(0), deUint32 width = 0, deUint32 height = 0, std::string exception = "")
4334 std::ostringstream combination;
4335 combination << "Test failure with combination: ";
4336 combination << " Format: " << getFormatName(format);
4337 combination << " Usageflags: " << vk::getImageUsageFlagsStr(usage);
4338 combination << " Createflags: " << vk::getImageCreateFlagsStr(create);
4339 combination << " Tiling: " << getImageTilingStr(tiling);
4340 if (width != 0 && height != 0)
4341 combination << " Size: " << "(" << width << ", " << height << ")";
4342 if (!exception.empty())
4343 combination << "Error message: " << exception;
4345 log << TestLog::Message << combination.str() << TestLog::EndMessage;
4348 bool ValidateAHardwareBuffer (TestLog& log, vk::VkFormat format, deUint64 requiredAhbUsage, const vk::DeviceDriver& vkd, const vk::VkDevice& device, vk::VkImageUsageFlags usageFlag, vk::VkImageCreateFlags createFlag, deUint32 layerCount, bool& enableMaxLayerTest)
4350 DE_UNREF(createFlag);
4352 AndroidHardwareBufferExternalApi* ahbApi = AndroidHardwareBufferExternalApi::getInstance();
4356 TCU_THROW(NotSupportedError, "Platform doesn't support Android Hardware Buffer handles");
4359 #if (DE_OS == DE_OS_ANDROID)
4360 // If CubeMap create flag is used and AHB doesn't support CubeMap return false.
4361 if(!AndroidHardwareBufferExternalApi::supportsCubeMap() && (createFlag & vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT))
4365 vk::pt::AndroidHardwareBufferPtr ahb = ahbApi->allocate(64u, 64u, layerCount, ahbApi->vkFormatToAhbFormat(format), requiredAhbUsage);
4366 if (ahb.internal == DE_NULL)
4368 enableMaxLayerTest = false;
4369 // try again with layerCount '1'
4370 ahb = ahbApi->allocate(64u, 64u, 1u, ahbApi->vkFormatToAhbFormat(format), requiredAhbUsage);
4371 if (ahb.internal == DE_NULL)
4376 NativeHandle nativeHandle(ahb);
4378 const vk::VkComponentMapping mappingA = { vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY };
4379 const vk::VkComponentMapping mappingB = { vk::VK_COMPONENT_SWIZZLE_R, vk::VK_COMPONENT_SWIZZLE_G, vk::VK_COMPONENT_SWIZZLE_B, vk::VK_COMPONENT_SWIZZLE_A };
4381 for (int variantIdx = 0; variantIdx < 2; ++variantIdx)
4383 // Both mappings should be equivalent and work.
4384 const vk::VkComponentMapping& mapping = ((variantIdx == 0) ? mappingA : mappingB);
4386 vk::VkAndroidHardwareBufferFormatPropertiesANDROID formatProperties =
4388 vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID,
4390 vk::VK_FORMAT_UNDEFINED,
4394 vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY,
4395 vk::VK_SAMPLER_YCBCR_RANGE_ITU_FULL,
4396 vk::VK_CHROMA_LOCATION_COSITED_EVEN,
4397 vk::VK_CHROMA_LOCATION_COSITED_EVEN
4400 vk::VkAndroidHardwareBufferPropertiesANDROID bufferProperties =
4402 vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID,
4410 VK_CHECK(vkd.getAndroidHardwareBufferPropertiesANDROID(device, ahb, &bufferProperties));
4411 TCU_CHECK(formatProperties.format != vk::VK_FORMAT_UNDEFINED);
4412 TCU_CHECK(formatProperties.format == format);
4413 TCU_CHECK(formatProperties.externalFormat != 0u);
4414 TCU_CHECK((formatProperties.formatFeatures & vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) != 0u);
4415 TCU_CHECK((formatProperties.formatFeatures & (vk::VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT | vk::VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT)) != 0u);
4417 catch (const tcu::Exception& exception)
4419 log << TestLog::Message << "Failure validating Android Hardware Buffer. See error message and combination: " << TestLog::EndMessage;
4420 generateFailureText(log, format, usageFlag, createFlag, static_cast<vk::VkImageTiling>(0), 0, 0, exception.getMessage());
4428 tcu::TestStatus testAndroidHardwareBufferImageFormat (Context& context, vk::VkFormat format)
4430 AndroidHardwareBufferExternalApi* ahbApi = AndroidHardwareBufferExternalApi::getInstance();
4433 TCU_THROW(NotSupportedError, "Platform doesn't support Android Hardware Buffer handles");
4436 bool testsFailed = false;
4438 const vk::VkExternalMemoryHandleTypeFlagBits externalMemoryType = vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
4439 const vk::PlatformInterface& vkp (context.getPlatformInterface());
4440 const CustomInstance instance (createTestInstance(context, 0u, externalMemoryType, 0u));
4441 const vk::InstanceDriver& vki (instance.getDriver());
4442 const vk::VkPhysicalDevice physicalDevice (vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
4444 vk::VkPhysicalDeviceProtectedMemoryFeatures protectedFeatures;
4445 protectedFeatures.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES;
4446 protectedFeatures.pNext = DE_NULL;
4447 protectedFeatures.protectedMemory = VK_FALSE;
4449 vk::VkPhysicalDeviceFeatures2 deviceFeatures;
4450 deviceFeatures.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
4451 deviceFeatures.pNext = &protectedFeatures;
4453 vki.getPhysicalDeviceFeatures2(physicalDevice, &deviceFeatures);
4455 const deUint32 queueFamilyIndex (chooseQueueFamilyIndex(vki, physicalDevice, 0u));
4456 const vk::Unique<vk::VkDevice> device (createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, externalMemoryType, 0u, queueFamilyIndex, false, &protectedFeatures));
4457 const vk::DeviceDriver vkd (vkp, instance, *device);
4458 TestLog& log = context.getTestContext().getLog();
4459 const vk::VkPhysicalDeviceLimits limits = getPhysicalDeviceProperties(vki, physicalDevice).limits;
4461 const vk::VkImageUsageFlagBits framebufferUsageFlag = vk::isDepthStencilFormat(format) ? vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
4462 : vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
4464 const vk::VkImageUsageFlagBits usageFlags[] =
4466 vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
4467 vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT,
4468 vk::VK_IMAGE_USAGE_SAMPLED_BIT,
4469 vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT,
4470 framebufferUsageFlag,
4472 const vk::VkImageCreateFlagBits createFlags[] =
4474 vk::VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT,
4475 vk::VK_IMAGE_CREATE_EXTENDED_USAGE_BIT,
4476 vk::VK_IMAGE_CREATE_PROTECTED_BIT,
4477 vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT,
4479 const vk::VkImageTiling tilings[] =
4481 vk::VK_IMAGE_TILING_OPTIMAL,
4482 vk::VK_IMAGE_TILING_LINEAR,
4484 deUint64 mustSupportAhbUsageFlags = ahbApi->mustSupportAhbUsageFlags();
4485 const size_t one = 1u;
4486 const size_t numOfUsageFlags = DE_LENGTH_OF_ARRAY(usageFlags);
4487 const size_t numOfCreateFlags = DE_LENGTH_OF_ARRAY(createFlags);
4488 const size_t numOfFlagCombos = one << (numOfUsageFlags + numOfCreateFlags);
4489 const size_t numOfTilings = DE_LENGTH_OF_ARRAY(tilings);
4491 for (size_t combo = 0; combo < numOfFlagCombos; combo++)
4493 vk::VkImageUsageFlags usage = 0;
4494 vk::VkImageCreateFlags createFlag = 0;
4495 deUint64 requiredAhbUsage = 0;
4496 bool enableMaxLayerTest = true;
4497 for (size_t usageNdx = 0; usageNdx < numOfUsageFlags; usageNdx++)
4499 if ((combo & (one << usageNdx)) == 0)
4501 usage |= usageFlags[usageNdx];
4502 requiredAhbUsage |= ahbApi->vkUsageToAhbUsage(usageFlags[usageNdx]);
4504 for (size_t createFlagNdx = 0; createFlagNdx < numOfCreateFlags; createFlagNdx++)
4506 const size_t bit = numOfUsageFlags + createFlagNdx;
4507 if ((combo & (one << bit)) == 0)
4509 if (((createFlags[createFlagNdx] & vk::VK_IMAGE_CREATE_PROTECTED_BIT) == vk::VK_IMAGE_CREATE_PROTECTED_BIT ) &&
4510 (protectedFeatures.protectedMemory == VK_FALSE))
4513 createFlag |= createFlags[createFlagNdx];
4514 requiredAhbUsage |= ahbApi->vkCreateToAhbUsage(createFlags[createFlagNdx]);
4517 // Only test a combination if the usage flags include at least one of the AHARDWAREBUFFER_USAGE_GPU_* flag.
4518 if ((requiredAhbUsage & mustSupportAhbUsageFlags) == 0u)
4521 // Only test a combination if AHardwareBuffer can be successfully allocated for it.
4522 if (!ValidateAHardwareBuffer(log, format, requiredAhbUsage, vkd, *device, usage, createFlag, limits.maxImageArrayLayers, enableMaxLayerTest))
4525 bool foundAnyUsableTiling = false;
4526 for (size_t tilingIndex = 0; tilingIndex < numOfTilings; tilingIndex++)
4528 const vk::VkImageTiling tiling = tilings[tilingIndex];
4530 const vk::VkPhysicalDeviceExternalImageFormatInfo externalInfo =
4532 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
4534 vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID
4536 const vk::VkPhysicalDeviceImageFormatInfo2 info =
4538 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
4541 vk::VK_IMAGE_TYPE_2D,
4547 vk::VkAndroidHardwareBufferUsageANDROID ahbUsageProperties =
4549 vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID,
4553 vk::VkExternalImageFormatProperties externalProperties =
4555 vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES,
4556 &ahbUsageProperties,
4559 vk::VkImageFormatProperties2 properties =
4561 vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
4562 &externalProperties,
4572 if (vki.getPhysicalDeviceImageFormatProperties2(physicalDevice, &info, &properties) == vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
4574 log << TestLog::Message << "Tiling " << tiling << " is not supported." << TestLog::EndMessage;
4578 foundAnyUsableTiling = true;
4582 TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) != 0);
4583 TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) != 0);
4584 TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0);
4585 deUint32 maxWidth = properties.imageFormatProperties.maxExtent.width;
4586 deUint32 maxHeight = properties.imageFormatProperties.maxExtent.height;
4587 TCU_CHECK(maxWidth >= 4096);
4588 TCU_CHECK(maxHeight >= 4096);
4589 // Even if not requested, at least one of GPU_* usage flags must be present.
4590 TCU_CHECK((ahbUsageProperties.androidHardwareBufferUsage & mustSupportAhbUsageFlags) != 0u);
4591 // The AHB usage flags corresponding to the create and usage flags used in info must be present.
4592 TCU_CHECK((ahbUsageProperties.androidHardwareBufferUsage & requiredAhbUsage) == requiredAhbUsage);
4594 catch (const tcu::Exception& exception)
4596 generateFailureText(log, format, usage, createFlag, tiling, 0, 0, exception.getMessage());
4601 log << TestLog::Message << "Required flags: " << std::hex << requiredAhbUsage << " Actual flags: " << std::hex << ahbUsageProperties.androidHardwareBufferUsage
4602 << TestLog::EndMessage;
4615 deUint32 exportedMemoryTypeIndex = 0;
4617 if (createFlag & vk::VK_IMAGE_CREATE_PROTECTED_BIT)
4619 const vk::VkPhysicalDeviceMemoryProperties memProperties(vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
4621 for (deUint32 memoryTypeIndex = 0; memoryTypeIndex < VK_MAX_MEMORY_TYPES; memoryTypeIndex++)
4623 if (memProperties.memoryTypes[memoryTypeIndex].propertyFlags & vk::VK_MEMORY_PROPERTY_PROTECTED_BIT)
4625 exportedMemoryTypeIndex = memoryTypeIndex;
4631 for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(sizes); i++)
4635 const vk::Unique<vk::VkImage> image (createExternalImage(vkd, *device, queueFamilyIndex, externalMemoryType, format, sizes[i].width, sizes[i].height, tiling, createFlag, usage));
4636 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *image, externalMemoryType));
4637 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, externalMemoryType, *image));
4638 NativeHandle handle;
4640 VK_CHECK(vkd.bindImageMemory(*device, *image, *memory, 0u));
4641 getMemoryNative(vkd, *device, *memory, externalMemoryType, handle);
4643 deUint32 ahbFormat = 0;
4644 deUint64 anhUsage = 0;
4645 ahbApi->describe(handle.getAndroidHardwareBuffer(), DE_NULL, DE_NULL, DE_NULL, &ahbFormat, &anhUsage, DE_NULL);
4646 TCU_CHECK(ahbFormat == ahbApi->vkFormatToAhbFormat(format));
4647 TCU_CHECK((anhUsage & requiredAhbUsage) == requiredAhbUsage);
4649 // Let watchdog know we're alive
4650 context.getTestContext().touchWatchdog();
4652 catch (const tcu::Exception& exception)
4654 generateFailureText(log, format, usage, createFlag, tiling, sizes[i].width, sizes[i].height, exception.getMessage());
4660 if (properties.imageFormatProperties.maxMipLevels >= 7u)
4664 const vk::Unique<vk::VkImage> image (createExternalImage(vkd, *device, queueFamilyIndex, externalMemoryType, format, 64u, 64u, tiling, createFlag, usage, 7u));
4665 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *image, externalMemoryType));
4666 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, externalMemoryType, *image));
4667 NativeHandle handle;
4669 VK_CHECK(vkd.bindImageMemory(*device, *image, *memory, 0u));
4670 getMemoryNative(vkd, *device, *memory, externalMemoryType, handle);
4672 deUint32 ahbFormat = 0;
4673 deUint64 anhUsage = 0;
4674 ahbApi->describe(handle.getAndroidHardwareBuffer(), DE_NULL, DE_NULL, DE_NULL, &ahbFormat, &anhUsage, DE_NULL);
4675 TCU_CHECK(ahbFormat == ahbApi->vkFormatToAhbFormat(format));
4676 TCU_CHECK((anhUsage & requiredAhbUsage) == requiredAhbUsage);
4678 catch (const tcu::Exception& exception)
4680 generateFailureText(log, format, usage, createFlag, tiling, 64, 64, exception.getMessage());
4686 if ((properties.imageFormatProperties.maxArrayLayers > 1u) && enableMaxLayerTest)
4690 const vk::Unique<vk::VkImage> image (createExternalImage(vkd, *device, queueFamilyIndex, externalMemoryType, format, 64u, 64u, tiling, createFlag, usage, 1u, properties.imageFormatProperties.maxArrayLayers));
4691 const vk::VkMemoryRequirements requirements (getImageMemoryRequirements(vkd, *device, *image, externalMemoryType));
4692 const vk::Unique<vk::VkDeviceMemory> memory (allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, externalMemoryType, *image));
4693 NativeHandle handle;
4695 VK_CHECK(vkd.bindImageMemory(*device, *image, *memory, 0u));
4696 getMemoryNative(vkd, *device, *memory, externalMemoryType, handle);
4698 deUint32 ahbFormat = 0;
4699 deUint64 anhUsage = 0;
4700 ahbApi->describe(handle.getAndroidHardwareBuffer(), DE_NULL, DE_NULL, DE_NULL, &ahbFormat, &anhUsage, DE_NULL);
4701 TCU_CHECK(ahbFormat == ahbApi->vkFormatToAhbFormat(format));
4702 TCU_CHECK((anhUsage & requiredAhbUsage) == requiredAhbUsage);
4704 catch (const tcu::Exception& exception)
4706 generateFailureText(log, format, usage, createFlag, tiling, 64, 64, exception.getMessage());
4713 if (!foundAnyUsableTiling)
4715 generateFailureText(log, format, usage, createFlag, static_cast<vk::VkImageTiling>(0));
4722 return tcu::TestStatus::fail("Failure in at least one subtest. Check log for failed tests.");
4724 return tcu::TestStatus::pass("Pass");
4727 de::MovePtr<tcu::TestCaseGroup> createFenceTests (tcu::TestContext& testCtx)
4729 de::MovePtr<tcu::TestCaseGroup> fenceGroup (new tcu::TestCaseGroup(testCtx, "fence", "Tests for external fences."));
4731 fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT).release());
4732 fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT).release());
4733 fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT).release());
4734 fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT).release());
4739 de::MovePtr<tcu::TestCaseGroup> createSemaphoreTests (tcu::TestContext& testCtx, vk::VkExternalSemaphoreHandleTypeFlagBits externalType)
4743 const char* const name;
4744 const Permanence permanence;
4747 { "temporary", PERMANENCE_TEMPORARY },
4748 { "permanent", PERMANENCE_PERMANENT }
4752 const char* const name;
4753 vk::VkSemaphoreType type;
4754 } semaphoreTypes[] =
4756 { "binary", vk::VK_SEMAPHORE_TYPE_BINARY },
4757 { "timeline", vk::VK_SEMAPHORE_TYPE_TIMELINE },
4760 de::MovePtr<tcu::TestCaseGroup> semaphoreGroup (new tcu::TestCaseGroup(testCtx, externalSemaphoreTypeToName(externalType), externalSemaphoreTypeToName(externalType)));
4762 for (size_t semaphoreTypeIdx = 0; semaphoreTypeIdx < DE_LENGTH_OF_ARRAY(permanences); semaphoreTypeIdx++)
4764 addFunctionCase(semaphoreGroup.get(), std::string("info_") + semaphoreTypes[semaphoreTypeIdx].name,
4765 "Test external semaphore queries.", testSemaphoreQueries,
4766 TestSemaphoreQueriesParameters(semaphoreTypes[semaphoreTypeIdx].type, externalType));
4769 for (size_t permanenceNdx = 0; permanenceNdx < DE_LENGTH_OF_ARRAY(permanences); permanenceNdx++)
4771 const Permanence permanence (permanences[permanenceNdx].permanence);
4772 const char* const permanenceName (permanences[permanenceNdx].name);
4773 const SemaphoreTestConfig config (externalType, permanence);
4775 if (!isSupportedPermanence(externalType, permanence))
4778 if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
4779 || externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
4781 addFunctionCase(semaphoreGroup.get(), std::string("create_win32_") + permanenceName, "Test creating semaphore with win32 properties.", testSemaphoreWin32Create, config);
4784 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("import_twice_") + permanenceName, "Test importing semaphore twice.", checkSupport, initProgramsToGetNativeFd, testSemaphoreImportTwice, config);
4785 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("reimport_") + permanenceName, "Test importing again over previously imported semaphore.", checkSupport, initProgramsToGetNativeFd, testSemaphoreImportReimport, config);
4786 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("import_multiple_times_") + permanenceName, "Test importing semaphore multiple times.", checkSupport, initProgramsToGetNativeFd, testSemaphoreMultipleImports, config);
4787 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("signal_export_import_wait_") + permanenceName, "Test signaling, exporting, importing and waiting for the sempahore.", checkEvent, initProgramsToGetNativeFd, testSemaphoreSignalExportImportWait, config);
4788 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("signal_import_") + permanenceName, "Test signaling and importing the semaphore.", checkSupport, initProgramsToGetNativeFd, testSemaphoreSignalImport, config);
4789 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("transference_") + permanenceName, "Test semaphores transference.", checkEvent, initProgramsToGetNativeFd, testSemaphoreTransference, config);
4791 if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT)
4793 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("import_signaled_") + permanenceName, "Test import signaled semaphore fd.", initProgramsToGetNativeFd, testSemaphoreImportSyncFdSignaled, config);
4797 if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT
4798 || externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT)
4800 // \note Not supported on WIN32 handles
4801 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("export_multiple_times_") + permanenceName, "Test exporting semaphore multiple times.", checkSupport, initProgramsToGetNativeFd, testSemaphoreMultipleExports, config);
4803 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("dup_") + permanenceName, "Test calling dup() on exported semaphore.", checkSupport, initProgramsToGetNativeFd, testSemaphoreFdDup, config);
4804 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("dup2_") + permanenceName, "Test calling dup2() on exported semaphore.", checkSupport, initProgramsToGetNativeFd, testSemaphoreFdDup2, config);
4805 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("dup3_") + permanenceName, "Test calling dup3() on exported semaphore.", checkSupport, initProgramsToGetNativeFd, testSemaphoreFdDup3, config);
4806 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("send_over_socket_") + permanenceName, "Test sending semaphore fd over socket.", checkSupport, initProgramsToGetNativeFd, testSemaphoreFdSendOverSocket, config);
4809 if (getHandelTypeTransferences(externalType) == TRANSFERENCE_REFERENCE)
4811 addFunctionCase(semaphoreGroup.get(), std::string("signal_wait_import_") + permanenceName, "Test signaling and then waiting for the the sepmahore.", testSemaphoreSignalWaitImport, config);
4812 addFunctionCase(semaphoreGroup.get(), std::string("export_signal_import_wait_") + permanenceName, "Test exporting, signaling, importing and waiting for the semaphore.", testSemaphoreExportSignalImportWait, config);
4813 addFunctionCase(semaphoreGroup.get(), std::string("export_import_signal_wait_") + permanenceName, "Test exporting, importing, signaling and waiting for the semaphore.", checkEvent, testSemaphoreExportImportSignalWait, config);
4817 return semaphoreGroup;
4820 de::MovePtr<tcu::TestCaseGroup> createSemaphoreTests (tcu::TestContext& testCtx)
4822 de::MovePtr<tcu::TestCaseGroup> semaphoreGroup (new tcu::TestCaseGroup(testCtx, "semaphore", "Tests for external semaphores."));
4824 semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT).release());
4825 semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT).release());
4826 semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT).release());
4827 semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT).release());
4828 semaphoreGroup->addChild(createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_ZIRCON_EVENT_BIT_FUCHSIA).release());
4830 return semaphoreGroup;
4833 de::MovePtr<tcu::TestCaseGroup> createMemoryTests (tcu::TestContext& testCtx, vk::VkExternalMemoryHandleTypeFlagBits externalType)
4835 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, externalMemoryTypeToName(externalType), "Tests for external memory"));
4837 for (size_t dedicatedNdx = 0; dedicatedNdx < 2; dedicatedNdx++)
4839 const bool dedicated (dedicatedNdx == 1);
4840 de::MovePtr<tcu::TestCaseGroup> dedicatedGroup (new tcu::TestCaseGroup(testCtx, dedicated ? "dedicated" : "suballocated", ""));
4842 for (size_t hostVisibleNdx = 0; hostVisibleNdx < 2; hostVisibleNdx++)
4844 const bool hostVisible (hostVisibleNdx == 1);
4845 de::MovePtr<tcu::TestCaseGroup> hostVisibleGroup (new tcu::TestCaseGroup(testCtx, hostVisible ? "host_visible" : "device_only", ""));
4846 const MemoryTestConfig memoryConfig (externalType, hostVisible, dedicated);
4848 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
4849 || externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
4851 addFunctionCase(hostVisibleGroup.get(), "create_win32", "Test creating memory with win32 properties .", testMemoryWin32Create, memoryConfig);
4854 addFunctionCase(hostVisibleGroup.get(), "import_twice", "Test importing memory object twice.", testMemoryImportTwice, memoryConfig);
4855 addFunctionCase(hostVisibleGroup.get(), "import_multiple_times", "Test importing memory object multiple times.", testMemoryMultipleImports, memoryConfig);
4857 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT
4858 || externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT)
4860 addFunctionCase(hostVisibleGroup.get(), "dup", "Test calling dup() on exported memory.", testMemoryFdDup, memoryConfig);
4861 addFunctionCase(hostVisibleGroup.get(), "dup2", "Test calling dup2() on exported memory.", testMemoryFdDup2, memoryConfig);
4862 addFunctionCase(hostVisibleGroup.get(), "dup3", "Test calling dup3() on exported memory.", testMemoryFdDup3, memoryConfig);
4863 addFunctionCase(hostVisibleGroup.get(), "send_over_socket", "Test sending memory fd over socket.", testMemoryFdSendOverSocket, memoryConfig);
4864 // \note Not supported on WIN32 handles
4865 addFunctionCase(hostVisibleGroup.get(), "export_multiple_times", "Test exporting memory multiple times.", testMemoryMultipleExports, memoryConfig);
4868 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT)
4870 addFunctionCase(hostVisibleGroup.get(), "fd_properties", "Test obtaining the FD memory properties", testMemoryFdProperties, memoryConfig);
4873 dedicatedGroup->addChild(hostVisibleGroup.release());
4877 de::MovePtr<tcu::TestCaseGroup> bufferGroup (new tcu::TestCaseGroup(testCtx, "buffer", ""));
4878 const BufferTestConfig bufferConfig (externalType, dedicated);
4880 addFunctionCase(bufferGroup.get(), "info", "External buffer memory info query.", testBufferQueries, externalType);
4881 addFunctionCase(bufferGroup.get(), "bind_export_import_bind", "Test binding, exporting, importing and binding buffer.", testBufferBindExportImportBind, bufferConfig);
4882 addFunctionCase(bufferGroup.get(), "export_bind_import_bind", "Test exporting, binding, importing and binding buffer.", testBufferExportBindImportBind, bufferConfig);
4883 addFunctionCase(bufferGroup.get(), "export_import_bind_bind", "Test exporting, importing and binding buffer.", testBufferExportImportBindBind, bufferConfig);
4885 dedicatedGroup->addChild(bufferGroup.release());
4889 de::MovePtr<tcu::TestCaseGroup> imageGroup (new tcu::TestCaseGroup(testCtx, "image", ""));
4890 const ImageTestConfig imageConfig (externalType, dedicated);
4892 addFunctionCase(imageGroup.get(), "info", "External image memory info query.", testImageQueries, externalType);
4893 addFunctionCase(imageGroup.get(), "bind_export_import_bind", "Test binding, exporting, importing and binding image.", testImageBindExportImportBind, imageConfig);
4894 addFunctionCase(imageGroup.get(), "export_bind_import_bind", "Test exporting, binding, importing and binding image.", testImageExportBindImportBind, imageConfig);
4895 addFunctionCase(imageGroup.get(), "export_import_bind_bind", "Test exporting, importing and binding image.", testImageExportImportBindBind, imageConfig);
4897 dedicatedGroup->addChild(imageGroup.release());
4900 group->addChild(dedicatedGroup.release());
4903 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
4905 de::MovePtr<tcu::TestCaseGroup> formatGroup (new tcu::TestCaseGroup(testCtx, "image_formats", "Test minimum image format support"));
4907 const vk::VkFormat ahbFormats[] =
4909 vk::VK_FORMAT_R8G8B8_UNORM,
4910 vk::VK_FORMAT_R8G8B8A8_UNORM,
4911 vk::VK_FORMAT_R5G6B5_UNORM_PACK16,
4912 vk::VK_FORMAT_R16G16B16A16_SFLOAT,
4913 vk::VK_FORMAT_A2B10G10R10_UNORM_PACK32,
4914 vk::VK_FORMAT_D16_UNORM,
4915 vk::VK_FORMAT_X8_D24_UNORM_PACK32,
4916 vk::VK_FORMAT_D24_UNORM_S8_UINT,
4917 vk::VK_FORMAT_D32_SFLOAT,
4918 vk::VK_FORMAT_D32_SFLOAT_S8_UINT,
4919 vk::VK_FORMAT_S8_UINT,
4920 vk::VK_FORMAT_R8_UNORM,
4922 const size_t numOfAhbFormats = DE_LENGTH_OF_ARRAY(ahbFormats);
4924 for (size_t ahbFormatNdx = 0; ahbFormatNdx < numOfAhbFormats; ahbFormatNdx++)
4926 const vk::VkFormat format = ahbFormats[ahbFormatNdx];
4927 const std::string testCaseName = getFormatCaseName(format);
4929 addFunctionCase(formatGroup.get(), testCaseName, "", testAndroidHardwareBufferImageFormat, format);
4932 group->addChild(formatGroup.release());
4938 de::MovePtr<tcu::TestCaseGroup> createMemoryTests (tcu::TestContext& testCtx)
4940 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "memory", "Tests for external memory"));
4942 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT).release());
4943 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT).release());
4944 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT).release());
4945 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID).release());
4946 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT).release());
4947 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA).release());
4954 tcu::TestCaseGroup* createExternalMemoryTests (tcu::TestContext& testCtx)
4956 de::MovePtr<tcu::TestCaseGroup> group (new tcu::TestCaseGroup(testCtx, "external", "Tests for external Vulkan objects"));
4958 group->addChild(createSemaphoreTests(testCtx).release());
4959 group->addChild(createMemoryTests(testCtx).release());
4960 group->addChild(createFenceTests(testCtx).release());
4962 return group.release();