• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2019 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // VulkanExternalImageTest.cpp : Tests of images allocated externally using Vulkan.
8 
9 #include "test_utils/ANGLETest.h"
10 
11 #include "common/debug.h"
12 #include "test_utils/VulkanHelper.h"
13 #include "test_utils/gl_raii.h"
14 
15 namespace angle
16 {
17 
18 namespace
19 {
20 
21 constexpr int kInvalidFd = -1;
22 
23 constexpr VkImageUsageFlags kDefaultImageUsageFlags =
24     VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT |
25     VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
26     VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
27 constexpr VkImageCreateFlags kDefaultImageCreateFlags = 0;
28 
29 constexpr VkImageUsageFlags kNoStorageImageUsageFlags =
30     kDefaultImageUsageFlags & ~VK_IMAGE_USAGE_STORAGE_BIT;
31 constexpr VkImageCreateFlags kMutableImageCreateFlags =
32     kDefaultImageCreateFlags | VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
33 
34 // List of VkFormat/internalformat combinations Chrome uses.
35 // This is compiled from the maps in
36 // components/viz/common/resources/resource_format_utils.cc.
37 const struct ImageFormatPair
38 {
39     VkFormat vkFormat;
40     GLenum internalFormat;
41     const char *requiredExtension;
42 } kChromeFormats[] = {
43     {VK_FORMAT_R8G8B8A8_UNORM, GL_RGBA8_OES},                    // RGBA_8888
44     {VK_FORMAT_B8G8R8A8_UNORM, GL_BGRA8_EXT},                    // BGRA_8888
45     {VK_FORMAT_R4G4B4A4_UNORM_PACK16, GL_RGBA4},                 // RGBA_4444
46     {VK_FORMAT_R16G16B16A16_SFLOAT, GL_RGBA16F_EXT},             // RGBA_F16
47     {VK_FORMAT_R8_UNORM, GL_R8_EXT},                             // RED_8
48     {VK_FORMAT_R5G6B5_UNORM_PACK16, GL_RGB565},                  // RGB_565
49     {VK_FORMAT_R16_UNORM, GL_R16_EXT, "GL_EXT_texture_norm16"},  // R16_EXT
50     {VK_FORMAT_A2B10G10R10_UNORM_PACK32, GL_RGB10_A2_EXT},       // RGBA_1010102
51     {VK_FORMAT_R8_UNORM, GL_ALPHA8_EXT},                         // ALPHA_8
52     {VK_FORMAT_R8_UNORM, GL_LUMINANCE8_EXT},                     // LUMINANCE_8
53     {VK_FORMAT_R8G8_UNORM, GL_RG8_EXT},                          // RG_88
54     {VK_FORMAT_R8G8B8A8_UNORM, GL_RGB8_OES},                     // RGBX_8888
55 };
56 
57 struct OpaqueFdTraits
58 {
59     using Handle = int;
InvalidHandleangle::__anonb5d5b6350111::OpaqueFdTraits60     static Handle InvalidHandle() { return kInvalidFd; }
61 
MemoryObjectExtensionangle::__anonb5d5b6350111::OpaqueFdTraits62     static const char *MemoryObjectExtension() { return "GL_EXT_memory_object_fd"; }
SemaphoreExtensionangle::__anonb5d5b6350111::OpaqueFdTraits63     static const char *SemaphoreExtension() { return "GL_EXT_semaphore_fd"; }
64 
CanCreateSemaphoreangle::__anonb5d5b6350111::OpaqueFdTraits65     static bool CanCreateSemaphore(const VulkanHelper &helper)
66     {
67         return helper.canCreateSemaphoreOpaqueFd();
68     }
69 
CreateSemaphoreangle::__anonb5d5b6350111::OpaqueFdTraits70     static VkResult CreateSemaphore(VulkanHelper *helper, VkSemaphore *semaphore)
71     {
72         return helper->createSemaphoreOpaqueFd(semaphore);
73     }
74 
ExportSemaphoreangle::__anonb5d5b6350111::OpaqueFdTraits75     static VkResult ExportSemaphore(VulkanHelper *helper, VkSemaphore semaphore, Handle *handle)
76     {
77         return helper->exportSemaphoreOpaqueFd(semaphore, handle);
78     }
79 
ImportSemaphoreangle::__anonb5d5b6350111::OpaqueFdTraits80     static void ImportSemaphore(GLuint semaphore, Handle handle)
81     {
82         glImportSemaphoreFdEXT(semaphore, GL_HANDLE_TYPE_OPAQUE_FD_EXT, handle);
83     }
84 
CanCreateImageangle::__anonb5d5b6350111::OpaqueFdTraits85     static bool CanCreateImage(const VulkanHelper &helper,
86                                VkFormat format,
87                                VkImageType type,
88                                VkImageTiling tiling,
89                                VkImageCreateFlags createFlags,
90                                VkImageUsageFlags usageFlags)
91     {
92         return helper.canCreateImageOpaqueFd(format, type, tiling, createFlags, usageFlags);
93     }
94 
CreateImage2Dangle::__anonb5d5b6350111::OpaqueFdTraits95     static VkResult CreateImage2D(VulkanHelper *helper,
96                                   VkFormat format,
97                                   VkImageCreateFlags createFlags,
98                                   VkImageUsageFlags usageFlags,
99                                   const void *imageCreateInfoPNext,
100                                   VkExtent3D extent,
101                                   VkImage *imageOut,
102                                   VkDeviceMemory *deviceMemoryOut,
103                                   VkDeviceSize *deviceMemorySizeOut)
104     {
105         return helper->createImage2DOpaqueFd(format, createFlags, usageFlags, imageCreateInfoPNext,
106                                              extent, imageOut, deviceMemoryOut,
107                                              deviceMemorySizeOut);
108     }
109 
ExportMemoryangle::__anonb5d5b6350111::OpaqueFdTraits110     static VkResult ExportMemory(VulkanHelper *helper, VkDeviceMemory deviceMemory, Handle *handle)
111     {
112         return helper->exportMemoryOpaqueFd(deviceMemory, handle);
113     }
114 
ImportMemoryangle::__anonb5d5b6350111::OpaqueFdTraits115     static void ImportMemory(GLuint memoryObject, GLuint64 size, Handle handle)
116     {
117         glImportMemoryFdEXT(memoryObject, size, GL_HANDLE_TYPE_OPAQUE_FD_EXT, handle);
118     }
119 };
120 
121 struct FuchsiaTraits
122 {
123     using Handle = zx_handle_t;
124 
InvalidHandleangle::__anonb5d5b6350111::FuchsiaTraits125     static Handle InvalidHandle() { return ZX_HANDLE_INVALID; }
126 
MemoryObjectExtensionangle::__anonb5d5b6350111::FuchsiaTraits127     static const char *MemoryObjectExtension() { return "GL_ANGLE_memory_object_fuchsia"; }
SemaphoreExtensionangle::__anonb5d5b6350111::FuchsiaTraits128     static const char *SemaphoreExtension() { return "GL_ANGLE_semaphore_fuchsia"; }
129 
CanCreateSemaphoreangle::__anonb5d5b6350111::FuchsiaTraits130     static bool CanCreateSemaphore(const VulkanHelper &helper)
131     {
132         return helper.canCreateSemaphoreZirconEvent();
133     }
134 
CreateSemaphoreangle::__anonb5d5b6350111::FuchsiaTraits135     static VkResult CreateSemaphore(VulkanHelper *helper, VkSemaphore *semaphore)
136     {
137         return helper->createSemaphoreZirconEvent(semaphore);
138     }
139 
ExportSemaphoreangle::__anonb5d5b6350111::FuchsiaTraits140     static VkResult ExportSemaphore(VulkanHelper *helper, VkSemaphore semaphore, Handle *handle)
141     {
142         return helper->exportSemaphoreZirconEvent(semaphore, handle);
143     }
144 
ImportSemaphoreangle::__anonb5d5b6350111::FuchsiaTraits145     static void ImportSemaphore(GLuint semaphore, Handle handle)
146     {
147         glImportSemaphoreZirconHandleANGLE(semaphore, GL_HANDLE_TYPE_ZIRCON_EVENT_ANGLE, handle);
148     }
149 
CanCreateImageangle::__anonb5d5b6350111::FuchsiaTraits150     static bool CanCreateImage(const VulkanHelper &helper,
151                                VkFormat format,
152                                VkImageType type,
153                                VkImageTiling tiling,
154                                VkImageCreateFlags createFlags,
155                                VkImageUsageFlags usageFlags)
156     {
157         return helper.canCreateImageZirconVmo(format, type, tiling, createFlags, usageFlags);
158     }
159 
CreateImage2Dangle::__anonb5d5b6350111::FuchsiaTraits160     static VkResult CreateImage2D(VulkanHelper *helper,
161                                   VkFormat format,
162                                   VkImageCreateFlags createFlags,
163                                   VkImageUsageFlags usageFlags,
164                                   const void *imageCreateInfoPNext,
165                                   VkExtent3D extent,
166                                   VkImage *imageOut,
167                                   VkDeviceMemory *deviceMemoryOut,
168                                   VkDeviceSize *deviceMemorySizeOut)
169     {
170         return helper->createImage2DZirconVmo(format, createFlags, usageFlags, imageCreateInfoPNext,
171                                               extent, imageOut, deviceMemoryOut,
172                                               deviceMemorySizeOut);
173     }
174 
ExportMemoryangle::__anonb5d5b6350111::FuchsiaTraits175     static VkResult ExportMemory(VulkanHelper *helper, VkDeviceMemory deviceMemory, Handle *handle)
176     {
177         return helper->exportMemoryZirconVmo(deviceMemory, handle);
178     }
179 
ImportMemoryangle::__anonb5d5b6350111::FuchsiaTraits180     static void ImportMemory(GLuint memoryObject, GLuint64 size, Handle handle)
181     {
182         glImportMemoryZirconHandleANGLE(memoryObject, size, GL_HANDLE_TYPE_ZIRCON_VMO_ANGLE,
183                                         handle);
184     }
185 };
186 
187 }  // namespace
188 
189 class VulkanExternalImageTest : public ANGLETest
190 {
191   protected:
VulkanExternalImageTest()192     VulkanExternalImageTest()
193     {
194         setWindowWidth(1);
195         setWindowHeight(1);
196         setConfigRedBits(8);
197         setConfigGreenBits(8);
198         setConfigBlueBits(8);
199         setConfigAlphaBits(8);
200     }
201 
202     template <typename Traits>
203     void runShouldDrawTest(bool isSwiftshader, bool enableDebugLayers);
204 
205     template <typename Traits>
206     void runWaitSemaphoresRetainsContentTest(bool isSwiftshader, bool enableDebugLayers);
207 };
208 
209 template <typename Traits>
RunShouldImportMemoryTest(VkImageCreateFlags createFlags,VkImageUsageFlags usageFlags,bool isSwiftshader,bool enableDebugLayers)210 void RunShouldImportMemoryTest(VkImageCreateFlags createFlags,
211                                VkImageUsageFlags usageFlags,
212                                bool isSwiftshader,
213                                bool enableDebugLayers)
214 {
215     ASSERT(EnsureGLExtensionEnabled(Traits::MemoryObjectExtension()));
216 
217     VulkanHelper helper;
218     helper.initialize(isSwiftshader, enableDebugLayers);
219 
220     VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
221     ANGLE_SKIP_TEST_IF(!Traits::CanCreateImage(helper, format, VK_IMAGE_TYPE_2D,
222                                                VK_IMAGE_TILING_OPTIMAL, createFlags, usageFlags));
223 
224     VkImage image                 = VK_NULL_HANDLE;
225     VkDeviceMemory deviceMemory   = VK_NULL_HANDLE;
226     VkDeviceSize deviceMemorySize = 0;
227 
228     VkExtent3D extent = {1, 1, 1};
229     VkResult result   = Traits::CreateImage2D(&helper, format, createFlags, usageFlags, nullptr,
230                                             extent, &image, &deviceMemory, &deviceMemorySize);
231     EXPECT_EQ(result, VK_SUCCESS);
232 
233     typename Traits::Handle memoryHandle = Traits::InvalidHandle();
234     result = Traits::ExportMemory(&helper, deviceMemory, &memoryHandle);
235     EXPECT_EQ(result, VK_SUCCESS);
236     EXPECT_NE(memoryHandle, Traits::InvalidHandle());
237 
238     {
239         GLMemoryObject memoryObject;
240         GLint dedicatedMemory = GL_TRUE;
241         glMemoryObjectParameterivEXT(memoryObject, GL_DEDICATED_MEMORY_OBJECT_EXT,
242                                      &dedicatedMemory);
243         Traits::ImportMemory(memoryObject, deviceMemorySize, memoryHandle);
244 
245         // Test that after calling glImportMemoryFdEXT, the parameters of the memory object cannot
246         // be changed
247         dedicatedMemory = GL_FALSE;
248         glMemoryObjectParameterivEXT(memoryObject, GL_DEDICATED_MEMORY_OBJECT_EXT,
249                                      &dedicatedMemory);
250         EXPECT_GL_ERROR(GL_INVALID_OPERATION);
251     }
252 
253     EXPECT_GL_NO_ERROR();
254 
255     vkDestroyImage(helper.getDevice(), image, nullptr);
256     vkFreeMemory(helper.getDevice(), deviceMemory, nullptr);
257 }
258 
259 // glImportMemoryFdEXT must be able to import a valid opaque fd.
TEST_P(VulkanExternalImageTest,ShouldImportMemoryOpaqueFd)260 TEST_P(VulkanExternalImageTest, ShouldImportMemoryOpaqueFd)
261 {
262     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
263     RunShouldImportMemoryTest<OpaqueFdTraits>(kDefaultImageCreateFlags, kDefaultImageUsageFlags,
264                                               isSwiftshader(), enableDebugLayers());
265 }
266 
267 // glImportMemoryZirconHandleANGLE must be able to import a valid vmo.
TEST_P(VulkanExternalImageTest,ShouldImportMemoryZirconVmo)268 TEST_P(VulkanExternalImageTest, ShouldImportMemoryZirconVmo)
269 {
270     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_fuchsia"));
271     RunShouldImportMemoryTest<FuchsiaTraits>(kDefaultImageCreateFlags, kDefaultImageUsageFlags,
272                                              isSwiftshader(), enableDebugLayers());
273 }
274 
275 template <typename Traits>
RunShouldImportSemaphoreTest(bool isSwiftshader,bool enableDebugLayers)276 void RunShouldImportSemaphoreTest(bool isSwiftshader, bool enableDebugLayers)
277 {
278     ASSERT(EnsureGLExtensionEnabled(Traits::SemaphoreExtension()));
279 
280     VulkanHelper helper;
281     helper.initialize(isSwiftshader, enableDebugLayers);
282 
283     ANGLE_SKIP_TEST_IF(!Traits::CanCreateSemaphore(helper));
284 
285     VkSemaphore vkSemaphore = VK_NULL_HANDLE;
286     VkResult result         = helper.createSemaphoreOpaqueFd(&vkSemaphore);
287     EXPECT_EQ(result, VK_SUCCESS);
288 
289     typename Traits::Handle semaphoreHandle = Traits::InvalidHandle();
290     result = Traits::ExportSemaphore(&helper, vkSemaphore, &semaphoreHandle);
291     EXPECT_EQ(result, VK_SUCCESS);
292     EXPECT_NE(semaphoreHandle, Traits::InvalidHandle());
293 
294     {
295         GLSemaphore glSemaphore;
296         Traits::ImportSemaphore(glSemaphore, semaphoreHandle);
297     }
298 
299     EXPECT_GL_NO_ERROR();
300 
301     vkDestroySemaphore(helper.getDevice(), vkSemaphore, nullptr);
302 }
303 
304 // glImportSemaphoreFdEXT must be able to import a valid opaque fd.
TEST_P(VulkanExternalImageTest,ShouldImportSemaphoreOpaqueFd)305 TEST_P(VulkanExternalImageTest, ShouldImportSemaphoreOpaqueFd)
306 {
307     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_semaphore_fd"));
308     RunShouldImportSemaphoreTest<OpaqueFdTraits>(isSwiftshader(), enableDebugLayers());
309 }
310 
311 // glImportSemaphoreZirconHandleANGLE must be able to import a valid handle.
TEST_P(VulkanExternalImageTest,ShouldImportSemaphoreZirconEvent)312 TEST_P(VulkanExternalImageTest, ShouldImportSemaphoreZirconEvent)
313 {
314     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_semaphore_fuchsia"));
315     RunShouldImportSemaphoreTest<FuchsiaTraits>(isSwiftshader(), enableDebugLayers());
316 }
317 
318 template <typename Traits>
RunShouldClearTest(bool useMemoryObjectFlags,VkImageCreateFlags createFlags,VkImageUsageFlags usageFlags,bool isSwiftshader,bool enableDebugLayers)319 void RunShouldClearTest(bool useMemoryObjectFlags,
320                         VkImageCreateFlags createFlags,
321                         VkImageUsageFlags usageFlags,
322                         bool isSwiftshader,
323                         bool enableDebugLayers)
324 {
325     ASSERT(EnsureGLExtensionEnabled(Traits::MemoryObjectExtension()));
326 
327     VulkanHelper helper;
328     helper.initialize(isSwiftshader, enableDebugLayers);
329 
330     VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
331     ANGLE_SKIP_TEST_IF(!Traits::CanCreateImage(helper, format, VK_IMAGE_TYPE_2D,
332                                                VK_IMAGE_TILING_OPTIMAL, createFlags, usageFlags));
333 
334     VkImage image                 = VK_NULL_HANDLE;
335     VkDeviceMemory deviceMemory   = VK_NULL_HANDLE;
336     VkDeviceSize deviceMemorySize = 0;
337 
338     VkExtent3D extent = {1, 1, 1};
339     VkResult result   = Traits::CreateImage2D(&helper, format, createFlags, usageFlags, nullptr,
340                                             extent, &image, &deviceMemory, &deviceMemorySize);
341     EXPECT_EQ(result, VK_SUCCESS);
342 
343     typename Traits::Handle memoryHandle = Traits::InvalidHandle();
344     result = Traits::ExportMemory(&helper, deviceMemory, &memoryHandle);
345     EXPECT_EQ(result, VK_SUCCESS);
346     EXPECT_NE(memoryHandle, Traits::InvalidHandle());
347 
348     {
349         GLMemoryObject memoryObject;
350         GLint dedicatedMemory = GL_TRUE;
351         glMemoryObjectParameterivEXT(memoryObject, GL_DEDICATED_MEMORY_OBJECT_EXT,
352                                      &dedicatedMemory);
353         Traits::ImportMemory(memoryObject, deviceMemorySize, memoryHandle);
354 
355         GLTexture texture;
356         glBindTexture(GL_TEXTURE_2D, texture);
357         if (useMemoryObjectFlags)
358         {
359             glTexStorageMemFlags2DANGLE(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1, memoryObject, 0,
360                                         createFlags, usageFlags, nullptr);
361         }
362         else
363         {
364             glTexStorageMem2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1, memoryObject, 0);
365         }
366 
367         GLFramebuffer framebuffer;
368         glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
369         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
370 
371         glClearColor(0.5f, 0.5f, 0.5f, 0.5f);
372         glClear(GL_COLOR_BUFFER_BIT);
373 
374         EXPECT_PIXEL_NEAR(0, 0, 128, 128, 128, 128, 1.0);
375     }
376 
377     EXPECT_GL_NO_ERROR();
378 
379     vkDestroyImage(helper.getDevice(), image, nullptr);
380     vkFreeMemory(helper.getDevice(), deviceMemory, nullptr);
381 }
382 
383 // Test creating and clearing a simple RGBA8 texture in an opaque fd.
TEST_P(VulkanExternalImageTest,ShouldClearOpaqueFdRGBA8)384 TEST_P(VulkanExternalImageTest, ShouldClearOpaqueFdRGBA8)
385 {
386     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
387     // http://anglebug.com/4630
388     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL() && (IsPixel2() || IsPixel2XL()));
389     RunShouldClearTest<OpaqueFdTraits>(false, kDefaultImageCreateFlags, kDefaultImageUsageFlags,
390                                        isSwiftshader(), enableDebugLayers());
391 }
392 
393 // Test creating and clearing a simple RGBA8 texture in an opaque fd, using
394 // GL_ANGLE_memory_object_flags.
TEST_P(VulkanExternalImageTest,ShouldClearOpaqueWithFlagsFdRGBA8)395 TEST_P(VulkanExternalImageTest, ShouldClearOpaqueWithFlagsFdRGBA8)
396 {
397     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
398     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
399     RunShouldClearTest<OpaqueFdTraits>(true, kDefaultImageCreateFlags, kDefaultImageUsageFlags,
400                                        isSwiftshader(), enableDebugLayers());
401 }
402 
403 // Test creating and clearing a simple RGBA8 texture without STORAGE usage in an opaque fd.
TEST_P(VulkanExternalImageTest,ShouldClearNoStorageUsageOpaqueFdRGBA8)404 TEST_P(VulkanExternalImageTest, ShouldClearNoStorageUsageOpaqueFdRGBA8)
405 {
406     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
407     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
408     RunShouldClearTest<OpaqueFdTraits>(true, kDefaultImageCreateFlags, kNoStorageImageUsageFlags,
409                                        isSwiftshader(), enableDebugLayers());
410 }
411 
412 // Test creating and clearing a simple RGBA8 texture without STORAGE usage but with MUTABLE in an
413 // opaque fd.
TEST_P(VulkanExternalImageTest,ShouldClearMutableNoStorageUsageOpaqueFdRGBA8)414 TEST_P(VulkanExternalImageTest, ShouldClearMutableNoStorageUsageOpaqueFdRGBA8)
415 {
416     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
417     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
418     RunShouldClearTest<OpaqueFdTraits>(true, kMutableImageCreateFlags, kNoStorageImageUsageFlags,
419                                        isSwiftshader(), enableDebugLayers());
420 }
421 
422 // Test creating and clearing a simple RGBA8 texture in a zircon vmo.
TEST_P(VulkanExternalImageTest,ShouldClearZirconVmoRGBA8)423 TEST_P(VulkanExternalImageTest, ShouldClearZirconVmoRGBA8)
424 {
425     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_fuchsia"));
426     RunShouldClearTest<FuchsiaTraits>(false, kDefaultImageCreateFlags, kDefaultImageUsageFlags,
427                                       isSwiftshader(), enableDebugLayers());
428 }
429 
430 // Test creating and clearing a simple RGBA8 texture in a zircon vmo, using
431 // GL_ANGLE_memory_object_flags.
TEST_P(VulkanExternalImageTest,ShouldClearZirconWithFlagsVmoRGBA8)432 TEST_P(VulkanExternalImageTest, ShouldClearZirconWithFlagsVmoRGBA8)
433 {
434     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_fuchsia"));
435     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
436     RunShouldClearTest<FuchsiaTraits>(true, kDefaultImageCreateFlags, kDefaultImageUsageFlags,
437                                       isSwiftshader(), enableDebugLayers());
438 }
439 
440 // Test creating and clearing a simple RGBA8 texture without STORAGE usage in a zircon vmo.
TEST_P(VulkanExternalImageTest,ShouldClearNoStorageUsageZirconVmoRGBA8)441 TEST_P(VulkanExternalImageTest, ShouldClearNoStorageUsageZirconVmoRGBA8)
442 {
443     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_fuchsia"));
444     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
445     RunShouldClearTest<FuchsiaTraits>(true, kDefaultImageCreateFlags, kNoStorageImageUsageFlags,
446                                       isSwiftshader(), enableDebugLayers());
447 }
448 
449 // Test creating and clearing a simple RGBA8 texture without STORAGE usage but with MUTABLE in a
450 // zircon vmo.
TEST_P(VulkanExternalImageTest,ShouldClearMutableNoStorageUsageZirconVmoRGBA8)451 TEST_P(VulkanExternalImageTest, ShouldClearMutableNoStorageUsageZirconVmoRGBA8)
452 {
453     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_fuchsia"));
454     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
455     RunShouldClearTest<FuchsiaTraits>(true, kMutableImageCreateFlags, kNoStorageImageUsageFlags,
456                                       isSwiftshader(), enableDebugLayers());
457 }
458 
459 template <typename Traits>
RunTextureFormatCompatChromiumTest(bool useMemoryObjectFlags,VkImageCreateFlags createFlags,VkImageUsageFlags usageFlags,bool isSwiftshader,bool enableDebugLayers,bool isES3)460 void RunTextureFormatCompatChromiumTest(bool useMemoryObjectFlags,
461                                         VkImageCreateFlags createFlags,
462                                         VkImageUsageFlags usageFlags,
463                                         bool isSwiftshader,
464                                         bool enableDebugLayers,
465                                         bool isES3)
466 {
467     ASSERT(EnsureGLExtensionEnabled(Traits::MemoryObjectExtension()));
468 
469     VulkanHelper helper;
470     helper.initialize(isSwiftshader, enableDebugLayers);
471     for (const ImageFormatPair &format : kChromeFormats)
472     {
473         // https://crbug.com/angleproject/5046
474         if ((format.vkFormat == VK_FORMAT_R4G4B4A4_UNORM_PACK16) && IsIntel())
475         {
476             continue;
477         }
478 
479         if (!Traits::CanCreateImage(helper, format.vkFormat, VK_IMAGE_TYPE_2D,
480                                     VK_IMAGE_TILING_OPTIMAL, createFlags, usageFlags))
481         {
482             continue;
483         }
484 
485         if (format.requiredExtension && !IsGLExtensionEnabled(format.requiredExtension))
486         {
487             continue;
488         }
489 
490         if (format.internalFormat == GL_RGB10_A2_EXT && !isES3 &&
491             !IsGLExtensionEnabled("GL_EXT_texture_type_2_10_10_10_REV"))
492         {
493             continue;
494         }
495 
496         VkImage image                 = VK_NULL_HANDLE;
497         VkDeviceMemory deviceMemory   = VK_NULL_HANDLE;
498         VkDeviceSize deviceMemorySize = 0;
499 
500         VkExtent3D extent = {113, 211, 1};
501         VkResult result =
502             Traits::CreateImage2D(&helper, format.vkFormat, createFlags, usageFlags, nullptr,
503                                   extent, &image, &deviceMemory, &deviceMemorySize);
504         EXPECT_EQ(result, VK_SUCCESS);
505 
506         typename Traits::Handle memoryHandle = Traits::InvalidHandle();
507         result = Traits::ExportMemory(&helper, deviceMemory, &memoryHandle);
508         EXPECT_EQ(result, VK_SUCCESS);
509         EXPECT_NE(memoryHandle, Traits::InvalidHandle());
510 
511         {
512             GLMemoryObject memoryObject;
513             GLint dedicatedMemory = GL_TRUE;
514             glMemoryObjectParameterivEXT(memoryObject, GL_DEDICATED_MEMORY_OBJECT_EXT,
515                                          &dedicatedMemory);
516             Traits::ImportMemory(memoryObject, deviceMemorySize, memoryHandle);
517 
518             GLTexture texture;
519             glBindTexture(GL_TEXTURE_2D, texture);
520             if (useMemoryObjectFlags)
521             {
522                 glTexStorageMemFlags2DANGLE(GL_TEXTURE_2D, 1, format.internalFormat, extent.width,
523                                             extent.height, memoryObject, 0, createFlags, usageFlags,
524                                             nullptr);
525             }
526             else
527             {
528                 glTexStorageMem2DEXT(GL_TEXTURE_2D, 1, format.internalFormat, extent.width,
529                                      extent.height, memoryObject, 0);
530             }
531         }
532 
533         EXPECT_GL_NO_ERROR();
534 
535         vkDestroyImage(helper.getDevice(), image, nullptr);
536         vkFreeMemory(helper.getDevice(), deviceMemory, nullptr);
537     }
538 }
539 
540 // Test all format combinations used by Chrome import successfully (opaque fd).
TEST_P(VulkanExternalImageTest,TextureFormatCompatChromiumFd)541 TEST_P(VulkanExternalImageTest, TextureFormatCompatChromiumFd)
542 {
543     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
544     RunTextureFormatCompatChromiumTest<OpaqueFdTraits>(
545         false, kDefaultImageCreateFlags, kDefaultImageUsageFlags, isSwiftshader(),
546         enableDebugLayers(), getClientMajorVersion() >= 3);
547 }
548 
549 // Test all format combinations used by Chrome import successfully (opaque fd), using
550 // GL_ANGLE_memory_object_flags.
TEST_P(VulkanExternalImageTest,TextureFormatCompatChromiumWithFlagsFd)551 TEST_P(VulkanExternalImageTest, TextureFormatCompatChromiumWithFlagsFd)
552 {
553     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
554     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
555     RunTextureFormatCompatChromiumTest<OpaqueFdTraits>(
556         true, kDefaultImageCreateFlags, kDefaultImageUsageFlags, isSwiftshader(),
557         enableDebugLayers(), getClientMajorVersion() >= 3);
558 }
559 
560 // Test all format combinations used by Chrome import successfully (opaque fd), without STORAGE
561 // usage.
TEST_P(VulkanExternalImageTest,TextureFormatCompatChromiumNoStorageFd)562 TEST_P(VulkanExternalImageTest, TextureFormatCompatChromiumNoStorageFd)
563 {
564     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
565     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
566     RunTextureFormatCompatChromiumTest<OpaqueFdTraits>(
567         true, kDefaultImageCreateFlags, kNoStorageImageUsageFlags, isSwiftshader(),
568         enableDebugLayers(), getClientMajorVersion() >= 3);
569 }
570 
571 // Test all format combinations used by Chrome import successfully (opaque fd), without STORAGE
572 // usage but with MUTABLE.
TEST_P(VulkanExternalImageTest,TextureFormatCompatChromiumMutableNoStorageFd)573 TEST_P(VulkanExternalImageTest, TextureFormatCompatChromiumMutableNoStorageFd)
574 {
575     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
576     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
577 
578     // http://anglebug.com/5682
579     ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsVulkan());
580 
581     RunTextureFormatCompatChromiumTest<OpaqueFdTraits>(
582         true, kMutableImageCreateFlags, kNoStorageImageUsageFlags, isSwiftshader(),
583         enableDebugLayers(), getClientMajorVersion() >= 3);
584 }
585 
586 // Test all format combinations used by Chrome import successfully (fuchsia).
TEST_P(VulkanExternalImageTest,TextureFormatCompatChromiumZirconVmo)587 TEST_P(VulkanExternalImageTest, TextureFormatCompatChromiumZirconVmo)
588 {
589     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_fuchsia"));
590     RunTextureFormatCompatChromiumTest<FuchsiaTraits>(
591         false, kDefaultImageCreateFlags, kDefaultImageUsageFlags, isSwiftshader(),
592         enableDebugLayers(), getClientMajorVersion() >= 3);
593 }
594 
595 // Test all format combinations used by Chrome import successfully (fuchsia), using
596 // GL_ANGLE_memory_object_flags.
TEST_P(VulkanExternalImageTest,TextureFormatCompatChromiumWithFlagsZirconVmo)597 TEST_P(VulkanExternalImageTest, TextureFormatCompatChromiumWithFlagsZirconVmo)
598 {
599     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_fuchsia"));
600     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
601     RunTextureFormatCompatChromiumTest<FuchsiaTraits>(
602         true, kDefaultImageCreateFlags, kDefaultImageUsageFlags, isSwiftshader(),
603         enableDebugLayers(), getClientMajorVersion() >= 3);
604 }
605 
606 // Test all format combinations used by Chrome import successfully (fuchsia), without STORAGE usage.
TEST_P(VulkanExternalImageTest,TextureFormatCompatChromiumNoStorageZirconVmo)607 TEST_P(VulkanExternalImageTest, TextureFormatCompatChromiumNoStorageZirconVmo)
608 {
609     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_fuchsia"));
610     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
611     RunTextureFormatCompatChromiumTest<FuchsiaTraits>(
612         true, kDefaultImageCreateFlags, kNoStorageImageUsageFlags, isSwiftshader(),
613         enableDebugLayers(), getClientMajorVersion() >= 3);
614 }
615 
616 // Test all format combinations used by Chrome import successfully (fuchsia), without STORAGE usage
617 // but with MUTABLE.
TEST_P(VulkanExternalImageTest,TextureFormatCompatChromiumMutableNoStorageZirconVmo)618 TEST_P(VulkanExternalImageTest, TextureFormatCompatChromiumMutableNoStorageZirconVmo)
619 {
620     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_fuchsia"));
621     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
622     RunTextureFormatCompatChromiumTest<FuchsiaTraits>(
623         true, kMutableImageCreateFlags, kNoStorageImageUsageFlags, isSwiftshader(),
624         enableDebugLayers(), getClientMajorVersion() >= 3);
625 }
626 
627 template <typename Traits>
RunShouldClearWithSemaphoresTest(bool useMemoryObjectFlags,VkImageCreateFlags createFlags,VkImageUsageFlags usageFlags,bool isSwiftshader,bool enableDebugLayers)628 void RunShouldClearWithSemaphoresTest(bool useMemoryObjectFlags,
629                                       VkImageCreateFlags createFlags,
630                                       VkImageUsageFlags usageFlags,
631                                       bool isSwiftshader,
632                                       bool enableDebugLayers)
633 {
634     ASSERT(EnsureGLExtensionEnabled(Traits::MemoryObjectExtension()));
635     ASSERT(EnsureGLExtensionEnabled(Traits::SemaphoreExtension()));
636 
637     VulkanHelper helper;
638     helper.initialize(isSwiftshader, enableDebugLayers);
639 
640     VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
641     ANGLE_SKIP_TEST_IF(!Traits::CanCreateImage(helper, format, VK_IMAGE_TYPE_2D,
642                                                VK_IMAGE_TILING_OPTIMAL, createFlags, usageFlags));
643     ANGLE_SKIP_TEST_IF(!Traits::CanCreateSemaphore(helper));
644 
645     VkSemaphore vkAcquireSemaphore = VK_NULL_HANDLE;
646     VkResult result                = Traits::CreateSemaphore(&helper, &vkAcquireSemaphore);
647     EXPECT_EQ(result, VK_SUCCESS);
648     EXPECT_TRUE(vkAcquireSemaphore != VK_NULL_HANDLE);
649 
650     VkSemaphore vkReleaseSemaphore = VK_NULL_HANDLE;
651     result                         = Traits::CreateSemaphore(&helper, &vkReleaseSemaphore);
652     EXPECT_EQ(result, VK_SUCCESS);
653     EXPECT_TRUE(vkReleaseSemaphore != VK_NULL_HANDLE);
654 
655     typename Traits::Handle acquireSemaphoreHandle = Traits::InvalidHandle();
656     result = Traits::ExportSemaphore(&helper, vkAcquireSemaphore, &acquireSemaphoreHandle);
657     EXPECT_EQ(result, VK_SUCCESS);
658     EXPECT_NE(acquireSemaphoreHandle, Traits::InvalidHandle());
659 
660     typename Traits::Handle releaseSemaphoreHandle = Traits::InvalidHandle();
661     result = Traits::ExportSemaphore(&helper, vkReleaseSemaphore, &releaseSemaphoreHandle);
662     EXPECT_EQ(result, VK_SUCCESS);
663     EXPECT_NE(releaseSemaphoreHandle, Traits::InvalidHandle());
664 
665     VkImage image                 = VK_NULL_HANDLE;
666     VkDeviceMemory deviceMemory   = VK_NULL_HANDLE;
667     VkDeviceSize deviceMemorySize = 0;
668 
669     VkExtent3D extent = {1, 1, 1};
670     result = Traits::CreateImage2D(&helper, format, createFlags, usageFlags, nullptr, extent,
671                                    &image, &deviceMemory, &deviceMemorySize);
672     EXPECT_EQ(result, VK_SUCCESS);
673 
674     typename Traits::Handle memoryHandle = Traits::InvalidHandle();
675     result = Traits::ExportMemory(&helper, deviceMemory, &memoryHandle);
676     EXPECT_EQ(result, VK_SUCCESS);
677     EXPECT_NE(memoryHandle, Traits::InvalidHandle());
678 
679     {
680         GLMemoryObject memoryObject;
681         GLint dedicatedMemory = GL_TRUE;
682         glMemoryObjectParameterivEXT(memoryObject, GL_DEDICATED_MEMORY_OBJECT_EXT,
683                                      &dedicatedMemory);
684         Traits::ImportMemory(memoryObject, deviceMemorySize, memoryHandle);
685 
686         GLTexture texture;
687         glBindTexture(GL_TEXTURE_2D, texture);
688         if (useMemoryObjectFlags)
689         {
690             glTexStorageMemFlags2DANGLE(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1, memoryObject, 0,
691                                         createFlags, usageFlags, nullptr);
692         }
693         else
694         {
695             glTexStorageMem2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1, memoryObject, 0);
696         }
697 
698         GLSemaphore glAcquireSemaphore;
699         Traits::ImportSemaphore(glAcquireSemaphore, acquireSemaphoreHandle);
700 
701         helper.releaseImageAndSignalSemaphore(image, VK_IMAGE_LAYOUT_UNDEFINED,
702                                               VK_IMAGE_LAYOUT_GENERAL, vkAcquireSemaphore);
703 
704         const GLuint barrierTextures[] = {
705             texture,
706         };
707         constexpr uint32_t textureBarriersCount = std::extent<decltype(barrierTextures)>();
708         const GLenum textureSrcLayouts[]        = {
709             GL_LAYOUT_GENERAL_EXT,
710         };
711         constexpr uint32_t textureSrcLayoutsCount = std::extent<decltype(textureSrcLayouts)>();
712         static_assert(textureBarriersCount == textureSrcLayoutsCount,
713                       "barrierTextures and textureSrcLayouts must be the same length");
714         glWaitSemaphoreEXT(glAcquireSemaphore, 0, nullptr, textureBarriersCount, barrierTextures,
715                            textureSrcLayouts);
716 
717         GLFramebuffer framebuffer;
718         glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
719         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
720 
721         glClearColor(0.5f, 0.5f, 0.5f, 0.5f);
722         glClear(GL_COLOR_BUFFER_BIT);
723 
724         GLSemaphore glReleaseSemaphore;
725         Traits::ImportSemaphore(glReleaseSemaphore, releaseSemaphoreHandle);
726 
727         const GLenum textureDstLayouts[] = {
728             GL_LAYOUT_TRANSFER_SRC_EXT,
729         };
730         constexpr uint32_t textureDstLayoutsCount = std::extent<decltype(textureSrcLayouts)>();
731         static_assert(textureBarriersCount == textureDstLayoutsCount,
732                       "barrierTextures and textureDstLayouts must be the same length");
733         glSignalSemaphoreEXT(glReleaseSemaphore, 0, nullptr, textureBarriersCount, barrierTextures,
734                              textureDstLayouts);
735 
736         helper.waitSemaphoreAndAcquireImage(image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
737                                             VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
738                                             vkReleaseSemaphore);
739         uint8_t pixels[4];
740         VkOffset3D offset = {};
741         helper.readPixels(image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, format, offset, extent,
742                           pixels, sizeof(pixels));
743 
744         EXPECT_NEAR(0x80, pixels[0], 1);
745         EXPECT_NEAR(0x80, pixels[1], 1);
746         EXPECT_NEAR(0x80, pixels[2], 1);
747         EXPECT_NEAR(0x80, pixels[3], 1);
748     }
749 
750     EXPECT_GL_NO_ERROR();
751 
752     vkDeviceWaitIdle(helper.getDevice());
753     vkDestroyImage(helper.getDevice(), image, nullptr);
754     vkDestroySemaphore(helper.getDevice(), vkAcquireSemaphore, nullptr);
755     vkDestroySemaphore(helper.getDevice(), vkReleaseSemaphore, nullptr);
756     vkFreeMemory(helper.getDevice(), deviceMemory, nullptr);
757 }
758 
759 // Test creating and clearing RGBA8 texture in opaque fd with acquire/release.
TEST_P(VulkanExternalImageTest,ShouldClearOpaqueFdWithSemaphores)760 TEST_P(VulkanExternalImageTest, ShouldClearOpaqueFdWithSemaphores)
761 {
762     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
763     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_semaphore_fd"));
764 
765     // http://issuetracker.google.com/173004081
766     ANGLE_SKIP_TEST_IF(IsVulkan() && IsIntel() && IsLinux() && isAsyncCommandQueueFeatureEnabled());
767     // http://anglebug.com/5383
768     ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
769 
770     RunShouldClearWithSemaphoresTest<OpaqueFdTraits>(false, kDefaultImageCreateFlags,
771                                                      kDefaultImageUsageFlags, isSwiftshader(),
772                                                      enableDebugLayers());
773 }
774 
775 // Test creating and clearing RGBA8 texture in opaque fd with acquire/release, using
776 // GL_ANGLE_memory_object_flags.
TEST_P(VulkanExternalImageTest,ShouldClearOpaqueFdWithSemaphoresWithFlags)777 TEST_P(VulkanExternalImageTest, ShouldClearOpaqueFdWithSemaphoresWithFlags)
778 {
779     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
780     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_semaphore_fd"));
781     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
782 
783     // http://issuetracker.google.com/173004081
784     ANGLE_SKIP_TEST_IF(IsVulkan() && IsIntel() && IsLinux() && isAsyncCommandQueueFeatureEnabled());
785 
786     RunShouldClearWithSemaphoresTest<OpaqueFdTraits>(true, kDefaultImageCreateFlags,
787                                                      kDefaultImageUsageFlags, isSwiftshader(),
788                                                      enableDebugLayers());
789 }
790 
791 // Test creating and clearing RGBA8 texture without STORAGE usage in opaque fd with acquire/release.
TEST_P(VulkanExternalImageTest,ShouldClearOpaqueFdWithSemaphoresNoStorage)792 TEST_P(VulkanExternalImageTest, ShouldClearOpaqueFdWithSemaphoresNoStorage)
793 {
794     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
795     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_semaphore_fd"));
796     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
797 
798     // http://issuetracker.google.com/173004081
799     ANGLE_SKIP_TEST_IF(IsVulkan() && IsIntel() && IsLinux() && isAsyncCommandQueueFeatureEnabled());
800 
801     RunShouldClearWithSemaphoresTest<OpaqueFdTraits>(true, kDefaultImageCreateFlags,
802                                                      kNoStorageImageUsageFlags, isSwiftshader(),
803                                                      enableDebugLayers());
804 }
805 
806 // Test creating and clearing RGBA8 texture without STORAGE usage but with MUTABLE in opaque fd with
807 // acquire/release.
TEST_P(VulkanExternalImageTest,ShouldClearOpaqueFdWithSemaphoresMutableNoStorage)808 TEST_P(VulkanExternalImageTest, ShouldClearOpaqueFdWithSemaphoresMutableNoStorage)
809 {
810     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
811     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_semaphore_fd"));
812     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
813 
814     // http://issuetracker.google.com/173004081
815     ANGLE_SKIP_TEST_IF(IsVulkan() && IsIntel() && IsLinux() && isAsyncCommandQueueFeatureEnabled());
816 
817     RunShouldClearWithSemaphoresTest<OpaqueFdTraits>(true, kMutableImageCreateFlags,
818                                                      kNoStorageImageUsageFlags, isSwiftshader(),
819                                                      enableDebugLayers());
820 }
821 
822 // Test creating and clearing RGBA8 texture in zircon vmo with acquire/release.
TEST_P(VulkanExternalImageTest,ShouldClearZirconVmoWithSemaphores)823 TEST_P(VulkanExternalImageTest, ShouldClearZirconVmoWithSemaphores)
824 {
825     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_fuchsia"));
826     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_semaphore_fuchsia"));
827     RunShouldClearWithSemaphoresTest<FuchsiaTraits>(false, kDefaultImageCreateFlags,
828                                                     kDefaultImageUsageFlags, isSwiftshader(),
829                                                     enableDebugLayers());
830 }
831 
832 // Test creating and clearing RGBA8 texture in zircon vmo with acquire/release, using
833 // GL_ANGLE_memory_object_flags.
TEST_P(VulkanExternalImageTest,ShouldClearZirconVmoWithSemaphoresWithFlags)834 TEST_P(VulkanExternalImageTest, ShouldClearZirconVmoWithSemaphoresWithFlags)
835 {
836     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_fuchsia"));
837     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_semaphore_fuchsia"));
838     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
839     RunShouldClearWithSemaphoresTest<FuchsiaTraits>(true, kDefaultImageCreateFlags,
840                                                     kDefaultImageUsageFlags, isSwiftshader(),
841                                                     enableDebugLayers());
842 }
843 
844 // Test creating and clearing RGBA8 texture without STORAGE usage in zircon vmo with
845 // acquire/release.
TEST_P(VulkanExternalImageTest,ShouldClearZirconVmoWithSemaphoresNoStorage)846 TEST_P(VulkanExternalImageTest, ShouldClearZirconVmoWithSemaphoresNoStorage)
847 {
848     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_fuchsia"));
849     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_semaphore_fuchsia"));
850     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
851     RunShouldClearWithSemaphoresTest<FuchsiaTraits>(true, kDefaultImageCreateFlags,
852                                                     kNoStorageImageUsageFlags, isSwiftshader(),
853                                                     enableDebugLayers());
854 }
855 
856 // Test creating and clearing RGBA8 texture without STORAGE usage but with MUTABLE in zircon vmo
857 // with acquire/release.
TEST_P(VulkanExternalImageTest,ShouldClearZirconVmoWithSemaphoresMutableNoStorage)858 TEST_P(VulkanExternalImageTest, ShouldClearZirconVmoWithSemaphoresMutableNoStorage)
859 {
860     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_fuchsia"));
861     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_semaphore_fuchsia"));
862     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
863     RunShouldClearWithSemaphoresTest<FuchsiaTraits>(true, kMutableImageCreateFlags,
864                                                     kNoStorageImageUsageFlags, isSwiftshader(),
865                                                     enableDebugLayers());
866 }
867 
868 template <typename Traits>
runShouldDrawTest(bool isSwiftshader,bool enableDebugLayers)869 void VulkanExternalImageTest::runShouldDrawTest(bool isSwiftshader, bool enableDebugLayers)
870 {
871     ASSERT(EnsureGLExtensionEnabled(Traits::MemoryObjectExtension()));
872     ASSERT(EnsureGLExtensionEnabled(Traits::SemaphoreExtension()));
873 
874     VulkanHelper helper;
875     helper.initialize(isSwiftshader, enableDebugLayers);
876 
877     VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
878     ANGLE_SKIP_TEST_IF(!Traits::CanCreateImage(helper, format, VK_IMAGE_TYPE_2D,
879                                                VK_IMAGE_TILING_OPTIMAL, kDefaultImageCreateFlags,
880                                                kDefaultImageUsageFlags));
881     ANGLE_SKIP_TEST_IF(!Traits::CanCreateSemaphore(helper));
882 
883     VkSemaphore vkAcquireSemaphore = VK_NULL_HANDLE;
884     VkResult result                = Traits::CreateSemaphore(&helper, &vkAcquireSemaphore);
885     EXPECT_EQ(result, VK_SUCCESS);
886     EXPECT_TRUE(vkAcquireSemaphore != VK_NULL_HANDLE);
887 
888     VkSemaphore vkReleaseSemaphore = VK_NULL_HANDLE;
889     result                         = Traits::CreateSemaphore(&helper, &vkReleaseSemaphore);
890     EXPECT_EQ(result, VK_SUCCESS);
891     EXPECT_TRUE(vkReleaseSemaphore != VK_NULL_HANDLE);
892 
893     typename Traits::Handle acquireSemaphoreHandle = Traits::InvalidHandle();
894     result = Traits::ExportSemaphore(&helper, vkAcquireSemaphore, &acquireSemaphoreHandle);
895     EXPECT_EQ(result, VK_SUCCESS);
896     EXPECT_NE(acquireSemaphoreHandle, Traits::InvalidHandle());
897 
898     typename Traits::Handle releaseSemaphoreHandle = Traits::InvalidHandle();
899     result = Traits::ExportSemaphore(&helper, vkReleaseSemaphore, &releaseSemaphoreHandle);
900     EXPECT_EQ(result, VK_SUCCESS);
901     EXPECT_NE(releaseSemaphoreHandle, Traits::InvalidHandle());
902 
903     VkImage image                 = VK_NULL_HANDLE;
904     VkDeviceMemory deviceMemory   = VK_NULL_HANDLE;
905     VkDeviceSize deviceMemorySize = 0;
906 
907     VkExtent3D extent = {1, 1, 1};
908     result =
909         Traits::CreateImage2D(&helper, format, kDefaultImageCreateFlags, kDefaultImageUsageFlags,
910                               nullptr, extent, &image, &deviceMemory, &deviceMemorySize);
911     EXPECT_EQ(result, VK_SUCCESS);
912 
913     typename Traits::Handle memoryHandle = Traits::InvalidHandle();
914     result = Traits::ExportMemory(&helper, deviceMemory, &memoryHandle);
915     EXPECT_EQ(result, VK_SUCCESS);
916     EXPECT_NE(memoryHandle, Traits::InvalidHandle());
917 
918     {
919         GLMemoryObject memoryObject;
920         GLint dedicatedMemory = GL_TRUE;
921         glMemoryObjectParameterivEXT(memoryObject, GL_DEDICATED_MEMORY_OBJECT_EXT,
922                                      &dedicatedMemory);
923         Traits::ImportMemory(memoryObject, deviceMemorySize, memoryHandle);
924 
925         GLTexture texture;
926         glBindTexture(GL_TEXTURE_2D, texture);
927         glTexStorageMem2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1, memoryObject, 0);
928 
929         GLSemaphore glAcquireSemaphore;
930         Traits::ImportSemaphore(glAcquireSemaphore, acquireSemaphoreHandle);
931 
932         // Transfer ownership to GL.
933         helper.releaseImageAndSignalSemaphore(image, VK_IMAGE_LAYOUT_UNDEFINED,
934                                               VK_IMAGE_LAYOUT_GENERAL, vkAcquireSemaphore);
935 
936         const GLuint barrierTextures[] = {
937             texture,
938         };
939         constexpr uint32_t textureBarriersCount = std::extent<decltype(barrierTextures)>();
940         const GLenum textureSrcLayouts[]        = {
941             GL_LAYOUT_GENERAL_EXT,
942         };
943         constexpr uint32_t textureSrcLayoutsCount = std::extent<decltype(textureSrcLayouts)>();
944         static_assert(textureBarriersCount == textureSrcLayoutsCount,
945                       "barrierTextures and textureSrcLayouts must be the same length");
946         glWaitSemaphoreEXT(glAcquireSemaphore, 0, nullptr, textureBarriersCount, barrierTextures,
947                            textureSrcLayouts);
948 
949         GLFramebuffer framebuffer;
950         glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
951         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
952         EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
953 
954         // Make the texture red.
955         ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
956         drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.0f);
957         EXPECT_GL_NO_ERROR();
958 
959         // Transfer ownership back to test.
960         GLSemaphore glReleaseSemaphore;
961         Traits::ImportSemaphore(glReleaseSemaphore, releaseSemaphoreHandle);
962 
963         const GLenum textureDstLayouts[] = {
964             GL_LAYOUT_TRANSFER_SRC_EXT,
965         };
966         constexpr uint32_t textureDstLayoutsCount = std::extent<decltype(textureSrcLayouts)>();
967         static_assert(textureBarriersCount == textureDstLayoutsCount,
968                       "barrierTextures and textureDstLayouts must be the same length");
969         glSignalSemaphoreEXT(glReleaseSemaphore, 0, nullptr, textureBarriersCount, barrierTextures,
970                              textureDstLayouts);
971 
972         helper.waitSemaphoreAndAcquireImage(image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
973                                             VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
974                                             vkReleaseSemaphore);
975 
976         uint8_t pixels[4];
977         VkOffset3D offset = {};
978         helper.readPixels(image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, format, offset, extent,
979                           pixels, sizeof(pixels));
980 
981         EXPECT_EQ(0xFF, pixels[0]);
982         EXPECT_EQ(0x00, pixels[1]);
983         EXPECT_EQ(0x00, pixels[2]);
984         EXPECT_EQ(0xFF, pixels[3]);
985     }
986 
987     EXPECT_GL_NO_ERROR();
988 
989     vkDeviceWaitIdle(helper.getDevice());
990     vkDestroyImage(helper.getDevice(), image, nullptr);
991     vkDestroySemaphore(helper.getDevice(), vkAcquireSemaphore, nullptr);
992     vkDestroySemaphore(helper.getDevice(), vkReleaseSemaphore, nullptr);
993     vkFreeMemory(helper.getDevice(), deviceMemory, nullptr);
994 }
995 
996 // Test drawing to RGBA8 texture in opaque fd with acquire/release.
TEST_P(VulkanExternalImageTest,ShouldDrawOpaqueFdWithSemaphores)997 TEST_P(VulkanExternalImageTest, ShouldDrawOpaqueFdWithSemaphores)
998 {
999     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
1000     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_semaphore_fd"));
1001 
1002     // http://issuetracker.google.com/173004081
1003     ANGLE_SKIP_TEST_IF(IsVulkan() && IsIntel() && IsLinux() && isAsyncCommandQueueFeatureEnabled());
1004     // http://anglebug.com/5383
1005     ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
1006 
1007     runShouldDrawTest<OpaqueFdTraits>(isSwiftshader(), enableDebugLayers());
1008 }
1009 
1010 // Test drawing to RGBA8 texture in zircon vmo with acquire/release multiple times.
TEST_P(VulkanExternalImageTest,ShouldDrawZirconVmoWithSemaphores)1011 TEST_P(VulkanExternalImageTest, ShouldDrawZirconVmoWithSemaphores)
1012 {
1013     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_fuchsia"));
1014     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_semaphore_fuchsia"));
1015     runShouldDrawTest<FuchsiaTraits>(isSwiftshader(), enableDebugLayers());
1016 }
1017 
1018 template <typename Traits>
runWaitSemaphoresRetainsContentTest(bool isSwiftshader,bool enableDebugLayers)1019 void VulkanExternalImageTest::runWaitSemaphoresRetainsContentTest(bool isSwiftshader,
1020                                                                   bool enableDebugLayers)
1021 {
1022     ASSERT(EnsureGLExtensionEnabled(Traits::MemoryObjectExtension()));
1023     ASSERT(EnsureGLExtensionEnabled(Traits::SemaphoreExtension()));
1024 
1025     VulkanHelper helper;
1026     helper.initialize(isSwiftshader, enableDebugLayers);
1027 
1028     VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
1029     ANGLE_SKIP_TEST_IF(!Traits::CanCreateImage(helper, format, VK_IMAGE_TYPE_2D,
1030                                                VK_IMAGE_TILING_OPTIMAL, kDefaultImageCreateFlags,
1031                                                kDefaultImageUsageFlags));
1032     ANGLE_SKIP_TEST_IF(!Traits::CanCreateSemaphore(helper));
1033 
1034     VkSemaphore vkAcquireSemaphore = VK_NULL_HANDLE;
1035     VkResult result                = Traits::CreateSemaphore(&helper, &vkAcquireSemaphore);
1036     EXPECT_EQ(result, VK_SUCCESS);
1037     EXPECT_TRUE(vkAcquireSemaphore != VK_NULL_HANDLE);
1038 
1039     VkSemaphore vkReleaseSemaphore = VK_NULL_HANDLE;
1040     result                         = Traits::CreateSemaphore(&helper, &vkReleaseSemaphore);
1041     EXPECT_EQ(result, VK_SUCCESS);
1042     EXPECT_TRUE(vkReleaseSemaphore != VK_NULL_HANDLE);
1043 
1044     typename Traits::Handle acquireSemaphoreHandle = Traits::InvalidHandle();
1045     result = Traits::ExportSemaphore(&helper, vkAcquireSemaphore, &acquireSemaphoreHandle);
1046     EXPECT_EQ(result, VK_SUCCESS);
1047     EXPECT_NE(acquireSemaphoreHandle, Traits::InvalidHandle());
1048 
1049     typename Traits::Handle releaseSemaphoreHandle = Traits::InvalidHandle();
1050     result = Traits::ExportSemaphore(&helper, vkReleaseSemaphore, &releaseSemaphoreHandle);
1051     EXPECT_EQ(result, VK_SUCCESS);
1052     EXPECT_NE(releaseSemaphoreHandle, Traits::InvalidHandle());
1053 
1054     VkImage image                 = VK_NULL_HANDLE;
1055     VkDeviceMemory deviceMemory   = VK_NULL_HANDLE;
1056     VkDeviceSize deviceMemorySize = 0;
1057 
1058     VkExtent3D extent = {1, 1, 1};
1059     result =
1060         Traits::CreateImage2D(&helper, format, kDefaultImageCreateFlags, kDefaultImageUsageFlags,
1061                               nullptr, extent, &image, &deviceMemory, &deviceMemorySize);
1062     EXPECT_EQ(result, VK_SUCCESS);
1063 
1064     typename Traits::Handle memoryHandle = Traits::InvalidHandle();
1065     result = Traits::ExportMemory(&helper, deviceMemory, &memoryHandle);
1066     EXPECT_EQ(result, VK_SUCCESS);
1067     EXPECT_NE(memoryHandle, Traits::InvalidHandle());
1068 
1069     {
1070         GLMemoryObject memoryObject;
1071         GLint dedicatedMemory = GL_TRUE;
1072         glMemoryObjectParameterivEXT(memoryObject, GL_DEDICATED_MEMORY_OBJECT_EXT,
1073                                      &dedicatedMemory);
1074         Traits::ImportMemory(memoryObject, deviceMemorySize, memoryHandle);
1075 
1076         GLTexture texture;
1077         glBindTexture(GL_TEXTURE_2D, texture);
1078         glTexStorageMem2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1, memoryObject, 0);
1079 
1080         GLSemaphore glAcquireSemaphore;
1081         Traits::ImportSemaphore(glAcquireSemaphore, acquireSemaphoreHandle);
1082 
1083         // Transfer ownership to GL.
1084         helper.releaseImageAndSignalSemaphore(image, VK_IMAGE_LAYOUT_UNDEFINED,
1085                                               VK_IMAGE_LAYOUT_GENERAL, vkAcquireSemaphore);
1086 
1087         const GLuint barrierTextures[] = {
1088             texture,
1089         };
1090         constexpr uint32_t textureBarriersCount = std::extent<decltype(barrierTextures)>();
1091         const GLenum textureSrcLayouts[]        = {
1092             GL_LAYOUT_GENERAL_EXT,
1093         };
1094         constexpr uint32_t textureSrcLayoutsCount = std::extent<decltype(textureSrcLayouts)>();
1095         static_assert(textureBarriersCount == textureSrcLayoutsCount,
1096                       "barrierTextures and textureSrcLayouts must be the same length");
1097         glWaitSemaphoreEXT(glAcquireSemaphore, 0, nullptr, textureBarriersCount, barrierTextures,
1098                            textureSrcLayouts);
1099 
1100         GLFramebuffer framebuffer;
1101         glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1102         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1103         EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1104 
1105         // Make the texture red.
1106         ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
1107         drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.0f);
1108         EXPECT_GL_NO_ERROR();
1109 
1110         // Transfer ownership back to test.
1111         GLSemaphore glReleaseSemaphore;
1112         Traits::ImportSemaphore(glReleaseSemaphore, releaseSemaphoreHandle);
1113 
1114         const GLenum textureDstLayouts[] = {
1115             GL_LAYOUT_TRANSFER_SRC_EXT,
1116         };
1117         constexpr uint32_t textureDstLayoutsCount = std::extent<decltype(textureSrcLayouts)>();
1118         static_assert(textureBarriersCount == textureDstLayoutsCount,
1119                       "barrierTextures and textureDstLayouts must be the same length");
1120         glSignalSemaphoreEXT(glReleaseSemaphore, 0, nullptr, textureBarriersCount, barrierTextures,
1121                              textureDstLayouts);
1122 
1123         helper.waitSemaphoreAndAcquireImage(image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1124                                             VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1125                                             vkReleaseSemaphore);
1126 
1127         // Transfer ownership to GL again, and make sure the contents are preserved.
1128         helper.releaseImageAndSignalSemaphore(image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1129                                               VK_IMAGE_LAYOUT_GENERAL, vkAcquireSemaphore);
1130         glWaitSemaphoreEXT(glAcquireSemaphore, 0, nullptr, textureBarriersCount, barrierTextures,
1131                            textureSrcLayouts);
1132 
1133         // Blend green
1134         ANGLE_GL_PROGRAM(drawGreen, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
1135         glEnable(GL_BLEND);
1136         glBlendFunc(GL_ONE, GL_ONE);
1137         drawQuad(drawGreen, essl1_shaders::PositionAttrib(), 0.0f);
1138 
1139         // Transfer ownership back to test
1140         glSignalSemaphoreEXT(glReleaseSemaphore, 0, nullptr, textureBarriersCount, barrierTextures,
1141                              textureDstLayouts);
1142         helper.waitSemaphoreAndAcquireImage(image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1143                                             VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1144                                             vkReleaseSemaphore);
1145 
1146         uint8_t pixels[4];
1147         VkOffset3D offset = {};
1148         helper.readPixels(image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, format, offset, extent,
1149                           pixels, sizeof(pixels));
1150 
1151         EXPECT_EQ(0xFF, pixels[0]);
1152         EXPECT_EQ(0xFF, pixels[1]);
1153         EXPECT_EQ(0x00, pixels[2]);
1154         EXPECT_EQ(0xFF, pixels[3]);
1155     }
1156 
1157     EXPECT_GL_NO_ERROR();
1158 
1159     vkDeviceWaitIdle(helper.getDevice());
1160     vkDestroyImage(helper.getDevice(), image, nullptr);
1161     vkDestroySemaphore(helper.getDevice(), vkAcquireSemaphore, nullptr);
1162     vkDestroySemaphore(helper.getDevice(), vkReleaseSemaphore, nullptr);
1163     vkFreeMemory(helper.getDevice(), deviceMemory, nullptr);
1164 }
1165 
1166 // Test drawing to RGBA8 texture in opaque fd with acquire/release multiple times.
TEST_P(VulkanExternalImageTest,WaitSemaphoresRetainsContentOpaqueFd)1167 TEST_P(VulkanExternalImageTest, WaitSemaphoresRetainsContentOpaqueFd)
1168 {
1169     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
1170     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_semaphore_fd"));
1171 
1172     // http://issuetracker.google.com/173004081
1173     ANGLE_SKIP_TEST_IF(IsVulkan() && IsIntel() && IsLinux() && isAsyncCommandQueueFeatureEnabled());
1174     // http://anglebug.com/5383
1175     ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
1176 
1177     runWaitSemaphoresRetainsContentTest<OpaqueFdTraits>(isSwiftshader(), enableDebugLayers());
1178 }
1179 
1180 // Test drawing to RGBA8 texture in zircon vmo with acquire/release multiple times.
TEST_P(VulkanExternalImageTest,WaitSemaphoresRetainsContentZirconVmo)1181 TEST_P(VulkanExternalImageTest, WaitSemaphoresRetainsContentZirconVmo)
1182 {
1183     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_fuchsia"));
1184     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_semaphore_fuchsia"));
1185     runWaitSemaphoresRetainsContentTest<FuchsiaTraits>(isSwiftshader(), enableDebugLayers());
1186 }
1187 
1188 // Support for Zircon handle types is mandatory on Fuchsia.
TEST_P(VulkanExternalImageTest,ShouldSupportExternalHandlesFuchsia)1189 TEST_P(VulkanExternalImageTest, ShouldSupportExternalHandlesFuchsia)
1190 {
1191     ANGLE_SKIP_TEST_IF(!IsFuchsia());
1192     EXPECT_TRUE(EnsureGLExtensionEnabled("GL_ANGLE_memory_object_fuchsia"));
1193     EXPECT_TRUE(EnsureGLExtensionEnabled("GL_ANGLE_semaphore_fuchsia"));
1194     VulkanHelper helper;
1195     helper.initialize(isSwiftshader(), enableDebugLayers());
1196     EXPECT_TRUE(helper.canCreateSemaphoreZirconEvent());
1197     EXPECT_TRUE(helper.canCreateImageZirconVmo(VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_TYPE_2D,
1198                                                VK_IMAGE_TILING_OPTIMAL, kDefaultImageCreateFlags,
1199                                                kDefaultImageUsageFlags));
1200 }
1201 
1202 // Use this to select which configurations (e.g. which renderer, which GLES major version) these
1203 // tests should be run against.
1204 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(VulkanExternalImageTest);
1205 
1206 }  // namespace angle
1207