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