1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2016 Google Inc.
6 *
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
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
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.
18 *
19 * \brief Vulkan external memory API tests
20 *//*--------------------------------------------------------------------*/
21
22 #include "vktApiExternalMemoryTests.hpp"
23 #include "vktCustomInstancesDevices.hpp"
24 #include "../compute/vktComputeTestsUtil.hpp"
25
26 #include "vktTestCase.hpp"
27 #include "vktTestCaseUtil.hpp"
28 #include "vkRefUtil.hpp"
29 #include "vkDeviceUtil.hpp"
30 #include "vkQueryUtil.hpp"
31 #include "vkPlatform.hpp"
32 #include "vkMemUtil.hpp"
33 #include "vkApiVersion.hpp"
34 #include "vkImageUtil.hpp"
35 #include "vkObjUtil.hpp"
36 #include "vkBuilderUtil.hpp"
37 #include "vkBarrierUtil.hpp"
38 #include "vkBufferWithMemory.hpp"
39
40 #include "tcuTestLog.hpp"
41 #include "tcuCommandLine.hpp"
42
43 #include "deUniquePtr.hpp"
44 #include "deStringUtil.hpp"
45 #include "deRandom.hpp"
46
47 #include "deMemory.h"
48
49 #include "vktExternalMemoryUtil.hpp"
50
51 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
52 #include <unistd.h>
53 #include <fcntl.h>
54 #include <errno.h>
55 #include <sys/types.h>
56 #include <sys/socket.h>
57 #endif
58
59 #if (DE_OS == DE_OS_WIN32)
60 #define WIN32_LEAN_AND_MEAN
61 #include <windows.h>
62 #include <dxgi1_2.h>
63 #endif
64
65 #include <chrono>
66
67 using tcu::TestLog;
68 using namespace vkt::ExternalMemoryUtil;
69
70 namespace vkt
71 {
72 namespace api
73 {
74 namespace
75 {
76
77 template <typename T, int size>
multiplyComponents(const tcu::Vector<T,size> & v)78 T multiplyComponents(const tcu::Vector<T, size> &v)
79 {
80 T accum = 1;
81 for (int i = 0; i < size; ++i)
82 accum *= v[i];
83 return accum;
84 }
85
getFormatCaseName(vk::VkFormat format)86 std::string getFormatCaseName(vk::VkFormat format)
87 {
88 return de::toLower(de::toString(getFormatStr(format)).substr(10));
89 }
90
getMemoryDedicatedRequirements(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkBuffer buffer)91 vk::VkMemoryDedicatedRequirements getMemoryDedicatedRequirements(const vk::DeviceInterface &vkd, vk::VkDevice device,
92 vk::VkBuffer buffer)
93 {
94 const vk::VkBufferMemoryRequirementsInfo2 requirementInfo = {
95 vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2, DE_NULL, buffer};
96 vk::VkMemoryDedicatedRequirements dedicatedRequirements = {vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
97 DE_NULL, VK_FALSE, VK_FALSE};
98 vk::VkMemoryRequirements2 requirements = {
99 vk::VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, &dedicatedRequirements, {0u, 0u, 0u}};
100
101 vkd.getBufferMemoryRequirements2(device, &requirementInfo, &requirements);
102
103 return dedicatedRequirements;
104 }
105
getMemoryDedicatedRequirements(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkImage image)106 vk::VkMemoryDedicatedRequirements getMemoryDedicatedRequirements(const vk::DeviceInterface &vkd, vk::VkDevice device,
107 vk::VkImage image)
108 {
109 const vk::VkImageMemoryRequirementsInfo2 requirementInfo = {vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
110 DE_NULL, image};
111 vk::VkMemoryDedicatedRequirements dedicatedRequirements = {vk::VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
112 DE_NULL, VK_FALSE, VK_FALSE};
113 vk::VkMemoryRequirements2 requirements = {
114 vk::VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, &dedicatedRequirements, {0u, 0u, 0u}};
115
116 vkd.getImageMemoryRequirements2(device, &requirementInfo, &requirements);
117
118 return dedicatedRequirements;
119 }
120
writeHostMemory(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkDeviceMemory memory,size_t size,const void * data)121 void writeHostMemory(const vk::DeviceInterface &vkd, vk::VkDevice device, vk::VkDeviceMemory memory, size_t size,
122 const void *data)
123 {
124 void *const ptr = vk::mapMemory(vkd, device, memory, 0, size, 0);
125
126 deMemcpy(ptr, data, size);
127
128 flushMappedMemoryRange(vkd, device, memory, 0, VK_WHOLE_SIZE);
129
130 vkd.unmapMemory(device, memory);
131 }
132
checkHostMemory(const vk::DeviceInterface & vkd,vk::VkDevice device,vk::VkDeviceMemory memory,size_t size,const void * data)133 void checkHostMemory(const vk::DeviceInterface &vkd, vk::VkDevice device, vk::VkDeviceMemory memory, size_t size,
134 const void *data)
135 {
136 void *const ptr = vk::mapMemory(vkd, device, memory, 0, size, 0);
137
138 invalidateMappedMemoryRange(vkd, device, memory, 0, VK_WHOLE_SIZE);
139
140 if (deMemCmp(ptr, data, size) != 0)
141 TCU_FAIL("Memory contents don't match");
142
143 vkd.unmapMemory(device, memory);
144 }
145
genTestData(uint32_t seed,size_t size)146 std::vector<uint8_t> genTestData(uint32_t seed, size_t size)
147 {
148 de::Random rng(seed);
149 std::vector<uint8_t> data(size);
150
151 for (size_t ndx = 0; ndx < size; ndx++)
152 {
153 data[ndx] = rng.getUint8();
154 }
155
156 return data;
157 }
158
chooseQueueFamilyIndex(const vk::InstanceInterface & vki,vk::VkPhysicalDevice device,vk::VkQueueFlags requireFlags)159 uint32_t chooseQueueFamilyIndex(const vk::InstanceInterface &vki, vk::VkPhysicalDevice device,
160 vk::VkQueueFlags requireFlags)
161 {
162 const std::vector<vk::VkQueueFamilyProperties> properties(vk::getPhysicalDeviceQueueFamilyProperties(vki, device));
163
164 for (uint32_t queueFamilyIndex = 0; queueFamilyIndex < (uint32_t)properties.size(); queueFamilyIndex++)
165 {
166 if ((properties[queueFamilyIndex].queueFlags & requireFlags) == requireFlags)
167 return queueFamilyIndex;
168 }
169
170 TCU_THROW(NotSupportedError, "Queue type not supported");
171 }
172
getInstanceExtensions(const uint32_t instanceVersion,const vk::VkExternalSemaphoreHandleTypeFlags externalSemaphoreTypes,const vk::VkExternalMemoryHandleTypeFlags externalMemoryTypes,const vk::VkExternalFenceHandleTypeFlags externalFenceTypes)173 std::vector<std::string> getInstanceExtensions(const uint32_t instanceVersion,
174 const vk::VkExternalSemaphoreHandleTypeFlags externalSemaphoreTypes,
175 const vk::VkExternalMemoryHandleTypeFlags externalMemoryTypes,
176 const vk::VkExternalFenceHandleTypeFlags externalFenceTypes)
177 {
178 std::vector<std::string> instanceExtensions;
179
180 if (!vk::isCoreInstanceExtension(instanceVersion, "VK_KHR_get_physical_device_properties2"))
181 instanceExtensions.push_back("VK_KHR_get_physical_device_properties2");
182
183 if (externalSemaphoreTypes != 0)
184 if (!vk::isCoreInstanceExtension(instanceVersion, "VK_KHR_external_semaphore_capabilities"))
185 instanceExtensions.push_back("VK_KHR_external_semaphore_capabilities");
186
187 if (externalMemoryTypes != 0)
188 if (!vk::isCoreInstanceExtension(instanceVersion, "VK_KHR_external_memory_capabilities"))
189 instanceExtensions.push_back("VK_KHR_external_memory_capabilities");
190
191 if (externalFenceTypes != 0)
192 if (!vk::isCoreInstanceExtension(instanceVersion, "VK_KHR_external_fence_capabilities"))
193 instanceExtensions.push_back("VK_KHR_external_fence_capabilities");
194
195 return instanceExtensions;
196 }
197
createTestInstance(Context & context,const vk::VkExternalSemaphoreHandleTypeFlags externalSemaphoreTypes,const vk::VkExternalMemoryHandleTypeFlags externalMemoryTypes,const vk::VkExternalFenceHandleTypeFlags externalFenceTypes)198 CustomInstance createTestInstance(Context &context, const vk::VkExternalSemaphoreHandleTypeFlags externalSemaphoreTypes,
199 const vk::VkExternalMemoryHandleTypeFlags externalMemoryTypes,
200 const vk::VkExternalFenceHandleTypeFlags externalFenceTypes)
201 {
202 try
203 {
204 return vkt::createCustomInstanceWithExtensions(
205 context, getInstanceExtensions(context.getUsedApiVersion(), externalSemaphoreTypes, externalMemoryTypes,
206 externalFenceTypes));
207 }
208 catch (const vk::Error &error)
209 {
210 if (error.getError() == vk::VK_ERROR_EXTENSION_NOT_PRESENT)
211 TCU_THROW(NotSupportedError, "Required extensions not supported");
212
213 throw;
214 }
215 }
216
createTestDevice(const Context & context,const vk::PlatformInterface & vkp,vk::VkInstance instance,const vk::InstanceInterface & vki,vk::VkPhysicalDevice physicalDevice,const vk::VkExternalSemaphoreHandleTypeFlags externalSemaphoreTypes,const vk::VkExternalMemoryHandleTypeFlags externalMemoryTypes,const vk::VkExternalFenceHandleTypeFlags externalFenceTypes,uint32_t queueFamilyIndex,bool useDedicatedAllocs=false,void * protectedFeatures=DE_NULL)217 vk::Move<vk::VkDevice> createTestDevice(const Context &context, const vk::PlatformInterface &vkp,
218 vk::VkInstance instance, const vk::InstanceInterface &vki,
219 vk::VkPhysicalDevice physicalDevice,
220 const vk::VkExternalSemaphoreHandleTypeFlags externalSemaphoreTypes,
221 const vk::VkExternalMemoryHandleTypeFlags externalMemoryTypes,
222 const vk::VkExternalFenceHandleTypeFlags externalFenceTypes,
223 uint32_t queueFamilyIndex, bool useDedicatedAllocs = false,
224 void *protectedFeatures = DE_NULL)
225 {
226 const uint32_t apiVersion = context.getUsedApiVersion();
227 bool useExternalSemaphore = false;
228 bool useExternalFence = false;
229 bool useExternalMemory = false;
230 std::vector<const char *> deviceExtensions;
231
232 if ((externalSemaphoreTypes & (vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT |
233 vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT)) != 0)
234 {
235 deviceExtensions.push_back("VK_KHR_external_semaphore_fd");
236 useExternalSemaphore = true;
237 }
238
239 if ((externalFenceTypes &
240 (vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT | vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT)) != 0)
241 {
242 deviceExtensions.push_back("VK_KHR_external_fence_fd");
243 useExternalFence = true;
244 }
245
246 if (useDedicatedAllocs)
247 {
248 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_dedicated_allocation"))
249 deviceExtensions.push_back("VK_KHR_dedicated_allocation");
250 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_get_memory_requirements2"))
251 deviceExtensions.push_back("VK_KHR_get_memory_requirements2");
252 }
253
254 if ((externalMemoryTypes &
255 (vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT)) != 0)
256 {
257 deviceExtensions.push_back("VK_KHR_external_memory_fd");
258 useExternalMemory = true;
259 }
260
261 if ((externalMemoryTypes & vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT) != 0)
262 {
263 deviceExtensions.push_back("VK_EXT_external_memory_dma_buf");
264 useExternalMemory = true;
265 }
266
267 if ((externalSemaphoreTypes & (vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT |
268 vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)) != 0)
269 {
270 deviceExtensions.push_back("VK_KHR_external_semaphore_win32");
271 useExternalSemaphore = true;
272 }
273
274 if ((externalFenceTypes & (vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT |
275 vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)) != 0)
276 {
277 deviceExtensions.push_back("VK_KHR_external_fence_win32");
278 useExternalFence = true;
279 }
280
281 if (externalMemoryTypes & vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA)
282 {
283 deviceExtensions.push_back("VK_FUCHSIA_external_memory");
284 }
285
286 if (externalSemaphoreTypes & vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_ZIRCON_EVENT_BIT_FUCHSIA)
287 {
288 deviceExtensions.push_back("VK_FUCHSIA_external_semaphore");
289 }
290
291 if ((externalMemoryTypes &
292 (vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT |
293 vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT |
294 vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT |
295 vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT | vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT |
296 vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT)) != 0)
297 {
298 deviceExtensions.push_back("VK_KHR_external_memory_win32");
299 useExternalMemory = true;
300 }
301
302 if ((externalMemoryTypes & vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID) != 0)
303 {
304 deviceExtensions.push_back("VK_ANDROID_external_memory_android_hardware_buffer");
305 useExternalMemory = true;
306 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_sampler_ycbcr_conversion"))
307 deviceExtensions.push_back("VK_KHR_sampler_ycbcr_conversion");
308 if (!vk::isCoreDeviceExtension(apiVersion, "VK_EXT_queue_family_foreign"))
309 deviceExtensions.push_back("VK_EXT_queue_family_foreign");
310 }
311
312 if (useExternalSemaphore)
313 {
314 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_external_semaphore"))
315 deviceExtensions.push_back("VK_KHR_external_semaphore");
316 }
317
318 if (useExternalFence)
319 {
320 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_external_fence"))
321 deviceExtensions.push_back("VK_KHR_external_fence");
322 }
323
324 if (useExternalMemory)
325 {
326 if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_external_memory"))
327 deviceExtensions.push_back("VK_KHR_external_memory");
328 }
329
330 const float priority = 0.5f;
331 const vk::VkDeviceQueueCreateInfo queues[] = {{vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, DE_NULL, 0u,
332
333 queueFamilyIndex, 1u, &priority}};
334 const vk::VkDeviceCreateInfo deviceCreateInfo = {vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
335 protectedFeatures,
336 0u,
337
338 DE_LENGTH_OF_ARRAY(queues),
339 queues,
340
341 0u,
342 DE_NULL,
343
344 (uint32_t)deviceExtensions.size(),
345 deviceExtensions.empty() ? DE_NULL : &deviceExtensions[0],
346 DE_NULL};
347
348 try
349 {
350 return createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), vkp, instance, vki,
351 physicalDevice, &deviceCreateInfo);
352 }
353 catch (const vk::Error &error)
354 {
355 if (error.getError() == vk::VK_ERROR_EXTENSION_NOT_PRESENT)
356 TCU_THROW(NotSupportedError, "Required extensions not supported");
357
358 throw;
359 }
360 }
361
getQueue(const vk::DeviceInterface & vkd,vk::VkDevice device,uint32_t queueFamilyIndex)362 vk::VkQueue getQueue(const vk::DeviceInterface &vkd, vk::VkDevice device, uint32_t queueFamilyIndex)
363 {
364 vk::VkQueue queue;
365
366 vkd.getDeviceQueue(device, queueFamilyIndex, 0, &queue);
367
368 return queue;
369 }
370
getMaxInvocations(const Context & context,uint32_t idx)371 uint32_t getMaxInvocations(const Context &context, uint32_t idx)
372 {
373 const auto &vki = context.getInstanceInterface();
374 const auto physicalDevice = context.getPhysicalDevice();
375 const auto properties = vk::getPhysicalDeviceProperties(vki, physicalDevice);
376
377 return properties.limits.maxComputeWorkGroupSize[idx];
378 }
379
checkSemaphoreSupport(const vk::InstanceInterface & vki,vk::VkPhysicalDevice device,vk::VkExternalSemaphoreHandleTypeFlagBits externalType)380 void checkSemaphoreSupport(const vk::InstanceInterface &vki, vk::VkPhysicalDevice device,
381 vk::VkExternalSemaphoreHandleTypeFlagBits externalType)
382 {
383 const vk::VkPhysicalDeviceExternalSemaphoreInfo info = {
384 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO, DE_NULL, externalType};
385 vk::VkExternalSemaphoreProperties properties = {vk::VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES, DE_NULL, 0u,
386 0u, 0u};
387
388 vki.getPhysicalDeviceExternalSemaphoreProperties(device, &info, &properties);
389
390 if ((properties.externalSemaphoreFeatures & vk::VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT) == 0)
391 TCU_THROW(NotSupportedError, "Semaphore doesn't support exporting in external type");
392
393 if ((properties.externalSemaphoreFeatures & vk::VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT) == 0)
394 TCU_THROW(NotSupportedError, "Semaphore doesn't support importing in external type");
395 }
396
checkFenceSupport(const vk::InstanceInterface & vki,vk::VkPhysicalDevice device,vk::VkExternalFenceHandleTypeFlagBits externalType)397 void checkFenceSupport(const vk::InstanceInterface &vki, vk::VkPhysicalDevice device,
398 vk::VkExternalFenceHandleTypeFlagBits externalType)
399 {
400 const vk::VkPhysicalDeviceExternalFenceInfo info = {vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO,
401 DE_NULL, externalType};
402 vk::VkExternalFenceProperties properties = {vk::VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES, DE_NULL, 0u, 0u, 0u};
403
404 vki.getPhysicalDeviceExternalFenceProperties(device, &info, &properties);
405
406 if ((properties.externalFenceFeatures & vk::VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT) == 0)
407 TCU_THROW(NotSupportedError, "Fence doesn't support exporting in external type");
408
409 if ((properties.externalFenceFeatures & vk::VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT) == 0)
410 TCU_THROW(NotSupportedError, "Fence doesn't support importing in external type");
411 }
412
checkBufferSupport(const vk::InstanceInterface & vki,vk::VkPhysicalDevice device,vk::VkExternalMemoryHandleTypeFlagBits externalType,vk::VkBufferViewCreateFlags createFlag,vk::VkBufferUsageFlags usageFlag,bool dedicated)413 void checkBufferSupport(const vk::InstanceInterface &vki, vk::VkPhysicalDevice device,
414 vk::VkExternalMemoryHandleTypeFlagBits externalType, vk::VkBufferViewCreateFlags createFlag,
415 vk::VkBufferUsageFlags usageFlag, bool dedicated)
416 {
417 const vk::VkPhysicalDeviceExternalBufferInfo info = {vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO,
418 DE_NULL,
419
420 createFlag, usageFlag, externalType};
421 vk::VkExternalBufferProperties properties = {vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES,
422 DE_NULL,
423
424 {0u, 0u, 0u}};
425
426 vki.getPhysicalDeviceExternalBufferProperties(device, &info, &properties);
427
428 if ((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) ==
429 0)
430 TCU_THROW(NotSupportedError, "External handle type doesn't support exporting buffer");
431
432 if ((properties.externalMemoryProperties.externalMemoryFeatures & vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) ==
433 0)
434 TCU_THROW(NotSupportedError, "External handle type doesn't support importing buffer");
435
436 if (!dedicated && (properties.externalMemoryProperties.externalMemoryFeatures &
437 vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0)
438 TCU_THROW(NotSupportedError, "External handle type requires dedicated allocation");
439 }
440
checkImageSupport(const vk::InstanceInterface & vki,vk::VkPhysicalDevice device,vk::VkExternalMemoryHandleTypeFlagBits externalType,vk::VkImageViewCreateFlags createFlag,vk::VkImageUsageFlags usageFlag,vk::VkFormat format,vk::VkImageTiling tiling,bool dedicated)441 void checkImageSupport(const vk::InstanceInterface &vki, vk::VkPhysicalDevice device,
442 vk::VkExternalMemoryHandleTypeFlagBits externalType, vk::VkImageViewCreateFlags createFlag,
443 vk::VkImageUsageFlags usageFlag, vk::VkFormat format, vk::VkImageTiling tiling, bool dedicated)
444 {
445 const vk::VkPhysicalDeviceExternalImageFormatInfo externalInfo = {
446 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO, DE_NULL, externalType};
447 const vk::VkPhysicalDeviceImageFormatInfo2 info = {
448 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
449 &externalInfo,
450
451 format,
452 vk::VK_IMAGE_TYPE_2D,
453 tiling,
454 usageFlag,
455 createFlag,
456 };
457 vk::VkExternalImageFormatProperties externalProperties = {
458 vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES, DE_NULL, {0u, 0u, 0u}};
459 vk::VkImageFormatProperties2 properties = {
460 vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2, &externalProperties, {{0u, 0u, 0u}, 0u, 0u, 0u, 0u}};
461
462 vki.getPhysicalDeviceImageFormatProperties2(device, &info, &properties);
463
464 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures &
465 vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) == 0)
466 TCU_THROW(NotSupportedError, "External handle type doesn't support exporting image");
467
468 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures &
469 vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) == 0)
470 TCU_THROW(NotSupportedError, "External handle type doesn't support importing image");
471
472 if (!dedicated && (externalProperties.externalMemoryProperties.externalMemoryFeatures &
473 vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0)
474 TCU_THROW(NotSupportedError, "External handle type requires dedicated allocation");
475 }
476
submitEmptySignal(const vk::DeviceInterface & vkd,vk::VkQueue queue,vk::VkSemaphore semaphore)477 void submitEmptySignal(const vk::DeviceInterface &vkd, vk::VkQueue queue, vk::VkSemaphore semaphore)
478 {
479 const vk::VkSubmitInfo submit = {vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
480 DE_NULL,
481
482 0u,
483 DE_NULL,
484 DE_NULL,
485
486 0u,
487 DE_NULL,
488
489 1u,
490 &semaphore};
491
492 VK_CHECK(vkd.queueSubmit(queue, 1, &submit, (vk::VkFence)0u));
493 }
494
tuneWorkSizeYAndPrepareCommandBuffer(const Context & context,const vk::DeviceInterface & vk,vk::VkDevice device,vk::VkQueue queue,vk::VkCommandBuffer cmdBuffer,vk::VkDescriptorSet descriptorSet,vk::VkPipelineLayout pipelineLayout,vk::VkPipeline computePipeline,vk::VkBufferMemoryBarrier computeFinishBarrier,vk::VkEvent event,tcu::UVec3 * maxWorkSize)495 void tuneWorkSizeYAndPrepareCommandBuffer(const Context &context, const vk::DeviceInterface &vk, vk::VkDevice device,
496 vk::VkQueue queue, vk::VkCommandBuffer cmdBuffer,
497 vk::VkDescriptorSet descriptorSet, vk::VkPipelineLayout pipelineLayout,
498 vk::VkPipeline computePipeline,
499 vk::VkBufferMemoryBarrier computeFinishBarrier, vk::VkEvent event,
500 tcu::UVec3 *maxWorkSize)
501
502 {
503 // Have it be static so we don't need to do tuning every time, especially for "export_multiple_times" tests.
504 static uint32_t yWorkSize = 1;
505 uint64_t timeElapsed = 0;
506 bool bOutLoop = false;
507
508 const vk::Unique<vk::VkFence> fence(vk::createFence(vk, device));
509
510 const vk::VkCommandBufferBeginInfo cmdBufferBeginInfo = {
511 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
512 nullptr,
513 vk::VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
514 nullptr,
515 };
516
517 while (true)
518 {
519 VK_CHECK(vk.beginCommandBuffer(cmdBuffer, &cmdBufferBeginInfo));
520
521 /*
522 * If the handle type is VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR, the spec allowed for implementations to return -1
523 * if the fence is already signaled. Previously, to avoid getting -1 in this case, this test had used vkCmdWaitEvents and
524 * vkSetEvent after submission to get a proper file descriptor before signaling but it's not invalid to call vkSetEvent
525 * after submission. So we just use vkCmdSetEvent and check the state of the event after submission to see if it's already
526 * signaled or an error happens while trying to get a file descriptor.
527 */
528 vk.cmdSetEvent(cmdBuffer, event, vk::VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT);
529
530 // And now we do a simple atomic calculation to avoid signalling instantly right after submit.
531 vk.cmdBindPipeline(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, computePipeline);
532 //vk.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, nullptr);
533 vk.cmdBindDescriptorSets(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout, 0u, 1u, &descriptorSet,
534 0u, nullptr);
535 vk.cmdDispatch(cmdBuffer, maxWorkSize->x(), yWorkSize, maxWorkSize->z());
536 vk.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, 0, 0,
537 nullptr, 1u, &computeFinishBarrier, 0, nullptr);
538 vk.endCommandBuffer(cmdBuffer);
539
540 if (bOutLoop)
541 break;
542
543 const vk::VkSubmitInfo submit = {vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
544 nullptr,
545
546 0u,
547 nullptr,
548 nullptr,
549
550 1u,
551 &cmdBuffer,
552
553 0u,
554 nullptr};
555
556 auto timeStart = std::chrono::high_resolution_clock::now();
557
558 VK_CHECK(vk.queueSubmit(queue, 1, &submit, (vk::VkFence)*fence));
559 vk.waitForFences(device, 1u, &fence.get(), true, ~0ull);
560
561 const auto executionTime = std::chrono::high_resolution_clock::now() - timeStart;
562 auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(executionTime);
563
564 timeElapsed = elapsed.count();
565
566 // we do loop until we get over 9 miliseconds as an execution time.
567 if (elapsed.count() > 9)
568 {
569 bOutLoop = true;
570 continue;
571 }
572
573 yWorkSize *= 2;
574
575 if (yWorkSize > maxWorkSize->y())
576 {
577 yWorkSize = maxWorkSize->y();
578 bOutLoop = true;
579 }
580
581 vk.resetCommandBuffer(cmdBuffer, 0u);
582 vk.resetFences(device, 1u, &*fence);
583 };
584
585 tcu::TestLog &log = context.getTestContext().getLog();
586 log << tcu::TestLog::Message << "Execution time to get a native file descriptor is " << timeElapsed
587 << "ms with Y WorkSize " << yWorkSize << tcu::TestLog::EndMessage;
588
589 return;
590 }
591
submitAtomicCalculationsAndGetSemaphoreNative(const Context & context,const vk::DeviceInterface & vk,vk::VkDevice device,vk::Allocator & alloc,vk::VkQueue queue,uint32_t queueFamilyIndex,vk::VkSemaphore semaphore,vk::VkExternalSemaphoreHandleTypeFlagBits externalType,NativeHandle & nativeHandle)592 void submitAtomicCalculationsAndGetSemaphoreNative(const Context &context, const vk::DeviceInterface &vk,
593 vk::VkDevice device, vk::Allocator &alloc, vk::VkQueue queue,
594 uint32_t queueFamilyIndex, vk::VkSemaphore semaphore,
595 vk::VkExternalSemaphoreHandleTypeFlagBits externalType,
596 NativeHandle &nativeHandle)
597 {
598 const vk::Unique<vk::VkCommandPool> cmdPool(
599 createCommandPool(vk, device, vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex, nullptr));
600 const vk::Unique<vk::VkCommandBuffer> cmdBuffer(
601 allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
602
603 const vk::VkEventCreateInfo eventCreateInfo = {vk::VK_STRUCTURE_TYPE_EVENT_CREATE_INFO, nullptr, 0u};
604
605 const vk::Unique<vk::VkEvent> event(createEvent(vk, device, &eventCreateInfo, nullptr));
606
607 const uint32_t maxXWorkSize = getMaxInvocations(context, 0);
608 const uint32_t maxYWorkSize = getMaxInvocations(context, 1);
609
610 tcu::UVec3 workSize = {maxXWorkSize, maxYWorkSize, 1u};
611 const uint32_t workGroupCount = multiplyComponents(workSize);
612
613 const vk::VkDeviceSize outputBufferSize = sizeof(uint32_t) * workGroupCount;
614 const vk::BufferWithMemory outputBuffer(
615 vk, device, alloc, makeBufferCreateInfo(outputBufferSize, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT),
616 vk::MemoryRequirement::Local);
617
618 // Create a compute shader
619 const vk::Unique<vk::VkShaderModule> compShader(
620 createShaderModule(vk, device, context.getBinaryCollection().get("compute"), 0u));
621
622 // Create descriptorSetLayout
623 vk::DescriptorSetLayoutBuilder layoutBuilder;
624 layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT);
625 vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout(layoutBuilder.build(vk, device));
626
627 // Create compute pipeline
628 const vk::Unique<vk::VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout));
629 const vk::Unique<vk::VkPipeline> computePipeline(makeComputePipeline(vk, device, *pipelineLayout, *compShader));
630
631 // Create descriptor pool
632 const vk::Unique<vk::VkDescriptorPool> descriptorPool(
633 vk::DescriptorPoolBuilder()
634 .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
635 .build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1));
636
637 const vk::Move<vk::VkDescriptorSet> descriptorSet(
638 makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
639 const vk::VkDescriptorBufferInfo outputBufferInfo = makeDescriptorBufferInfo(*outputBuffer, 0ull, outputBufferSize);
640 const vk::VkBufferMemoryBarrier computeFinishBarrier = vk::makeBufferMemoryBarrier(
641 vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_ACCESS_HOST_READ_BIT, *outputBuffer, 0ull, outputBufferSize);
642
643 vk::DescriptorSetUpdateBuilder()
644 .writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u),
645 vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &outputBufferInfo)
646 .update(vk, device);
647
648 // Now start tuning work size of Y to have time enough to get a fd at the device.
649 tuneWorkSizeYAndPrepareCommandBuffer(context, vk, device, queue, *cmdBuffer, *descriptorSet, *pipelineLayout,
650 *computePipeline, computeFinishBarrier, *event, &workSize);
651
652 const vk::VkSubmitInfo submit = {vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
653 nullptr,
654
655 0u,
656 nullptr,
657 nullptr,
658
659 1u,
660 &cmdBuffer.get(),
661
662 1u,
663 &semaphore};
664
665 VK_CHECK(vk.queueSubmit(queue, 1, &submit, (vk::VkFence)0u));
666
667 getSemaphoreNative(vk, device, semaphore, externalType, nativeHandle);
668
669 // Allow -1, that is valid if signaled properly.
670 if (nativeHandle.hasValidFd() && nativeHandle.getFd() == -1)
671 TCU_CHECK(vk.getEventStatus(device, *event) == vk::VK_EVENT_SET);
672
673 VK_CHECK(vk.queueWaitIdle(queue));
674 }
675
submitEmptyWait(const vk::DeviceInterface & vkd,vk::VkQueue queue,vk::VkSemaphore semaphore)676 void submitEmptyWait(const vk::DeviceInterface &vkd, vk::VkQueue queue, vk::VkSemaphore semaphore)
677 {
678 const vk::VkPipelineStageFlags stage = vk::VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
679 const vk::VkSubmitInfo submit = {
680 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
681 DE_NULL,
682
683 1u,
684 &semaphore,
685 &stage,
686
687 0u,
688 DE_NULL,
689
690 0u,
691 DE_NULL,
692 };
693
694 VK_CHECK(vkd.queueSubmit(queue, 1, &submit, (vk::VkFence)0u));
695 }
696
submitEmptySignal(const vk::DeviceInterface & vkd,vk::VkQueue queue,vk::VkFence fence)697 void submitEmptySignal(const vk::DeviceInterface &vkd, vk::VkQueue queue, vk::VkFence fence)
698 {
699 const vk::VkSubmitInfo submit = {vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
700 DE_NULL,
701
702 0u,
703 DE_NULL,
704 DE_NULL,
705
706 0u,
707 DE_NULL,
708
709 0u,
710 DE_NULL};
711
712 VK_CHECK(vkd.queueSubmit(queue, 1, &submit, fence));
713 }
714
submitAtomicCalculationsAndGetFenceNative(const Context & context,const vk::DeviceInterface & vk,vk::VkDevice device,vk::Allocator & alloc,vk::VkQueue queue,uint32_t queueFamilyIndex,vk::VkFence fence,vk::VkExternalFenceHandleTypeFlagBits externalType,NativeHandle & nativeHandle,bool expectFenceUnsignaled=true)715 void submitAtomicCalculationsAndGetFenceNative(const Context &context, const vk::DeviceInterface &vk,
716 vk::VkDevice device, vk::Allocator &alloc, vk::VkQueue queue,
717 uint32_t queueFamilyIndex, vk::VkFence fence,
718 vk::VkExternalFenceHandleTypeFlagBits externalType,
719 NativeHandle &nativeHandle, bool expectFenceUnsignaled = true)
720 {
721 const vk::Unique<vk::VkCommandPool> cmdPool(
722 createCommandPool(vk, device, vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex, nullptr));
723 const vk::Unique<vk::VkCommandBuffer> cmdBuffer(
724 allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
725
726 const vk::VkEventCreateInfo eventCreateInfo = {vk::VK_STRUCTURE_TYPE_EVENT_CREATE_INFO, DE_NULL, 0u};
727
728 const vk::Unique<vk::VkEvent> event(createEvent(vk, device, &eventCreateInfo, DE_NULL));
729
730 const uint32_t maxXWorkSize = getMaxInvocations(context, 0);
731 const uint32_t maxYWorkSize = getMaxInvocations(context, 1);
732
733 tcu::UVec3 workSize = {maxXWorkSize, maxYWorkSize, 1u};
734 const uint32_t workGroupCount = multiplyComponents(workSize);
735
736 const vk::VkDeviceSize outputBufferSize = sizeof(uint32_t) * workGroupCount;
737 const vk::BufferWithMemory outputBuffer(
738 vk, device, alloc, makeBufferCreateInfo(outputBufferSize, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT),
739 vk::MemoryRequirement::Local);
740
741 // Create a compute shader
742 const vk::Unique<vk::VkShaderModule> compShader(
743 createShaderModule(vk, device, context.getBinaryCollection().get("compute"), 0u));
744
745 // Create descriptorSetLayout
746 vk::DescriptorSetLayoutBuilder layoutBuilder;
747 layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_COMPUTE_BIT);
748 vk::Unique<vk::VkDescriptorSetLayout> descriptorSetLayout(layoutBuilder.build(vk, device));
749
750 // Create compute pipeline
751 const vk::Unique<vk::VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout));
752 const vk::Unique<vk::VkPipeline> computePipeline(makeComputePipeline(vk, device, *pipelineLayout, *compShader));
753
754 // Create descriptor pool
755 const vk::Unique<vk::VkDescriptorPool> descriptorPool(
756 vk::DescriptorPoolBuilder()
757 .addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
758 .build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1));
759
760 const vk::Move<vk::VkDescriptorSet> descriptorSet(
761 makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
762 const vk::VkDescriptorBufferInfo outputBufferInfo = makeDescriptorBufferInfo(*outputBuffer, 0ull, outputBufferSize);
763 const vk::VkBufferMemoryBarrier computeFinishBarrier = vk::makeBufferMemoryBarrier(
764 vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_ACCESS_HOST_READ_BIT, *outputBuffer, 0ull, outputBufferSize);
765
766 vk::DescriptorSetUpdateBuilder()
767 .writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u),
768 vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &outputBufferInfo)
769 .update(vk, device);
770
771 // Now start tuning work size of Y to have time enough to get a fd at the device.
772 tuneWorkSizeYAndPrepareCommandBuffer(context, vk, device, queue, *cmdBuffer, *descriptorSet, *pipelineLayout,
773 *computePipeline, computeFinishBarrier, *event, &workSize);
774
775 const vk::VkSubmitInfo submit = {vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,
776 DE_NULL,
777
778 0u,
779 DE_NULL,
780 DE_NULL,
781
782 1u,
783 &cmdBuffer.get(),
784
785 0u,
786 DE_NULL};
787
788 VK_CHECK(vk.queueSubmit(queue, 1, &submit, fence));
789
790 getFenceNative(vk, device, fence, externalType, nativeHandle, expectFenceUnsignaled);
791
792 // Allow -1, that is valid if signaled properly.
793 if (nativeHandle.hasValidFd() && nativeHandle.getFd() == -1)
794 TCU_CHECK(vk.getEventStatus(device, *event) == vk::VK_EVENT_SET);
795
796 VK_CHECK(vk.queueWaitIdle(queue));
797 }
798
799 struct TestSemaphoreQueriesParameters
800 {
801 vk::VkSemaphoreType semaphoreType;
802 vk::VkExternalSemaphoreHandleTypeFlagBits externalType;
803
TestSemaphoreQueriesParametersvkt::api::__anone405665c0111::TestSemaphoreQueriesParameters804 TestSemaphoreQueriesParameters(vk::VkSemaphoreType semaphoreType_,
805 vk::VkExternalSemaphoreHandleTypeFlagBits externalType_)
806 : semaphoreType(semaphoreType_)
807 , externalType(externalType_)
808 {
809 }
810 };
811
testSemaphoreQueries(Context & context,const TestSemaphoreQueriesParameters params)812 tcu::TestStatus testSemaphoreQueries(Context &context, const TestSemaphoreQueriesParameters params)
813 {
814 const CustomInstance instance(createTestInstance(context, params.externalType, 0u, 0u));
815 const vk::InstanceDriver &vki(instance.getDriver());
816 const vk::VkPhysicalDevice device(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
817
818 TestLog &log = context.getTestContext().getLog();
819
820 const vk::VkSemaphoreTypeCreateInfo semaphoreTypeInfo = {
821 vk::VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO,
822 DE_NULL,
823 params.semaphoreType,
824 0,
825 };
826 const vk::VkPhysicalDeviceExternalSemaphoreInfo info = {
827 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO, &semaphoreTypeInfo, params.externalType};
828 vk::VkExternalSemaphoreProperties properties = {vk::VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES, DE_NULL, 0u,
829 0u, 0u};
830
831 vki.getPhysicalDeviceExternalSemaphoreProperties(device, &info, &properties);
832 log << TestLog::Message << properties << TestLog::EndMessage;
833
834 TCU_CHECK(properties.pNext == DE_NULL);
835 TCU_CHECK(properties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES);
836
837 if (params.semaphoreType == vk::VK_SEMAPHORE_TYPE_TIMELINE)
838 {
839 context.requireDeviceFunctionality("VK_KHR_timeline_semaphore");
840
841 if (properties.compatibleHandleTypes & vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT)
842 return tcu::TestStatus::fail("Timeline semaphores are not compatible with SYNC_FD");
843
844 if (properties.exportFromImportedHandleTypes & vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT)
845 return tcu::TestStatus::fail("Timeline semaphores imported from SYNC_FD");
846 }
847
848 return tcu::TestStatus::pass("Pass");
849 }
850
851 struct SemaphoreTestConfig
852 {
SemaphoreTestConfigvkt::api::__anone405665c0111::SemaphoreTestConfig853 SemaphoreTestConfig(vk::VkExternalSemaphoreHandleTypeFlagBits externalType_, Permanence permanence_)
854 : externalType(externalType_)
855 , permanence(permanence_)
856 {
857 }
858
859 vk::VkExternalSemaphoreHandleTypeFlagBits externalType;
860 Permanence permanence;
861 };
862
863 template <class TestConfig>
initProgramsToGetNativeFd(vk::SourceCollections & dst,const TestConfig)864 void initProgramsToGetNativeFd(vk::SourceCollections &dst, const TestConfig)
865 {
866 const tcu::IVec3 localSize = {64, 1, 1};
867
868 std::ostringstream src;
869 src << "#version 310 es\n"
870 << "layout (local_size_x = " << localSize.x() << ", local_size_y = " << localSize.y()
871 << ", local_size_z = " << localSize.z() << ") in;\n"
872 << "layout(binding = 0) writeonly buffer Output {\n"
873 << " uint values[];\n"
874 << "};\n"
875 << "\n"
876 << "void main (void) {\n"
877 << " uint offset = gl_NumWorkGroups.x*gl_NumWorkGroups.y*gl_WorkGroupID.z + "
878 "gl_NumWorkGroups.x*gl_WorkGroupID.y + gl_WorkGroupID.x;\n"
879 << "\n"
880 << " atomicAdd(values[offset], 1u);\n"
881 << "}\n";
882
883 dst.glslSources.add("compute") << glu::ComputeSource(src.str());
884 }
885
testSemaphoreWin32Create(Context & context,const SemaphoreTestConfig config)886 tcu::TestStatus testSemaphoreWin32Create(Context &context, const SemaphoreTestConfig config)
887 {
888 #if (DE_OS == DE_OS_WIN32)
889 const Transference transference(getHandelTypeTransferences(config.externalType));
890 const vk::PlatformInterface &vkp(context.getPlatformInterface());
891 const CustomInstance instance(createTestInstance(context, config.externalType, 0u, 0u));
892 const vk::InstanceDriver &vki(instance.getDriver());
893 const vk::VkPhysicalDevice physicalDevice(
894 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
895 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
896
897 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
898
899 {
900 const vk::Unique<vk::VkDevice> device(createTestDevice(context, vkp, instance, vki, physicalDevice,
901 config.externalType, 0u, 0u, queueFamilyIndex));
902 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
903 context.getTestContext().getCommandLine());
904 const vk::VkQueue queue(getQueue(vkd, *device, queueFamilyIndex));
905 const vk::VkExportSemaphoreWin32HandleInfoKHR win32ExportInfo = {
906 vk::VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR, DE_NULL,
907
908 (vk::pt::Win32SecurityAttributesPtr)DE_NULL, DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
909 (vk::pt::Win32LPCWSTR)DE_NULL};
910 const vk::VkExportSemaphoreCreateInfo exportCreateInfo = {
911 vk::VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO, &win32ExportInfo,
912 (vk::VkExternalMemoryHandleTypeFlags)config.externalType};
913 const vk::VkSemaphoreCreateInfo createInfo = {vk::VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, &exportCreateInfo,
914 0u};
915 const vk::Unique<vk::VkSemaphore> semaphore(vk::createSemaphore(vkd, *device, &createInfo));
916
917 if (transference == TRANSFERENCE_COPY)
918 submitEmptySignal(vkd, queue, *semaphore);
919
920 NativeHandle handleA;
921 getSemaphoreNative(vkd, *device, *semaphore, config.externalType, handleA);
922
923 {
924 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ?
925 vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT :
926 (vk::VkSemaphoreImportFlagBits)0u;
927 const vk::Unique<vk::VkSemaphore> semaphoreA(
928 createAndImportSemaphore(vkd, *device, config.externalType, handleA, flags));
929
930 if (transference == TRANSFERENCE_COPY)
931 submitEmptyWait(vkd, queue, *semaphoreA);
932 else if (transference == TRANSFERENCE_REFERENCE)
933 {
934 submitEmptySignal(vkd, queue, *semaphore);
935 submitEmptyWait(vkd, queue, *semaphoreA);
936 }
937 else
938 DE_FATAL("Unknown transference.");
939
940 VK_CHECK(vkd.queueWaitIdle(queue));
941 }
942
943 return tcu::TestStatus::pass("Pass");
944 }
945 #else
946 DE_UNREF(context);
947 DE_UNREF(config);
948 TCU_THROW(NotSupportedError, "Platform doesn't support win32 handles");
949 #endif
950 }
951
testSemaphoreImportTwice(Context & context,const SemaphoreTestConfig config)952 tcu::TestStatus testSemaphoreImportTwice(Context &context, const SemaphoreTestConfig config)
953 {
954 const Transference transference(getHandelTypeTransferences(config.externalType));
955 const vk::PlatformInterface &vkp(context.getPlatformInterface());
956 const CustomInstance instance(createTestInstance(context, config.externalType, 0u, 0u));
957 const vk::InstanceDriver &vki(instance.getDriver());
958 const vk::VkPhysicalDevice physicalDevice(
959 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
960 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
961
962 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
963
964 {
965 const vk::Unique<vk::VkDevice> device(createTestDevice(context, vkp, instance, vki, physicalDevice,
966 config.externalType, 0u, 0u, queueFamilyIndex));
967 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
968 context.getTestContext().getCommandLine());
969 vk::SimpleAllocator alloc(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
970 const vk::VkQueue queue(getQueue(vkd, *device, queueFamilyIndex));
971 const vk::Unique<vk::VkSemaphore> semaphore(createExportableSemaphore(vkd, *device, config.externalType));
972 NativeHandle handleA;
973
974 if (transference == TRANSFERENCE_COPY)
975 {
976 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex,
977 *semaphore, config.externalType, handleA);
978 if (handleA.hasValidFd() && handleA.getFd() == -1)
979 return tcu::TestStatus::pass(
980 "Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
981 }
982 else
983 getSemaphoreNative(vkd, *device, *semaphore, config.externalType, handleA);
984
985 {
986 NativeHandle handleB(handleA);
987 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ?
988 vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT :
989 (vk::VkSemaphoreImportFlagBits)0u;
990 const vk::Unique<vk::VkSemaphore> semaphoreA(
991 createAndImportSemaphore(vkd, *device, config.externalType, handleA, flags));
992 const vk::Unique<vk::VkSemaphore> semaphoreB(
993 createAndImportSemaphore(vkd, *device, config.externalType, handleB, flags));
994
995 if (transference == TRANSFERENCE_COPY)
996 submitEmptyWait(vkd, queue, *semaphoreA);
997 else if (transference == TRANSFERENCE_REFERENCE)
998 {
999 submitEmptySignal(vkd, queue, *semaphoreA);
1000 submitEmptyWait(vkd, queue, *semaphoreB);
1001 }
1002 else
1003 DE_FATAL("Unknown transference.");
1004
1005 VK_CHECK(vkd.queueWaitIdle(queue));
1006 }
1007
1008 return tcu::TestStatus::pass("Pass");
1009 }
1010 }
1011
testSemaphoreImportReimport(Context & context,const SemaphoreTestConfig config)1012 tcu::TestStatus testSemaphoreImportReimport(Context &context, const SemaphoreTestConfig config)
1013 {
1014 const Transference transference(getHandelTypeTransferences(config.externalType));
1015 const vk::PlatformInterface &vkp(context.getPlatformInterface());
1016 const CustomInstance instance(createTestInstance(context, config.externalType, 0u, 0u));
1017 const vk::InstanceDriver &vki(instance.getDriver());
1018 const vk::VkPhysicalDevice physicalDevice(
1019 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1020 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1021
1022 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1023
1024 {
1025 const vk::Unique<vk::VkDevice> device(createTestDevice(context, vkp, instance, vki, physicalDevice,
1026 config.externalType, 0u, 0u, queueFamilyIndex));
1027 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
1028 context.getTestContext().getCommandLine());
1029 vk::SimpleAllocator alloc(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1030 const vk::VkQueue queue(getQueue(vkd, *device, queueFamilyIndex));
1031
1032 const vk::Unique<vk::VkSemaphore> semaphoreA(createExportableSemaphore(vkd, *device, config.externalType));
1033 NativeHandle handleA;
1034
1035 if (transference == TRANSFERENCE_COPY)
1036 {
1037 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex,
1038 *semaphoreA, config.externalType, handleA);
1039 if (handleA.hasValidFd() && handleA.getFd() == -1)
1040 return tcu::TestStatus::pass(
1041 "Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1042 }
1043 else
1044 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handleA);
1045
1046 NativeHandle handleB(handleA);
1047 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ?
1048 vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT :
1049 (vk::VkSemaphoreImportFlagBits)0u;
1050 const vk::Unique<vk::VkSemaphore> semaphoreB(
1051 createAndImportSemaphore(vkd, *device, config.externalType, handleA, flags));
1052
1053 importSemaphore(vkd, *device, *semaphoreB, config.externalType, handleB, flags);
1054
1055 if (transference == TRANSFERENCE_COPY)
1056 submitEmptyWait(vkd, queue, *semaphoreB);
1057 else if (transference == TRANSFERENCE_REFERENCE)
1058 {
1059 submitEmptySignal(vkd, queue, *semaphoreA);
1060 submitEmptyWait(vkd, queue, *semaphoreB);
1061 }
1062 else
1063 DE_FATAL("Unknown transference.");
1064
1065 VK_CHECK(vkd.queueWaitIdle(queue));
1066
1067 return tcu::TestStatus::pass("Pass");
1068 }
1069 }
1070
testSemaphoreSignalExportImportWait(Context & context,const SemaphoreTestConfig config)1071 tcu::TestStatus testSemaphoreSignalExportImportWait(Context &context, const SemaphoreTestConfig config)
1072 {
1073 const vk::PlatformInterface &vkp(context.getPlatformInterface());
1074 const CustomInstance instance(createTestInstance(context, config.externalType, 0u, 0u));
1075 const vk::InstanceDriver &vki(instance.getDriver());
1076 const vk::VkPhysicalDevice physicalDevice(
1077 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1078 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1079 const Transference transference(getHandelTypeTransferences(config.externalType));
1080
1081 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1082
1083 {
1084 const vk::Unique<vk::VkDevice> device(createTestDevice(context, vkp, instance, vki, physicalDevice,
1085 config.externalType, 0u, 0u, queueFamilyIndex));
1086 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
1087 context.getTestContext().getCommandLine());
1088 vk::SimpleAllocator alloc(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1089 const vk::VkQueue queue(getQueue(vkd, *device, queueFamilyIndex));
1090 const vk::Unique<vk::VkSemaphore> semaphoreA(createExportableSemaphore(vkd, *device, config.externalType));
1091 {
1092 NativeHandle handle;
1093
1094 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex,
1095 *semaphoreA, config.externalType, handle);
1096 if (transference == TRANSFERENCE_COPY && handle.hasValidFd() && handle.getFd() == -1)
1097 return tcu::TestStatus::pass(
1098 "Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1099
1100 {
1101 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ?
1102 vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT :
1103 (vk::VkSemaphoreImportFlagBits)0u;
1104 const vk::Unique<vk::VkSemaphore> semaphoreB(
1105 createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1106 submitEmptyWait(vkd, queue, *semaphoreB);
1107
1108 VK_CHECK(vkd.queueWaitIdle(queue));
1109 }
1110 }
1111
1112 return tcu::TestStatus::pass("Pass");
1113 }
1114 }
1115
testSemaphoreExportSignalImportWait(Context & context,const SemaphoreTestConfig config)1116 tcu::TestStatus testSemaphoreExportSignalImportWait(Context &context, const SemaphoreTestConfig config)
1117 {
1118 const vk::PlatformInterface &vkp(context.getPlatformInterface());
1119 const CustomInstance instance(createTestInstance(context, config.externalType, 0u, 0u));
1120 const vk::InstanceDriver &vki(instance.getDriver());
1121 const vk::VkPhysicalDevice physicalDevice(
1122 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1123 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1124 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ?
1125 vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT :
1126 (vk::VkSemaphoreImportFlagBits)0u;
1127
1128 DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
1129 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1130
1131 {
1132 const vk::Unique<vk::VkDevice> device(createTestDevice(context, vkp, instance, vki, physicalDevice,
1133 config.externalType, 0u, 0u, queueFamilyIndex));
1134 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
1135 context.getTestContext().getCommandLine());
1136 const vk::VkQueue queue(getQueue(vkd, *device, queueFamilyIndex));
1137
1138 const vk::Unique<vk::VkSemaphore> semaphoreA(createExportableSemaphore(vkd, *device, config.externalType));
1139 NativeHandle handle;
1140
1141 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
1142
1143 submitEmptySignal(vkd, queue, *semaphoreA);
1144 {
1145 {
1146 const vk::Unique<vk::VkSemaphore> semaphoreB(
1147 createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1148
1149 submitEmptyWait(vkd, queue, *semaphoreB);
1150 VK_CHECK(vkd.queueWaitIdle(queue));
1151 }
1152 }
1153
1154 return tcu::TestStatus::pass("Pass");
1155 }
1156 }
1157
testSemaphoreExportImportSignalWait(Context & context,const SemaphoreTestConfig config)1158 tcu::TestStatus testSemaphoreExportImportSignalWait(Context &context, const SemaphoreTestConfig config)
1159 {
1160 const vk::PlatformInterface &vkp(context.getPlatformInterface());
1161 const CustomInstance instance(createTestInstance(context, config.externalType, 0u, 0u));
1162 const vk::InstanceDriver &vki(instance.getDriver());
1163 const vk::VkPhysicalDevice physicalDevice(
1164 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1165 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1166
1167 DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
1168 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1169
1170 {
1171 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ?
1172 vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT :
1173 (vk::VkSemaphoreImportFlagBits)0u;
1174 const vk::Unique<vk::VkDevice> device(createTestDevice(context, vkp, instance, vki, physicalDevice,
1175 config.externalType, 0u, 0u, queueFamilyIndex));
1176 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
1177 context.getTestContext().getCommandLine());
1178 const vk::VkQueue queue(getQueue(vkd, *device, queueFamilyIndex));
1179
1180 const vk::Unique<vk::VkSemaphore> semaphoreA(createExportableSemaphore(vkd, *device, config.externalType));
1181 NativeHandle handle;
1182
1183 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
1184
1185 const vk::Unique<vk::VkSemaphore> semaphoreB(
1186 createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1187
1188 submitEmptySignal(vkd, queue, *semaphoreA);
1189 submitEmptyWait(vkd, queue, *semaphoreB);
1190
1191 VK_CHECK(vkd.queueWaitIdle(queue));
1192
1193 return tcu::TestStatus::pass("Pass");
1194 }
1195 }
1196
testSemaphoreSignalImport(Context & context,const SemaphoreTestConfig config)1197 tcu::TestStatus testSemaphoreSignalImport(Context &context, const SemaphoreTestConfig config)
1198 {
1199 const Transference transference(getHandelTypeTransferences(config.externalType));
1200 const vk::PlatformInterface &vkp(context.getPlatformInterface());
1201 const CustomInstance instance(createTestInstance(context, config.externalType, 0u, 0u));
1202 const vk::InstanceDriver &vki(instance.getDriver());
1203 const vk::VkPhysicalDevice physicalDevice(
1204 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1205 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1206
1207 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1208
1209 {
1210 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ?
1211 vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT :
1212 (vk::VkSemaphoreImportFlagBits)0u;
1213 const vk::Unique<vk::VkDevice> device(createTestDevice(context, vkp, instance, vki, physicalDevice,
1214 config.externalType, 0u, 0u, queueFamilyIndex));
1215 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
1216 context.getTestContext().getCommandLine());
1217 vk::SimpleAllocator alloc(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1218 const vk::VkQueue queue(getQueue(vkd, *device, queueFamilyIndex));
1219
1220 const vk::Unique<vk::VkSemaphore> semaphoreA(createExportableSemaphore(vkd, *device, config.externalType));
1221 const vk::Unique<vk::VkSemaphore> semaphoreB(createSemaphore(vkd, *device));
1222 NativeHandle handle;
1223
1224 submitEmptySignal(vkd, queue, *semaphoreB);
1225 VK_CHECK(vkd.queueWaitIdle(queue));
1226
1227 if (transference == TRANSFERENCE_COPY)
1228 {
1229 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex,
1230 *semaphoreA, config.externalType, handle);
1231 if (handle.hasValidFd() && handle.getFd() == -1)
1232 return tcu::TestStatus::pass(
1233 "Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1234 }
1235 else
1236 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
1237
1238 importSemaphore(vkd, *device, *semaphoreB, config.externalType, handle, flags);
1239
1240 if (transference == TRANSFERENCE_COPY)
1241 submitEmptyWait(vkd, queue, *semaphoreB);
1242 else if (transference == TRANSFERENCE_REFERENCE)
1243 {
1244 submitEmptySignal(vkd, queue, *semaphoreA);
1245 submitEmptyWait(vkd, queue, *semaphoreB);
1246 }
1247 else
1248 DE_FATAL("Unknown transference.");
1249
1250 VK_CHECK(vkd.queueWaitIdle(queue));
1251
1252 return tcu::TestStatus::pass("Pass");
1253 }
1254 }
1255
testSemaphoreSignalWaitImport(Context & context,const SemaphoreTestConfig config)1256 tcu::TestStatus testSemaphoreSignalWaitImport(Context &context, const SemaphoreTestConfig config)
1257 {
1258 const vk::PlatformInterface &vkp(context.getPlatformInterface());
1259 const CustomInstance instance(createTestInstance(context, config.externalType, 0u, 0u));
1260 const vk::InstanceDriver &vki(instance.getDriver());
1261 const vk::VkPhysicalDevice physicalDevice(
1262 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1263 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1264
1265 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1266
1267 {
1268 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ?
1269 vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT :
1270 (vk::VkSemaphoreImportFlagBits)0u;
1271 const vk::Unique<vk::VkDevice> device(createTestDevice(context, vkp, instance, vki, physicalDevice,
1272 config.externalType, 0u, 0u, queueFamilyIndex));
1273 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
1274 context.getTestContext().getCommandLine());
1275 const vk::VkQueue queue(getQueue(vkd, *device, queueFamilyIndex));
1276
1277 const vk::Unique<vk::VkSemaphore> semaphoreA(createExportableSemaphore(vkd, *device, config.externalType));
1278 const vk::Unique<vk::VkSemaphore> semaphoreB(createSemaphore(vkd, *device));
1279 NativeHandle handle;
1280
1281 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handle);
1282
1283 submitEmptySignal(vkd, queue, *semaphoreB);
1284 submitEmptyWait(vkd, queue, *semaphoreB);
1285
1286 VK_CHECK(vkd.queueWaitIdle(queue));
1287
1288 importSemaphore(vkd, *device, *semaphoreB, config.externalType, handle, flags);
1289
1290 submitEmptySignal(vkd, queue, *semaphoreA);
1291 submitEmptyWait(vkd, queue, *semaphoreB);
1292
1293 VK_CHECK(vkd.queueWaitIdle(queue));
1294
1295 return tcu::TestStatus::pass("Pass");
1296 }
1297 }
1298
testSemaphoreImportSyncFdSignaled(Context & context,const SemaphoreTestConfig config)1299 tcu::TestStatus testSemaphoreImportSyncFdSignaled(Context &context, const SemaphoreTestConfig config)
1300 {
1301 const vk::PlatformInterface &vkp(context.getPlatformInterface());
1302 const CustomInstance instance(createTestInstance(context, config.externalType, 0u, 0u));
1303 const vk::InstanceDriver &vki(instance.getDriver());
1304 const vk::VkPhysicalDevice physicalDevice(
1305 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1306 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1307 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ?
1308 vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT :
1309 (vk::VkSemaphoreImportFlagBits)0u;
1310
1311 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1312
1313 {
1314 const vk::Unique<vk::VkDevice> device(createTestDevice(context, vkp, instance, vki, physicalDevice,
1315 config.externalType, 0u, 0u, queueFamilyIndex));
1316 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
1317 context.getTestContext().getCommandLine());
1318 const vk::VkQueue queue(getQueue(vkd, *device, queueFamilyIndex));
1319 NativeHandle handle = -1;
1320 const vk::Unique<vk::VkSemaphore> semaphore(
1321 createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1322
1323 submitEmptyWait(vkd, queue, *semaphore);
1324 VK_CHECK(vkd.queueWaitIdle(queue));
1325
1326 return tcu::TestStatus::pass("Pass");
1327 }
1328 }
1329
testSemaphoreMultipleExports(Context & context,const SemaphoreTestConfig config)1330 tcu::TestStatus testSemaphoreMultipleExports(Context &context, const SemaphoreTestConfig config)
1331 {
1332 const size_t exportCount = 1024;
1333 const Transference transference(getHandelTypeTransferences(config.externalType));
1334 const vk::PlatformInterface &vkp(context.getPlatformInterface());
1335 const CustomInstance instance(createTestInstance(context, config.externalType, 0u, 0u));
1336 const vk::InstanceDriver &vki(instance.getDriver());
1337 const vk::VkPhysicalDevice physicalDevice(
1338 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1339 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1340
1341 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1342
1343 {
1344 const vk::Unique<vk::VkDevice> device(createTestDevice(context, vkp, instance, vki, physicalDevice,
1345 config.externalType, 0u, 0u, queueFamilyIndex));
1346 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
1347 context.getTestContext().getCommandLine());
1348 vk::SimpleAllocator alloc(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1349 const vk::VkQueue queue(getQueue(vkd, *device, queueFamilyIndex));
1350 const vk::Unique<vk::VkSemaphore> semaphore(createExportableSemaphore(vkd, *device, config.externalType));
1351
1352 for (size_t exportNdx = 0; exportNdx < exportCount; exportNdx++)
1353 {
1354 NativeHandle handle;
1355
1356 // Need to touch watchdog due to how long one iteration takes
1357 context.getTestContext().touchWatchdog();
1358
1359 if (transference == TRANSFERENCE_COPY)
1360 {
1361 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex,
1362 *semaphore, config.externalType, handle);
1363 if (handle.hasValidFd() && handle.getFd() == -1)
1364 return tcu::TestStatus::pass(
1365 "Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1366 }
1367 else
1368 getSemaphoreNative(vkd, *device, *semaphore, config.externalType, handle);
1369 }
1370
1371 submitEmptySignal(vkd, queue, *semaphore);
1372 submitEmptyWait(vkd, queue, *semaphore);
1373
1374 VK_CHECK(vkd.queueWaitIdle(queue));
1375 }
1376
1377 return tcu::TestStatus::pass("Pass");
1378 }
1379
testSemaphoreMultipleImports(Context & context,const SemaphoreTestConfig config)1380 tcu::TestStatus testSemaphoreMultipleImports(Context &context, const SemaphoreTestConfig config)
1381 {
1382 const size_t importCount = 4 * 1024;
1383 const Transference transference(getHandelTypeTransferences(config.externalType));
1384 const vk::PlatformInterface &vkp(context.getPlatformInterface());
1385 const CustomInstance instance(createTestInstance(context, config.externalType, 0u, 0u));
1386 const vk::InstanceDriver &vki(instance.getDriver());
1387 const vk::VkPhysicalDevice physicalDevice(
1388 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1389 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1390
1391 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1392
1393 {
1394 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ?
1395 vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT :
1396 (vk::VkSemaphoreImportFlagBits)0u;
1397 const vk::Unique<vk::VkDevice> device(createTestDevice(context, vkp, instance, vki, physicalDevice,
1398 config.externalType, 0u, 0u, queueFamilyIndex));
1399 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
1400 context.getTestContext().getCommandLine());
1401 vk::SimpleAllocator alloc(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1402 const vk::VkQueue queue(getQueue(vkd, *device, queueFamilyIndex));
1403 const vk::Unique<vk::VkSemaphore> semaphoreA(createExportableSemaphore(vkd, *device, config.externalType));
1404 NativeHandle handleA;
1405
1406 if (transference == TRANSFERENCE_COPY)
1407 {
1408 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex,
1409 *semaphoreA, config.externalType, handleA);
1410 if (handleA.hasValidFd() && handleA.getFd() == -1)
1411 return tcu::TestStatus::pass(
1412 "Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1413 }
1414 else
1415 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, handleA);
1416
1417 for (size_t importNdx = 0; importNdx < importCount; importNdx++)
1418 {
1419 NativeHandle handleB(handleA);
1420 const vk::Unique<vk::VkSemaphore> semaphoreB(
1421 createAndImportSemaphore(vkd, *device, config.externalType, handleB, flags));
1422 }
1423
1424 if (transference == TRANSFERENCE_COPY)
1425 {
1426 importSemaphore(vkd, *device, *semaphoreA, config.externalType, handleA, flags);
1427 submitEmptyWait(vkd, queue, *semaphoreA);
1428 }
1429 else if (transference == TRANSFERENCE_REFERENCE)
1430 {
1431 submitEmptySignal(vkd, queue, *semaphoreA);
1432 submitEmptyWait(vkd, queue, *semaphoreA);
1433 }
1434 else
1435 DE_FATAL("Unknown transference.");
1436
1437 VK_CHECK(vkd.queueWaitIdle(queue));
1438 }
1439
1440 return tcu::TestStatus::pass("Pass");
1441 }
1442
testSemaphoreTransference(Context & context,const SemaphoreTestConfig config)1443 tcu::TestStatus testSemaphoreTransference(Context &context, const SemaphoreTestConfig config)
1444 {
1445 const Transference transference(getHandelTypeTransferences(config.externalType));
1446 const vk::PlatformInterface &vkp(context.getPlatformInterface());
1447 const CustomInstance instance(createTestInstance(context, config.externalType, 0u, 0u));
1448 const vk::InstanceDriver &vki(instance.getDriver());
1449 const vk::VkPhysicalDevice physicalDevice(
1450 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1451 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1452
1453 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1454
1455 {
1456 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ?
1457 vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT :
1458 (vk::VkSemaphoreImportFlagBits)0u;
1459 const vk::Unique<vk::VkDevice> device(createTestDevice(context, vkp, instance, vki, physicalDevice,
1460 config.externalType, 0u, 0u, queueFamilyIndex));
1461 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
1462 context.getTestContext().getCommandLine());
1463 vk::SimpleAllocator alloc(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1464 const vk::VkQueue queue(getQueue(vkd, *device, queueFamilyIndex));
1465
1466 const vk::Unique<vk::VkSemaphore> semaphoreA(createExportableSemaphore(vkd, *device, config.externalType));
1467 NativeHandle handle;
1468
1469 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex,
1470 *semaphoreA, config.externalType, handle);
1471 if (transference == TRANSFERENCE_COPY && handle.hasValidFd() && handle.getFd() == -1)
1472 return tcu::TestStatus::pass(
1473 "Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1474
1475 {
1476 const vk::Unique<vk::VkSemaphore> semaphoreB(
1477 createAndImportSemaphore(vkd, *device, config.externalType, handle, flags));
1478
1479 if (config.permanence == PERMANENCE_PERMANENT)
1480 {
1481 if (transference == TRANSFERENCE_COPY)
1482 {
1483 submitEmptySignal(vkd, queue, *semaphoreA);
1484 submitEmptyWait(vkd, queue, *semaphoreB);
1485 VK_CHECK(vkd.queueWaitIdle(queue));
1486
1487 submitEmptySignal(vkd, queue, *semaphoreB);
1488
1489 submitEmptyWait(vkd, queue, *semaphoreA);
1490 submitEmptyWait(vkd, queue, *semaphoreB);
1491 VK_CHECK(vkd.queueWaitIdle(queue));
1492 }
1493 else if (transference == TRANSFERENCE_REFERENCE)
1494 {
1495 submitEmptyWait(vkd, queue, *semaphoreB);
1496 VK_CHECK(vkd.queueWaitIdle(queue));
1497
1498 submitEmptySignal(vkd, queue, *semaphoreA);
1499 submitEmptyWait(vkd, queue, *semaphoreB);
1500
1501 submitEmptySignal(vkd, queue, *semaphoreB);
1502 submitEmptyWait(vkd, queue, *semaphoreA);
1503 VK_CHECK(vkd.queueWaitIdle(queue));
1504 }
1505 else
1506 DE_FATAL("Unknown transference.");
1507 }
1508 else if (config.permanence == PERMANENCE_TEMPORARY)
1509 {
1510 if (transference == TRANSFERENCE_COPY)
1511 {
1512 submitEmptySignal(vkd, queue, *semaphoreA);
1513 submitEmptyWait(vkd, queue, *semaphoreB);
1514 VK_CHECK(vkd.queueWaitIdle(queue));
1515
1516 submitEmptySignal(vkd, queue, *semaphoreB);
1517
1518 submitEmptyWait(vkd, queue, *semaphoreA);
1519 submitEmptyWait(vkd, queue, *semaphoreB);
1520 VK_CHECK(vkd.queueWaitIdle(queue));
1521 }
1522 else if (transference == TRANSFERENCE_REFERENCE)
1523 {
1524 submitEmptyWait(vkd, queue, *semaphoreB);
1525 VK_CHECK(vkd.queueWaitIdle(queue));
1526
1527 submitEmptySignal(vkd, queue, *semaphoreA);
1528 submitEmptySignal(vkd, queue, *semaphoreB);
1529
1530 submitEmptyWait(vkd, queue, *semaphoreB);
1531 submitEmptyWait(vkd, queue, *semaphoreA);
1532 VK_CHECK(vkd.queueWaitIdle(queue));
1533 }
1534 else
1535 DE_FATAL("Unknown transference.");
1536 }
1537 else
1538 DE_FATAL("Unknown permanence.");
1539 }
1540
1541 return tcu::TestStatus::pass("Pass");
1542 }
1543 }
1544
testSemaphoreFdDup(Context & context,const SemaphoreTestConfig config)1545 tcu::TestStatus testSemaphoreFdDup(Context &context, const SemaphoreTestConfig config)
1546 {
1547 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
1548 const Transference transference(getHandelTypeTransferences(config.externalType));
1549 const vk::PlatformInterface &vkp(context.getPlatformInterface());
1550 const CustomInstance instance(createTestInstance(context, config.externalType, 0u, 0u));
1551 const vk::InstanceDriver &vki(instance.getDriver());
1552 const vk::VkPhysicalDevice physicalDevice(
1553 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1554 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1555
1556 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1557
1558 {
1559 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ?
1560 vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT :
1561 (vk::VkSemaphoreImportFlagBits)0u;
1562 const vk::Unique<vk::VkDevice> device(createTestDevice(context, vkp, instance, vki, physicalDevice,
1563 config.externalType, 0u, 0u, queueFamilyIndex));
1564 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
1565 context.getTestContext().getCommandLine());
1566 vk::SimpleAllocator alloc(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1567 const vk::VkQueue queue(getQueue(vkd, *device, queueFamilyIndex));
1568
1569 TestLog &log = context.getTestContext().getLog();
1570 const vk::Unique<vk::VkSemaphore> semaphoreA(createExportableSemaphore(vkd, *device, config.externalType));
1571
1572 {
1573 NativeHandle fd;
1574
1575 if (transference == TRANSFERENCE_COPY)
1576 {
1577 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex,
1578 *semaphoreA, config.externalType, fd);
1579 if (fd.getFd() == -1)
1580 return tcu::TestStatus::pass(
1581 "Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1582 }
1583 else
1584 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, fd);
1585
1586 NativeHandle newFd(dup(fd.getFd()));
1587
1588 if (newFd.getFd() < 0)
1589 log << TestLog::Message << "dup() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
1590
1591 TCU_CHECK_MSG(newFd.getFd() >= 0, "Failed to call dup() for semaphores fd");
1592
1593 {
1594 const vk::Unique<vk::VkSemaphore> semaphoreB(
1595 createAndImportSemaphore(vkd, *device, config.externalType, newFd, flags));
1596
1597 if (transference == TRANSFERENCE_COPY)
1598 submitEmptyWait(vkd, queue, *semaphoreB);
1599 else if (transference == TRANSFERENCE_REFERENCE)
1600 {
1601 submitEmptySignal(vkd, queue, *semaphoreA);
1602 submitEmptyWait(vkd, queue, *semaphoreB);
1603 }
1604 else
1605 DE_FATAL("Unknown permanence.");
1606
1607 VK_CHECK(vkd.queueWaitIdle(queue));
1608 }
1609 }
1610
1611 return tcu::TestStatus::pass("Pass");
1612 }
1613 #else
1614 DE_UNREF(context);
1615 DE_UNREF(config);
1616 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
1617 #endif
1618 }
1619
testSemaphoreFdDup2(Context & context,const SemaphoreTestConfig config)1620 tcu::TestStatus testSemaphoreFdDup2(Context &context, const SemaphoreTestConfig config)
1621 {
1622 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
1623 const Transference transference(getHandelTypeTransferences(config.externalType));
1624 const vk::PlatformInterface &vkp(context.getPlatformInterface());
1625 const CustomInstance instance(createTestInstance(context, config.externalType, 0u, 0u));
1626 const vk::InstanceDriver &vki(instance.getDriver());
1627 const vk::VkPhysicalDevice physicalDevice(
1628 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1629 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1630
1631 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1632
1633 {
1634 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ?
1635 vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT :
1636 (vk::VkSemaphoreImportFlagBits)0u;
1637 const vk::Unique<vk::VkDevice> device(createTestDevice(context, vkp, instance, vki, physicalDevice,
1638 config.externalType, 0u, 0u, queueFamilyIndex));
1639 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
1640 context.getTestContext().getCommandLine());
1641 vk::SimpleAllocator alloc(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1642 const vk::VkQueue queue(getQueue(vkd, *device, queueFamilyIndex));
1643
1644 TestLog &log = context.getTestContext().getLog();
1645 const vk::Unique<vk::VkSemaphore> semaphoreA(createExportableSemaphore(vkd, *device, config.externalType));
1646 const vk::Unique<vk::VkSemaphore> semaphoreB(createExportableSemaphore(vkd, *device, config.externalType));
1647
1648 {
1649 NativeHandle fd, secondFd;
1650
1651 if (transference == TRANSFERENCE_COPY)
1652 {
1653 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex,
1654 *semaphoreA, config.externalType, fd);
1655 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex,
1656 *semaphoreB, config.externalType, secondFd);
1657 if (fd.getFd() == -1 || secondFd.getFd() == -1)
1658 return tcu::TestStatus::pass(
1659 "Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1660 }
1661 else
1662 {
1663 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, fd);
1664 getSemaphoreNative(vkd, *device, *semaphoreB, config.externalType, secondFd);
1665 }
1666
1667 int newFd(dup2(fd.getFd(), secondFd.getFd()));
1668
1669 if (newFd < 0)
1670 log << TestLog::Message << "dup2() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
1671
1672 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup2() for fences fd");
1673
1674 {
1675 const vk::Unique<vk::VkSemaphore> semaphoreC(
1676 createAndImportSemaphore(vkd, *device, config.externalType, secondFd, flags));
1677
1678 if (transference == TRANSFERENCE_COPY)
1679 submitEmptyWait(vkd, queue, *semaphoreC);
1680 else if (transference == TRANSFERENCE_REFERENCE)
1681 {
1682 submitEmptySignal(vkd, queue, *semaphoreA);
1683 submitEmptyWait(vkd, queue, *semaphoreC);
1684 }
1685 else
1686 DE_FATAL("Unknown permanence.");
1687
1688 VK_CHECK(vkd.queueWaitIdle(queue));
1689 }
1690 }
1691
1692 return tcu::TestStatus::pass("Pass");
1693 }
1694 #else
1695 DE_UNREF(context);
1696 DE_UNREF(config);
1697 TCU_THROW(NotSupportedError, "Platform doesn't support dup2()");
1698 #endif
1699 }
1700
testSemaphoreFdDup3(Context & context,const SemaphoreTestConfig config)1701 tcu::TestStatus testSemaphoreFdDup3(Context &context, const SemaphoreTestConfig config)
1702 {
1703 #if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
1704 const Transference transference(getHandelTypeTransferences(config.externalType));
1705 const vk::PlatformInterface &vkp(context.getPlatformInterface());
1706 const CustomInstance instance(createTestInstance(context, config.externalType, 0u, 0u));
1707 const vk::InstanceDriver &vki(instance.getDriver());
1708 const vk::VkPhysicalDevice physicalDevice(
1709 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1710 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1711
1712 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1713
1714 {
1715 const vk::Unique<vk::VkDevice> device(createTestDevice(context, vkp, instance, vki, physicalDevice,
1716 config.externalType, 0u, 0u, queueFamilyIndex));
1717 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
1718 context.getTestContext().getCommandLine());
1719 vk::SimpleAllocator alloc(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1720 const vk::VkQueue queue(getQueue(vkd, *device, queueFamilyIndex));
1721
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));
1725
1726 {
1727 NativeHandle fd, secondFd;
1728
1729 if (transference == TRANSFERENCE_COPY)
1730 {
1731 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex,
1732 *semaphoreA, config.externalType, fd);
1733 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex,
1734 *semaphoreB, config.externalType, secondFd);
1735 if (fd.getFd() == -1 || secondFd.getFd() == -1)
1736 return tcu::TestStatus::pass(
1737 "Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1738 }
1739 else
1740 {
1741 getSemaphoreNative(vkd, *device, *semaphoreA, config.externalType, fd);
1742 getSemaphoreNative(vkd, *device, *semaphoreB, config.externalType, secondFd);
1743 }
1744
1745 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ?
1746 vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT :
1747 (vk::VkSemaphoreImportFlagBits)0u;
1748 const int newFd(dup3(fd.getFd(), secondFd.getFd(), 0));
1749
1750 if (newFd < 0)
1751 log << TestLog::Message << "dup3() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
1752
1753 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup3() for fences fd");
1754
1755 {
1756 const vk::Unique<vk::VkSemaphore> semaphoreC(
1757 createAndImportSemaphore(vkd, *device, config.externalType, secondFd, flags));
1758
1759 if (transference == TRANSFERENCE_COPY)
1760 submitEmptyWait(vkd, queue, *semaphoreC);
1761 else if (transference == TRANSFERENCE_REFERENCE)
1762 {
1763 submitEmptySignal(vkd, queue, *semaphoreA);
1764 submitEmptyWait(vkd, queue, *semaphoreC);
1765 }
1766 else
1767 DE_FATAL("Unknown permanence.");
1768
1769 VK_CHECK(vkd.queueWaitIdle(queue));
1770 }
1771 }
1772
1773 return tcu::TestStatus::pass("Pass");
1774 }
1775 #else
1776 DE_UNREF(context);
1777 DE_UNREF(config);
1778 TCU_THROW(NotSupportedError, "Platform doesn't support dup3()");
1779 #endif
1780 }
1781
testSemaphoreFdSendOverSocket(Context & context,const SemaphoreTestConfig config)1782 tcu::TestStatus testSemaphoreFdSendOverSocket(Context &context, const SemaphoreTestConfig config)
1783 {
1784 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
1785 const Transference transference(getHandelTypeTransferences(config.externalType));
1786 const vk::PlatformInterface &vkp(context.getPlatformInterface());
1787 const CustomInstance instance(createTestInstance(context, config.externalType, 0u, 0u));
1788 const vk::InstanceDriver &vki(instance.getDriver());
1789 const vk::VkPhysicalDevice physicalDevice(
1790 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1791 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1792
1793 checkSemaphoreSupport(vki, physicalDevice, config.externalType);
1794
1795 {
1796 const vk::Unique<vk::VkDevice> device(createTestDevice(context, vkp, instance, vki, physicalDevice,
1797 config.externalType, 0u, 0u, queueFamilyIndex));
1798 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
1799 context.getTestContext().getCommandLine());
1800 vk::SimpleAllocator alloc(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
1801 const vk::VkQueue queue(getQueue(vkd, *device, queueFamilyIndex));
1802
1803 TestLog &log = context.getTestContext().getLog();
1804 const vk::Unique<vk::VkSemaphore> semaphore(createExportableSemaphore(vkd, *device, config.externalType));
1805 NativeHandle fd;
1806
1807 if (transference == TRANSFERENCE_COPY)
1808 {
1809 submitAtomicCalculationsAndGetSemaphoreNative(context, vkd, *device, alloc, queue, queueFamilyIndex,
1810 *semaphore, config.externalType, fd);
1811 if (fd.getFd() == -1)
1812 return tcu::TestStatus::pass(
1813 "Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
1814 }
1815 else
1816 getSemaphoreNative(vkd, *device, *semaphore, config.externalType, fd);
1817
1818 {
1819 int sv[2];
1820
1821 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
1822 {
1823 log << TestLog::Message << "Failed to create socket pair: '" << strerror(errno) << "'"
1824 << TestLog::EndMessage;
1825 TCU_FAIL("Failed to create socket pair");
1826 }
1827
1828 {
1829 const NativeHandle srcSocket(sv[0]);
1830 const NativeHandle dstSocket(sv[1]);
1831 std::string sendData("deqp");
1832
1833 // Send FD
1834 {
1835 const int fdRaw(fd.getFd());
1836 msghdr msg;
1837 cmsghdr *cmsg;
1838 char buffer[CMSG_SPACE(sizeof(int))];
1839 iovec iov = {&sendData[0], sendData.length()};
1840
1841 deMemset(&msg, 0, sizeof(msg));
1842
1843 msg.msg_control = buffer;
1844 msg.msg_controllen = sizeof(buffer);
1845 msg.msg_iovlen = 1;
1846 msg.msg_iov = &iov;
1847
1848 cmsg = CMSG_FIRSTHDR(&msg);
1849 cmsg->cmsg_level = SOL_SOCKET;
1850 cmsg->cmsg_type = SCM_RIGHTS;
1851 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
1852
1853 deMemcpy(CMSG_DATA(cmsg), &fdRaw, sizeof(int));
1854 msg.msg_controllen = cmsg->cmsg_len;
1855
1856 if (sendmsg(srcSocket.getFd(), &msg, 0) < 0)
1857 {
1858 log << TestLog::Message << "Failed to send fd over socket: '" << strerror(errno) << "'"
1859 << TestLog::EndMessage;
1860 TCU_FAIL("Failed to send fd over socket");
1861 }
1862 }
1863
1864 // Recv FD
1865 {
1866 msghdr msg;
1867 char buffer[CMSG_SPACE(sizeof(int))];
1868 std::string recvData(4, '\0');
1869 iovec iov = {&recvData[0], recvData.length()};
1870
1871 deMemset(&msg, 0, sizeof(msg));
1872
1873 msg.msg_control = buffer;
1874 msg.msg_controllen = sizeof(buffer);
1875 msg.msg_iovlen = 1;
1876 msg.msg_iov = &iov;
1877
1878 const ssize_t bytes = recvmsg(dstSocket.getFd(), &msg, 0);
1879
1880 if (bytes < 0)
1881 {
1882 log << TestLog::Message << "Failed to recv fd over socket: '" << strerror(errno) << "'"
1883 << TestLog::EndMessage;
1884 TCU_FAIL("Failed to recv fd over socket");
1885 }
1886 else if (bytes != (ssize_t)sendData.length())
1887 {
1888 TCU_FAIL("recvmsg() returned unpexpected number of bytes");
1889 }
1890 else
1891 {
1892 const vk::VkSemaphoreImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ?
1893 vk::VK_SEMAPHORE_IMPORT_TEMPORARY_BIT :
1894 (vk::VkSemaphoreImportFlagBits)0u;
1895 const cmsghdr *const cmsg = CMSG_FIRSTHDR(&msg);
1896 int newFd_;
1897 deMemcpy(&newFd_, CMSG_DATA(cmsg), sizeof(int));
1898 NativeHandle newFd(newFd_);
1899
1900 TCU_CHECK(cmsg->cmsg_level == SOL_SOCKET);
1901 TCU_CHECK(cmsg->cmsg_type == SCM_RIGHTS);
1902 TCU_CHECK(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
1903 TCU_CHECK(recvData == sendData);
1904 TCU_CHECK_MSG(newFd.getFd() >= 0, "Didn't receive valid fd from socket");
1905
1906 {
1907 const vk::Unique<vk::VkSemaphore> newSemaphore(
1908 createAndImportSemaphore(vkd, *device, config.externalType, newFd, flags));
1909
1910 if (transference == TRANSFERENCE_COPY)
1911 submitEmptyWait(vkd, queue, *newSemaphore);
1912 else if (transference == TRANSFERENCE_REFERENCE)
1913 {
1914 submitEmptySignal(vkd, queue, *newSemaphore);
1915 submitEmptyWait(vkd, queue, *newSemaphore);
1916 }
1917 else
1918 DE_FATAL("Unknown permanence.");
1919
1920 VK_CHECK(vkd.queueWaitIdle(queue));
1921 }
1922 }
1923 }
1924 }
1925 }
1926 }
1927
1928 return tcu::TestStatus::pass("Pass");
1929 #else
1930 DE_UNREF(context);
1931 DE_UNREF(config);
1932 TCU_THROW(NotSupportedError, "Platform doesn't support sending file descriptors over socket");
1933 #endif
1934 }
1935
testFenceQueries(Context & context,vk::VkExternalFenceHandleTypeFlagBits externalType)1936 tcu::TestStatus testFenceQueries(Context &context, vk::VkExternalFenceHandleTypeFlagBits externalType)
1937 {
1938 const CustomInstance instance(createTestInstance(context, 0u, 0u, externalType));
1939 const vk::InstanceDriver &vki(instance.getDriver());
1940 const vk::VkPhysicalDevice device(vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1941
1942 TestLog &log = context.getTestContext().getLog();
1943
1944 const vk::VkPhysicalDeviceExternalFenceInfo info = {vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO,
1945 DE_NULL, externalType};
1946 vk::VkExternalFenceProperties properties = {vk::VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES, DE_NULL, 0u, 0u, 0u};
1947
1948 vki.getPhysicalDeviceExternalFenceProperties(device, &info, &properties);
1949 log << TestLog::Message << properties << TestLog::EndMessage;
1950
1951 TCU_CHECK(properties.pNext == DE_NULL);
1952 TCU_CHECK(properties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_FENCE_PROPERTIES);
1953
1954 return tcu::TestStatus::pass("Pass");
1955 }
1956
1957 struct FenceTestConfig
1958 {
FenceTestConfigvkt::api::__anone405665c0111::FenceTestConfig1959 FenceTestConfig(vk::VkExternalFenceHandleTypeFlagBits externalType_, Permanence permanence_)
1960 : externalType(externalType_)
1961 , permanence(permanence_)
1962 {
1963 }
1964
1965 vk::VkExternalFenceHandleTypeFlagBits externalType;
1966 Permanence permanence;
1967 };
1968
testFenceWin32Create(Context & context,const FenceTestConfig config)1969 tcu::TestStatus testFenceWin32Create(Context &context, const FenceTestConfig config)
1970 {
1971 #if (DE_OS == DE_OS_WIN32)
1972 const Transference transference(getHandelTypeTransferences(config.externalType));
1973 const vk::PlatformInterface &vkp(context.getPlatformInterface());
1974 const CustomInstance instance(createTestInstance(context, 0u, 0u, config.externalType));
1975 const vk::InstanceDriver &vki(instance.getDriver());
1976 const vk::VkPhysicalDevice physicalDevice(
1977 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
1978 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
1979
1980 checkFenceSupport(vki, physicalDevice, config.externalType);
1981
1982 {
1983 const vk::Unique<vk::VkDevice> device(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u,
1984 config.externalType, queueFamilyIndex));
1985 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
1986 context.getTestContext().getCommandLine());
1987 const vk::VkQueue queue(getQueue(vkd, *device, queueFamilyIndex));
1988 const vk::VkExportFenceWin32HandleInfoKHR win32ExportInfo = {
1989 vk::VK_STRUCTURE_TYPE_EXPORT_FENCE_WIN32_HANDLE_INFO_KHR, DE_NULL,
1990
1991 (vk::pt::Win32SecurityAttributesPtr)DE_NULL, DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
1992 (vk::pt::Win32LPCWSTR)DE_NULL};
1993 const vk::VkExportFenceCreateInfo exportCreateInfo = {vk::VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO,
1994 &win32ExportInfo,
1995 (vk::VkExternalFenceHandleTypeFlags)config.externalType};
1996 const vk::VkFenceCreateInfo createInfo = {vk::VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, &exportCreateInfo, 0u};
1997 const vk::Unique<vk::VkFence> fence(vk::createFence(vkd, *device, &createInfo));
1998
1999 if (transference == TRANSFERENCE_COPY)
2000 submitEmptySignal(vkd, queue, *fence);
2001
2002 NativeHandle handleA;
2003 getFenceNative(vkd, *device, *fence, config.externalType, handleA);
2004
2005 {
2006 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ?
2007 vk::VK_FENCE_IMPORT_TEMPORARY_BIT :
2008 (vk::VkFenceImportFlagBits)0u;
2009 const vk::Unique<vk::VkFence> fenceA(
2010 createAndImportFence(vkd, *device, config.externalType, handleA, flags));
2011
2012 if (transference == TRANSFERENCE_COPY)
2013 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2014 else if (transference == TRANSFERENCE_REFERENCE)
2015 {
2016 submitEmptySignal(vkd, queue, *fence);
2017 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2018 }
2019 else
2020 DE_FATAL("Unknown transference.");
2021
2022 VK_CHECK(vkd.queueWaitIdle(queue));
2023 }
2024
2025 return tcu::TestStatus::pass("Pass");
2026 }
2027 #else
2028 DE_UNREF(context);
2029 DE_UNREF(config);
2030 TCU_THROW(NotSupportedError, "Platform doesn't support win32 handles");
2031 #endif
2032 }
2033
testFenceImportTwice(Context & context,const FenceTestConfig config)2034 tcu::TestStatus testFenceImportTwice(Context &context, const FenceTestConfig config)
2035 {
2036 const Transference transference(getHandelTypeTransferences(config.externalType));
2037 const vk::PlatformInterface &vkp(context.getPlatformInterface());
2038 const CustomInstance instance(createTestInstance(context, 0u, 0u, config.externalType));
2039 const vk::InstanceDriver &vki(instance.getDriver());
2040 const vk::VkPhysicalDevice physicalDevice(
2041 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2042 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2043
2044 checkFenceSupport(vki, physicalDevice, config.externalType);
2045
2046 {
2047 const vk::Unique<vk::VkDevice> device(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u,
2048 config.externalType, queueFamilyIndex));
2049 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
2050 context.getTestContext().getCommandLine());
2051 vk::SimpleAllocator alloc(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2052 const vk::VkQueue queue(getQueue(vkd, *device, queueFamilyIndex));
2053 const vk::Unique<vk::VkFence> fence(createExportableFence(vkd, *device, config.externalType));
2054 NativeHandle handleA;
2055
2056 if (transference == TRANSFERENCE_COPY)
2057 {
2058 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fence,
2059 config.externalType, handleA);
2060 if (handleA.hasValidFd() && handleA.getFd() == -1)
2061 return tcu::TestStatus::pass(
2062 "Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2063 }
2064 else
2065 getFenceNative(vkd, *device, *fence, config.externalType, handleA);
2066
2067 {
2068 NativeHandle handleB(handleA);
2069 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ?
2070 vk::VK_FENCE_IMPORT_TEMPORARY_BIT :
2071 (vk::VkFenceImportFlagBits)0u;
2072 const vk::Unique<vk::VkFence> fenceA(
2073 createAndImportFence(vkd, *device, config.externalType, handleA, flags));
2074 const vk::Unique<vk::VkFence> fenceB(
2075 createAndImportFence(vkd, *device, config.externalType, handleB, flags));
2076
2077 if (transference == TRANSFERENCE_COPY)
2078 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2079 else if (transference == TRANSFERENCE_REFERENCE)
2080 {
2081 submitEmptySignal(vkd, queue, *fenceA);
2082 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2083 }
2084 else
2085 DE_FATAL("Unknown transference.");
2086
2087 VK_CHECK(vkd.queueWaitIdle(queue));
2088 }
2089
2090 return tcu::TestStatus::pass("Pass");
2091 }
2092 }
2093
testFenceImportReimport(Context & context,const FenceTestConfig config)2094 tcu::TestStatus testFenceImportReimport(Context &context, const FenceTestConfig config)
2095 {
2096 const Transference transference(getHandelTypeTransferences(config.externalType));
2097 const vk::PlatformInterface &vkp(context.getPlatformInterface());
2098 const CustomInstance instance(createTestInstance(context, 0u, 0u, config.externalType));
2099 const vk::InstanceDriver &vki(instance.getDriver());
2100 const vk::VkPhysicalDevice physicalDevice(
2101 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2102 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2103
2104 checkFenceSupport(vki, physicalDevice, config.externalType);
2105
2106 {
2107 const vk::Unique<vk::VkDevice> device(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u,
2108 config.externalType, queueFamilyIndex));
2109 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
2110 context.getTestContext().getCommandLine());
2111 vk::SimpleAllocator alloc(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2112 const vk::VkQueue queue(getQueue(vkd, *device, queueFamilyIndex));
2113
2114 const vk::Unique<vk::VkFence> fenceA(createExportableFence(vkd, *device, config.externalType));
2115 NativeHandle handleA;
2116
2117 if (transference == TRANSFERENCE_COPY)
2118 {
2119 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA,
2120 config.externalType, handleA);
2121 if (handleA.hasValidFd() && handleA.getFd() == -1)
2122 return tcu::TestStatus::pass(
2123 "Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2124 }
2125 else
2126 getFenceNative(vkd, *device, *fenceA, config.externalType, handleA);
2127
2128 NativeHandle handleB(handleA);
2129 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ?
2130 vk::VK_FENCE_IMPORT_TEMPORARY_BIT :
2131 (vk::VkFenceImportFlagBits)0u;
2132 const vk::Unique<vk::VkFence> fenceB(createAndImportFence(vkd, *device, config.externalType, handleA, flags));
2133
2134 importFence(vkd, *device, *fenceB, config.externalType, handleB, flags);
2135
2136 if (transference == TRANSFERENCE_COPY)
2137 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2138 else if (transference == TRANSFERENCE_REFERENCE)
2139 {
2140 submitEmptySignal(vkd, queue, *fenceA);
2141 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2142 }
2143 else
2144 DE_FATAL("Unknown transference.");
2145
2146 VK_CHECK(vkd.queueWaitIdle(queue));
2147
2148 return tcu::TestStatus::pass("Pass");
2149 }
2150 }
2151
testFenceSignalExportImportWait(Context & context,const FenceTestConfig config)2152 tcu::TestStatus testFenceSignalExportImportWait(Context &context, const FenceTestConfig config)
2153 {
2154 const vk::PlatformInterface &vkp(context.getPlatformInterface());
2155 const CustomInstance instance(createTestInstance(context, 0u, 0u, config.externalType));
2156 const vk::InstanceDriver &vki(instance.getDriver());
2157 const vk::VkPhysicalDevice physicalDevice(
2158 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2159 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2160
2161 checkFenceSupport(vki, physicalDevice, config.externalType);
2162
2163 {
2164 const vk::Unique<vk::VkDevice> device(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u,
2165 config.externalType, queueFamilyIndex));
2166 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
2167 context.getTestContext().getCommandLine());
2168 vk::SimpleAllocator alloc(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2169 const vk::VkQueue queue(getQueue(vkd, *device, queueFamilyIndex));
2170 const vk::Unique<vk::VkFence> fenceA(createExportableFence(vkd, *device, config.externalType));
2171
2172 {
2173 NativeHandle handle;
2174
2175 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA,
2176 config.externalType, handle);
2177 if (handle.hasValidFd() && handle.getFd() == -1)
2178 return tcu::TestStatus::pass(
2179 "Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2180
2181 {
2182 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ?
2183 vk::VK_FENCE_IMPORT_TEMPORARY_BIT :
2184 (vk::VkFenceImportFlagBits)0u;
2185 const vk::Unique<vk::VkFence> fenceB(
2186 createAndImportFence(vkd, *device, config.externalType, handle, flags));
2187 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2188
2189 VK_CHECK(vkd.queueWaitIdle(queue));
2190 }
2191 }
2192
2193 return tcu::TestStatus::pass("Pass");
2194 }
2195 }
2196
testFenceImportSyncFdSignaled(Context & context,const FenceTestConfig config)2197 tcu::TestStatus testFenceImportSyncFdSignaled(Context &context, const FenceTestConfig config)
2198 {
2199 const vk::PlatformInterface &vkp(context.getPlatformInterface());
2200 const CustomInstance instance(createTestInstance(context, 0u, 0u, config.externalType));
2201 const vk::InstanceDriver &vki(instance.getDriver());
2202 const vk::VkPhysicalDevice physicalDevice(
2203 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2204 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2205 const vk::VkFenceImportFlags flags =
2206 config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2207
2208 checkFenceSupport(vki, physicalDevice, config.externalType);
2209
2210 {
2211 const vk::Unique<vk::VkDevice> device(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u,
2212 config.externalType, queueFamilyIndex));
2213 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
2214 context.getTestContext().getCommandLine());
2215 NativeHandle handle = -1;
2216 const vk::Unique<vk::VkFence> fence(createAndImportFence(vkd, *device, config.externalType, handle, flags));
2217
2218 if (vkd.waitForFences(*device, 1u, &*fence, VK_TRUE, 0) != vk::VK_SUCCESS)
2219 return tcu::TestStatus::pass("Imported -1 sync fd isn't signaled");
2220
2221 return tcu::TestStatus::pass("Pass");
2222 }
2223 }
2224
testFenceExportSignalImportWait(Context & context,const FenceTestConfig config)2225 tcu::TestStatus testFenceExportSignalImportWait(Context &context, const FenceTestConfig config)
2226 {
2227 const vk::PlatformInterface &vkp(context.getPlatformInterface());
2228 const CustomInstance instance(createTestInstance(context, 0u, 0u, config.externalType));
2229 const vk::InstanceDriver &vki(instance.getDriver());
2230 const vk::VkPhysicalDevice physicalDevice(
2231 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2232 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2233 const vk::VkFenceImportFlags flags =
2234 config.permanence == PERMANENCE_TEMPORARY ? vk::VK_FENCE_IMPORT_TEMPORARY_BIT : (vk::VkFenceImportFlagBits)0u;
2235
2236 DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
2237 checkFenceSupport(vki, physicalDevice, config.externalType);
2238
2239 {
2240 const vk::Unique<vk::VkDevice> device(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u,
2241 config.externalType, queueFamilyIndex));
2242 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
2243 context.getTestContext().getCommandLine());
2244 const vk::VkQueue queue(getQueue(vkd, *device, queueFamilyIndex));
2245
2246 const vk::Unique<vk::VkFence> fenceA(createExportableFence(vkd, *device, config.externalType));
2247 NativeHandle handle;
2248
2249 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2250
2251 submitEmptySignal(vkd, queue, *fenceA);
2252 {
2253 {
2254 const vk::Unique<vk::VkFence> fenceB(
2255 createAndImportFence(vkd, *device, config.externalType, handle, flags));
2256
2257 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2258 VK_CHECK(vkd.queueWaitIdle(queue));
2259 }
2260 }
2261
2262 return tcu::TestStatus::pass("Pass");
2263 }
2264 }
2265
testFenceExportImportSignalWait(Context & context,const FenceTestConfig config)2266 tcu::TestStatus testFenceExportImportSignalWait(Context &context, const FenceTestConfig config)
2267 {
2268 const vk::PlatformInterface &vkp(context.getPlatformInterface());
2269 const CustomInstance instance(createTestInstance(context, 0u, 0u, config.externalType));
2270 const vk::InstanceDriver &vki(instance.getDriver());
2271 const vk::VkPhysicalDevice physicalDevice(
2272 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2273 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2274
2275 DE_ASSERT(getHandelTypeTransferences(config.externalType) == TRANSFERENCE_REFERENCE);
2276 checkFenceSupport(vki, physicalDevice, config.externalType);
2277
2278 {
2279 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ?
2280 vk::VK_FENCE_IMPORT_TEMPORARY_BIT :
2281 (vk::VkFenceImportFlagBits)0u;
2282 const vk::Unique<vk::VkDevice> device(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u,
2283 config.externalType, queueFamilyIndex));
2284 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
2285 context.getTestContext().getCommandLine());
2286 const vk::VkQueue queue(getQueue(vkd, *device, queueFamilyIndex));
2287
2288 const vk::Unique<vk::VkFence> fenceA(createExportableFence(vkd, *device, config.externalType));
2289 NativeHandle handle;
2290
2291 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2292
2293 const vk::Unique<vk::VkFence> fenceB(createAndImportFence(vkd, *device, config.externalType, handle, flags));
2294
2295 submitEmptySignal(vkd, queue, *fenceA);
2296 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2297
2298 VK_CHECK(vkd.queueWaitIdle(queue));
2299
2300 return tcu::TestStatus::pass("Pass");
2301 }
2302 }
2303
testFenceSignalImport(Context & context,const FenceTestConfig config)2304 tcu::TestStatus testFenceSignalImport(Context &context, const FenceTestConfig config)
2305 {
2306 const Transference transference(getHandelTypeTransferences(config.externalType));
2307 const vk::PlatformInterface &vkp(context.getPlatformInterface());
2308 const CustomInstance instance(createTestInstance(context, 0u, 0u, config.externalType));
2309 const vk::InstanceDriver &vki(instance.getDriver());
2310 const vk::VkPhysicalDevice physicalDevice(
2311 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2312 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2313
2314 checkFenceSupport(vki, physicalDevice, config.externalType);
2315
2316 {
2317 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ?
2318 vk::VK_FENCE_IMPORT_TEMPORARY_BIT :
2319 (vk::VkFenceImportFlagBits)0u;
2320 const vk::Unique<vk::VkDevice> device(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u,
2321 config.externalType, queueFamilyIndex));
2322 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
2323 context.getTestContext().getCommandLine());
2324 vk::SimpleAllocator alloc(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2325 const vk::VkQueue queue(getQueue(vkd, *device, queueFamilyIndex));
2326
2327 const vk::Unique<vk::VkFence> fenceA(createExportableFence(vkd, *device, config.externalType));
2328 const vk::Unique<vk::VkFence> fenceB(createFence(vkd, *device));
2329 NativeHandle handle;
2330
2331 submitEmptySignal(vkd, queue, *fenceB);
2332 VK_CHECK(vkd.queueWaitIdle(queue));
2333
2334 if (transference == TRANSFERENCE_COPY)
2335 {
2336 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA,
2337 config.externalType, handle);
2338 if (handle.hasValidFd() && handle.getFd() == -1)
2339 return tcu::TestStatus::pass(
2340 "Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2341 }
2342 else
2343 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2344
2345 importFence(vkd, *device, *fenceB, config.externalType, handle, flags);
2346
2347 if (transference == TRANSFERENCE_COPY)
2348 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2349 else if (transference == TRANSFERENCE_REFERENCE)
2350 {
2351 submitEmptySignal(vkd, queue, *fenceA);
2352 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2353 }
2354 else
2355 DE_FATAL("Unknown transference.");
2356
2357 VK_CHECK(vkd.queueWaitIdle(queue));
2358
2359 return tcu::TestStatus::pass("Pass");
2360 }
2361 }
2362
testFenceReset(Context & context,const FenceTestConfig config)2363 tcu::TestStatus testFenceReset(Context &context, const FenceTestConfig config)
2364 {
2365 const Transference transference(getHandelTypeTransferences(config.externalType));
2366 const vk::PlatformInterface &vkp(context.getPlatformInterface());
2367 const CustomInstance instance(createTestInstance(context, 0u, 0u, config.externalType));
2368 const vk::InstanceDriver &vki(instance.getDriver());
2369 const vk::VkPhysicalDevice physicalDevice(
2370 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2371 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2372
2373 checkFenceSupport(vki, physicalDevice, config.externalType);
2374
2375 {
2376 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ?
2377 vk::VK_FENCE_IMPORT_TEMPORARY_BIT :
2378 (vk::VkFenceImportFlagBits)0u;
2379 const vk::Unique<vk::VkDevice> device(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u,
2380 config.externalType, queueFamilyIndex));
2381 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
2382 context.getTestContext().getCommandLine());
2383 vk::SimpleAllocator alloc(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2384 const vk::VkQueue queue(getQueue(vkd, *device, queueFamilyIndex));
2385
2386 const vk::Unique<vk::VkFence> fenceA(createExportableFence(vkd, *device, config.externalType));
2387 const vk::Unique<vk::VkFence> fenceB(createFence(vkd, *device));
2388 const vk::Unique<vk::VkFence> fenceC(createFence(vkd, *device));
2389 NativeHandle handle;
2390
2391 submitEmptySignal(vkd, queue, *fenceB);
2392 VK_CHECK(vkd.queueWaitIdle(queue));
2393
2394 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA,
2395 config.externalType, handle);
2396 if (handle.hasValidFd() && handle.getFd() == -1)
2397 return tcu::TestStatus::pass(
2398 "Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2399
2400 NativeHandle handleB(handle);
2401 importFence(vkd, *device, *fenceB, config.externalType, handleB, flags);
2402 importFence(vkd, *device, *fenceC, config.externalType, handle, flags);
2403
2404 VK_CHECK(vkd.queueWaitIdle(queue));
2405 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2406
2407 if (config.permanence == PERMANENCE_TEMPORARY || transference == TRANSFERENCE_COPY)
2408 {
2409 // vkResetFences() should restore fenceBs prior payload and reset that no affecting fenceCs payload
2410 // or fenceB should be separate copy of the payload and not affect fenceC
2411 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2412
2413 // vkResetFences() should have restored fenceBs prior state and should be now reset
2414 // or fenceB should have it's separate payload
2415 submitEmptySignal(vkd, queue, *fenceB);
2416 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2417 }
2418 else if (config.permanence == PERMANENCE_PERMANENT)
2419 {
2420 DE_ASSERT(transference == TRANSFERENCE_REFERENCE);
2421
2422 // Reset fences should have reset all of the fences
2423 submitEmptySignal(vkd, queue, *fenceC);
2424
2425 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2426 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2427 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2428 }
2429 else
2430 DE_FATAL("Unknown permanence");
2431
2432 VK_CHECK(vkd.queueWaitIdle(queue));
2433
2434 return tcu::TestStatus::pass("Pass");
2435 }
2436 }
2437
testFenceSignalWaitImport(Context & context,const FenceTestConfig config)2438 tcu::TestStatus testFenceSignalWaitImport(Context &context, const FenceTestConfig config)
2439 {
2440 const vk::PlatformInterface &vkp(context.getPlatformInterface());
2441 const CustomInstance instance(createTestInstance(context, 0u, 0u, config.externalType));
2442 const vk::InstanceDriver &vki(instance.getDriver());
2443 const vk::VkPhysicalDevice physicalDevice(
2444 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2445 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2446
2447 checkFenceSupport(vki, physicalDevice, config.externalType);
2448
2449 {
2450 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ?
2451 vk::VK_FENCE_IMPORT_TEMPORARY_BIT :
2452 (vk::VkFenceImportFlagBits)0u;
2453 const vk::Unique<vk::VkDevice> device(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u,
2454 config.externalType, queueFamilyIndex));
2455 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
2456 context.getTestContext().getCommandLine());
2457 const vk::VkQueue queue(getQueue(vkd, *device, queueFamilyIndex));
2458
2459 const vk::Unique<vk::VkFence> fenceA(createExportableFence(vkd, *device, config.externalType));
2460 const vk::Unique<vk::VkFence> fenceB(createFence(vkd, *device));
2461 NativeHandle handle;
2462
2463 getFenceNative(vkd, *device, *fenceA, config.externalType, handle);
2464
2465 submitEmptySignal(vkd, queue, *fenceB);
2466 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2467
2468 VK_CHECK(vkd.queueWaitIdle(queue));
2469
2470 importFence(vkd, *device, *fenceB, config.externalType, handle, flags);
2471
2472 submitEmptySignal(vkd, queue, *fenceA);
2473 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2474
2475 VK_CHECK(vkd.queueWaitIdle(queue));
2476
2477 return tcu::TestStatus::pass("Pass");
2478 }
2479 }
2480
testFenceMultipleExports(Context & context,const FenceTestConfig config)2481 tcu::TestStatus testFenceMultipleExports(Context &context, const FenceTestConfig config)
2482 {
2483 const size_t exportCount = 1024;
2484 const Transference transference(getHandelTypeTransferences(config.externalType));
2485 const vk::PlatformInterface &vkp(context.getPlatformInterface());
2486 const CustomInstance instance(createTestInstance(context, 0u, 0u, config.externalType));
2487 const vk::InstanceDriver &vki(instance.getDriver());
2488 const vk::VkPhysicalDevice physicalDevice(
2489 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2490 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2491
2492 checkFenceSupport(vki, physicalDevice, config.externalType);
2493
2494 {
2495 const vk::Unique<vk::VkDevice> device(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u,
2496 config.externalType, queueFamilyIndex));
2497 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
2498 context.getTestContext().getCommandLine());
2499 vk::SimpleAllocator alloc(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2500 const vk::VkQueue queue(getQueue(vkd, *device, queueFamilyIndex));
2501 const vk::Unique<vk::VkFence> fence(createExportableFence(vkd, *device, config.externalType));
2502
2503 for (size_t exportNdx = 0; exportNdx < exportCount; exportNdx++)
2504 {
2505 NativeHandle handle;
2506
2507 // Need to touch watchdog due to how long one iteration takes
2508 context.getTestContext().touchWatchdog();
2509
2510 if (transference == TRANSFERENCE_COPY)
2511 {
2512 submitAtomicCalculationsAndGetFenceNative(
2513 context, vkd, *device, alloc, queue, queueFamilyIndex, *fence, config.externalType, handle,
2514 exportNdx == 0 /* expect fence to be signaled after first pass */);
2515 if (handle.hasValidFd() && handle.getFd() == -1)
2516 return tcu::TestStatus::pass(
2517 "Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2518 }
2519 else
2520 getFenceNative(vkd, *device, *fence, config.externalType, handle,
2521 exportNdx == 0 /* expect fence to be signaled after first pass */);
2522 }
2523
2524 submitEmptySignal(vkd, queue, *fence);
2525 VK_CHECK(vkd.waitForFences(*device, 1u, &*fence, VK_TRUE, ~0ull));
2526
2527 VK_CHECK(vkd.queueWaitIdle(queue));
2528 }
2529
2530 return tcu::TestStatus::pass("Pass");
2531 }
2532
testFenceMultipleImports(Context & context,const FenceTestConfig config)2533 tcu::TestStatus testFenceMultipleImports(Context &context, const FenceTestConfig config)
2534 {
2535 const size_t importCount = 4 * 1024;
2536 const Transference transference(getHandelTypeTransferences(config.externalType));
2537 const vk::PlatformInterface &vkp(context.getPlatformInterface());
2538 const CustomInstance instance(createTestInstance(context, 0u, 0u, config.externalType));
2539 const vk::InstanceDriver &vki(instance.getDriver());
2540 const vk::VkPhysicalDevice physicalDevice(
2541 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2542 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2543
2544 checkFenceSupport(vki, physicalDevice, config.externalType);
2545
2546 {
2547 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ?
2548 vk::VK_FENCE_IMPORT_TEMPORARY_BIT :
2549 (vk::VkFenceImportFlagBits)0u;
2550 const vk::Unique<vk::VkDevice> device(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u,
2551 config.externalType, queueFamilyIndex));
2552 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
2553 context.getTestContext().getCommandLine());
2554 vk::SimpleAllocator alloc(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2555 const vk::VkQueue queue(getQueue(vkd, *device, queueFamilyIndex));
2556 const vk::Unique<vk::VkFence> fenceA(createExportableFence(vkd, *device, config.externalType));
2557 NativeHandle handleA;
2558
2559 if (transference == TRANSFERENCE_COPY)
2560 {
2561 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA,
2562 config.externalType, handleA);
2563 if (handleA.hasValidFd() && handleA.getFd() == -1)
2564 return tcu::TestStatus::pass(
2565 "Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2566 }
2567 else
2568 getFenceNative(vkd, *device, *fenceA, config.externalType, handleA);
2569
2570 for (size_t importNdx = 0; importNdx < importCount; importNdx++)
2571 {
2572 NativeHandle handleB(handleA);
2573 const vk::Unique<vk::VkFence> fenceB(
2574 createAndImportFence(vkd, *device, config.externalType, handleB, flags));
2575 }
2576
2577 if (transference == TRANSFERENCE_COPY)
2578 {
2579 importFence(vkd, *device, *fenceA, config.externalType, handleA, flags);
2580 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2581 }
2582 else if (transference == TRANSFERENCE_REFERENCE)
2583 {
2584 submitEmptySignal(vkd, queue, *fenceA);
2585 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2586 }
2587 else
2588 DE_FATAL("Unknown transference.");
2589
2590 VK_CHECK(vkd.queueWaitIdle(queue));
2591 }
2592
2593 return tcu::TestStatus::pass("Pass");
2594 }
2595
testFenceTransference(Context & context,const FenceTestConfig config)2596 tcu::TestStatus testFenceTransference(Context &context, const FenceTestConfig config)
2597 {
2598 const Transference transference(getHandelTypeTransferences(config.externalType));
2599 const vk::PlatformInterface &vkp(context.getPlatformInterface());
2600 const CustomInstance instance(createTestInstance(context, 0u, 0u, config.externalType));
2601 const vk::InstanceDriver &vki(instance.getDriver());
2602 const vk::VkPhysicalDevice physicalDevice(
2603 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2604 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2605
2606 checkFenceSupport(vki, physicalDevice, config.externalType);
2607
2608 {
2609 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ?
2610 vk::VK_FENCE_IMPORT_TEMPORARY_BIT :
2611 (vk::VkFenceImportFlagBits)0u;
2612 const vk::Unique<vk::VkDevice> device(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u,
2613 config.externalType, queueFamilyIndex));
2614 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
2615 context.getTestContext().getCommandLine());
2616 vk::SimpleAllocator alloc(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2617 const vk::VkQueue queue(getQueue(vkd, *device, queueFamilyIndex));
2618
2619 const vk::Unique<vk::VkFence> fenceA(createExportableFence(vkd, *device, config.externalType));
2620 NativeHandle handle;
2621
2622 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fenceA,
2623 config.externalType, handle);
2624 if (handle.hasValidFd() && handle.getFd() == -1)
2625 return tcu::TestStatus::pass(
2626 "Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2627
2628 {
2629 const vk::Unique<vk::VkFence> fenceB(
2630 createAndImportFence(vkd, *device, config.externalType, handle, flags));
2631
2632 if (config.permanence == PERMANENCE_PERMANENT)
2633 {
2634 if (transference == TRANSFERENCE_COPY)
2635 {
2636 submitEmptySignal(vkd, queue, *fenceA);
2637 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2638 VK_CHECK(vkd.queueWaitIdle(queue));
2639
2640 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2641 submitEmptySignal(vkd, queue, *fenceB);
2642
2643 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2644 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2645 VK_CHECK(vkd.queueWaitIdle(queue));
2646 }
2647 else if (transference == TRANSFERENCE_REFERENCE)
2648 {
2649 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2650 VK_CHECK(vkd.queueWaitIdle(queue));
2651
2652 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2653 submitEmptySignal(vkd, queue, *fenceA);
2654 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2655
2656 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceA));
2657 submitEmptySignal(vkd, queue, *fenceB);
2658 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2659 VK_CHECK(vkd.queueWaitIdle(queue));
2660 }
2661 else
2662 DE_FATAL("Unknown transference.");
2663 }
2664 else if (config.permanence == PERMANENCE_TEMPORARY)
2665 {
2666 if (transference == TRANSFERENCE_COPY)
2667 {
2668 submitEmptySignal(vkd, queue, *fenceA);
2669 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2670 VK_CHECK(vkd.queueWaitIdle(queue));
2671
2672 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2673 submitEmptySignal(vkd, queue, *fenceB);
2674
2675 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2676 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2677 VK_CHECK(vkd.queueWaitIdle(queue));
2678 }
2679 else if (transference == TRANSFERENCE_REFERENCE)
2680 {
2681 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2682 VK_CHECK(vkd.queueWaitIdle(queue));
2683
2684 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceA));
2685 VK_CHECK(vkd.resetFences(*device, 1u, &*fenceB));
2686 submitEmptySignal(vkd, queue, *fenceA);
2687 submitEmptySignal(vkd, queue, *fenceB);
2688
2689 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2690 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceA, VK_TRUE, ~0ull));
2691 VK_CHECK(vkd.queueWaitIdle(queue));
2692 }
2693 else
2694 DE_FATAL("Unknown transference.");
2695 }
2696 else
2697 DE_FATAL("Unknown permanence.");
2698 }
2699
2700 return tcu::TestStatus::pass("Pass");
2701 }
2702 }
2703
testFenceFdDup(Context & context,const FenceTestConfig config)2704 tcu::TestStatus testFenceFdDup(Context &context, const FenceTestConfig config)
2705 {
2706 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2707 const Transference transference(getHandelTypeTransferences(config.externalType));
2708 const vk::PlatformInterface &vkp(context.getPlatformInterface());
2709 const CustomInstance instance(createTestInstance(context, 0u, 0u, config.externalType));
2710 const vk::InstanceDriver &vki(instance.getDriver());
2711 const vk::VkPhysicalDevice physicalDevice(
2712 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2713 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2714
2715 checkFenceSupport(vki, physicalDevice, config.externalType);
2716
2717 {
2718 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ?
2719 vk::VK_FENCE_IMPORT_TEMPORARY_BIT :
2720 (vk::VkFenceImportFlagBits)0u;
2721 const vk::Unique<vk::VkDevice> device(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u,
2722 config.externalType, queueFamilyIndex));
2723 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
2724 context.getTestContext().getCommandLine());
2725 vk::SimpleAllocator alloc(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2726 const vk::VkQueue queue(getQueue(vkd, *device, queueFamilyIndex));
2727
2728 TestLog &log = context.getTestContext().getLog();
2729 const vk::Unique<vk::VkFence> fenceA(createExportableFence(vkd, *device, config.externalType));
2730
2731 {
2732 NativeHandle fd;
2733
2734 if (transference == TRANSFERENCE_COPY)
2735 {
2736 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex,
2737 *fenceA, config.externalType, fd);
2738 if (fd.getFd() == -1)
2739 return tcu::TestStatus::pass(
2740 "Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2741 }
2742 else
2743 getFenceNative(vkd, *device, *fenceA, config.externalType, fd);
2744
2745 NativeHandle newFd(dup(fd.getFd()));
2746
2747 if (newFd.getFd() < 0)
2748 log << TestLog::Message << "dup() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2749
2750 TCU_CHECK_MSG(newFd.getFd() >= 0, "Failed to call dup() for fences fd");
2751
2752 {
2753 const vk::Unique<vk::VkFence> fenceB(
2754 createAndImportFence(vkd, *device, config.externalType, newFd, flags));
2755
2756 if (transference == TRANSFERENCE_COPY)
2757 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2758 else if (transference == TRANSFERENCE_REFERENCE)
2759 {
2760 submitEmptySignal(vkd, queue, *fenceA);
2761 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceB, VK_TRUE, ~0ull));
2762 }
2763 else
2764 DE_FATAL("Unknown permanence.");
2765
2766 VK_CHECK(vkd.queueWaitIdle(queue));
2767 }
2768 }
2769
2770 return tcu::TestStatus::pass("Pass");
2771 }
2772 #else
2773 DE_UNREF(context);
2774 DE_UNREF(config);
2775 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
2776 #endif
2777 }
2778
testFenceFdDup2(Context & context,const FenceTestConfig config)2779 tcu::TestStatus testFenceFdDup2(Context &context, const FenceTestConfig config)
2780 {
2781 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2782 const Transference transference(getHandelTypeTransferences(config.externalType));
2783 const vk::PlatformInterface &vkp(context.getPlatformInterface());
2784 const CustomInstance instance(createTestInstance(context, 0u, 0u, config.externalType));
2785 const vk::InstanceDriver &vki(instance.getDriver());
2786 const vk::VkPhysicalDevice physicalDevice(
2787 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2788 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2789
2790 checkFenceSupport(vki, physicalDevice, config.externalType);
2791
2792 {
2793 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ?
2794 vk::VK_FENCE_IMPORT_TEMPORARY_BIT :
2795 (vk::VkFenceImportFlagBits)0u;
2796 const vk::Unique<vk::VkDevice> device(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u,
2797 config.externalType, queueFamilyIndex));
2798 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
2799 context.getTestContext().getCommandLine());
2800 vk::SimpleAllocator alloc(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2801 const vk::VkQueue queue(getQueue(vkd, *device, queueFamilyIndex));
2802
2803 TestLog &log = context.getTestContext().getLog();
2804 const vk::Unique<vk::VkFence> fenceA(createExportableFence(vkd, *device, config.externalType));
2805 const vk::Unique<vk::VkFence> fenceB(createExportableFence(vkd, *device, config.externalType));
2806
2807 {
2808 NativeHandle fd, secondFd;
2809
2810 if (transference == TRANSFERENCE_COPY)
2811 {
2812 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex,
2813 *fenceA, config.externalType, fd);
2814 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex,
2815 *fenceB, config.externalType, secondFd);
2816 if (fd.getFd() == -1 || secondFd.getFd() == -1)
2817 return tcu::TestStatus::pass(
2818 "Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2819 }
2820 else
2821 {
2822 getFenceNative(vkd, *device, *fenceA, config.externalType, fd);
2823 getFenceNative(vkd, *device, *fenceB, config.externalType, secondFd);
2824 }
2825
2826 int newFd(dup2(fd.getFd(), secondFd.getFd()));
2827
2828 if (newFd < 0)
2829 log << TestLog::Message << "dup2() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2830
2831 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup2() for fences fd");
2832
2833 {
2834 const vk::Unique<vk::VkFence> fenceC(
2835 createAndImportFence(vkd, *device, config.externalType, secondFd, flags));
2836
2837 if (transference == TRANSFERENCE_COPY)
2838 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2839 else if (transference == TRANSFERENCE_REFERENCE)
2840 {
2841 submitEmptySignal(vkd, queue, *fenceA);
2842 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2843 }
2844 else
2845 DE_FATAL("Unknown permanence.");
2846
2847 VK_CHECK(vkd.queueWaitIdle(queue));
2848 }
2849 }
2850
2851 return tcu::TestStatus::pass("Pass");
2852 }
2853 #else
2854 DE_UNREF(context);
2855 DE_UNREF(config);
2856 TCU_THROW(NotSupportedError, "Platform doesn't support dup2()");
2857 #endif
2858 }
2859
testFenceFdDup3(Context & context,const FenceTestConfig config)2860 tcu::TestStatus testFenceFdDup3(Context &context, const FenceTestConfig config)
2861 {
2862 #if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
2863 const Transference transference(getHandelTypeTransferences(config.externalType));
2864 const vk::PlatformInterface &vkp(context.getPlatformInterface());
2865 const CustomInstance instance(createTestInstance(context, 0u, 0u, config.externalType));
2866 const vk::InstanceDriver &vki(instance.getDriver());
2867 const vk::VkPhysicalDevice physicalDevice(
2868 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2869 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2870
2871 checkFenceSupport(vki, physicalDevice, config.externalType);
2872
2873 {
2874 const vk::Unique<vk::VkDevice> device(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u,
2875 config.externalType, queueFamilyIndex));
2876 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
2877 context.getTestContext().getCommandLine());
2878 vk::SimpleAllocator alloc(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2879 const vk::VkQueue queue(getQueue(vkd, *device, queueFamilyIndex));
2880
2881 TestLog &log = context.getTestContext().getLog();
2882 const vk::Unique<vk::VkFence> fenceA(createExportableFence(vkd, *device, config.externalType));
2883 const vk::Unique<vk::VkFence> fenceB(createExportableFence(vkd, *device, config.externalType));
2884
2885 {
2886 NativeHandle fd, secondFd;
2887
2888 if (transference == TRANSFERENCE_COPY)
2889 {
2890 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex,
2891 *fenceA, config.externalType, fd);
2892 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex,
2893 *fenceB, config.externalType, secondFd);
2894 if (fd.getFd() == -1 || secondFd.getFd() == -1)
2895 return tcu::TestStatus::pass(
2896 "Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2897 }
2898 else
2899 {
2900 getFenceNative(vkd, *device, *fenceA, config.externalType, fd);
2901 getFenceNative(vkd, *device, *fenceB, config.externalType, secondFd);
2902 }
2903
2904 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ?
2905 vk::VK_FENCE_IMPORT_TEMPORARY_BIT :
2906 (vk::VkFenceImportFlagBits)0u;
2907 const int newFd(dup3(fd.getFd(), secondFd.getFd(), 0));
2908
2909 if (newFd < 0)
2910 log << TestLog::Message << "dup3() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
2911
2912 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup3() for fences fd");
2913
2914 {
2915 const vk::Unique<vk::VkFence> fenceC(
2916 createAndImportFence(vkd, *device, config.externalType, secondFd, flags));
2917
2918 if (transference == TRANSFERENCE_COPY)
2919 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2920 else if (transference == TRANSFERENCE_REFERENCE)
2921 {
2922 submitEmptySignal(vkd, queue, *fenceA);
2923 VK_CHECK(vkd.waitForFences(*device, 1u, &*fenceC, VK_TRUE, ~0ull));
2924 }
2925 else
2926 DE_FATAL("Unknown permanence.");
2927
2928 VK_CHECK(vkd.queueWaitIdle(queue));
2929 }
2930 }
2931
2932 return tcu::TestStatus::pass("Pass");
2933 }
2934 #else
2935 DE_UNREF(context);
2936 DE_UNREF(config);
2937 TCU_THROW(NotSupportedError, "Platform doesn't support dup3()");
2938 #endif
2939 }
2940
testFenceFdSendOverSocket(Context & context,const FenceTestConfig config)2941 tcu::TestStatus testFenceFdSendOverSocket(Context &context, const FenceTestConfig config)
2942 {
2943 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
2944 const Transference transference(getHandelTypeTransferences(config.externalType));
2945 const vk::PlatformInterface &vkp(context.getPlatformInterface());
2946 const CustomInstance instance(createTestInstance(context, 0u, 0u, config.externalType));
2947 const vk::InstanceDriver &vki(instance.getDriver());
2948 const vk::VkPhysicalDevice physicalDevice(
2949 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
2950 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
2951
2952 checkFenceSupport(vki, physicalDevice, config.externalType);
2953
2954 {
2955 const vk::Unique<vk::VkDevice> device(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, 0u,
2956 config.externalType, queueFamilyIndex));
2957 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
2958 context.getTestContext().getCommandLine());
2959 vk::SimpleAllocator alloc(vkd, *device, vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
2960 const vk::VkQueue queue(getQueue(vkd, *device, queueFamilyIndex));
2961
2962 TestLog &log = context.getTestContext().getLog();
2963 const vk::Unique<vk::VkFence> fence(createExportableFence(vkd, *device, config.externalType));
2964 NativeHandle fd;
2965
2966 if (transference == TRANSFERENCE_COPY)
2967 {
2968 submitAtomicCalculationsAndGetFenceNative(context, vkd, *device, alloc, queue, queueFamilyIndex, *fence,
2969 config.externalType, fd);
2970 if (fd.getFd() == -1)
2971 return tcu::TestStatus::pass(
2972 "Pass: got -1 as a file descriptor, which is valid with a handle type of copy transference");
2973 }
2974 else
2975 getFenceNative(vkd, *device, *fence, config.externalType, fd);
2976
2977 {
2978 int sv[2];
2979
2980 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
2981 {
2982 log << TestLog::Message << "Failed to create socket pair: '" << strerror(errno) << "'"
2983 << TestLog::EndMessage;
2984 TCU_FAIL("Failed to create socket pair");
2985 }
2986
2987 {
2988 const NativeHandle srcSocket(sv[0]);
2989 const NativeHandle dstSocket(sv[1]);
2990 std::string sendData("deqp");
2991
2992 // Send FD
2993 {
2994 const int fdRaw(fd.getFd());
2995 msghdr msg;
2996 cmsghdr *cmsg;
2997 char buffer[CMSG_SPACE(sizeof(int))];
2998 iovec iov = {&sendData[0], sendData.length()};
2999
3000 deMemset(&msg, 0, sizeof(msg));
3001
3002 msg.msg_control = buffer;
3003 msg.msg_controllen = sizeof(buffer);
3004 msg.msg_iovlen = 1;
3005 msg.msg_iov = &iov;
3006
3007 cmsg = CMSG_FIRSTHDR(&msg);
3008 cmsg->cmsg_level = SOL_SOCKET;
3009 cmsg->cmsg_type = SCM_RIGHTS;
3010 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
3011
3012 deMemcpy(CMSG_DATA(cmsg), &fdRaw, sizeof(int));
3013 msg.msg_controllen = cmsg->cmsg_len;
3014
3015 if (sendmsg(srcSocket.getFd(), &msg, 0) < 0)
3016 {
3017 log << TestLog::Message << "Failed to send fd over socket: '" << strerror(errno) << "'"
3018 << TestLog::EndMessage;
3019 TCU_FAIL("Failed to send fd over socket");
3020 }
3021 }
3022
3023 // Recv FD
3024 {
3025 msghdr msg;
3026 char buffer[CMSG_SPACE(sizeof(int))];
3027 std::string recvData(4, '\0');
3028 iovec iov = {&recvData[0], recvData.length()};
3029
3030 deMemset(&msg, 0, sizeof(msg));
3031
3032 msg.msg_control = buffer;
3033 msg.msg_controllen = sizeof(buffer);
3034 msg.msg_iovlen = 1;
3035 msg.msg_iov = &iov;
3036
3037 const ssize_t bytes = recvmsg(dstSocket.getFd(), &msg, 0);
3038
3039 if (bytes < 0)
3040 {
3041 log << TestLog::Message << "Failed to recv fd over socket: '" << strerror(errno) << "'"
3042 << TestLog::EndMessage;
3043 TCU_FAIL("Failed to recv fd over socket");
3044 }
3045 else if (bytes != (ssize_t)sendData.length())
3046 {
3047 TCU_FAIL("recvmsg() returned unpexpected number of bytes");
3048 }
3049 else
3050 {
3051 const vk::VkFenceImportFlags flags = config.permanence == PERMANENCE_TEMPORARY ?
3052 vk::VK_FENCE_IMPORT_TEMPORARY_BIT :
3053 (vk::VkFenceImportFlagBits)0u;
3054 const cmsghdr *const cmsg = CMSG_FIRSTHDR(&msg);
3055 int newFd_;
3056 deMemcpy(&newFd_, CMSG_DATA(cmsg), sizeof(int));
3057 NativeHandle newFd(newFd_);
3058
3059 TCU_CHECK(cmsg->cmsg_level == SOL_SOCKET);
3060 TCU_CHECK(cmsg->cmsg_type == SCM_RIGHTS);
3061 TCU_CHECK(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
3062 TCU_CHECK(recvData == sendData);
3063 TCU_CHECK_MSG(newFd.getFd() >= 0, "Didn't receive valid fd from socket");
3064
3065 {
3066 const vk::Unique<vk::VkFence> newFence(
3067 createAndImportFence(vkd, *device, config.externalType, newFd, flags));
3068
3069 if (transference == TRANSFERENCE_COPY)
3070 VK_CHECK(vkd.waitForFences(*device, 1u, &*newFence, VK_TRUE, ~0ull));
3071 else if (transference == TRANSFERENCE_REFERENCE)
3072 {
3073 submitEmptySignal(vkd, queue, *newFence);
3074 VK_CHECK(vkd.waitForFences(*device, 1u, &*newFence, VK_TRUE, ~0ull));
3075 }
3076 else
3077 DE_FATAL("Unknown permanence.");
3078
3079 VK_CHECK(vkd.queueWaitIdle(queue));
3080 }
3081 }
3082 }
3083 }
3084 }
3085 }
3086
3087 return tcu::TestStatus::pass("Pass");
3088 #else
3089 DE_UNREF(context);
3090 DE_UNREF(config);
3091 TCU_THROW(NotSupportedError, "Platform doesn't support sending file descriptors over socket");
3092 #endif
3093 }
3094
testBufferQueries(Context & context,vk::VkExternalMemoryHandleTypeFlagBits externalType)3095 tcu::TestStatus testBufferQueries(Context &context, vk::VkExternalMemoryHandleTypeFlagBits externalType)
3096 {
3097 const vk::VkBufferCreateFlags createFlags[] = {
3098 0u, vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT,
3099 vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT | vk::VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT,
3100 vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT | vk::VK_BUFFER_CREATE_SPARSE_ALIASED_BIT};
3101 const vk::VkBufferUsageFlags usageFlags[] = {
3102 vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT,
3103 vk::VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, vk::VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT,
3104 vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
3105 vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
3106 vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT};
3107 const vk::PlatformInterface &vkp(context.getPlatformInterface());
3108 const CustomInstance instance(createTestInstance(context, 0u, externalType, 0u));
3109 const vk::InstanceDriver &vki(instance.getDriver());
3110 const vk::VkPhysicalDevice physicalDevice(
3111 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3112 const vk::VkPhysicalDeviceFeatures deviceFeatures(vk::getPhysicalDeviceFeatures(vki, physicalDevice));
3113 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3114
3115 // VkDevice is only created if physical device claims to support any of these types.
3116 vk::Move<vk::VkDevice> device;
3117 de::MovePtr<vk::DeviceDriver> vkd;
3118 bool deviceHasDedicated = false;
3119
3120 TestLog &log = context.getTestContext().getLog();
3121
3122 for (size_t createFlagNdx = 0; createFlagNdx < DE_LENGTH_OF_ARRAY(createFlags); createFlagNdx++)
3123 for (size_t usageFlagNdx = 0; usageFlagNdx < DE_LENGTH_OF_ARRAY(usageFlags); usageFlagNdx++)
3124 {
3125 const vk::VkBufferViewCreateFlags createFlag = createFlags[createFlagNdx];
3126 const vk::VkBufferUsageFlags usageFlag = usageFlags[usageFlagNdx];
3127 const vk::VkPhysicalDeviceExternalBufferInfo info = {
3128 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO, DE_NULL, createFlag, usageFlag,
3129 externalType};
3130 vk::VkExternalBufferProperties properties = {
3131 vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES, DE_NULL, {0u, 0u, 0u}};
3132
3133 if (((createFlag & vk::VK_BUFFER_CREATE_SPARSE_BINDING_BIT) != 0) &&
3134 (deviceFeatures.sparseBinding == VK_FALSE))
3135 continue;
3136
3137 if (((createFlag & vk::VK_BUFFER_CREATE_SPARSE_ALIASED_BIT) != 0) &&
3138 (deviceFeatures.sparseResidencyAliased == VK_FALSE))
3139 continue;
3140
3141 if (((createFlag & vk::VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT) != 0) &&
3142 (deviceFeatures.sparseResidencyBuffer == VK_FALSE))
3143 continue;
3144
3145 vki.getPhysicalDeviceExternalBufferProperties(physicalDevice, &info, &properties);
3146
3147 log << TestLog::Message << properties << TestLog::EndMessage;
3148
3149 TCU_CHECK(properties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_BUFFER_PROPERTIES);
3150 TCU_CHECK(properties.pNext == DE_NULL);
3151 // \todo [2017-06-06 pyry] Can we validate anything else? Compatible types?
3152
3153 if ((properties.externalMemoryProperties.externalMemoryFeatures &
3154 (vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT)) != 0)
3155 {
3156 const bool requiresDedicated = (properties.externalMemoryProperties.externalMemoryFeatures &
3157 vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
3158
3159 if (!device || (requiresDedicated && !deviceHasDedicated))
3160 {
3161 // \note We need to re-create with dedicated mem extensions if previous device instance didn't have them
3162 try
3163 {
3164 device = createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, externalType, 0u,
3165 queueFamilyIndex, requiresDedicated);
3166 vkd = de::MovePtr<vk::DeviceDriver>(
3167 new vk::DeviceDriver(vkp, instance, *device, context.getUsedApiVersion(),
3168 context.getTestContext().getCommandLine()));
3169 deviceHasDedicated = requiresDedicated;
3170 }
3171 catch (const tcu::NotSupportedError &e)
3172 {
3173 log << e;
3174 TCU_FAIL(
3175 "Physical device claims to support handle type but required extensions are not supported");
3176 }
3177 }
3178 }
3179
3180 if ((properties.externalMemoryProperties.externalMemoryFeatures &
3181 vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) != 0)
3182 {
3183 DE_ASSERT(!!device);
3184 DE_ASSERT(vkd);
3185
3186 if (deviceHasDedicated)
3187 {
3188 const vk::Unique<vk::VkBuffer> buffer(createExternalBuffer(
3189 *vkd, *device, queueFamilyIndex, externalType, 1024u, createFlag, usageFlag));
3190 const vk::VkMemoryDedicatedRequirements reqs(
3191 getMemoryDedicatedRequirements(*vkd, *device, *buffer));
3192 const bool propertiesRequiresDedicated =
3193 (properties.externalMemoryProperties.externalMemoryFeatures &
3194 vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
3195 const bool objectRequiresDedicated = (reqs.requiresDedicatedAllocation != VK_FALSE);
3196
3197 if (propertiesRequiresDedicated != objectRequiresDedicated)
3198 TCU_FAIL("vkGetPhysicalDeviceExternalBufferProperties and vkGetBufferMemoryRequirements2 "
3199 "report different dedicated requirements");
3200 }
3201 else
3202 {
3203 // We can't query whether dedicated memory is required or not on per-object basis.
3204 // This check should be redundant as the code above tries to create device with
3205 // VK_KHR_dedicated_allocation & VK_KHR_get_memory_requirements2 if dedicated memory
3206 // is required. However, checking again doesn't hurt.
3207 TCU_CHECK((properties.externalMemoryProperties.externalMemoryFeatures &
3208 vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) == 0);
3209 }
3210 }
3211 }
3212
3213 return tcu::TestStatus::pass("Pass");
3214 }
3215
testBufferQueriesMaintenance5(Context & context,vk::VkExternalMemoryHandleTypeFlagBits externalType)3216 tcu::TestStatus testBufferQueriesMaintenance5(Context &context, vk::VkExternalMemoryHandleTypeFlagBits externalType)
3217 {
3218 const vk::VkBufferUsageFlags usageFlags[]{
3219 vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT,
3220 vk::VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, vk::VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT,
3221 vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
3222 vk::VK_BUFFER_USAGE_INDEX_BUFFER_BIT, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
3223 vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT,
3224 };
3225
3226 const CustomInstance instance(createTestInstance(context, 0u, externalType, 0u));
3227 const vk::InstanceDriver &vki(instance.getDriver());
3228 const vk::VkPhysicalDevice physicalDevice(
3229 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3230
3231 for (auto usageFlag : usageFlags)
3232 {
3233 vk::VkPhysicalDeviceExternalBufferInfo info{vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_BUFFER_INFO, DE_NULL,
3234 0u, usageFlag, externalType};
3235
3236 vk::VkExternalBufferProperties properties1 = vk::initVulkanStructure();
3237 vki.getPhysicalDeviceExternalBufferProperties(physicalDevice, &info, &properties1);
3238
3239 vk::VkBufferUsageFlags2CreateInfoKHR bufferUsageFlags2CreateInfo = vk::initVulkanStructure();
3240 bufferUsageFlags2CreateInfo.usage = (vk::VkBufferUsageFlags2KHR)usageFlag;
3241 vk::VkExternalBufferProperties properties2 = vk::initVulkanStructure();
3242 info.pNext = &bufferUsageFlags2CreateInfo;
3243 info.usage = 0;
3244 vki.getPhysicalDeviceExternalBufferProperties(physicalDevice, &info, &properties2);
3245
3246 if (deMemCmp(&properties1, &properties2, sizeof(vk::VkExternalBufferProperties)) != 0)
3247 return tcu::TestStatus::pass(std::string("Fail (") + de::toString(usageFlag) + ")");
3248 }
3249
3250 return tcu::TestStatus::pass("Pass");
3251 }
3252
3253 struct MemoryTestConfig
3254 {
MemoryTestConfigvkt::api::__anone405665c0111::MemoryTestConfig3255 MemoryTestConfig(vk::VkExternalMemoryHandleTypeFlagBits externalType_, bool hostVisible_, bool dedicated_)
3256 : externalType(externalType_)
3257 , hostVisible(hostVisible_)
3258 , dedicated(dedicated_)
3259 {
3260 }
3261
3262 vk::VkExternalMemoryHandleTypeFlagBits externalType;
3263 bool hostVisible;
3264 bool dedicated;
3265 };
3266
3267 #if (DE_OS == DE_OS_WIN32)
chooseWin32MemoryType(uint32_t bits)3268 uint32_t chooseWin32MemoryType(uint32_t bits)
3269 {
3270 if (bits == 0)
3271 TCU_THROW(NotSupportedError, "No compatible memory type found");
3272
3273 return deCtz32(bits);
3274 }
3275 #endif
3276
testMemoryWin32Create(Context & context,MemoryTestConfig config)3277 tcu::TestStatus testMemoryWin32Create(Context &context, MemoryTestConfig config)
3278 {
3279 #if (DE_OS == DE_OS_WIN32)
3280 const vk::PlatformInterface &vkp(context.getPlatformInterface());
3281 const CustomInstance instance(createTestInstance(context, 0u, config.externalType, 0u));
3282 const vk::InstanceDriver &vki(instance.getDriver());
3283 const vk::VkPhysicalDevice physicalDevice(
3284 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3285 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3286 const vk::Unique<vk::VkDevice> device(
3287 createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3288 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
3289 context.getTestContext().getCommandLine());
3290 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT | vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3291 const uint32_t seed = 1261033864u;
3292 const vk::VkDeviceSize bufferSize = 1024;
3293 const std::vector<uint8_t> testData(genTestData(seed, (size_t)bufferSize));
3294
3295 const vk::VkPhysicalDeviceMemoryProperties memoryProps =
3296 vk::getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice());
3297 const uint32_t compatibleMemTypes = vk::getCompatibleMemoryTypes(
3298 memoryProps, config.hostVisible ? vk::MemoryRequirement::HostVisible : vk::MemoryRequirement::Any);
3299
3300 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3301
3302 // \note Buffer is only allocated to get memory requirements
3303 const vk::Unique<vk::VkBuffer> buffer(
3304 createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3305 const vk::VkMemoryRequirements requirements(getBufferMemoryRequirements(vkd, *device, *buffer));
3306 const vk::VkExportMemoryWin32HandleInfoKHR win32Info = {
3307 vk::VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR, DE_NULL,
3308
3309 (vk::pt::Win32SecurityAttributesPtr)DE_NULL, DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
3310 (vk::pt::Win32LPCWSTR)DE_NULL};
3311 const vk::VkExportMemoryAllocateInfo exportInfo = {vk::VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO, &win32Info,
3312 (vk::VkExternalMemoryHandleTypeFlags)config.externalType};
3313
3314 const uint32_t exportedMemoryTypeIndex = chooseWin32MemoryType(requirements.memoryTypeBits & compatibleMemTypes);
3315 const vk::VkMemoryAllocateInfo info = {vk::VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, &exportInfo, requirements.size,
3316 exportedMemoryTypeIndex};
3317 const vk::Unique<vk::VkDeviceMemory> memory(vk::allocateMemory(vkd, *device, &info));
3318 NativeHandle handleA;
3319
3320 if (config.hostVisible)
3321 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3322
3323 getMemoryNative(vkd, *device, *memory, config.externalType, handleA);
3324
3325 {
3326 const vk::Unique<vk::VkDeviceMemory> memoryA(
3327 importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleA));
3328
3329 if (config.hostVisible)
3330 {
3331 const std::vector<uint8_t> testDataA(genTestData(seed ^ 124798807u, (size_t)bufferSize));
3332 const std::vector<uint8_t> testDataB(genTestData(seed ^ 970834278u, (size_t)bufferSize));
3333
3334 checkHostMemory(vkd, *device, *memoryA, testData.size(), &testData[0]);
3335 checkHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3336
3337 writeHostMemory(vkd, *device, *memoryA, testDataA.size(), &testDataA[0]);
3338 writeHostMemory(vkd, *device, *memory, testDataA.size(), &testDataB[0]);
3339
3340 checkHostMemory(vkd, *device, *memoryA, testData.size(), &testDataB[0]);
3341 checkHostMemory(vkd, *device, *memory, testData.size(), &testDataB[0]);
3342 }
3343 }
3344
3345 return tcu::TestStatus::pass("Pass");
3346 #else
3347 DE_UNREF(context);
3348 DE_UNREF(config);
3349 TCU_THROW(NotSupportedError, "Platform doesn't support win32 handles");
3350 #endif
3351 }
3352
getExportedMemoryTypeIndex(const vk::InstanceDriver & vki,const vk::VkPhysicalDevice physicalDevice,bool hostVisible,uint32_t memoryBits)3353 uint32_t getExportedMemoryTypeIndex(const vk::InstanceDriver &vki, const vk::VkPhysicalDevice physicalDevice,
3354 bool hostVisible, uint32_t memoryBits)
3355 {
3356 if (hostVisible)
3357 {
3358 const vk::VkPhysicalDeviceMemoryProperties properties(
3359 vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
3360 return chooseHostVisibleMemoryType(memoryBits, properties);
3361 }
3362
3363 return chooseMemoryType(memoryBits);
3364 }
3365
testMemoryImportTwice(Context & context,MemoryTestConfig config)3366 tcu::TestStatus testMemoryImportTwice(Context &context, MemoryTestConfig config)
3367 {
3368 const vk::PlatformInterface &vkp(context.getPlatformInterface());
3369 const CustomInstance instance(createTestInstance(context, 0u, config.externalType, 0u));
3370 const vk::InstanceDriver &vki(instance.getDriver());
3371 const vk::VkPhysicalDevice physicalDevice(
3372 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3373 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3374 const vk::Unique<vk::VkDevice> device(
3375 createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3376 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
3377 context.getTestContext().getCommandLine());
3378 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT | vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3379 const uint32_t seed = 1261033864u;
3380 const vk::VkDeviceSize bufferSize = 1024;
3381 const std::vector<uint8_t> testData(genTestData(seed, (size_t)bufferSize));
3382
3383 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3384
3385 // \note Buffer is only allocated to get memory requirements
3386 const vk::Unique<vk::VkBuffer> buffer(
3387 createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3388 const vk::VkMemoryRequirements requirements(getBufferMemoryRequirements(vkd, *device, *buffer));
3389 uint32_t exportedMemoryTypeIndex(
3390 getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3391 const vk::Unique<vk::VkDeviceMemory> memory(allocateExportableMemory(vkd, *device, requirements.size,
3392 exportedMemoryTypeIndex, config.externalType,
3393 config.dedicated ? *buffer : (vk::VkBuffer)0));
3394 NativeHandle handleA;
3395
3396 if (config.hostVisible)
3397 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3398
3399 getMemoryNative(vkd, *device, *memory, config.externalType, handleA);
3400
3401 // Need to query again memory type index since we are forced to have same type bits as the ahb buffer
3402 // Avoids VUID-VkMemoryAllocateInfo-memoryTypeIndex-02385
3403 if (config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
3404 {
3405 vk::VkAndroidHardwareBufferPropertiesANDROID ahbProperties = {
3406 vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID, // VkStructureType sType
3407 DE_NULL, // void* pNext
3408 0u, // VkDeviceSize allocationSize
3409 0u // uint32_t memoryTypeBits
3410 };
3411 vkd.getAndroidHardwareBufferPropertiesANDROID(device.get(), handleA.getAndroidHardwareBuffer(), &ahbProperties);
3412
3413 exportedMemoryTypeIndex =
3414 getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, ahbProperties.memoryTypeBits);
3415 }
3416
3417 {
3418 const vk::Unique<vk::VkBuffer> bufferA(
3419 createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3420 const vk::Unique<vk::VkBuffer> bufferB(
3421 createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3422 NativeHandle handleB(handleA);
3423 const vk::Unique<vk::VkDeviceMemory> memoryA(
3424 config.dedicated ?
3425 importDedicatedMemory(vkd, *device, *bufferA, requirements, config.externalType,
3426 exportedMemoryTypeIndex, handleA) :
3427 importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleA));
3428 const vk::Unique<vk::VkDeviceMemory> memoryB(
3429 config.dedicated ?
3430 importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType,
3431 exportedMemoryTypeIndex, handleB) :
3432 importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleB));
3433
3434 if (config.hostVisible)
3435 {
3436 const std::vector<uint8_t> testDataA(genTestData(seed ^ 124798807u, (size_t)bufferSize));
3437 const std::vector<uint8_t> testDataB(genTestData(seed ^ 970834278u, (size_t)bufferSize));
3438
3439 checkHostMemory(vkd, *device, *memoryA, testData.size(), &testData[0]);
3440 checkHostMemory(vkd, *device, *memoryB, testData.size(), &testData[0]);
3441
3442 writeHostMemory(vkd, *device, *memoryA, testData.size(), &testDataA[0]);
3443 writeHostMemory(vkd, *device, *memoryB, testData.size(), &testDataB[0]);
3444
3445 checkHostMemory(vkd, *device, *memoryA, testData.size(), &testDataB[0]);
3446 checkHostMemory(vkd, *device, *memory, testData.size(), &testDataB[0]);
3447 }
3448 }
3449
3450 return tcu::TestStatus::pass("Pass");
3451 }
3452
testMemoryMultipleImports(Context & context,MemoryTestConfig config)3453 tcu::TestStatus testMemoryMultipleImports(Context &context, MemoryTestConfig config)
3454 {
3455 const size_t count = 4 * 1024;
3456 const vk::PlatformInterface &vkp(context.getPlatformInterface());
3457 const CustomInstance instance(createTestInstance(context, 0u, config.externalType, 0u));
3458 const vk::InstanceDriver &vki(instance.getDriver());
3459 const vk::VkPhysicalDevice physicalDevice(
3460 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3461 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3462 const vk::Unique<vk::VkDevice> device(
3463 createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3464 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
3465 context.getTestContext().getCommandLine());
3466 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT | vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3467 const vk::VkDeviceSize bufferSize = 1024;
3468
3469 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3470
3471 // \note Buffer is only allocated to get memory requirements
3472 const vk::Unique<vk::VkBuffer> buffer(
3473 createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3474 const vk::VkMemoryRequirements requirements(getBufferMemoryRequirements(vkd, *device, *buffer));
3475 uint32_t exportedMemoryTypeIndex(
3476 getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3477 const vk::Unique<vk::VkDeviceMemory> memory(allocateExportableMemory(vkd, *device, requirements.size,
3478 exportedMemoryTypeIndex, config.externalType,
3479 config.dedicated ? *buffer : (vk::VkBuffer)0));
3480 NativeHandle handleA;
3481
3482 getMemoryNative(vkd, *device, *memory, config.externalType, handleA);
3483
3484 // Need to query again memory type index since we are forced to have same type bits as the ahb buffer
3485 // Avoids VUID-VkMemoryAllocateInfo-memoryTypeIndex-02385
3486 if (config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
3487 {
3488 vk::VkAndroidHardwareBufferPropertiesANDROID ahbProperties = {
3489 vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID, // VkStructureType sType
3490 DE_NULL, // void* pNext
3491 0u, // VkDeviceSize allocationSize
3492 0u // uint32_t memoryTypeBits
3493 };
3494 vkd.getAndroidHardwareBufferPropertiesANDROID(device.get(), handleA.getAndroidHardwareBuffer(), &ahbProperties);
3495
3496 exportedMemoryTypeIndex =
3497 getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, ahbProperties.memoryTypeBits);
3498 }
3499
3500 for (size_t ndx = 0; ndx < count; ndx++)
3501 {
3502 const vk::Unique<vk::VkBuffer> bufferB(
3503 createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3504 NativeHandle handleB(handleA);
3505 const vk::Unique<vk::VkDeviceMemory> memoryB(
3506 config.dedicated ?
3507 importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType,
3508 exportedMemoryTypeIndex, handleB) :
3509 importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handleB));
3510 }
3511
3512 return tcu::TestStatus::pass("Pass");
3513 }
3514
testMemoryMultipleExports(Context & context,MemoryTestConfig config)3515 tcu::TestStatus testMemoryMultipleExports(Context &context, MemoryTestConfig config)
3516 {
3517 const size_t count = 4 * 1024;
3518 const vk::PlatformInterface &vkp(context.getPlatformInterface());
3519 const CustomInstance instance(createTestInstance(context, 0u, config.externalType, 0u));
3520 const vk::InstanceDriver &vki(instance.getDriver());
3521 const vk::VkPhysicalDevice physicalDevice(
3522 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3523 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3524 const vk::Unique<vk::VkDevice> device(
3525 createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3526 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
3527 context.getTestContext().getCommandLine());
3528 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT | vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3529 const vk::VkDeviceSize bufferSize = 1024;
3530
3531 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3532
3533 // \note Buffer is only allocated to get memory requirements
3534 const vk::Unique<vk::VkBuffer> buffer(
3535 createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3536 const vk::VkMemoryRequirements requirements(getBufferMemoryRequirements(vkd, *device, *buffer));
3537 const uint32_t exportedMemoryTypeIndex(
3538 getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3539 const vk::Unique<vk::VkDeviceMemory> memory(allocateExportableMemory(vkd, *device, requirements.size,
3540 exportedMemoryTypeIndex, config.externalType,
3541 config.dedicated ? *buffer : (vk::VkBuffer)0));
3542
3543 for (size_t ndx = 0; ndx < count; ndx++)
3544 {
3545 NativeHandle handle;
3546 getMemoryNative(vkd, *device, *memory, config.externalType, handle);
3547 }
3548
3549 return tcu::TestStatus::pass("Pass");
3550 }
3551
testMemoryFdProperties(Context & context,MemoryTestConfig config)3552 tcu::TestStatus testMemoryFdProperties(Context &context, MemoryTestConfig config)
3553 {
3554 const vk::PlatformInterface &vkp(context.getPlatformInterface());
3555 const CustomInstance instance(createTestInstance(context, 0u, config.externalType, 0u));
3556 const vk::InstanceDriver &vki(instance.getDriver());
3557 const vk::VkPhysicalDevice physicalDevice(
3558 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3559 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3560 const vk::Unique<vk::VkDevice> device(
3561 createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex));
3562 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
3563 context.getTestContext().getCommandLine());
3564 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT | vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3565 const vk::VkDeviceSize bufferSize = 1024;
3566
3567 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3568
3569 // \note Buffer is only allocated to get memory requirements
3570 const vk::Unique<vk::VkBuffer> buffer(
3571 createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3572 const vk::VkMemoryRequirements requirements(getBufferMemoryRequirements(vkd, *device, *buffer));
3573 const uint32_t exportedMemoryTypeIndex(
3574 getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3575 const vk::Unique<vk::VkDeviceMemory> memory(allocateExportableMemory(vkd, *device, requirements.size,
3576 exportedMemoryTypeIndex, config.externalType,
3577 config.dedicated ? *buffer : (vk::VkBuffer)0));
3578
3579 vk::VkMemoryFdPropertiesKHR properties;
3580 NativeHandle handle;
3581
3582 getMemoryNative(vkd, *device, *memory, config.externalType, handle);
3583 properties.sType = vk::VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR;
3584 vk::VkResult res = vkd.getMemoryFdPropertiesKHR(*device, config.externalType, handle.getFd(), &properties);
3585
3586 switch (config.externalType)
3587 {
3588 case vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
3589 TCU_CHECK_MSG(res == vk::VK_SUCCESS,
3590 "vkGetMemoryFdPropertiesKHR failed for VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT");
3591 break;
3592 default:
3593 // Invalid external memory type for this test.
3594 DE_ASSERT(false);
3595 break;
3596 }
3597
3598 return tcu::TestStatus::pass("Pass");
3599 }
3600
testMemoryFdDup(Context & context,MemoryTestConfig config)3601 tcu::TestStatus testMemoryFdDup(Context &context, MemoryTestConfig config)
3602 {
3603 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
3604 const vk::PlatformInterface &vkp(context.getPlatformInterface());
3605 const CustomInstance instance(createTestInstance(context, 0u, config.externalType, 0u));
3606 const vk::InstanceDriver &vki(instance.getDriver());
3607 const vk::VkPhysicalDevice physicalDevice(
3608 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3609 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3610
3611 {
3612 const vk::Unique<vk::VkDevice> device(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u,
3613 config.externalType, 0u, queueFamilyIndex));
3614 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
3615 context.getTestContext().getCommandLine());
3616
3617 TestLog &log = context.getTestContext().getLog();
3618 const vk::VkBufferUsageFlags usage =
3619 vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT | vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3620 const vk::VkDeviceSize bufferSize = 1024;
3621 const uint32_t seed = 851493858u;
3622 const std::vector<uint8_t> testData(genTestData(seed, (size_t)bufferSize));
3623
3624 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3625
3626 // \note Buffer is only allocated to get memory requirements
3627 const vk::Unique<vk::VkBuffer> buffer(
3628 createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3629 const vk::VkMemoryRequirements requirements(getBufferMemoryRequirements(vkd, *device, *buffer));
3630 const uint32_t exportedMemoryTypeIndex(
3631 getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3632 const vk::Unique<vk::VkDeviceMemory> memory(
3633 allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType,
3634 config.dedicated ? *buffer : (vk::VkBuffer)0));
3635
3636 if (config.hostVisible)
3637 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3638
3639 const NativeHandle fd(getMemoryFd(vkd, *device, *memory, config.externalType));
3640 NativeHandle newFd(dup(fd.getFd()));
3641
3642 if (newFd.getFd() < 0)
3643 log << TestLog::Message << "dup() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
3644
3645 TCU_CHECK_MSG(newFd.getFd() >= 0, "Failed to call dup() for memorys fd");
3646
3647 {
3648 const vk::Unique<vk::VkBuffer> newBuffer(
3649 createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3650 const vk::Unique<vk::VkDeviceMemory> newMemory(
3651 config.dedicated ?
3652 importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType,
3653 exportedMemoryTypeIndex, newFd) :
3654 importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, newFd));
3655
3656 if (config.hostVisible)
3657 {
3658 const std::vector<uint8_t> testDataA(genTestData(seed ^ 672929437u, (size_t)bufferSize));
3659
3660 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3661
3662 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3663 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3664 }
3665 }
3666
3667 return tcu::TestStatus::pass("Pass");
3668 }
3669 #else
3670 DE_UNREF(context);
3671 DE_UNREF(config);
3672 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
3673 #endif
3674 }
3675
testMemoryFdDup2(Context & context,MemoryTestConfig config)3676 tcu::TestStatus testMemoryFdDup2(Context &context, MemoryTestConfig config)
3677 {
3678 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
3679 const vk::PlatformInterface &vkp(context.getPlatformInterface());
3680 const CustomInstance instance(createTestInstance(context, 0u, config.externalType, 0u));
3681 const vk::InstanceDriver &vki(instance.getDriver());
3682 const vk::VkPhysicalDevice physicalDevice(
3683 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3684 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3685
3686 {
3687 const vk::Unique<vk::VkDevice> device(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u,
3688 config.externalType, 0u, queueFamilyIndex));
3689 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
3690 context.getTestContext().getCommandLine());
3691
3692 TestLog &log = context.getTestContext().getLog();
3693 const vk::VkBufferUsageFlags usage =
3694 vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT | vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3695 const vk::VkDeviceSize bufferSize = 1024;
3696 const uint32_t seed = 224466865u;
3697 const std::vector<uint8_t> testData(genTestData(seed, (size_t)bufferSize));
3698
3699 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3700
3701 // \note Buffer is only allocated to get memory requirements
3702 const vk::Unique<vk::VkBuffer> buffer(
3703 createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3704 const vk::VkMemoryRequirements requirements(getBufferMemoryRequirements(vkd, *device, *buffer));
3705 const uint32_t exportedMemoryTypeIndex(
3706 getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3707 const vk::Unique<vk::VkDeviceMemory> memory(
3708 allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType,
3709 config.dedicated ? *buffer : (vk::VkBuffer)0));
3710
3711 if (config.hostVisible)
3712 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3713
3714 const NativeHandle fd(getMemoryFd(vkd, *device, *memory, config.externalType));
3715 NativeHandle secondFd(getMemoryFd(vkd, *device, *memory, config.externalType));
3716 const int newFd(dup2(fd.getFd(), secondFd.getFd()));
3717
3718 if (newFd < 0)
3719 log << TestLog::Message << "dup2() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
3720
3721 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup2() for memorys fd");
3722
3723 {
3724 const vk::Unique<vk::VkBuffer> newBuffer(
3725 createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3726 const vk::Unique<vk::VkDeviceMemory> newMemory(
3727 config.dedicated ?
3728 importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType,
3729 exportedMemoryTypeIndex, secondFd) :
3730 importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, secondFd));
3731
3732 if (config.hostVisible)
3733 {
3734 const std::vector<uint8_t> testDataA(genTestData(seed ^ 99012346u, (size_t)bufferSize));
3735
3736 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3737
3738 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3739 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3740 }
3741 }
3742
3743 return tcu::TestStatus::pass("Pass");
3744 }
3745 #else
3746 DE_UNREF(context);
3747 DE_UNREF(config);
3748 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
3749 #endif
3750 }
3751
testMemoryFdDup3(Context & context,MemoryTestConfig config)3752 tcu::TestStatus testMemoryFdDup3(Context &context, MemoryTestConfig config)
3753 {
3754 #if (DE_OS == DE_OS_UNIX) && defined(_GNU_SOURCE)
3755 const vk::PlatformInterface &vkp(context.getPlatformInterface());
3756 const CustomInstance instance(createTestInstance(context, 0u, config.externalType, 0u));
3757 const vk::InstanceDriver &vki(instance.getDriver());
3758 const vk::VkPhysicalDevice physicalDevice(
3759 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3760 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3761
3762 {
3763 const vk::Unique<vk::VkDevice> device(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u,
3764 config.externalType, 0u, queueFamilyIndex));
3765 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
3766 context.getTestContext().getCommandLine());
3767
3768 TestLog &log = context.getTestContext().getLog();
3769 const vk::VkBufferUsageFlags usage =
3770 vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT | vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3771 const vk::VkDeviceSize bufferSize = 1024;
3772 const uint32_t seed = 2554088961u;
3773 const std::vector<uint8_t> testData(genTestData(seed, (size_t)bufferSize));
3774
3775 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3776
3777 // \note Buffer is only allocated to get memory requirements
3778 const vk::Unique<vk::VkBuffer> buffer(
3779 createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3780 const vk::VkMemoryRequirements requirements(getBufferMemoryRequirements(vkd, *device, *buffer));
3781 const uint32_t exportedMemoryTypeIndex(
3782 getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3783 const vk::Unique<vk::VkDeviceMemory> memory(
3784 allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType,
3785 config.dedicated ? *buffer : (vk::VkBuffer)0));
3786
3787 if (config.hostVisible)
3788 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3789
3790 const NativeHandle fd(getMemoryFd(vkd, *device, *memory, config.externalType));
3791 NativeHandle secondFd(getMemoryFd(vkd, *device, *memory, config.externalType));
3792 const int newFd(dup3(fd.getFd(), secondFd.getFd(), 0));
3793
3794 if (newFd < 0)
3795 log << TestLog::Message << "dup3() failed: '" << strerror(errno) << "'" << TestLog::EndMessage;
3796
3797 TCU_CHECK_MSG(newFd >= 0, "Failed to call dup3() for memorys fd");
3798
3799 {
3800 const vk::Unique<vk::VkBuffer> newBuffer(
3801 createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3802 const vk::Unique<vk::VkDeviceMemory> newMemory(
3803 config.dedicated ?
3804 importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType,
3805 exportedMemoryTypeIndex, secondFd) :
3806 importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, secondFd));
3807
3808 if (config.hostVisible)
3809 {
3810 const std::vector<uint8_t> testDataA(genTestData(seed ^ 4210342378u, (size_t)bufferSize));
3811
3812 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3813
3814 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3815 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3816 }
3817 }
3818
3819 return tcu::TestStatus::pass("Pass");
3820 }
3821 #else
3822 DE_UNREF(context);
3823 DE_UNREF(config);
3824 TCU_THROW(NotSupportedError, "Platform doesn't support dup()");
3825 #endif
3826 }
3827
testMemoryFdSendOverSocket(Context & context,MemoryTestConfig config)3828 tcu::TestStatus testMemoryFdSendOverSocket(Context &context, MemoryTestConfig config)
3829 {
3830 #if (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_UNIX)
3831 const vk::PlatformInterface &vkp(context.getPlatformInterface());
3832 const CustomInstance instance(createTestInstance(context, 0u, config.externalType, 0u));
3833 const vk::InstanceDriver &vki(instance.getDriver());
3834 const vk::VkPhysicalDevice physicalDevice(
3835 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
3836 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
3837
3838 {
3839 const vk::Unique<vk::VkDevice> device(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u,
3840 config.externalType, 0u, queueFamilyIndex));
3841 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
3842 context.getTestContext().getCommandLine());
3843
3844 TestLog &log = context.getTestContext().getLog();
3845 const vk::VkBufferUsageFlags usage =
3846 vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT | vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3847 const vk::VkDeviceSize bufferSize = 1024;
3848 const uint32_t seed = 3403586456u;
3849 const std::vector<uint8_t> testData(genTestData(seed, (size_t)bufferSize));
3850
3851 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
3852
3853 // \note Buffer is only allocated to get memory requirements
3854 const vk::Unique<vk::VkBuffer> buffer(
3855 createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3856 const vk::VkMemoryRequirements requirements(getBufferMemoryRequirements(vkd, *device, *buffer));
3857 const uint32_t exportedMemoryTypeIndex(
3858 getExportedMemoryTypeIndex(vki, physicalDevice, config.hostVisible, requirements.memoryTypeBits));
3859 const vk::Unique<vk::VkDeviceMemory> memory(
3860 allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType,
3861 config.dedicated ? *buffer : (vk::VkBuffer)0));
3862
3863 if (config.hostVisible)
3864 writeHostMemory(vkd, *device, *memory, testData.size(), &testData[0]);
3865
3866 const NativeHandle fd(getMemoryFd(vkd, *device, *memory, config.externalType));
3867
3868 {
3869 int sv[2];
3870
3871 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0)
3872 {
3873 log << TestLog::Message << "Failed to create socket pair: '" << strerror(errno) << "'"
3874 << TestLog::EndMessage;
3875 TCU_FAIL("Failed to create socket pair");
3876 }
3877
3878 {
3879 const NativeHandle srcSocket(sv[0]);
3880 const NativeHandle dstSocket(sv[1]);
3881 std::string sendData("deqp");
3882
3883 // Send FD
3884 {
3885 const int fdRaw(fd.getFd());
3886 msghdr msg;
3887 cmsghdr *cmsg;
3888 char tmpBuffer[CMSG_SPACE(sizeof(int))];
3889 iovec iov = {&sendData[0], sendData.length()};
3890
3891 deMemset(&msg, 0, sizeof(msg));
3892
3893 msg.msg_control = tmpBuffer;
3894 msg.msg_controllen = sizeof(tmpBuffer);
3895 msg.msg_iovlen = 1;
3896 msg.msg_iov = &iov;
3897
3898 cmsg = CMSG_FIRSTHDR(&msg);
3899 cmsg->cmsg_level = SOL_SOCKET;
3900 cmsg->cmsg_type = SCM_RIGHTS;
3901 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
3902
3903 deMemcpy(CMSG_DATA(cmsg), &fdRaw, sizeof(int));
3904 msg.msg_controllen = cmsg->cmsg_len;
3905
3906 if (sendmsg(srcSocket.getFd(), &msg, 0) < 0)
3907 {
3908 log << TestLog::Message << "Failed to send fd over socket: '" << strerror(errno) << "'"
3909 << TestLog::EndMessage;
3910 TCU_FAIL("Failed to send fd over socket");
3911 }
3912 }
3913
3914 // Recv FD
3915 {
3916 msghdr msg;
3917 char tmpBuffer[CMSG_SPACE(sizeof(int))];
3918 std::string recvData(4, '\0');
3919 iovec iov = {&recvData[0], recvData.length()};
3920
3921 deMemset(&msg, 0, sizeof(msg));
3922
3923 msg.msg_control = tmpBuffer;
3924 msg.msg_controllen = sizeof(tmpBuffer);
3925 msg.msg_iovlen = 1;
3926 msg.msg_iov = &iov;
3927
3928 const ssize_t bytes = recvmsg(dstSocket.getFd(), &msg, 0);
3929
3930 if (bytes < 0)
3931 {
3932 log << TestLog::Message << "Failed to recv fd over socket: '" << strerror(errno) << "'"
3933 << TestLog::EndMessage;
3934 TCU_FAIL("Failed to recv fd over socket");
3935 }
3936 else if (bytes != (ssize_t)sendData.length())
3937 {
3938 TCU_FAIL("recvmsg() returned unpexpected number of bytes");
3939 }
3940 else
3941 {
3942 const cmsghdr *const cmsg = CMSG_FIRSTHDR(&msg);
3943 int newFd_;
3944 deMemcpy(&newFd_, CMSG_DATA(cmsg), sizeof(int));
3945 NativeHandle newFd(newFd_);
3946
3947 TCU_CHECK(cmsg->cmsg_level == SOL_SOCKET);
3948 TCU_CHECK(cmsg->cmsg_type == SCM_RIGHTS);
3949 TCU_CHECK(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
3950 TCU_CHECK(recvData == sendData);
3951 TCU_CHECK_MSG(newFd.getFd() >= 0, "Didn't receive valid fd from socket");
3952
3953 {
3954 const vk::Unique<vk::VkBuffer> newBuffer(createExternalBuffer(
3955 vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
3956 const vk::Unique<vk::VkDeviceMemory> newMemory(
3957 config.dedicated ?
3958 importDedicatedMemory(vkd, *device, *newBuffer, requirements, config.externalType,
3959 exportedMemoryTypeIndex, newFd) :
3960 importMemory(vkd, *device, requirements, config.externalType,
3961 exportedMemoryTypeIndex, newFd));
3962
3963 if (config.hostVisible)
3964 {
3965 const std::vector<uint8_t> testDataA(genTestData(seed ^ 23478978u, (size_t)bufferSize));
3966
3967 checkHostMemory(vkd, *device, *newMemory, testData.size(), &testData[0]);
3968
3969 writeHostMemory(vkd, *device, *newMemory, testDataA.size(), &testDataA[0]);
3970 checkHostMemory(vkd, *device, *memory, testDataA.size(), &testDataA[0]);
3971 }
3972 }
3973 }
3974 }
3975 }
3976 }
3977 }
3978
3979 return tcu::TestStatus::pass("Pass");
3980 #else
3981 DE_UNREF(context);
3982 DE_UNREF(config);
3983 TCU_THROW(NotSupportedError, "Platform doesn't support sending file descriptors over socket");
3984 #endif
3985 }
3986
3987 struct BufferTestConfig
3988 {
BufferTestConfigvkt::api::__anone405665c0111::BufferTestConfig3989 BufferTestConfig(vk::VkExternalMemoryHandleTypeFlagBits externalType_, bool dedicated_)
3990 : externalType(externalType_)
3991 , dedicated(dedicated_)
3992 {
3993 }
3994
3995 vk::VkExternalMemoryHandleTypeFlagBits externalType;
3996 bool dedicated;
3997 };
3998
testBufferBindExportImportBind(Context & context,const BufferTestConfig config)3999 tcu::TestStatus testBufferBindExportImportBind(Context &context, const BufferTestConfig config)
4000 {
4001 const vk::PlatformInterface &vkp(context.getPlatformInterface());
4002 const CustomInstance instance(createTestInstance(context, 0u, config.externalType, 0u));
4003 const vk::InstanceDriver &vki(instance.getDriver());
4004 const vk::VkPhysicalDevice physicalDevice(
4005 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
4006 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
4007 const vk::Unique<vk::VkDevice> device(createTestDevice(
4008 context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
4009 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
4010 context.getTestContext().getCommandLine());
4011 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT | vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
4012 const vk::VkDeviceSize bufferSize = 1024;
4013
4014 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
4015
4016 // \note Buffer is only allocated to get memory requirements
4017 const vk::Unique<vk::VkBuffer> bufferA(
4018 createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
4019 const vk::VkMemoryRequirements requirements(getBufferMemoryRequirements(vkd, *device, *bufferA));
4020 uint32_t exportedMemoryTypeIndex(chooseMemoryType(requirements.memoryTypeBits));
4021 const vk::Unique<vk::VkDeviceMemory> memoryA(
4022 allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType,
4023 config.dedicated ? *bufferA : (vk::VkBuffer)0));
4024 NativeHandle handle;
4025
4026 VK_CHECK(vkd.bindBufferMemory(*device, *bufferA, *memoryA, 0u));
4027
4028 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
4029
4030 // Need to query again memory type index since we are forced to have same type bits as the ahb buffer
4031 // Avoids VUID-VkMemoryAllocateInfo-memoryTypeIndex-02385
4032 if (config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
4033 {
4034 vk::VkAndroidHardwareBufferPropertiesANDROID ahbProperties = {
4035 vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID, // VkStructureType sType
4036 DE_NULL, // void* pNext
4037 0u, // VkDeviceSize allocationSize
4038 0u // uint32_t memoryTypeBits
4039 };
4040 vkd.getAndroidHardwareBufferPropertiesANDROID(device.get(), handle.getAndroidHardwareBuffer(), &ahbProperties);
4041
4042 exportedMemoryTypeIndex = chooseMemoryType(ahbProperties.memoryTypeBits);
4043 }
4044
4045 {
4046 const vk::Unique<vk::VkBuffer> bufferB(
4047 createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
4048 const vk::Unique<vk::VkDeviceMemory> memoryB(
4049 config.dedicated ?
4050 importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType,
4051 exportedMemoryTypeIndex, handle) :
4052 importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
4053
4054 VK_CHECK(vkd.bindBufferMemory(*device, *bufferB, *memoryB, 0u));
4055 }
4056
4057 return tcu::TestStatus::pass("Pass");
4058 }
4059
testBufferExportBindImportBind(Context & context,const BufferTestConfig config)4060 tcu::TestStatus testBufferExportBindImportBind(Context &context, const BufferTestConfig config)
4061 {
4062 const vk::PlatformInterface &vkp(context.getPlatformInterface());
4063 const CustomInstance instance(createTestInstance(context, 0u, config.externalType, 0u));
4064 const vk::InstanceDriver &vki(instance.getDriver());
4065 const vk::VkPhysicalDevice physicalDevice(
4066 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
4067 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
4068 const vk::Unique<vk::VkDevice> device(createTestDevice(
4069 context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
4070 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
4071 context.getTestContext().getCommandLine());
4072 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT | vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
4073 const vk::VkDeviceSize bufferSize = 1024;
4074
4075 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
4076
4077 // \note Buffer is only allocated to get memory requirements
4078 const vk::Unique<vk::VkBuffer> bufferA(
4079 createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
4080 const vk::VkMemoryRequirements requirements(getBufferMemoryRequirements(vkd, *device, *bufferA));
4081 uint32_t exportedMemoryTypeIndex(chooseMemoryType(requirements.memoryTypeBits));
4082 const vk::Unique<vk::VkDeviceMemory> memoryA(
4083 allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType,
4084 config.dedicated ? *bufferA : (vk::VkBuffer)0));
4085 NativeHandle handle;
4086
4087 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
4088 VK_CHECK(vkd.bindBufferMemory(*device, *bufferA, *memoryA, 0u));
4089
4090 // Need to query again memory type index since we are forced to have same type bits as the ahb buffer
4091 // Avoids VUID-VkMemoryAllocateInfo-memoryTypeIndex-02385
4092 if (config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
4093 {
4094 vk::VkAndroidHardwareBufferPropertiesANDROID ahbProperties = {
4095 vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID, // VkStructureType sType
4096 DE_NULL, // void* pNext
4097 0u, // VkDeviceSize allocationSize
4098 0u // uint32_t memoryTypeBits
4099 };
4100 vkd.getAndroidHardwareBufferPropertiesANDROID(device.get(), handle.getAndroidHardwareBuffer(), &ahbProperties);
4101
4102 exportedMemoryTypeIndex = chooseMemoryType(ahbProperties.memoryTypeBits);
4103 }
4104
4105 {
4106 const vk::Unique<vk::VkBuffer> bufferB(
4107 createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
4108 const vk::Unique<vk::VkDeviceMemory> memoryB(
4109 config.dedicated ?
4110 importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType,
4111 exportedMemoryTypeIndex, handle) :
4112 importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
4113
4114 VK_CHECK(vkd.bindBufferMemory(*device, *bufferB, *memoryB, 0u));
4115 }
4116
4117 return tcu::TestStatus::pass("Pass");
4118 }
4119
testBufferExportImportBindBind(Context & context,const BufferTestConfig config)4120 tcu::TestStatus testBufferExportImportBindBind(Context &context, const BufferTestConfig config)
4121 {
4122 const vk::PlatformInterface &vkp(context.getPlatformInterface());
4123 const CustomInstance instance(createTestInstance(context, 0u, config.externalType, 0u));
4124 const vk::InstanceDriver &vki(instance.getDriver());
4125 const vk::VkPhysicalDevice physicalDevice(
4126 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
4127 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
4128 const vk::Unique<vk::VkDevice> device(createTestDevice(
4129 context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
4130 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
4131 context.getTestContext().getCommandLine());
4132 const vk::VkBufferUsageFlags usage = vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT | vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT;
4133 const vk::VkDeviceSize bufferSize = 1024;
4134
4135 checkBufferSupport(vki, physicalDevice, config.externalType, 0u, usage, config.dedicated);
4136
4137 // \note Buffer is only allocated to get memory requirements
4138 const vk::Unique<vk::VkBuffer> bufferA(
4139 createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
4140 const vk::VkMemoryRequirements requirements(getBufferMemoryRequirements(vkd, *device, *bufferA));
4141 uint32_t exportedMemoryTypeIndex(chooseMemoryType(requirements.memoryTypeBits));
4142 const vk::Unique<vk::VkDeviceMemory> memoryA(
4143 allocateExportableMemory(vkd, *device, requirements.size, exportedMemoryTypeIndex, config.externalType,
4144 config.dedicated ? *bufferA : (vk::VkBuffer)0));
4145 NativeHandle handle;
4146
4147 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
4148
4149 // Need to query again memory type index since we are forced to have same type bits as the ahb buffer
4150 // Avoids VUID-VkMemoryAllocateInfo-memoryTypeIndex-02385
4151 if (config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
4152 {
4153 vk::VkAndroidHardwareBufferPropertiesANDROID ahbProperties = {
4154 vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID, // VkStructureType sType
4155 DE_NULL, // void* pNext
4156 0u, // VkDeviceSize allocationSize
4157 0u // uint32_t memoryTypeBits
4158 };
4159 vkd.getAndroidHardwareBufferPropertiesANDROID(device.get(), handle.getAndroidHardwareBuffer(), &ahbProperties);
4160
4161 exportedMemoryTypeIndex = chooseMemoryType(ahbProperties.memoryTypeBits);
4162 }
4163
4164 {
4165 const vk::Unique<vk::VkBuffer> bufferB(
4166 createExternalBuffer(vkd, *device, queueFamilyIndex, config.externalType, bufferSize, 0u, usage));
4167 const vk::Unique<vk::VkDeviceMemory> memoryB(
4168 config.dedicated ?
4169 importDedicatedMemory(vkd, *device, *bufferB, requirements, config.externalType,
4170 exportedMemoryTypeIndex, handle) :
4171 importMemory(vkd, *device, requirements, config.externalType, exportedMemoryTypeIndex, handle));
4172
4173 VK_CHECK(vkd.bindBufferMemory(*device, *bufferA, *memoryA, 0u));
4174 VK_CHECK(vkd.bindBufferMemory(*device, *bufferB, *memoryB, 0u));
4175 }
4176
4177 return tcu::TestStatus::pass("Pass");
4178 }
4179
testImageQueries(Context & context,vk::VkExternalMemoryHandleTypeFlagBits externalType)4180 tcu::TestStatus testImageQueries(Context &context, vk::VkExternalMemoryHandleTypeFlagBits externalType)
4181 {
4182 const vk::VkImageCreateFlags createFlags[] = {
4183 0u,
4184 vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT,
4185 vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT | vk::VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT,
4186 vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT | vk::VK_IMAGE_CREATE_SPARSE_ALIASED_BIT,
4187 vk::VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT,
4188 vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT};
4189 const vk::VkImageUsageFlags usageFlags[] = {
4190 vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
4191 vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT,
4192 vk::VK_IMAGE_USAGE_SAMPLED_BIT,
4193 vk::VK_IMAGE_USAGE_STORAGE_BIT,
4194 vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
4195 vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
4196 vk::VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
4197 vk::VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
4198 vk::VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT,
4199 vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT};
4200 const vk::PlatformInterface &vkp(context.getPlatformInterface());
4201 const CustomInstance instance(createTestInstance(context, 0u, externalType, 0u));
4202 const vk::InstanceDriver &vki(instance.getDriver());
4203 const vk::VkPhysicalDevice physicalDevice(
4204 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
4205 const vk::VkPhysicalDeviceFeatures deviceFeatures(vk::getPhysicalDeviceFeatures(vki, physicalDevice));
4206 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
4207
4208 // VkDevice is only created if physical device claims to support any of these types.
4209 vk::Move<vk::VkDevice> device;
4210 de::MovePtr<vk::DeviceDriver> vkd;
4211 bool deviceHasDedicated = false;
4212
4213 TestLog &log = context.getTestContext().getLog();
4214
4215 for (size_t createFlagNdx = 0; createFlagNdx < DE_LENGTH_OF_ARRAY(createFlags); createFlagNdx++)
4216 for (size_t usageFlagNdx = 0; usageFlagNdx < DE_LENGTH_OF_ARRAY(usageFlags); usageFlagNdx++)
4217 {
4218 const vk::VkImageViewCreateFlags createFlag = createFlags[createFlagNdx];
4219 const vk::VkImageUsageFlags usageFlag = usageFlags[usageFlagNdx];
4220 const vk::VkFormat format = (usageFlags[usageFlagNdx] & vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ?
4221 vk::VK_FORMAT_D16_UNORM :
4222 vk::VK_FORMAT_R8G8B8A8_UNORM;
4223 const vk::VkImageType type = vk::VK_IMAGE_TYPE_2D;
4224 const vk::VkImageTiling tiling = vk::VK_IMAGE_TILING_OPTIMAL;
4225 const vk::VkPhysicalDeviceExternalImageFormatInfo externalInfo = {
4226 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO, DE_NULL, externalType};
4227 const vk::VkPhysicalDeviceImageFormatInfo2 info = {
4228 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
4229 &externalInfo,
4230
4231 format,
4232 type,
4233 tiling,
4234 usageFlag,
4235 createFlag,
4236 };
4237 vk::VkExternalImageFormatProperties externalProperties = {
4238 vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES, DE_NULL, {0u, 0u, 0u}};
4239 vk::VkImageFormatProperties2 properties = {
4240 vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2, &externalProperties, {{0u, 0u, 0u}, 0u, 0u, 0u, 0u}};
4241
4242 if (((createFlag & vk::VK_IMAGE_CREATE_SPARSE_BINDING_BIT) != 0) &&
4243 (deviceFeatures.sparseBinding == VK_FALSE))
4244 continue;
4245
4246 if (((createFlag & vk::VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT) != 0) &&
4247 (deviceFeatures.sparseResidencyImage2D == VK_FALSE))
4248 continue;
4249
4250 if (((createFlag & vk::VK_IMAGE_CREATE_SPARSE_ALIASED_BIT) != 0) &&
4251 (deviceFeatures.sparseResidencyAliased == VK_FALSE))
4252 continue;
4253
4254 if (vki.getPhysicalDeviceImageFormatProperties2(physicalDevice, &info, &properties) ==
4255 vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
4256 {
4257 continue;
4258 }
4259
4260 log << TestLog::Message << externalProperties << TestLog::EndMessage;
4261 TCU_CHECK(externalProperties.sType == vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES);
4262 TCU_CHECK(externalProperties.pNext == DE_NULL);
4263 // \todo [2017-06-06 pyry] Can we validate anything else? Compatible types?
4264
4265 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures &
4266 (vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT)) != 0)
4267 {
4268 const bool requiresDedicated = (externalProperties.externalMemoryProperties.externalMemoryFeatures &
4269 vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
4270
4271 if (!device || (requiresDedicated && !deviceHasDedicated))
4272 {
4273 // \note We need to re-create with dedicated mem extensions if previous device instance didn't have them
4274 try
4275 {
4276 device = createTestDevice(context, vkp, instance, vki, physicalDevice, 0u, externalType, 0u,
4277 queueFamilyIndex, requiresDedicated);
4278 vkd = de::MovePtr<vk::DeviceDriver>(
4279 new vk::DeviceDriver(vkp, instance, *device, context.getUsedApiVersion(),
4280 context.getTestContext().getCommandLine()));
4281 deviceHasDedicated = requiresDedicated;
4282 }
4283 catch (const tcu::NotSupportedError &e)
4284 {
4285 log << e;
4286 TCU_FAIL(
4287 "Physical device claims to support handle type but required extensions are not supported");
4288 }
4289 }
4290 }
4291
4292 if ((externalProperties.externalMemoryProperties.externalMemoryFeatures &
4293 vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) != 0)
4294 {
4295 DE_ASSERT(!!device);
4296 DE_ASSERT(vkd);
4297
4298 if (deviceHasDedicated)
4299 {
4300 // Memory requirements cannot be queried without binding the image.
4301 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
4302 continue;
4303
4304 const vk::Unique<vk::VkImage> image(createExternalImage(*vkd, *device, queueFamilyIndex,
4305 externalType, format, 16u, 16u, tiling,
4306 createFlag, usageFlag));
4307 const vk::VkMemoryDedicatedRequirements reqs(getMemoryDedicatedRequirements(*vkd, *device, *image));
4308 const bool propertiesRequiresDedicated =
4309 (externalProperties.externalMemoryProperties.externalMemoryFeatures &
4310 vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0;
4311 const bool objectRequiresDedicated = (reqs.requiresDedicatedAllocation != VK_FALSE);
4312
4313 if (propertiesRequiresDedicated != objectRequiresDedicated)
4314 TCU_FAIL("vkGetPhysicalDeviceExternalBufferProperties and vkGetBufferMemoryRequirements2 "
4315 "report different dedicated requirements");
4316 }
4317 else
4318 {
4319 // We can't query whether dedicated memory is required or not on per-object basis.
4320 // This check should be redundant as the code above tries to create device with
4321 // VK_KHR_dedicated_allocation & VK_KHR_get_memory_requirements2 if dedicated memory
4322 // is required. However, checking again doesn't hurt.
4323 TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures &
4324 vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) == 0);
4325 }
4326 }
4327 }
4328
4329 return tcu::TestStatus::pass("Pass");
4330 }
4331
4332 struct ImageTestConfig
4333 {
ImageTestConfigvkt::api::__anone405665c0111::ImageTestConfig4334 ImageTestConfig(vk::VkExternalMemoryHandleTypeFlagBits externalType_, bool dedicated_)
4335 : externalType(externalType_)
4336 , dedicated(dedicated_)
4337 {
4338 }
4339
4340 vk::VkExternalMemoryHandleTypeFlagBits externalType;
4341 bool dedicated;
4342 };
4343
testImageBindExportImportBind(Context & context,const ImageTestConfig config)4344 tcu::TestStatus testImageBindExportImportBind(Context &context, const ImageTestConfig config)
4345 {
4346 const vk::PlatformInterface &vkp(context.getPlatformInterface());
4347 const CustomInstance instance(createTestInstance(context, 0u, config.externalType, 0u));
4348 const vk::InstanceDriver &vki(instance.getDriver());
4349 const vk::VkPhysicalDevice physicalDevice(
4350 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
4351 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
4352 const vk::Unique<vk::VkDevice> device(createTestDevice(
4353 context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
4354 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
4355 context.getTestContext().getCommandLine());
4356 const vk::VkImageUsageFlags usage =
4357 vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT |
4358 (config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID ?
4359 vk::VK_IMAGE_USAGE_SAMPLED_BIT :
4360 0);
4361 const vk::VkFormat format = vk::VK_FORMAT_R8G8B8A8_UNORM;
4362 const uint32_t width = 64u;
4363 const uint32_t height = 64u;
4364 const vk::VkImageTiling tiling = vk::VK_IMAGE_TILING_OPTIMAL;
4365
4366 checkImageSupport(vki, physicalDevice, config.externalType, 0u, usage, format, tiling, config.dedicated);
4367
4368 const vk::Unique<vk::VkImage> imageA(createExternalImage(vkd, *device, queueFamilyIndex, config.externalType,
4369 format, width, height, tiling, 0u, usage));
4370 const vk::VkMemoryRequirements requirements(getImageMemoryRequirements(vkd, *device, *imageA, config.externalType));
4371 const uint32_t exportedMemoryTypeIndex(chooseMemoryType(requirements.memoryTypeBits));
4372 const vk::Unique<vk::VkDeviceMemory> memoryA(allocateExportableMemory(vkd, *device, requirements.size,
4373 exportedMemoryTypeIndex, config.externalType,
4374 config.dedicated ? *imageA : (vk::VkImage)0));
4375 NativeHandle handle;
4376
4377 VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
4378
4379 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
4380
4381 {
4382 const vk::Unique<vk::VkImage> imageB(createExternalImage(vkd, *device, queueFamilyIndex, config.externalType,
4383 format, width, height, tiling, 0u, usage));
4384 const uint32_t idx =
4385 config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID ?
4386 ~0u :
4387 exportedMemoryTypeIndex;
4388 const vk::Unique<vk::VkDeviceMemory> memoryB(
4389 config.dedicated ?
4390 importDedicatedMemory(vkd, *device, *imageB, requirements, config.externalType, idx, handle) :
4391 importMemory(vkd, *device, requirements, config.externalType, idx, handle));
4392
4393 VK_CHECK(vkd.bindImageMemory(*device, *imageB, *memoryB, 0u));
4394 }
4395
4396 return tcu::TestStatus::pass("Pass");
4397 }
4398
testImageExportBindImportBind(Context & context,const ImageTestConfig config)4399 tcu::TestStatus testImageExportBindImportBind(Context &context, const ImageTestConfig config)
4400 {
4401 const vk::PlatformInterface &vkp(context.getPlatformInterface());
4402 const CustomInstance instance(createTestInstance(context, 0u, config.externalType, 0u));
4403 const vk::InstanceDriver &vki(instance.getDriver());
4404 const vk::VkPhysicalDevice physicalDevice(
4405 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
4406 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
4407 const vk::Unique<vk::VkDevice> device(createTestDevice(
4408 context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
4409 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
4410 context.getTestContext().getCommandLine());
4411 const vk::VkImageUsageFlags usage =
4412 vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT |
4413 (config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID ?
4414 vk::VK_IMAGE_USAGE_SAMPLED_BIT :
4415 0);
4416 const vk::VkFormat format = vk::VK_FORMAT_R8G8B8A8_UNORM;
4417 const uint32_t width = 64u;
4418 const uint32_t height = 64u;
4419 const vk::VkImageTiling tiling = vk::VK_IMAGE_TILING_OPTIMAL;
4420
4421 checkImageSupport(vki, physicalDevice, config.externalType, 0u, usage, format, tiling, config.dedicated);
4422
4423 const vk::Unique<vk::VkImage> imageA(createExternalImage(vkd, *device, queueFamilyIndex, config.externalType,
4424 format, width, height, tiling, 0u, usage));
4425 const vk::VkMemoryRequirements requirements(getImageMemoryRequirements(vkd, *device, *imageA, config.externalType));
4426 const uint32_t exportedMemoryTypeIndex(chooseMemoryType(requirements.memoryTypeBits));
4427 const vk::Unique<vk::VkDeviceMemory> memoryA(allocateExportableMemory(vkd, *device, requirements.size,
4428 exportedMemoryTypeIndex, config.externalType,
4429 config.dedicated ? *imageA : (vk::VkImage)0));
4430 NativeHandle handle;
4431
4432 if (config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID &&
4433 config.dedicated)
4434 {
4435 // AHB required the image memory to be bound first.
4436 VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
4437 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
4438 }
4439 else
4440 {
4441 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
4442 VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
4443 }
4444
4445 {
4446 const vk::Unique<vk::VkImage> imageB(createExternalImage(vkd, *device, queueFamilyIndex, config.externalType,
4447 format, width, height, tiling, 0u, usage));
4448 const uint32_t idx =
4449 config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID ?
4450 ~0u :
4451 exportedMemoryTypeIndex;
4452 const vk::Unique<vk::VkDeviceMemory> memoryB(
4453 config.dedicated ?
4454 importDedicatedMemory(vkd, *device, *imageB, requirements, config.externalType, idx, handle) :
4455 importMemory(vkd, *device, requirements, config.externalType, idx, handle));
4456
4457 VK_CHECK(vkd.bindImageMemory(*device, *imageB, *memoryB, 0u));
4458 }
4459
4460 return tcu::TestStatus::pass("Pass");
4461 }
4462
testImageExportImportBindBind(Context & context,const ImageTestConfig config)4463 tcu::TestStatus testImageExportImportBindBind(Context &context, const ImageTestConfig config)
4464 {
4465 const vk::PlatformInterface &vkp(context.getPlatformInterface());
4466 const CustomInstance instance(createTestInstance(context, 0u, config.externalType, 0u));
4467 const vk::InstanceDriver &vki(instance.getDriver());
4468 const vk::VkPhysicalDevice physicalDevice(
4469 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
4470 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
4471 const vk::Unique<vk::VkDevice> device(createTestDevice(
4472 context, vkp, instance, vki, physicalDevice, 0u, config.externalType, 0u, queueFamilyIndex, config.dedicated));
4473 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
4474 context.getTestContext().getCommandLine());
4475 const vk::VkImageUsageFlags usage =
4476 vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT |
4477 (config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID ?
4478 vk::VK_IMAGE_USAGE_SAMPLED_BIT :
4479 0);
4480 const vk::VkFormat format = vk::VK_FORMAT_R8G8B8A8_UNORM;
4481 const uint32_t width = 64u;
4482 const uint32_t height = 64u;
4483 const vk::VkImageTiling tiling = vk::VK_IMAGE_TILING_OPTIMAL;
4484
4485 checkImageSupport(vki, physicalDevice, config.externalType, 0u, usage, format, tiling, config.dedicated);
4486
4487 if (config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID &&
4488 config.dedicated)
4489 {
4490 // AHB required the image memory to be bound first, which is not possible in this test.
4491 TCU_THROW(NotSupportedError, "Unsupported for Android Hardware Buffer");
4492 }
4493
4494 // \note Image is only allocated to get memory requirements
4495 const vk::Unique<vk::VkImage> imageA(createExternalImage(vkd, *device, queueFamilyIndex, config.externalType,
4496 format, width, height, tiling, 0u, usage));
4497 const vk::VkMemoryRequirements requirements(getImageMemoryRequirements(vkd, *device, *imageA, config.externalType));
4498 const uint32_t exportedMemoryTypeIndex(chooseMemoryType(requirements.memoryTypeBits));
4499 const vk::Unique<vk::VkDeviceMemory> memoryA(allocateExportableMemory(vkd, *device, requirements.size,
4500 exportedMemoryTypeIndex, config.externalType,
4501 config.dedicated ? *imageA : (vk::VkImage)0));
4502 NativeHandle handle;
4503
4504 getMemoryNative(vkd, *device, *memoryA, config.externalType, handle);
4505
4506 {
4507 const vk::Unique<vk::VkImage> imageB(createExternalImage(vkd, *device, queueFamilyIndex, config.externalType,
4508 format, width, height, tiling, 0u, usage));
4509 const uint32_t idx =
4510 config.externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID ?
4511 ~0u :
4512 exportedMemoryTypeIndex;
4513 const vk::Unique<vk::VkDeviceMemory> memoryB(
4514 config.dedicated ?
4515 importDedicatedMemory(vkd, *device, *imageB, requirements, config.externalType, idx, handle) :
4516 importMemory(vkd, *device, requirements, config.externalType, idx, handle));
4517
4518 VK_CHECK(vkd.bindImageMemory(*device, *imageA, *memoryA, 0u));
4519 VK_CHECK(vkd.bindImageMemory(*device, *imageB, *memoryB, 0u));
4520 }
4521
4522 return tcu::TestStatus::pass("Pass");
4523 }
4524
4525 template <class TestConfig>
checkEvent(Context & context,const TestConfig)4526 void checkEvent(Context &context, const TestConfig)
4527 {
4528 if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
4529 !context.getPortabilitySubsetFeatures().events)
4530 TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Events are not supported by this implementation");
4531 }
4532
4533 template <class TestConfig>
checkSupport(Context & context,const TestConfig config)4534 void checkSupport(Context &context, const TestConfig config)
4535 {
4536 const Transference transference(getHandelTypeTransferences(config.externalType));
4537 if (transference == TRANSFERENCE_COPY)
4538 checkEvent(context, config);
4539 }
4540
createFenceTests(tcu::TestContext & testCtx,vk::VkExternalFenceHandleTypeFlagBits externalType)4541 de::MovePtr<tcu::TestCaseGroup> createFenceTests(tcu::TestContext &testCtx,
4542 vk::VkExternalFenceHandleTypeFlagBits externalType)
4543 {
4544 const struct
4545 {
4546 const char *const name;
4547 const Permanence permanence;
4548 } permanences[] = {{"temporary", PERMANENCE_TEMPORARY}, {"permanent", PERMANENCE_PERMANENT}};
4549
4550 de::MovePtr<tcu::TestCaseGroup> fenceGroup(new tcu::TestCaseGroup(testCtx, externalFenceTypeToName(externalType)));
4551
4552 // Test external fence queries.
4553 addFunctionCase(fenceGroup.get(), "info", testFenceQueries, externalType);
4554
4555 for (size_t permanenceNdx = 0; permanenceNdx < DE_LENGTH_OF_ARRAY(permanences); permanenceNdx++)
4556 {
4557 const Permanence permanence(permanences[permanenceNdx].permanence);
4558 const char *const permanenceName(permanences[permanenceNdx].name);
4559 const FenceTestConfig config(externalType, permanence);
4560
4561 if (!isSupportedPermanence(externalType, permanence))
4562 continue;
4563
4564 if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT ||
4565 externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
4566 {
4567 // Test creating fence with win32 properties.
4568 addFunctionCase(fenceGroup.get(), std::string("create_win32_") + permanenceName, testFenceWin32Create,
4569 config);
4570 }
4571
4572 // Test importing fence twice.
4573 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("import_twice_") + permanenceName, checkSupport,
4574 initProgramsToGetNativeFd, testFenceImportTwice, config);
4575 // Test importing again over previously imported fence.
4576 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("reimport_") + permanenceName, checkSupport,
4577 initProgramsToGetNativeFd, testFenceImportReimport, config);
4578 // Test importing fence multiple times.
4579 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("import_multiple_times_") + permanenceName,
4580 checkSupport, initProgramsToGetNativeFd, testFenceMultipleImports, config);
4581 // Test signaling, exporting, importing and waiting for the sempahore.
4582 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("signal_export_import_wait_") + permanenceName,
4583 checkEvent, initProgramsToGetNativeFd, testFenceSignalExportImportWait, config);
4584 // Test signaling and importing the fence.
4585 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("signal_import_") + permanenceName, checkSupport,
4586 initProgramsToGetNativeFd, testFenceSignalImport, config);
4587 // Test resetting the fence.
4588 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("reset_") + permanenceName, checkEvent,
4589 initProgramsToGetNativeFd, testFenceReset, config);
4590 // Test fences transference.
4591 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("transference_") + permanenceName, checkEvent,
4592 initProgramsToGetNativeFd, testFenceTransference, config);
4593
4594 if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT)
4595 {
4596 // Test import signaled fence fd.
4597 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("import_signaled_") + permanenceName,
4598 initProgramsToGetNativeFd, testFenceImportSyncFdSignaled, config);
4599 }
4600
4601 if (externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT ||
4602 externalType == vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT)
4603 {
4604 // \note Not supported on WIN32 handles
4605 // Test exporting fence multiple times.
4606 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("export_multiple_times_") + permanenceName,
4607 checkSupport, initProgramsToGetNativeFd, testFenceMultipleExports, config);
4608
4609 // Test calling dup() on exported fence.
4610 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("dup_") + permanenceName, checkSupport,
4611 initProgramsToGetNativeFd, testFenceFdDup, config);
4612 // Test calling dup2() on exported fence.
4613 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("dup2_") + permanenceName, checkSupport,
4614 initProgramsToGetNativeFd, testFenceFdDup2, config);
4615 // Test calling dup3() on exported fence.
4616 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("dup3_") + permanenceName, checkSupport,
4617 initProgramsToGetNativeFd, testFenceFdDup3, config);
4618 // Test sending fence fd over socket.
4619 addFunctionCaseWithPrograms(fenceGroup.get(), std::string("send_over_socket_") + permanenceName,
4620 checkSupport, initProgramsToGetNativeFd, testFenceFdSendOverSocket, config);
4621 }
4622
4623 if (getHandelTypeTransferences(externalType) == TRANSFERENCE_REFERENCE)
4624 {
4625 // Test signaling and then waiting for the the sepmahore.
4626 addFunctionCase(fenceGroup.get(), std::string("signal_wait_import_") + permanenceName,
4627 testFenceSignalWaitImport, config);
4628 // Test exporting, signaling, importing and waiting for the fence.
4629 addFunctionCase(fenceGroup.get(), std::string("export_signal_import_wait_") + permanenceName,
4630 testFenceExportSignalImportWait, config);
4631 // Test exporting, importing, signaling and waiting for the fence.
4632 addFunctionCase(fenceGroup.get(), std::string("export_import_signal_wait_") + permanenceName,
4633 testFenceExportImportSignalWait, config);
4634 }
4635 }
4636
4637 return fenceGroup;
4638 }
4639
generateFailureText(TestLog & log,vk::VkFormat format,vk::VkImageUsageFlags usage,vk::VkImageCreateFlags create,vk::VkImageTiling tiling=static_cast<vk::VkImageTiling> (0),uint32_t width=0,uint32_t height=0,std::string exception="")4640 void generateFailureText(TestLog &log, vk::VkFormat format, vk::VkImageUsageFlags usage, vk::VkImageCreateFlags create,
4641 vk::VkImageTiling tiling = static_cast<vk::VkImageTiling>(0), uint32_t width = 0,
4642 uint32_t height = 0, std::string exception = "")
4643 {
4644 std::ostringstream combination;
4645 combination << "Test failure with combination: ";
4646 combination << " Format: " << getFormatName(format);
4647 combination << " Usageflags: " << vk::getImageUsageFlagsStr(usage);
4648 combination << " Createflags: " << vk::getImageCreateFlagsStr(create);
4649 combination << " Tiling: " << getImageTilingStr(tiling);
4650 if (width != 0 && height != 0)
4651 combination << " Size: "
4652 << "(" << width << ", " << height << ")";
4653 if (!exception.empty())
4654 combination << "Error message: " << exception;
4655
4656 log << TestLog::Message << combination.str() << TestLog::EndMessage;
4657 }
4658
ValidateAHardwareBuffer(TestLog & log,vk::VkFormat format,uint64_t requiredAhbUsage,const vk::DeviceDriver & vkd,const vk::VkDevice & device,vk::VkImageUsageFlags usageFlag,vk::VkImageCreateFlags createFlag,uint32_t layerCount,bool & enableMaxLayerTest)4659 bool ValidateAHardwareBuffer(TestLog &log, vk::VkFormat format, uint64_t requiredAhbUsage, const vk::DeviceDriver &vkd,
4660 const vk::VkDevice &device, vk::VkImageUsageFlags usageFlag,
4661 vk::VkImageCreateFlags createFlag, uint32_t layerCount, bool &enableMaxLayerTest)
4662 {
4663 DE_UNREF(createFlag);
4664
4665 AndroidHardwareBufferExternalApi *ahbApi = AndroidHardwareBufferExternalApi::getInstance();
4666
4667 if (!ahbApi)
4668 {
4669 TCU_THROW(NotSupportedError, "Platform doesn't support Android Hardware Buffer handles");
4670 }
4671
4672 #if (DE_OS == DE_OS_ANDROID)
4673 // If CubeMap create flag is used and AHB doesn't support CubeMap return false.
4674 if (!AndroidHardwareBufferExternalApi::supportsCubeMap() && (createFlag & vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT))
4675 return false;
4676 #endif
4677
4678 vk::pt::AndroidHardwareBufferPtr ahb =
4679 ahbApi->allocate(64u, 64u, layerCount, ahbApi->vkFormatToAhbFormat(format), requiredAhbUsage);
4680 if (ahb.internal == DE_NULL)
4681 {
4682 enableMaxLayerTest = false;
4683 // try again with layerCount '1'
4684 ahb = ahbApi->allocate(64u, 64u, 1u, ahbApi->vkFormatToAhbFormat(format), requiredAhbUsage);
4685 if (ahb.internal == DE_NULL)
4686 {
4687 return false;
4688 }
4689 }
4690 NativeHandle nativeHandle(ahb);
4691
4692 const vk::VkComponentMapping mappingA = {vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY,
4693 vk::VK_COMPONENT_SWIZZLE_IDENTITY, vk::VK_COMPONENT_SWIZZLE_IDENTITY};
4694 const vk::VkComponentMapping mappingB = {vk::VK_COMPONENT_SWIZZLE_R, vk::VK_COMPONENT_SWIZZLE_G,
4695 vk::VK_COMPONENT_SWIZZLE_B, vk::VK_COMPONENT_SWIZZLE_A};
4696
4697 for (int variantIdx = 0; variantIdx < 2; ++variantIdx)
4698 {
4699 // Both mappings should be equivalent and work.
4700 const vk::VkComponentMapping &mapping = ((variantIdx == 0) ? mappingA : mappingB);
4701
4702 vk::VkAndroidHardwareBufferFormatPropertiesANDROID formatProperties = {
4703 vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID,
4704 DE_NULL,
4705 vk::VK_FORMAT_UNDEFINED,
4706 0u,
4707 0u,
4708 mapping,
4709 vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY,
4710 vk::VK_SAMPLER_YCBCR_RANGE_ITU_FULL,
4711 vk::VK_CHROMA_LOCATION_COSITED_EVEN,
4712 vk::VK_CHROMA_LOCATION_COSITED_EVEN};
4713
4714 vk::VkAndroidHardwareBufferPropertiesANDROID bufferProperties = {
4715 vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID, &formatProperties, 0u, 0u};
4716
4717 try
4718 {
4719 VK_CHECK(vkd.getAndroidHardwareBufferPropertiesANDROID(device, ahb, &bufferProperties));
4720 TCU_CHECK(formatProperties.format != vk::VK_FORMAT_UNDEFINED);
4721 TCU_CHECK(formatProperties.format == format);
4722 TCU_CHECK(formatProperties.externalFormat != 0u);
4723 TCU_CHECK((formatProperties.formatFeatures & vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) != 0u);
4724 TCU_CHECK((formatProperties.formatFeatures & (vk::VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT |
4725 vk::VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT)) != 0u);
4726 }
4727 catch (const tcu::Exception &exception)
4728 {
4729 log << TestLog::Message << "Failure validating Android Hardware Buffer. See error message and combination: "
4730 << TestLog::EndMessage;
4731 generateFailureText(log, format, usageFlag, createFlag, static_cast<vk::VkImageTiling>(0), 0, 0,
4732 exception.getMessage());
4733 return false;
4734 }
4735 }
4736
4737 return true;
4738 }
4739
testAndroidHardwareBufferImageFormat(Context & context,vk::VkFormat format)4740 tcu::TestStatus testAndroidHardwareBufferImageFormat(Context &context, vk::VkFormat format)
4741 {
4742 AndroidHardwareBufferExternalApi *ahbApi = AndroidHardwareBufferExternalApi::getInstance();
4743 if (!ahbApi)
4744 {
4745 TCU_THROW(NotSupportedError, "Platform doesn't support Android Hardware Buffer handles");
4746 }
4747
4748 bool testsFailed = false;
4749
4750 const vk::VkExternalMemoryHandleTypeFlagBits externalMemoryType =
4751 vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
4752 const vk::PlatformInterface &vkp(context.getPlatformInterface());
4753 const CustomInstance instance(createTestInstance(context, 0u, externalMemoryType, 0u));
4754 const vk::InstanceDriver &vki(instance.getDriver());
4755 const vk::VkPhysicalDevice physicalDevice(
4756 vk::chooseDevice(vki, instance, context.getTestContext().getCommandLine()));
4757
4758 vk::VkPhysicalDeviceProtectedMemoryFeatures protectedFeatures;
4759 protectedFeatures.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES;
4760 protectedFeatures.pNext = DE_NULL;
4761 protectedFeatures.protectedMemory = VK_FALSE;
4762
4763 vk::VkPhysicalDeviceFeatures2 deviceFeatures;
4764 deviceFeatures.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
4765 deviceFeatures.pNext = &protectedFeatures;
4766
4767 vki.getPhysicalDeviceFeatures2(physicalDevice, &deviceFeatures);
4768
4769 const uint32_t queueFamilyIndex(chooseQueueFamilyIndex(vki, physicalDevice, 0u));
4770 const vk::Unique<vk::VkDevice> device(createTestDevice(context, vkp, instance, vki, physicalDevice, 0u,
4771 externalMemoryType, 0u, queueFamilyIndex, false,
4772 &protectedFeatures));
4773 const vk::DeviceDriver vkd(vkp, instance, *device, context.getUsedApiVersion(),
4774 context.getTestContext().getCommandLine());
4775 TestLog &log = context.getTestContext().getLog();
4776 const vk::VkPhysicalDeviceLimits limits = getPhysicalDeviceProperties(vki, physicalDevice).limits;
4777
4778 const vk::VkImageUsageFlagBits framebufferUsageFlag = vk::isDepthStencilFormat(format) ?
4779 vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT :
4780 vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
4781
4782 const vk::VkImageUsageFlagBits usageFlags[] = {
4783 vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
4784 vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT,
4785 vk::VK_IMAGE_USAGE_SAMPLED_BIT,
4786 vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT,
4787 framebufferUsageFlag,
4788 };
4789 const vk::VkImageCreateFlagBits createFlags[] = {
4790 vk::VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT,
4791 vk::VK_IMAGE_CREATE_EXTENDED_USAGE_BIT,
4792 vk::VK_IMAGE_CREATE_PROTECTED_BIT,
4793 vk::VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT,
4794 };
4795 const vk::VkImageTiling tilings[] = {
4796 vk::VK_IMAGE_TILING_OPTIMAL,
4797 vk::VK_IMAGE_TILING_LINEAR,
4798 };
4799 uint64_t mustSupportAhbUsageFlags = ahbApi->mustSupportAhbUsageFlags();
4800 const size_t one = 1u;
4801 const size_t numOfUsageFlags = DE_LENGTH_OF_ARRAY(usageFlags);
4802 const size_t numOfCreateFlags = DE_LENGTH_OF_ARRAY(createFlags);
4803 const size_t numOfFlagCombos = one << (numOfUsageFlags + numOfCreateFlags);
4804 const size_t numOfTilings = DE_LENGTH_OF_ARRAY(tilings);
4805
4806 for (size_t combo = 0; combo < numOfFlagCombos; combo++)
4807 {
4808 vk::VkImageUsageFlags usage = 0;
4809 vk::VkImageCreateFlags createFlag = 0;
4810 uint64_t requiredAhbUsage = 0;
4811 bool enableMaxLayerTest = true;
4812 for (size_t usageNdx = 0; usageNdx < numOfUsageFlags; usageNdx++)
4813 {
4814 if ((combo & (one << usageNdx)) == 0)
4815 continue;
4816 usage |= usageFlags[usageNdx];
4817 requiredAhbUsage |= ahbApi->vkUsageToAhbUsage(usageFlags[usageNdx]);
4818 }
4819 for (size_t createFlagNdx = 0; createFlagNdx < numOfCreateFlags; createFlagNdx++)
4820 {
4821 const size_t bit = numOfUsageFlags + createFlagNdx;
4822 if ((combo & (one << bit)) == 0)
4823 continue;
4824 if (((createFlags[createFlagNdx] & vk::VK_IMAGE_CREATE_PROTECTED_BIT) ==
4825 vk::VK_IMAGE_CREATE_PROTECTED_BIT) &&
4826 (protectedFeatures.protectedMemory == VK_FALSE))
4827 continue;
4828
4829 createFlag |= createFlags[createFlagNdx];
4830 requiredAhbUsage |= ahbApi->vkCreateToAhbUsage(createFlags[createFlagNdx]);
4831 }
4832
4833 // Only test a combination if the usage flags include at least one of the AHARDWAREBUFFER_USAGE_GPU_* flag.
4834 if ((requiredAhbUsage & mustSupportAhbUsageFlags) == 0u)
4835 continue;
4836
4837 // Only test a combination if AHardwareBuffer can be successfully allocated for it.
4838 if (!ValidateAHardwareBuffer(log, format, requiredAhbUsage, vkd, *device, usage, createFlag,
4839 limits.maxImageArrayLayers, enableMaxLayerTest))
4840 continue;
4841
4842 bool foundAnyUsableTiling = false;
4843 for (size_t tilingIndex = 0; tilingIndex < numOfTilings; tilingIndex++)
4844 {
4845 const vk::VkImageTiling tiling = tilings[tilingIndex];
4846
4847 const vk::VkPhysicalDeviceExternalImageFormatInfo externalInfo = {
4848 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO, DE_NULL,
4849 vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID};
4850 const vk::VkPhysicalDeviceImageFormatInfo2 info = {
4851 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
4852 &externalInfo,
4853 format,
4854 vk::VK_IMAGE_TYPE_2D,
4855 tiling,
4856 usage,
4857 createFlag,
4858 };
4859
4860 vk::VkAndroidHardwareBufferUsageANDROID ahbUsageProperties = {
4861 vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID, DE_NULL, 0u};
4862 vk::VkExternalImageFormatProperties externalProperties = {
4863 vk::VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES, &ahbUsageProperties, {0u, 0u, 0u}};
4864 vk::VkImageFormatProperties2 properties = {
4865 vk::VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2, &externalProperties, {{0u, 0u, 0u}, 0u, 0u, 0u, 0u}};
4866
4867 if (vki.getPhysicalDeviceImageFormatProperties2(physicalDevice, &info, &properties) ==
4868 vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
4869 {
4870 log << TestLog::Message << "Tiling " << tiling << " is not supported." << TestLog::EndMessage;
4871 continue;
4872 }
4873
4874 foundAnyUsableTiling = true;
4875
4876 try
4877 {
4878 TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures &
4879 vk::VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT) != 0);
4880 TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures &
4881 vk::VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT) != 0);
4882 TCU_CHECK((externalProperties.externalMemoryProperties.externalMemoryFeatures &
4883 vk::VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT) != 0);
4884 uint32_t maxWidth = properties.imageFormatProperties.maxExtent.width;
4885 uint32_t maxHeight = properties.imageFormatProperties.maxExtent.height;
4886 TCU_CHECK(maxWidth >= 4096);
4887 TCU_CHECK(maxHeight >= 4096);
4888 // Even if not requested, at least one of GPU_* usage flags must be present.
4889 TCU_CHECK((ahbUsageProperties.androidHardwareBufferUsage & mustSupportAhbUsageFlags) != 0u);
4890 // The AHB usage flags corresponding to the create and usage flags used in info must be present.
4891 TCU_CHECK((ahbUsageProperties.androidHardwareBufferUsage & requiredAhbUsage) == requiredAhbUsage);
4892 }
4893 catch (const tcu::Exception &exception)
4894 {
4895 generateFailureText(log, format, usage, createFlag, tiling, 0, 0, exception.getMessage());
4896 testsFailed = true;
4897 continue;
4898 }
4899
4900 log << TestLog::Message << "Required flags: " << std::hex << requiredAhbUsage
4901 << " Actual flags: " << std::hex << ahbUsageProperties.androidHardwareBufferUsage
4902 << TestLog::EndMessage;
4903
4904 struct ImageSize
4905 {
4906 uint32_t width;
4907 uint32_t height;
4908 };
4909 ImageSize sizes[] = {
4910 {64u, 64u},
4911 {1024u, 2096u},
4912 };
4913
4914 uint32_t exportedMemoryTypeIndex = 0;
4915
4916 if (createFlag & vk::VK_IMAGE_CREATE_PROTECTED_BIT)
4917 {
4918 const vk::VkPhysicalDeviceMemoryProperties memProperties(
4919 vk::getPhysicalDeviceMemoryProperties(vki, physicalDevice));
4920
4921 for (uint32_t memoryTypeIndex = 0; memoryTypeIndex < VK_MAX_MEMORY_TYPES; memoryTypeIndex++)
4922 {
4923 if (memProperties.memoryTypes[memoryTypeIndex].propertyFlags & vk::VK_MEMORY_PROPERTY_PROTECTED_BIT)
4924 {
4925 exportedMemoryTypeIndex = memoryTypeIndex;
4926 break;
4927 }
4928 }
4929 }
4930
4931 for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(sizes); i++)
4932 {
4933 try
4934 {
4935 const vk::Unique<vk::VkImage> image(
4936 createExternalImage(vkd, *device, queueFamilyIndex, externalMemoryType, format, sizes[i].width,
4937 sizes[i].height, tiling, createFlag, usage));
4938 const vk::VkMemoryRequirements requirements(
4939 getImageMemoryRequirements(vkd, *device, *image, externalMemoryType));
4940 const vk::Unique<vk::VkDeviceMemory> memory(allocateExportableMemory(
4941 vkd, *device, requirements.size, exportedMemoryTypeIndex, externalMemoryType, *image));
4942 NativeHandle handle;
4943
4944 VK_CHECK(vkd.bindImageMemory(*device, *image, *memory, 0u));
4945 getMemoryNative(vkd, *device, *memory, externalMemoryType, handle);
4946
4947 uint32_t ahbFormat = 0;
4948 uint64_t anhUsage = 0;
4949 ahbApi->describe(handle.getAndroidHardwareBuffer(), DE_NULL, DE_NULL, DE_NULL, &ahbFormat,
4950 &anhUsage, DE_NULL);
4951 TCU_CHECK(ahbFormat == ahbApi->vkFormatToAhbFormat(format));
4952 TCU_CHECK((anhUsage & requiredAhbUsage) == requiredAhbUsage);
4953
4954 // Let watchdog know we're alive
4955 context.getTestContext().touchWatchdog();
4956 }
4957 catch (const tcu::Exception &exception)
4958 {
4959 generateFailureText(log, format, usage, createFlag, tiling, sizes[i].width, sizes[i].height,
4960 exception.getMessage());
4961 testsFailed = true;
4962 continue;
4963 }
4964 }
4965
4966 if (properties.imageFormatProperties.maxMipLevels >= 7u)
4967 {
4968 try
4969 {
4970 const vk::Unique<vk::VkImage> image(createExternalImage(vkd, *device, queueFamilyIndex,
4971 externalMemoryType, format, 64u, 64u,
4972 tiling, createFlag, usage, 7u));
4973 const vk::VkMemoryRequirements requirements(
4974 getImageMemoryRequirements(vkd, *device, *image, externalMemoryType));
4975 const vk::Unique<vk::VkDeviceMemory> memory(allocateExportableMemory(
4976 vkd, *device, requirements.size, exportedMemoryTypeIndex, externalMemoryType, *image));
4977 NativeHandle handle;
4978
4979 VK_CHECK(vkd.bindImageMemory(*device, *image, *memory, 0u));
4980 getMemoryNative(vkd, *device, *memory, externalMemoryType, handle);
4981
4982 uint32_t ahbFormat = 0;
4983 uint64_t anhUsage = 0;
4984 ahbApi->describe(handle.getAndroidHardwareBuffer(), DE_NULL, DE_NULL, DE_NULL, &ahbFormat,
4985 &anhUsage, DE_NULL);
4986 TCU_CHECK(ahbFormat == ahbApi->vkFormatToAhbFormat(format));
4987 TCU_CHECK((anhUsage & requiredAhbUsage) == requiredAhbUsage);
4988 }
4989 catch (const tcu::Exception &exception)
4990 {
4991 generateFailureText(log, format, usage, createFlag, tiling, 64, 64, exception.getMessage());
4992 testsFailed = true;
4993 continue;
4994 }
4995 }
4996
4997 if ((properties.imageFormatProperties.maxArrayLayers > 1u) && enableMaxLayerTest)
4998 {
4999 try
5000 {
5001 const vk::Unique<vk::VkImage> image(createExternalImage(
5002 vkd, *device, queueFamilyIndex, externalMemoryType, format, 64u, 64u, tiling, createFlag, usage,
5003 1u, properties.imageFormatProperties.maxArrayLayers));
5004 const vk::VkMemoryRequirements requirements(
5005 getImageMemoryRequirements(vkd, *device, *image, externalMemoryType));
5006 const vk::Unique<vk::VkDeviceMemory> memory(allocateExportableMemory(
5007 vkd, *device, requirements.size, exportedMemoryTypeIndex, externalMemoryType, *image));
5008 NativeHandle handle;
5009
5010 VK_CHECK(vkd.bindImageMemory(*device, *image, *memory, 0u));
5011 getMemoryNative(vkd, *device, *memory, externalMemoryType, handle);
5012
5013 uint32_t ahbFormat = 0;
5014 uint64_t anhUsage = 0;
5015 ahbApi->describe(handle.getAndroidHardwareBuffer(), DE_NULL, DE_NULL, DE_NULL, &ahbFormat,
5016 &anhUsage, DE_NULL);
5017 TCU_CHECK(ahbFormat == ahbApi->vkFormatToAhbFormat(format));
5018 TCU_CHECK((anhUsage & requiredAhbUsage) == requiredAhbUsage);
5019 }
5020 catch (const tcu::Exception &exception)
5021 {
5022 generateFailureText(log, format, usage, createFlag, tiling, 64, 64, exception.getMessage());
5023 testsFailed = true;
5024 continue;
5025 }
5026 }
5027 }
5028
5029 if (!foundAnyUsableTiling)
5030 {
5031 generateFailureText(log, format, usage, createFlag, static_cast<vk::VkImageTiling>(0));
5032 testsFailed = true;
5033 continue;
5034 }
5035 }
5036
5037 if (testsFailed)
5038 return tcu::TestStatus::fail("Failure in at least one subtest. Check log for failed tests.");
5039 else
5040 return tcu::TestStatus::pass("Pass");
5041 }
5042
5043 class AhbExternalFormatResolveApiCase : public TestCase
5044 {
5045 public:
5046 AhbExternalFormatResolveApiCase(tcu::TestContext &context, const std::string &name,
5047 AndroidHardwareBufferInstance::Format format);
5048
5049 TestInstance *createInstance(Context &context) const override;
5050 void checkSupport(Context &context) const override;
5051
5052 private:
5053 const AndroidHardwareBufferInstance::Format m_format;
5054 };
5055
5056 class AhbExternalFormatResolveApiInstance : public TestInstance
5057 {
5058 public:
5059 AhbExternalFormatResolveApiInstance(Context &context, AndroidHardwareBufferInstance::Format format);
5060
5061 tcu::TestStatus iterate(void) override;
5062
5063 private:
5064 const AndroidHardwareBufferInstance::Format m_format;
5065 const AndroidHardwareBufferInstance::Usage m_usage =
5066 static_cast<AndroidHardwareBufferInstance::Usage>(AndroidHardwareBufferInstance::Usage::GPU_FRAMEBUFFER);
5067 const uint32_t m_width = 32u;
5068 const uint32_t m_height = 32u;
5069 const uint32_t m_layers = 1u;
5070 };
5071
AhbExternalFormatResolveApiCase(tcu::TestContext & context,const std::string & name,AndroidHardwareBufferInstance::Format format)5072 AhbExternalFormatResolveApiCase::AhbExternalFormatResolveApiCase(tcu::TestContext &context, const std::string &name,
5073 AndroidHardwareBufferInstance::Format format)
5074 : TestCase(context, name)
5075 , m_format(format)
5076 {
5077 }
5078
createInstance(Context & context) const5079 TestInstance *AhbExternalFormatResolveApiCase::createInstance(Context &context) const
5080 {
5081 return new AhbExternalFormatResolveApiInstance(context, m_format);
5082 }
5083
checkSupport(Context & context) const5084 void AhbExternalFormatResolveApiCase::checkSupport(Context &context) const
5085 {
5086 context.requireDeviceFunctionality("VK_ANDROID_external_format_resolve");
5087
5088 if (!AndroidHardwareBufferExternalApi::getInstance())
5089 TCU_THROW(NotSupportedError, "No AHB api peresent");
5090 }
5091
AhbExternalFormatResolveApiInstance(Context & context,AndroidHardwareBufferInstance::Format format)5092 AhbExternalFormatResolveApiInstance::AhbExternalFormatResolveApiInstance(Context &context,
5093 AndroidHardwareBufferInstance::Format format)
5094 : TestInstance(context)
5095 , m_format(format)
5096 {
5097 }
5098
iterate(void)5099 tcu::TestStatus AhbExternalFormatResolveApiInstance::iterate(void)
5100 {
5101 const vk::DeviceInterface &vk = m_context.getDeviceInterface();
5102 const vk::VkDevice device = m_context.getDevice();
5103 tcu::TestLog &log = m_context.getTestContext().getLog();
5104 AndroidHardwareBufferExternalApi *ahbApi = AndroidHardwareBufferExternalApi::getInstance();
5105
5106 if (!ahbApi)
5107 TCU_THROW(NotSupportedError, "Android Hardware Buffer not present");
5108
5109 AndroidHardwareBufferInstance androidBuffer;
5110
5111 // If the allocation failed it means AHB format is not supported, test next
5112 if (!androidBuffer.allocate(m_format, m_width, m_height, m_layers, m_usage))
5113 {
5114 std::string skipReason = "Unable to allocate renderable AHB with parameters: width(" + std::to_string(m_width) +
5115 "), height(" + std::to_string(m_height) + "), layers(" + std::to_string(m_layers) +
5116 "), usage(" + std::to_string(m_usage) + ")";
5117
5118 log << tcu::TestLog::Message << skipReason << tcu::TestLog::EndMessage;
5119 TCU_THROW(NotSupportedError, "Failed to allocate buffer");
5120 }
5121
5122 vk::VkAndroidHardwareBufferFormatResolvePropertiesANDROID formatResolveProperties = {
5123 vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_RESOLVE_PROPERTIES_ANDROID, // VkStructureType sType
5124 nullptr, // void* pNext
5125 vk::VK_FORMAT_UNDEFINED // VkFormat colorAttachmentFormat
5126 };
5127
5128 vk::VkAndroidHardwareBufferFormatPropertiesANDROID formatProperties = {
5129 vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID, // VkStructureType sType
5130 &formatResolveProperties, // void* pNext
5131 vk::VK_FORMAT_UNDEFINED, // VkFormat format
5132 0u, // uint64_t externalFormat
5133 0u, // VkFormatFeatureFlags formatFeatures
5134 vk::VkComponentMapping(), // VkComponentMapping samplerYcbcrConversionComponents
5135 vk::VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY, // VkSamplerYcbcrModelConversion suggestedYcbcrModel
5136 vk::VK_SAMPLER_YCBCR_RANGE_ITU_FULL, // VkSamplerYcbcrRange suggestedYcbcrRange
5137 vk::VK_CHROMA_LOCATION_COSITED_EVEN, // VkChromaLocation suggestedXChromaOffset
5138 vk::VK_CHROMA_LOCATION_COSITED_EVEN // VkChromaLocation suggestedYChromaOffset
5139 };
5140
5141 vk::VkAndroidHardwareBufferPropertiesANDROID bufferProperties = {
5142 vk::VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID, // VkStructureType sType
5143 &formatProperties, // void* pNext
5144 0u, // VkDeviceSize allocationSize
5145 0u // uint32_t memoryTypeBits
5146 };
5147
5148 VK_CHECK(vk.getAndroidHardwareBufferPropertiesANDROID(device, androidBuffer.getHandle(), &bufferProperties));
5149
5150 if (formatProperties.format != vk::VK_FORMAT_UNDEFINED)
5151 {
5152 vk::VkFormatProperties3 colorAttachmentFormatProperties =
5153 m_context.getFormatProperties(formatProperties.format);
5154 vk::VkFormatFeatureFlags requiredFlags =
5155 vk::VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | vk::VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
5156
5157 if ((colorAttachmentFormatProperties.optimalTilingFeatures & requiredFlags) ||
5158 (colorAttachmentFormatProperties.linearTilingFeatures & requiredFlags))
5159 return tcu::TestStatus::pass("");
5160 // Depth and stencil format must be supported through this path. No external format resolve is allowed for depth/stencil formats
5161 else if (AndroidHardwareBufferInstance::isFormatDepth(m_format) ||
5162 AndroidHardwareBufferInstance::isFormatStencil(m_format))
5163 return tcu::TestStatus::fail("Depth/stencil must be supported through Vulkan Format mapping");
5164 }
5165
5166 if (formatResolveProperties.colorAttachmentFormat != vk::VK_FORMAT_UNDEFINED)
5167 {
5168 vk::VkFormatProperties3 colorAttachmentFormatProperties =
5169 m_context.getFormatProperties(formatResolveProperties.colorAttachmentFormat);
5170
5171 // External formats require optimal tiling
5172 if (colorAttachmentFormatProperties.optimalTilingFeatures & vk::VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)
5173 return tcu::TestStatus::pass("");
5174 }
5175
5176 return tcu::TestStatus::fail("No draw support");
5177 }
5178
checkMaintenance5(Context & context,vk::VkExternalMemoryHandleTypeFlagBits)5179 void checkMaintenance5(Context &context, vk::VkExternalMemoryHandleTypeFlagBits)
5180 {
5181 context.requireDeviceFunctionality("VK_KHR_maintenance5");
5182 }
5183
createFenceTests(tcu::TestContext & testCtx)5184 de::MovePtr<tcu::TestCaseGroup> createFenceTests(tcu::TestContext &testCtx)
5185 {
5186 de::MovePtr<tcu::TestCaseGroup> fenceGroup(new tcu::TestCaseGroup(testCtx, "fence"));
5187
5188 fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT).release());
5189 fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT).release());
5190 fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT).release());
5191 fenceGroup->addChild(createFenceTests(testCtx, vk::VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT).release());
5192
5193 return fenceGroup;
5194 }
5195
createSemaphoreTests(tcu::TestContext & testCtx,vk::VkExternalSemaphoreHandleTypeFlagBits externalType)5196 de::MovePtr<tcu::TestCaseGroup> createSemaphoreTests(tcu::TestContext &testCtx,
5197 vk::VkExternalSemaphoreHandleTypeFlagBits externalType)
5198 {
5199 const struct
5200 {
5201 const char *const name;
5202 const Permanence permanence;
5203 } permanences[] = {{"temporary", PERMANENCE_TEMPORARY}, {"permanent", PERMANENCE_PERMANENT}};
5204 const struct
5205 {
5206 const char *const name;
5207 vk::VkSemaphoreType type;
5208 } semaphoreTypes[] = {
5209 {"binary", vk::VK_SEMAPHORE_TYPE_BINARY},
5210 {"timeline", vk::VK_SEMAPHORE_TYPE_TIMELINE},
5211 };
5212
5213 de::MovePtr<tcu::TestCaseGroup> semaphoreGroup(
5214 new tcu::TestCaseGroup(testCtx, externalSemaphoreTypeToName(externalType)));
5215
5216 for (size_t semaphoreTypeIdx = 0; semaphoreTypeIdx < DE_LENGTH_OF_ARRAY(permanences); semaphoreTypeIdx++)
5217 {
5218 // Test external semaphore queries
5219 addFunctionCase(semaphoreGroup.get(), std::string("info_") + semaphoreTypes[semaphoreTypeIdx].name,
5220 testSemaphoreQueries,
5221 TestSemaphoreQueriesParameters(semaphoreTypes[semaphoreTypeIdx].type, externalType));
5222 }
5223
5224 for (size_t permanenceNdx = 0; permanenceNdx < DE_LENGTH_OF_ARRAY(permanences); permanenceNdx++)
5225 {
5226 const Permanence permanence(permanences[permanenceNdx].permanence);
5227 const char *const permanenceName(permanences[permanenceNdx].name);
5228 const SemaphoreTestConfig config(externalType, permanence);
5229
5230 if (!isSupportedPermanence(externalType, permanence))
5231 continue;
5232
5233 if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT ||
5234 externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
5235 {
5236 // Test creating semaphore with win32 properties.
5237 addFunctionCase(semaphoreGroup.get(), std::string("create_win32_") + permanenceName,
5238 testSemaphoreWin32Create, config);
5239 }
5240
5241 // Test importing semaphore twice.
5242 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("import_twice_") + permanenceName, checkSupport,
5243 initProgramsToGetNativeFd, testSemaphoreImportTwice, config);
5244 // Test importing again over previously imported semaphore.
5245 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("reimport_") + permanenceName, checkSupport,
5246 initProgramsToGetNativeFd, testSemaphoreImportReimport, config);
5247 // Test importing semaphore multiple times.
5248 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("import_multiple_times_") + permanenceName,
5249 checkSupport, initProgramsToGetNativeFd, testSemaphoreMultipleImports, config);
5250 // Test signaling, exporting, importing and waiting for the sempahore.
5251 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("signal_export_import_wait_") + permanenceName,
5252 checkEvent, initProgramsToGetNativeFd, testSemaphoreSignalExportImportWait, config);
5253 // Test signaling and importing the semaphore.
5254 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("signal_import_") + permanenceName, checkSupport,
5255 initProgramsToGetNativeFd, testSemaphoreSignalImport, config);
5256 // Test semaphores transference.
5257 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("transference_") + permanenceName, checkEvent,
5258 initProgramsToGetNativeFd, testSemaphoreTransference, config);
5259
5260 if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT)
5261 {
5262 // Test import signaled semaphore fd.
5263 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("import_signaled_") + permanenceName,
5264 initProgramsToGetNativeFd, testSemaphoreImportSyncFdSignaled, config);
5265 }
5266
5267 if (externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT ||
5268 externalType == vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT)
5269 {
5270 // \note Not supported on WIN32 handles
5271 // Test exporting semaphore multiple times.
5272 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("export_multiple_times_") + permanenceName,
5273 checkSupport, initProgramsToGetNativeFd, testSemaphoreMultipleExports, config);
5274
5275 // Test calling dup() on exported semaphore.
5276 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("dup_") + permanenceName, checkSupport,
5277 initProgramsToGetNativeFd, testSemaphoreFdDup, config);
5278 // Test calling dup2() on exported semaphore.
5279 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("dup2_") + permanenceName, checkSupport,
5280 initProgramsToGetNativeFd, testSemaphoreFdDup2, config);
5281 // Test calling dup3() on exported semaphore.
5282 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("dup3_") + permanenceName, checkSupport,
5283 initProgramsToGetNativeFd, testSemaphoreFdDup3, config);
5284 // Test sending semaphore fd over socket.
5285 addFunctionCaseWithPrograms(semaphoreGroup.get(), std::string("send_over_socket_") + permanenceName,
5286 checkSupport, initProgramsToGetNativeFd, testSemaphoreFdSendOverSocket, config);
5287 }
5288
5289 if (getHandelTypeTransferences(externalType) == TRANSFERENCE_REFERENCE)
5290 {
5291 // Test signaling and then waiting for the the sepmahore.
5292 addFunctionCase(semaphoreGroup.get(), std::string("signal_wait_import_") + permanenceName,
5293 testSemaphoreSignalWaitImport, config);
5294 // Test exporting, signaling, importing and waiting for the semaphore.
5295 addFunctionCase(semaphoreGroup.get(), std::string("export_signal_import_wait_") + permanenceName,
5296 testSemaphoreExportSignalImportWait, config);
5297 // Test exporting, importing, signaling and waiting for the semaphore.
5298 addFunctionCase(semaphoreGroup.get(), std::string("export_import_signal_wait_") + permanenceName,
5299 checkEvent, testSemaphoreExportImportSignalWait, config);
5300 }
5301 }
5302
5303 return semaphoreGroup;
5304 }
5305
createSemaphoreTests(tcu::TestContext & testCtx)5306 de::MovePtr<tcu::TestCaseGroup> createSemaphoreTests(tcu::TestContext &testCtx)
5307 {
5308 // Tests for external semaphores.
5309 de::MovePtr<tcu::TestCaseGroup> semaphoreGroup(new tcu::TestCaseGroup(testCtx, "semaphore"));
5310
5311 semaphoreGroup->addChild(
5312 createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT).release());
5313 semaphoreGroup->addChild(
5314 createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT).release());
5315 semaphoreGroup->addChild(
5316 createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT).release());
5317 semaphoreGroup->addChild(
5318 createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT).release());
5319 semaphoreGroup->addChild(
5320 createSemaphoreTests(testCtx, vk::VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_ZIRCON_EVENT_BIT_FUCHSIA).release());
5321
5322 return semaphoreGroup;
5323 }
5324
createMemoryTests(tcu::TestContext & testCtx,vk::VkExternalMemoryHandleTypeFlagBits externalType)5325 de::MovePtr<tcu::TestCaseGroup> createMemoryTests(tcu::TestContext &testCtx,
5326 vk::VkExternalMemoryHandleTypeFlagBits externalType)
5327 {
5328 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, externalMemoryTypeToName(externalType)));
5329
5330 for (size_t dedicatedNdx = 0; dedicatedNdx < 2; dedicatedNdx++)
5331 {
5332 const bool dedicated(dedicatedNdx == 1);
5333 de::MovePtr<tcu::TestCaseGroup> dedicatedGroup(
5334 new tcu::TestCaseGroup(testCtx, dedicated ? "dedicated" : "suballocated"));
5335
5336 for (size_t hostVisibleNdx = 0; hostVisibleNdx < 2; hostVisibleNdx++)
5337 {
5338 const bool hostVisible(hostVisibleNdx == 1);
5339 de::MovePtr<tcu::TestCaseGroup> hostVisibleGroup(
5340 new tcu::TestCaseGroup(testCtx, hostVisible ? "host_visible" : "device_only"));
5341 const MemoryTestConfig memoryConfig(externalType, hostVisible, dedicated);
5342
5343 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT ||
5344 externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT)
5345 {
5346 // Test creating memory with win32 properties .
5347 addFunctionCase(hostVisibleGroup.get(), "create_win32", testMemoryWin32Create, memoryConfig);
5348 }
5349
5350 // Test importing memory object twice.
5351 addFunctionCase(hostVisibleGroup.get(), "import_twice", testMemoryImportTwice, memoryConfig);
5352 // Test importing memory object multiple times.
5353 addFunctionCase(hostVisibleGroup.get(), "import_multiple_times", testMemoryMultipleImports, memoryConfig);
5354
5355 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ||
5356 externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT)
5357 {
5358 // Test calling dup() on exported memory.
5359 addFunctionCase(hostVisibleGroup.get(), "dup", testMemoryFdDup, memoryConfig);
5360 // Test calling dup2() on exported memory.
5361 addFunctionCase(hostVisibleGroup.get(), "dup2", testMemoryFdDup2, memoryConfig);
5362 // Test calling dup3() on exported memory.
5363 addFunctionCase(hostVisibleGroup.get(), "dup3", testMemoryFdDup3, memoryConfig);
5364 // Test sending memory fd over socket.
5365 addFunctionCase(hostVisibleGroup.get(), "send_over_socket", testMemoryFdSendOverSocket, memoryConfig);
5366 // \note Not supported on WIN32 handles
5367 // Test exporting memory multiple times.
5368 addFunctionCase(hostVisibleGroup.get(), "export_multiple_times", testMemoryMultipleExports,
5369 memoryConfig);
5370 }
5371
5372 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT)
5373 {
5374 // Test obtaining the FD memory properties
5375 addFunctionCase(hostVisibleGroup.get(), "fd_properties", testMemoryFdProperties, memoryConfig);
5376 }
5377
5378 dedicatedGroup->addChild(hostVisibleGroup.release());
5379 }
5380
5381 {
5382 de::MovePtr<tcu::TestCaseGroup> bufferGroup(new tcu::TestCaseGroup(testCtx, "buffer"));
5383 const BufferTestConfig bufferConfig(externalType, dedicated);
5384
5385 // External buffer memory info query.
5386 addFunctionCase(bufferGroup.get(), "info", testBufferQueries, externalType);
5387 // External buffer memory info query using BufferUsageFlags2CreateInfoKHR.
5388 addFunctionCase(bufferGroup.get(), "maintenance5", checkMaintenance5, testBufferQueriesMaintenance5,
5389 externalType);
5390 // Test binding, exporting, importing and binding buffer.
5391 addFunctionCase(bufferGroup.get(), "bind_export_import_bind", testBufferBindExportImportBind, bufferConfig);
5392 // Test exporting, binding, importing and binding buffer.
5393 addFunctionCase(bufferGroup.get(), "export_bind_import_bind", testBufferExportBindImportBind, bufferConfig);
5394 // Test exporting, importing and binding buffer.
5395 addFunctionCase(bufferGroup.get(), "export_import_bind_bind", testBufferExportImportBindBind, bufferConfig);
5396
5397 dedicatedGroup->addChild(bufferGroup.release());
5398 }
5399
5400 {
5401 de::MovePtr<tcu::TestCaseGroup> imageGroup(new tcu::TestCaseGroup(testCtx, "image"));
5402 const ImageTestConfig imageConfig(externalType, dedicated);
5403
5404 // External image memory info query.
5405 addFunctionCase(imageGroup.get(), "info", testImageQueries, externalType);
5406 // Test binding, exporting, importing and binding image.
5407 addFunctionCase(imageGroup.get(), "bind_export_import_bind", testImageBindExportImportBind, imageConfig);
5408 // Test exporting, binding, importing and binding image.
5409 addFunctionCase(imageGroup.get(), "export_bind_import_bind", testImageExportBindImportBind, imageConfig);
5410 // Test exporting, importing and binding image.
5411 addFunctionCase(imageGroup.get(), "export_import_bind_bind", testImageExportImportBindBind, imageConfig);
5412
5413 dedicatedGroup->addChild(imageGroup.release());
5414 }
5415
5416 group->addChild(dedicatedGroup.release());
5417 }
5418
5419 if (externalType == vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
5420 {
5421 {
5422 // Test minimum image format support
5423 de::MovePtr<tcu::TestCaseGroup> formatGroup(new tcu::TestCaseGroup(testCtx, "image_formats"));
5424
5425 const vk::VkFormat ahbFormats[] = {
5426 vk::VK_FORMAT_R8G8B8_UNORM,
5427 vk::VK_FORMAT_R8G8B8A8_UNORM,
5428 vk::VK_FORMAT_R5G6B5_UNORM_PACK16,
5429 vk::VK_FORMAT_R16G16B16A16_SFLOAT,
5430 vk::VK_FORMAT_A2B10G10R10_UNORM_PACK32,
5431 vk::VK_FORMAT_D16_UNORM,
5432 vk::VK_FORMAT_X8_D24_UNORM_PACK32,
5433 vk::VK_FORMAT_D24_UNORM_S8_UINT,
5434 vk::VK_FORMAT_D32_SFLOAT,
5435 vk::VK_FORMAT_D32_SFLOAT_S8_UINT,
5436 vk::VK_FORMAT_S8_UINT,
5437 vk::VK_FORMAT_R8_UNORM,
5438 vk::VK_FORMAT_R16_UINT,
5439 vk::VK_FORMAT_R16G16_UINT,
5440 vk::VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,
5441 };
5442 const size_t numOfAhbFormats = DE_LENGTH_OF_ARRAY(ahbFormats);
5443
5444 for (size_t ahbFormatNdx = 0; ahbFormatNdx < numOfAhbFormats; ahbFormatNdx++)
5445 {
5446 const vk::VkFormat format = ahbFormats[ahbFormatNdx];
5447 const std::string testCaseName = getFormatCaseName(format);
5448
5449 addFunctionCase(formatGroup.get(), testCaseName, testAndroidHardwareBufferImageFormat, format);
5450 }
5451
5452 group->addChild(formatGroup.release());
5453 }
5454
5455 {
5456 // Test minimum image format support
5457 de::MovePtr<tcu::TestCaseGroup> externalFormatResolve(
5458 new tcu::TestCaseGroup(testCtx, "external_format_resolve"));
5459 for (uint32_t i = 0u; i < AndroidHardwareBufferInstance::Format::COUNT; ++i)
5460 {
5461 const AndroidHardwareBufferInstance::Format format =
5462 static_cast<AndroidHardwareBufferInstance::Format>(i);
5463 if (AndroidHardwareBufferInstance::Format::BLOB == format)
5464 continue;
5465
5466 const std::string formatName = AndroidHardwareBufferInstance::getFormatName(format);
5467 externalFormatResolve->addChild(
5468 new AhbExternalFormatResolveApiCase(externalFormatResolve->getTestContext(), formatName, format));
5469 }
5470
5471 group->addChild(externalFormatResolve.release());
5472 }
5473 }
5474
5475 return group;
5476 }
5477
createMemoryTests(tcu::TestContext & testCtx)5478 de::MovePtr<tcu::TestCaseGroup> createMemoryTests(tcu::TestContext &testCtx)
5479 {
5480 // Tests for external memory
5481 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "memory"));
5482
5483 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT).release());
5484 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT).release());
5485 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT).release());
5486 group->addChild(
5487 createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID).release());
5488 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT).release());
5489 group->addChild(createMemoryTests(testCtx, vk::VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA).release());
5490
5491 return group;
5492 }
5493
5494 } // namespace
5495
createExternalMemoryTests(tcu::TestContext & testCtx)5496 tcu::TestCaseGroup *createExternalMemoryTests(tcu::TestContext &testCtx)
5497 {
5498 de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "external"));
5499
5500 group->addChild(createSemaphoreTests(testCtx).release());
5501 group->addChild(createMemoryTests(testCtx).release());
5502 group->addChild(createFenceTests(testCtx).release());
5503
5504 return group.release();
5505 }
5506
5507 } // namespace api
5508 } // namespace vkt
5509