• 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::__anon855fcff20111::OpaqueFdTraits60     static Handle InvalidHandle() { return kInvalidFd; }
61 
MemoryObjectExtensionangle::__anon855fcff20111::OpaqueFdTraits62     static const char *MemoryObjectExtension() { return "GL_EXT_memory_object_fd"; }
SemaphoreExtensionangle::__anon855fcff20111::OpaqueFdTraits63     static const char *SemaphoreExtension() { return "GL_EXT_semaphore_fd"; }
64 
CanCreateSemaphoreangle::__anon855fcff20111::OpaqueFdTraits65     static bool CanCreateSemaphore(const VulkanHelper &helper)
66     {
67         return helper.canCreateSemaphoreOpaqueFd();
68     }
69 
CreateSemaphoreangle::__anon855fcff20111::OpaqueFdTraits70     static VkResult CreateSemaphore(VulkanHelper *helper, VkSemaphore *semaphore)
71     {
72         return helper->createSemaphoreOpaqueFd(semaphore);
73     }
74 
ExportSemaphoreangle::__anon855fcff20111::OpaqueFdTraits75     static VkResult ExportSemaphore(VulkanHelper *helper, VkSemaphore semaphore, Handle *handle)
76     {
77         return helper->exportSemaphoreOpaqueFd(semaphore, handle);
78     }
79 
ImportSemaphoreangle::__anon855fcff20111::OpaqueFdTraits80     static void ImportSemaphore(GLuint semaphore, Handle handle)
81     {
82         glImportSemaphoreFdEXT(semaphore, GL_HANDLE_TYPE_OPAQUE_FD_EXT, handle);
83     }
84 
CanCreateImageangle::__anon855fcff20111::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::__anon855fcff20111::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::__anon855fcff20111::OpaqueFdTraits110     static VkResult ExportMemory(VulkanHelper *helper, VkDeviceMemory deviceMemory, Handle *handle)
111     {
112         return helper->exportMemoryOpaqueFd(deviceMemory, handle);
113     }
114 
ImportMemoryangle::__anon855fcff20111::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::__anon855fcff20111::FuchsiaTraits125     static Handle InvalidHandle() { return ZX_HANDLE_INVALID; }
126 
MemoryObjectExtensionangle::__anon855fcff20111::FuchsiaTraits127     static const char *MemoryObjectExtension() { return "GL_ANGLE_memory_object_fuchsia"; }
SemaphoreExtensionangle::__anon855fcff20111::FuchsiaTraits128     static const char *SemaphoreExtension() { return "GL_ANGLE_semaphore_fuchsia"; }
129 
CanCreateSemaphoreangle::__anon855fcff20111::FuchsiaTraits130     static bool CanCreateSemaphore(const VulkanHelper &helper)
131     {
132         return helper.canCreateSemaphoreZirconEvent();
133     }
134 
CreateSemaphoreangle::__anon855fcff20111::FuchsiaTraits135     static VkResult CreateSemaphore(VulkanHelper *helper, VkSemaphore *semaphore)
136     {
137         return helper->createSemaphoreZirconEvent(semaphore);
138     }
139 
ExportSemaphoreangle::__anon855fcff20111::FuchsiaTraits140     static VkResult ExportSemaphore(VulkanHelper *helper, VkSemaphore semaphore, Handle *handle)
141     {
142         return helper->exportSemaphoreZirconEvent(semaphore, handle);
143     }
144 
ImportSemaphoreangle::__anon855fcff20111::FuchsiaTraits145     static void ImportSemaphore(GLuint semaphore, Handle handle)
146     {
147         glImportSemaphoreZirconHandleANGLE(semaphore, GL_HANDLE_TYPE_ZIRCON_EVENT_ANGLE, handle);
148     }
149 
CanCreateImageangle::__anon855fcff20111::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::__anon855fcff20111::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::__anon855fcff20111::FuchsiaTraits175     static VkResult ExportMemory(VulkanHelper *helper, VkDeviceMemory deviceMemory, Handle *handle)
176     {
177         return helper->exportMemoryZirconVmo(deviceMemory, handle);
178     }
179 
ImportMemoryangle::__anon855fcff20111::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 
GetPostReleaseVulkanLayout(GLenum glLayout)187 VkImageLayout GetPostReleaseVulkanLayout(GLenum glLayout)
188 {
189     switch (glLayout)
190     {
191         case GL_NONE:
192         case GL_LAYOUT_GENERAL_EXT:
193         default:
194             return VK_IMAGE_LAYOUT_GENERAL;
195         case GL_LAYOUT_COLOR_ATTACHMENT_EXT:
196             return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
197         case GL_LAYOUT_DEPTH_STENCIL_ATTACHMENT_EXT:
198             return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
199         case GL_LAYOUT_DEPTH_STENCIL_READ_ONLY_EXT:
200             return VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
201         case GL_LAYOUT_SHADER_READ_ONLY_EXT:
202             return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
203         case GL_LAYOUT_TRANSFER_SRC_EXT:
204             return VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
205         case GL_LAYOUT_TRANSFER_DST_EXT:
206             return VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
207         case GL_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_EXT:
208             return VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL_KHR;
209         case GL_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_EXT:
210             return VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL_KHR;
211     }
212 }
213 
AdjustCreateFlags(bool useMemoryObjectFlags,VkImageCreateFlags * createFlags)214 void AdjustCreateFlags(bool useMemoryObjectFlags, VkImageCreateFlags *createFlags)
215 {
216     // If the GL_ANGLE_memory_object_flags extension is not supported, GL assumes that the mutable
217     // create flag is specified.
218     if (!useMemoryObjectFlags)
219     {
220         *createFlags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
221     }
222 
223     // The spec is not clear about the other create flags.
224 }
225 
226 constexpr uint32_t kWidth  = 64;
227 constexpr uint32_t kHeight = 64;
228 
229 }  // namespace
230 
231 class VulkanExternalImageTest : public ANGLETest<>
232 {
233   protected:
VulkanExternalImageTest()234     VulkanExternalImageTest()
235     {
236         setWindowWidth(1);
237         setWindowHeight(1);
238         setConfigRedBits(8);
239         setConfigGreenBits(8);
240         setConfigBlueBits(8);
241         setConfigAlphaBits(8);
242     }
243 
244     template <typename Traits>
245     void runShouldDrawTest(bool isSwiftshader, bool enableDebugLayers);
246 
247     template <typename Traits>
248     void runWaitSemaphoresRetainsContentTest(bool isSwiftshader, bool enableDebugLayers);
249 };
250 
251 class VulkanExternalImageTestES31 : public VulkanExternalImageTest
252 {};
253 
254 template <typename Traits>
RunShouldImportMemoryTest(VkImageCreateFlags createFlags,VkImageUsageFlags usageFlags,bool isSwiftshader,bool enableDebugLayers)255 void RunShouldImportMemoryTest(VkImageCreateFlags createFlags,
256                                VkImageUsageFlags usageFlags,
257                                bool isSwiftshader,
258                                bool enableDebugLayers)
259 {
260     ASSERT(EnsureGLExtensionEnabled(Traits::MemoryObjectExtension()));
261 
262     VulkanHelper helper;
263     helper.initialize(isSwiftshader, enableDebugLayers);
264 
265     VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
266     ANGLE_SKIP_TEST_IF(!Traits::CanCreateImage(helper, format, VK_IMAGE_TYPE_2D,
267                                                VK_IMAGE_TILING_OPTIMAL, createFlags, usageFlags));
268 
269     VkImage image                 = VK_NULL_HANDLE;
270     VkDeviceMemory deviceMemory   = VK_NULL_HANDLE;
271     VkDeviceSize deviceMemorySize = 0;
272 
273     VkExtent3D extent = {1, 1, 1};
274     VkResult result   = Traits::CreateImage2D(&helper, format, createFlags, usageFlags, nullptr,
275                                               extent, &image, &deviceMemory, &deviceMemorySize);
276     EXPECT_EQ(result, VK_SUCCESS);
277 
278     typename Traits::Handle memoryHandle = Traits::InvalidHandle();
279     result = Traits::ExportMemory(&helper, deviceMemory, &memoryHandle);
280     EXPECT_EQ(result, VK_SUCCESS);
281     EXPECT_NE(memoryHandle, Traits::InvalidHandle());
282 
283     {
284         GLMemoryObject memoryObject;
285         GLint dedicatedMemory = GL_TRUE;
286         glMemoryObjectParameterivEXT(memoryObject, GL_DEDICATED_MEMORY_OBJECT_EXT,
287                                      &dedicatedMemory);
288         Traits::ImportMemory(memoryObject, deviceMemorySize, memoryHandle);
289 
290         // Test that after calling glImportMemoryFdEXT, the parameters of the memory object cannot
291         // be changed
292         dedicatedMemory = GL_FALSE;
293         glMemoryObjectParameterivEXT(memoryObject, GL_DEDICATED_MEMORY_OBJECT_EXT,
294                                      &dedicatedMemory);
295         EXPECT_GL_ERROR(GL_INVALID_OPERATION);
296     }
297 
298     EXPECT_GL_NO_ERROR();
299 
300     vkDestroyImage(helper.getDevice(), image, nullptr);
301     vkFreeMemory(helper.getDevice(), deviceMemory, nullptr);
302 }
303 
304 // glImportMemoryFdEXT must be able to import a valid opaque fd.
TEST_P(VulkanExternalImageTest,ShouldImportMemoryOpaqueFd)305 TEST_P(VulkanExternalImageTest, ShouldImportMemoryOpaqueFd)
306 {
307     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
308     RunShouldImportMemoryTest<OpaqueFdTraits>(kDefaultImageCreateFlags, kDefaultImageUsageFlags,
309                                               isSwiftshader(), enableDebugLayers());
310 }
311 
312 // glImportMemoryZirconHandleANGLE must be able to import a valid vmo.
TEST_P(VulkanExternalImageTest,ShouldImportMemoryZirconVmo)313 TEST_P(VulkanExternalImageTest, ShouldImportMemoryZirconVmo)
314 {
315     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_fuchsia"));
316     RunShouldImportMemoryTest<FuchsiaTraits>(kDefaultImageCreateFlags, kDefaultImageUsageFlags,
317                                              isSwiftshader(), enableDebugLayers());
318 }
319 
320 template <typename Traits>
RunShouldImportSemaphoreTest(bool isSwiftshader,bool enableDebugLayers)321 void RunShouldImportSemaphoreTest(bool isSwiftshader, bool enableDebugLayers)
322 {
323     ASSERT(EnsureGLExtensionEnabled(Traits::SemaphoreExtension()));
324 
325     VulkanHelper helper;
326     helper.initialize(isSwiftshader, enableDebugLayers);
327 
328     ANGLE_SKIP_TEST_IF(!Traits::CanCreateSemaphore(helper));
329 
330     VkSemaphore vkSemaphore = VK_NULL_HANDLE;
331     VkResult result         = helper.createSemaphoreOpaqueFd(&vkSemaphore);
332     EXPECT_EQ(result, VK_SUCCESS);
333 
334     typename Traits::Handle semaphoreHandle = Traits::InvalidHandle();
335     result = Traits::ExportSemaphore(&helper, vkSemaphore, &semaphoreHandle);
336     EXPECT_EQ(result, VK_SUCCESS);
337     EXPECT_NE(semaphoreHandle, Traits::InvalidHandle());
338 
339     {
340         GLSemaphore glSemaphore;
341         Traits::ImportSemaphore(glSemaphore, semaphoreHandle);
342     }
343 
344     EXPECT_GL_NO_ERROR();
345 
346     vkDestroySemaphore(helper.getDevice(), vkSemaphore, nullptr);
347 }
348 
349 // glImportSemaphoreFdEXT must be able to import a valid opaque fd.
TEST_P(VulkanExternalImageTest,ShouldImportSemaphoreOpaqueFd)350 TEST_P(VulkanExternalImageTest, ShouldImportSemaphoreOpaqueFd)
351 {
352     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_semaphore_fd"));
353     RunShouldImportSemaphoreTest<OpaqueFdTraits>(isSwiftshader(), enableDebugLayers());
354 }
355 
356 // glImportSemaphoreZirconHandleANGLE must be able to import a valid handle.
TEST_P(VulkanExternalImageTest,ShouldImportSemaphoreZirconEvent)357 TEST_P(VulkanExternalImageTest, ShouldImportSemaphoreZirconEvent)
358 {
359     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_semaphore_fuchsia"));
360     RunShouldImportSemaphoreTest<FuchsiaTraits>(isSwiftshader(), enableDebugLayers());
361 }
362 
363 template <typename Traits>
RunShouldClearTest(bool useMemoryObjectFlags,VkImageCreateFlags createFlags,VkImageUsageFlags usageFlags,bool isSwiftshader,bool enableDebugLayers)364 void RunShouldClearTest(bool useMemoryObjectFlags,
365                         VkImageCreateFlags createFlags,
366                         VkImageUsageFlags usageFlags,
367                         bool isSwiftshader,
368                         bool enableDebugLayers)
369 {
370     ASSERT(EnsureGLExtensionEnabled(Traits::MemoryObjectExtension()));
371 
372     VulkanHelper helper;
373     helper.initialize(isSwiftshader, enableDebugLayers);
374 
375     AdjustCreateFlags(useMemoryObjectFlags, &createFlags);
376 
377     VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
378     ANGLE_SKIP_TEST_IF(!Traits::CanCreateImage(helper, format, VK_IMAGE_TYPE_2D,
379                                                VK_IMAGE_TILING_OPTIMAL, createFlags, usageFlags));
380 
381     VkImage image                 = VK_NULL_HANDLE;
382     VkDeviceMemory deviceMemory   = VK_NULL_HANDLE;
383     VkDeviceSize deviceMemorySize = 0;
384 
385     VkExtent3D extent = {1, 1, 1};
386     VkResult result   = Traits::CreateImage2D(&helper, format, createFlags, usageFlags, nullptr,
387                                               extent, &image, &deviceMemory, &deviceMemorySize);
388     EXPECT_EQ(result, VK_SUCCESS);
389 
390     typename Traits::Handle memoryHandle = Traits::InvalidHandle();
391     result = Traits::ExportMemory(&helper, deviceMemory, &memoryHandle);
392     EXPECT_EQ(result, VK_SUCCESS);
393     EXPECT_NE(memoryHandle, Traits::InvalidHandle());
394 
395     {
396         GLMemoryObject memoryObject;
397         GLint dedicatedMemory = GL_TRUE;
398         glMemoryObjectParameterivEXT(memoryObject, GL_DEDICATED_MEMORY_OBJECT_EXT,
399                                      &dedicatedMemory);
400         Traits::ImportMemory(memoryObject, deviceMemorySize, memoryHandle);
401 
402         GLTexture texture;
403         glBindTexture(GL_TEXTURE_2D, texture);
404         if (useMemoryObjectFlags)
405         {
406             glTexStorageMemFlags2DANGLE(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1, memoryObject, 0,
407                                         createFlags, usageFlags, nullptr);
408         }
409         else
410         {
411             glTexStorageMem2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1, memoryObject, 0);
412         }
413 
414         GLFramebuffer framebuffer;
415         glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
416         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
417 
418         glClearColor(0.5f, 0.5f, 0.5f, 0.5f);
419         glClear(GL_COLOR_BUFFER_BIT);
420 
421         EXPECT_PIXEL_NEAR(0, 0, 128, 128, 128, 128, 1.0);
422     }
423 
424     EXPECT_GL_NO_ERROR();
425 
426     vkDestroyImage(helper.getDevice(), image, nullptr);
427     vkFreeMemory(helper.getDevice(), deviceMemory, nullptr);
428 }
429 
430 // Test creating and clearing a simple RGBA8 texture in an opaque fd.
TEST_P(VulkanExternalImageTest,ShouldClearOpaqueFdRGBA8)431 TEST_P(VulkanExternalImageTest, ShouldClearOpaqueFdRGBA8)
432 {
433     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
434     // http://anglebug.com/42263236
435     ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGL() && (IsPixel2() || IsPixel2XL()));
436     RunShouldClearTest<OpaqueFdTraits>(false, kDefaultImageCreateFlags, kDefaultImageUsageFlags,
437                                        isSwiftshader(), enableDebugLayers());
438 }
439 
440 // Test creating and clearing a simple RGBA8 texture in an opaque fd, using
441 // GL_ANGLE_memory_object_flags.
TEST_P(VulkanExternalImageTest,ShouldClearOpaqueWithFlagsFdRGBA8)442 TEST_P(VulkanExternalImageTest, ShouldClearOpaqueWithFlagsFdRGBA8)
443 {
444     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
445     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
446     RunShouldClearTest<OpaqueFdTraits>(true, kDefaultImageCreateFlags, kDefaultImageUsageFlags,
447                                        isSwiftshader(), enableDebugLayers());
448 }
449 
450 // Test creating and clearing a simple RGBA8 texture without STORAGE usage in an opaque fd.
TEST_P(VulkanExternalImageTest,ShouldClearNoStorageUsageOpaqueFdRGBA8)451 TEST_P(VulkanExternalImageTest, ShouldClearNoStorageUsageOpaqueFdRGBA8)
452 {
453     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
454     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
455     RunShouldClearTest<OpaqueFdTraits>(true, kDefaultImageCreateFlags, kNoStorageImageUsageFlags,
456                                        isSwiftshader(), enableDebugLayers());
457 }
458 
459 // Test creating and clearing a simple RGBA8 texture without STORAGE usage but with MUTABLE in an
460 // opaque fd.
TEST_P(VulkanExternalImageTest,ShouldClearMutableNoStorageUsageOpaqueFdRGBA8)461 TEST_P(VulkanExternalImageTest, ShouldClearMutableNoStorageUsageOpaqueFdRGBA8)
462 {
463     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
464     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
465     RunShouldClearTest<OpaqueFdTraits>(true, kMutableImageCreateFlags, kNoStorageImageUsageFlags,
466                                        isSwiftshader(), enableDebugLayers());
467 }
468 
469 // Test creating and clearing a simple RGBA8 texture in a zircon vmo.
TEST_P(VulkanExternalImageTest,ShouldClearZirconVmoRGBA8)470 TEST_P(VulkanExternalImageTest, ShouldClearZirconVmoRGBA8)
471 {
472     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_fuchsia"));
473     RunShouldClearTest<FuchsiaTraits>(false, kDefaultImageCreateFlags, kDefaultImageUsageFlags,
474                                       isSwiftshader(), enableDebugLayers());
475 }
476 
477 // Test creating and clearing a simple RGBA8 texture in a zircon vmo, using
478 // GL_ANGLE_memory_object_flags.
TEST_P(VulkanExternalImageTest,ShouldClearZirconWithFlagsVmoRGBA8)479 TEST_P(VulkanExternalImageTest, ShouldClearZirconWithFlagsVmoRGBA8)
480 {
481     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_fuchsia"));
482     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
483     RunShouldClearTest<FuchsiaTraits>(true, kDefaultImageCreateFlags, kDefaultImageUsageFlags,
484                                       isSwiftshader(), enableDebugLayers());
485 }
486 
487 // Test creating and clearing a simple RGBA8 texture without STORAGE usage in a zircon vmo.
TEST_P(VulkanExternalImageTest,ShouldClearNoStorageUsageZirconVmoRGBA8)488 TEST_P(VulkanExternalImageTest, ShouldClearNoStorageUsageZirconVmoRGBA8)
489 {
490     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_fuchsia"));
491     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
492     RunShouldClearTest<FuchsiaTraits>(true, kDefaultImageCreateFlags, kNoStorageImageUsageFlags,
493                                       isSwiftshader(), enableDebugLayers());
494 }
495 
496 // Test creating and clearing a simple RGBA8 texture without STORAGE usage but with MUTABLE in a
497 // zircon vmo.
TEST_P(VulkanExternalImageTest,ShouldClearMutableNoStorageUsageZirconVmoRGBA8)498 TEST_P(VulkanExternalImageTest, ShouldClearMutableNoStorageUsageZirconVmoRGBA8)
499 {
500     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_fuchsia"));
501     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
502     RunShouldClearTest<FuchsiaTraits>(true, kMutableImageCreateFlags, kNoStorageImageUsageFlags,
503                                       isSwiftshader(), enableDebugLayers());
504 }
505 
506 template <typename Traits>
RunTextureFormatCompatChromiumTest(bool useMemoryObjectFlags,VkImageCreateFlags createFlags,VkImageUsageFlags usageFlags,bool isSwiftshader,bool enableDebugLayers,bool isES3)507 void RunTextureFormatCompatChromiumTest(bool useMemoryObjectFlags,
508                                         VkImageCreateFlags createFlags,
509                                         VkImageUsageFlags usageFlags,
510                                         bool isSwiftshader,
511                                         bool enableDebugLayers,
512                                         bool isES3)
513 {
514     ASSERT(EnsureGLExtensionEnabled(Traits::MemoryObjectExtension()));
515 
516     AdjustCreateFlags(useMemoryObjectFlags, &createFlags);
517 
518     VulkanHelper helper;
519     helper.initialize(isSwiftshader, enableDebugLayers);
520     for (const ImageFormatPair &format : kChromeFormats)
521     {
522         // https://crbug.com/angleproject/5046
523         if ((format.vkFormat == VK_FORMAT_R4G4B4A4_UNORM_PACK16) && IsIntel())
524         {
525             continue;
526         }
527 
528         if (!Traits::CanCreateImage(helper, format.vkFormat, VK_IMAGE_TYPE_2D,
529                                     VK_IMAGE_TILING_OPTIMAL, createFlags, usageFlags))
530         {
531             continue;
532         }
533 
534         if (format.requiredExtension && !IsGLExtensionEnabled(format.requiredExtension))
535         {
536             continue;
537         }
538 
539         if (format.internalFormat == GL_RGB10_A2_EXT && !isES3 &&
540             !IsGLExtensionEnabled("GL_EXT_texture_type_2_10_10_10_REV"))
541         {
542             continue;
543         }
544 
545         VkImage image                 = VK_NULL_HANDLE;
546         VkDeviceMemory deviceMemory   = VK_NULL_HANDLE;
547         VkDeviceSize deviceMemorySize = 0;
548 
549         VkExtent3D extent = {113, 211, 1};
550         VkResult result =
551             Traits::CreateImage2D(&helper, format.vkFormat, createFlags, usageFlags, nullptr,
552                                   extent, &image, &deviceMemory, &deviceMemorySize);
553         EXPECT_EQ(result, VK_SUCCESS);
554 
555         typename Traits::Handle memoryHandle = Traits::InvalidHandle();
556         result = Traits::ExportMemory(&helper, deviceMemory, &memoryHandle);
557         EXPECT_EQ(result, VK_SUCCESS);
558         EXPECT_NE(memoryHandle, Traits::InvalidHandle());
559 
560         {
561             GLMemoryObject memoryObject;
562             GLint dedicatedMemory = GL_TRUE;
563             glMemoryObjectParameterivEXT(memoryObject, GL_DEDICATED_MEMORY_OBJECT_EXT,
564                                          &dedicatedMemory);
565             Traits::ImportMemory(memoryObject, deviceMemorySize, memoryHandle);
566 
567             GLTexture texture;
568             glBindTexture(GL_TEXTURE_2D, texture);
569             if (useMemoryObjectFlags)
570             {
571                 glTexStorageMemFlags2DANGLE(GL_TEXTURE_2D, 1, format.internalFormat, extent.width,
572                                             extent.height, memoryObject, 0, createFlags, usageFlags,
573                                             nullptr);
574             }
575             else
576             {
577                 glTexStorageMem2DEXT(GL_TEXTURE_2D, 1, format.internalFormat, extent.width,
578                                      extent.height, memoryObject, 0);
579             }
580         }
581 
582         EXPECT_GL_NO_ERROR();
583 
584         vkDestroyImage(helper.getDevice(), image, nullptr);
585         vkFreeMemory(helper.getDevice(), deviceMemory, nullptr);
586     }
587 }
588 
589 // Test all format combinations used by Chrome import successfully (opaque fd).
TEST_P(VulkanExternalImageTest,TextureFormatCompatChromiumFd)590 TEST_P(VulkanExternalImageTest, TextureFormatCompatChromiumFd)
591 {
592     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
593     RunTextureFormatCompatChromiumTest<OpaqueFdTraits>(
594         false, kDefaultImageCreateFlags, kDefaultImageUsageFlags, isSwiftshader(),
595         enableDebugLayers(), getClientMajorVersion() >= 3);
596 }
597 
598 // Test all format combinations used by Chrome import successfully (opaque fd), using
599 // GL_ANGLE_memory_object_flags.
TEST_P(VulkanExternalImageTest,TextureFormatCompatChromiumWithFlagsFd)600 TEST_P(VulkanExternalImageTest, TextureFormatCompatChromiumWithFlagsFd)
601 {
602     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
603     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
604     RunTextureFormatCompatChromiumTest<OpaqueFdTraits>(
605         true, kDefaultImageCreateFlags, kDefaultImageUsageFlags, isSwiftshader(),
606         enableDebugLayers(), getClientMajorVersion() >= 3);
607 }
608 
609 // Test all format combinations used by Chrome import successfully (opaque fd), without STORAGE
610 // usage.
TEST_P(VulkanExternalImageTest,TextureFormatCompatChromiumNoStorageFd)611 TEST_P(VulkanExternalImageTest, TextureFormatCompatChromiumNoStorageFd)
612 {
613     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
614     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
615     RunTextureFormatCompatChromiumTest<OpaqueFdTraits>(
616         true, kDefaultImageCreateFlags, kNoStorageImageUsageFlags, isSwiftshader(),
617         enableDebugLayers(), getClientMajorVersion() >= 3);
618 }
619 
620 // Test all format combinations used by Chrome import successfully (opaque fd), without STORAGE
621 // usage but with MUTABLE.
TEST_P(VulkanExternalImageTest,TextureFormatCompatChromiumMutableNoStorageFd)622 TEST_P(VulkanExternalImageTest, TextureFormatCompatChromiumMutableNoStorageFd)
623 {
624     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
625     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
626 
627     // http://anglebug.com/42264218
628     ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsVulkan());
629 
630     RunTextureFormatCompatChromiumTest<OpaqueFdTraits>(
631         true, kMutableImageCreateFlags, kNoStorageImageUsageFlags, isSwiftshader(),
632         enableDebugLayers(), getClientMajorVersion() >= 3);
633 }
634 
635 // Test all format combinations used by Chrome import successfully (fuchsia).
TEST_P(VulkanExternalImageTest,TextureFormatCompatChromiumZirconVmo)636 TEST_P(VulkanExternalImageTest, TextureFormatCompatChromiumZirconVmo)
637 {
638     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_fuchsia"));
639     RunTextureFormatCompatChromiumTest<FuchsiaTraits>(
640         false, kDefaultImageCreateFlags, kDefaultImageUsageFlags, isSwiftshader(),
641         enableDebugLayers(), getClientMajorVersion() >= 3);
642 }
643 
644 // Test all format combinations used by Chrome import successfully (fuchsia), using
645 // GL_ANGLE_memory_object_flags.
TEST_P(VulkanExternalImageTest,TextureFormatCompatChromiumWithFlagsZirconVmo)646 TEST_P(VulkanExternalImageTest, TextureFormatCompatChromiumWithFlagsZirconVmo)
647 {
648     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_fuchsia"));
649     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
650     RunTextureFormatCompatChromiumTest<FuchsiaTraits>(
651         true, kDefaultImageCreateFlags, kDefaultImageUsageFlags, isSwiftshader(),
652         enableDebugLayers(), getClientMajorVersion() >= 3);
653 }
654 
655 // Test all format combinations used by Chrome import successfully (fuchsia), without STORAGE usage.
TEST_P(VulkanExternalImageTest,TextureFormatCompatChromiumNoStorageZirconVmo)656 TEST_P(VulkanExternalImageTest, TextureFormatCompatChromiumNoStorageZirconVmo)
657 {
658     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_fuchsia"));
659     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
660     RunTextureFormatCompatChromiumTest<FuchsiaTraits>(
661         true, kDefaultImageCreateFlags, kNoStorageImageUsageFlags, isSwiftshader(),
662         enableDebugLayers(), getClientMajorVersion() >= 3);
663 }
664 
665 // Test all format combinations used by Chrome import successfully (fuchsia), without STORAGE usage
666 // but with MUTABLE.
TEST_P(VulkanExternalImageTest,TextureFormatCompatChromiumMutableNoStorageZirconVmo)667 TEST_P(VulkanExternalImageTest, TextureFormatCompatChromiumMutableNoStorageZirconVmo)
668 {
669     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_fuchsia"));
670     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
671     RunTextureFormatCompatChromiumTest<FuchsiaTraits>(
672         true, kMutableImageCreateFlags, kNoStorageImageUsageFlags, isSwiftshader(),
673         enableDebugLayers(), getClientMajorVersion() >= 3);
674 }
675 
676 template <typename Traits>
RunShouldClearWithSemaphoresTest(bool useMemoryObjectFlags,VkImageCreateFlags createFlags,VkImageUsageFlags usageFlags,bool isSwiftshader,bool enableDebugLayers)677 void RunShouldClearWithSemaphoresTest(bool useMemoryObjectFlags,
678                                       VkImageCreateFlags createFlags,
679                                       VkImageUsageFlags usageFlags,
680                                       bool isSwiftshader,
681                                       bool enableDebugLayers)
682 {
683     ASSERT(EnsureGLExtensionEnabled(Traits::MemoryObjectExtension()));
684     ASSERT(EnsureGLExtensionEnabled(Traits::SemaphoreExtension()));
685 
686     AdjustCreateFlags(useMemoryObjectFlags, &createFlags);
687 
688     VulkanHelper helper;
689     helper.initialize(isSwiftshader, enableDebugLayers);
690 
691     VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
692     ANGLE_SKIP_TEST_IF(!Traits::CanCreateImage(helper, format, VK_IMAGE_TYPE_2D,
693                                                VK_IMAGE_TILING_OPTIMAL, createFlags, usageFlags));
694     ANGLE_SKIP_TEST_IF(!Traits::CanCreateSemaphore(helper));
695 
696     VkSemaphore vkAcquireSemaphore = VK_NULL_HANDLE;
697     VkResult result                = Traits::CreateSemaphore(&helper, &vkAcquireSemaphore);
698     EXPECT_EQ(result, VK_SUCCESS);
699     EXPECT_TRUE(vkAcquireSemaphore != VK_NULL_HANDLE);
700 
701     VkSemaphore vkReleaseSemaphore = VK_NULL_HANDLE;
702     result                         = Traits::CreateSemaphore(&helper, &vkReleaseSemaphore);
703     EXPECT_EQ(result, VK_SUCCESS);
704     EXPECT_TRUE(vkReleaseSemaphore != VK_NULL_HANDLE);
705 
706     typename Traits::Handle acquireSemaphoreHandle = Traits::InvalidHandle();
707     result = Traits::ExportSemaphore(&helper, vkAcquireSemaphore, &acquireSemaphoreHandle);
708     EXPECT_EQ(result, VK_SUCCESS);
709     EXPECT_NE(acquireSemaphoreHandle, Traits::InvalidHandle());
710 
711     typename Traits::Handle releaseSemaphoreHandle = Traits::InvalidHandle();
712     result = Traits::ExportSemaphore(&helper, vkReleaseSemaphore, &releaseSemaphoreHandle);
713     EXPECT_EQ(result, VK_SUCCESS);
714     EXPECT_NE(releaseSemaphoreHandle, Traits::InvalidHandle());
715 
716     VkImage image                 = VK_NULL_HANDLE;
717     VkDeviceMemory deviceMemory   = VK_NULL_HANDLE;
718     VkDeviceSize deviceMemorySize = 0;
719 
720     VkExtent3D extent = {1, 1, 1};
721     result = Traits::CreateImage2D(&helper, format, createFlags, usageFlags, nullptr, extent,
722                                    &image, &deviceMemory, &deviceMemorySize);
723     EXPECT_EQ(result, VK_SUCCESS);
724 
725     typename Traits::Handle memoryHandle = Traits::InvalidHandle();
726     result = Traits::ExportMemory(&helper, deviceMemory, &memoryHandle);
727     EXPECT_EQ(result, VK_SUCCESS);
728     EXPECT_NE(memoryHandle, Traits::InvalidHandle());
729 
730     {
731         GLMemoryObject memoryObject;
732         GLint dedicatedMemory = GL_TRUE;
733         glMemoryObjectParameterivEXT(memoryObject, GL_DEDICATED_MEMORY_OBJECT_EXT,
734                                      &dedicatedMemory);
735         Traits::ImportMemory(memoryObject, deviceMemorySize, memoryHandle);
736 
737         GLTexture texture;
738         glBindTexture(GL_TEXTURE_2D, texture);
739         if (useMemoryObjectFlags)
740         {
741             glTexStorageMemFlags2DANGLE(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1, memoryObject, 0,
742                                         createFlags, usageFlags, nullptr);
743         }
744         else
745         {
746             glTexStorageMem2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1, memoryObject, 0);
747         }
748 
749         GLSemaphore glAcquireSemaphore;
750         Traits::ImportSemaphore(glAcquireSemaphore, acquireSemaphoreHandle);
751 
752         helper.releaseImageAndSignalSemaphore(image, VK_IMAGE_LAYOUT_UNDEFINED,
753                                               VK_IMAGE_LAYOUT_GENERAL, vkAcquireSemaphore);
754 
755         const GLuint barrierTextures[] = {
756             texture,
757         };
758         constexpr uint32_t textureBarriersCount = std::extent<decltype(barrierTextures)>();
759         const GLenum textureSrcLayouts[]        = {
760             GL_LAYOUT_GENERAL_EXT,
761         };
762         constexpr uint32_t textureSrcLayoutsCount = std::extent<decltype(textureSrcLayouts)>();
763         static_assert(textureBarriersCount == textureSrcLayoutsCount,
764                       "barrierTextures and textureSrcLayouts must be the same length");
765         glWaitSemaphoreEXT(glAcquireSemaphore, 0, nullptr, textureBarriersCount, barrierTextures,
766                            textureSrcLayouts);
767 
768         GLFramebuffer framebuffer;
769         glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
770         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
771 
772         glClearColor(0.5f, 0.5f, 0.5f, 0.5f);
773         glClear(GL_COLOR_BUFFER_BIT);
774 
775         GLSemaphore glReleaseSemaphore;
776         Traits::ImportSemaphore(glReleaseSemaphore, releaseSemaphoreHandle);
777 
778         const GLenum textureDstLayouts[] = {
779             GL_LAYOUT_TRANSFER_SRC_EXT,
780         };
781         constexpr uint32_t textureDstLayoutsCount = std::extent<decltype(textureSrcLayouts)>();
782         static_assert(textureBarriersCount == textureDstLayoutsCount,
783                       "barrierTextures and textureDstLayouts must be the same length");
784         glSignalSemaphoreEXT(glReleaseSemaphore, 0, nullptr, textureBarriersCount, barrierTextures,
785                              textureDstLayouts);
786 
787         helper.waitSemaphoreAndAcquireImage(image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
788                                             VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
789                                             vkReleaseSemaphore);
790         uint8_t pixels[4];
791         VkOffset3D offset = {};
792         helper.readPixels(image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, format, offset, extent,
793                           pixels, sizeof(pixels));
794 
795         EXPECT_NEAR(0x80, pixels[0], 1);
796         EXPECT_NEAR(0x80, pixels[1], 1);
797         EXPECT_NEAR(0x80, pixels[2], 1);
798         EXPECT_NEAR(0x80, pixels[3], 1);
799     }
800 
801     EXPECT_GL_NO_ERROR();
802 
803     vkDeviceWaitIdle(helper.getDevice());
804     vkDestroyImage(helper.getDevice(), image, nullptr);
805     vkDestroySemaphore(helper.getDevice(), vkAcquireSemaphore, nullptr);
806     vkDestroySemaphore(helper.getDevice(), vkReleaseSemaphore, nullptr);
807     vkFreeMemory(helper.getDevice(), deviceMemory, nullptr);
808 }
809 
810 // Test creating and clearing RGBA8 texture in opaque fd with acquire/release.
TEST_P(VulkanExternalImageTest,ShouldClearOpaqueFdWithSemaphores)811 TEST_P(VulkanExternalImageTest, ShouldClearOpaqueFdWithSemaphores)
812 {
813     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
814     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_semaphore_fd"));
815 
816     // http://anglebug.com/42263923
817     ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
818 
819     RunShouldClearWithSemaphoresTest<OpaqueFdTraits>(false, kDefaultImageCreateFlags,
820                                                      kDefaultImageUsageFlags, isSwiftshader(),
821                                                      enableDebugLayers());
822 }
823 
824 // Test creating and clearing RGBA8 texture in opaque fd with acquire/release, using
825 // GL_ANGLE_memory_object_flags.
TEST_P(VulkanExternalImageTest,ShouldClearOpaqueFdWithSemaphoresWithFlags)826 TEST_P(VulkanExternalImageTest, ShouldClearOpaqueFdWithSemaphoresWithFlags)
827 {
828     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
829     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_semaphore_fd"));
830     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
831 
832     RunShouldClearWithSemaphoresTest<OpaqueFdTraits>(true, kDefaultImageCreateFlags,
833                                                      kDefaultImageUsageFlags, isSwiftshader(),
834                                                      enableDebugLayers());
835 }
836 
837 // Test creating and clearing RGBA8 texture without STORAGE usage in opaque fd with acquire/release.
TEST_P(VulkanExternalImageTest,ShouldClearOpaqueFdWithSemaphoresNoStorage)838 TEST_P(VulkanExternalImageTest, ShouldClearOpaqueFdWithSemaphoresNoStorage)
839 {
840     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
841     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_semaphore_fd"));
842     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
843 
844     RunShouldClearWithSemaphoresTest<OpaqueFdTraits>(true, kDefaultImageCreateFlags,
845                                                      kNoStorageImageUsageFlags, isSwiftshader(),
846                                                      enableDebugLayers());
847 }
848 
849 // Test creating and clearing RGBA8 texture without STORAGE usage but with MUTABLE in opaque fd with
850 // acquire/release.
TEST_P(VulkanExternalImageTest,ShouldClearOpaqueFdWithSemaphoresMutableNoStorage)851 TEST_P(VulkanExternalImageTest, ShouldClearOpaqueFdWithSemaphoresMutableNoStorage)
852 {
853     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
854     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_semaphore_fd"));
855     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
856 
857     RunShouldClearWithSemaphoresTest<OpaqueFdTraits>(true, kMutableImageCreateFlags,
858                                                      kNoStorageImageUsageFlags, isSwiftshader(),
859                                                      enableDebugLayers());
860 }
861 
862 // Test creating and clearing RGBA8 texture in zircon vmo with acquire/release.
TEST_P(VulkanExternalImageTest,ShouldClearZirconVmoWithSemaphores)863 TEST_P(VulkanExternalImageTest, ShouldClearZirconVmoWithSemaphores)
864 {
865     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_fuchsia"));
866     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_semaphore_fuchsia"));
867     RunShouldClearWithSemaphoresTest<FuchsiaTraits>(false, kDefaultImageCreateFlags,
868                                                     kDefaultImageUsageFlags, isSwiftshader(),
869                                                     enableDebugLayers());
870 }
871 
872 // Test creating and clearing RGBA8 texture in zircon vmo with acquire/release, using
873 // GL_ANGLE_memory_object_flags.
TEST_P(VulkanExternalImageTest,ShouldClearZirconVmoWithSemaphoresWithFlags)874 TEST_P(VulkanExternalImageTest, ShouldClearZirconVmoWithSemaphoresWithFlags)
875 {
876     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_fuchsia"));
877     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_semaphore_fuchsia"));
878     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
879     RunShouldClearWithSemaphoresTest<FuchsiaTraits>(true, kDefaultImageCreateFlags,
880                                                     kDefaultImageUsageFlags, isSwiftshader(),
881                                                     enableDebugLayers());
882 }
883 
884 // Test creating and clearing RGBA8 texture without STORAGE usage in zircon vmo with
885 // acquire/release.
TEST_P(VulkanExternalImageTest,ShouldClearZirconVmoWithSemaphoresNoStorage)886 TEST_P(VulkanExternalImageTest, ShouldClearZirconVmoWithSemaphoresNoStorage)
887 {
888     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_fuchsia"));
889     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_semaphore_fuchsia"));
890     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
891     RunShouldClearWithSemaphoresTest<FuchsiaTraits>(true, kDefaultImageCreateFlags,
892                                                     kNoStorageImageUsageFlags, isSwiftshader(),
893                                                     enableDebugLayers());
894 }
895 
896 // Test creating and clearing RGBA8 texture without STORAGE usage but with MUTABLE in zircon vmo
897 // with acquire/release.
TEST_P(VulkanExternalImageTest,ShouldClearZirconVmoWithSemaphoresMutableNoStorage)898 TEST_P(VulkanExternalImageTest, ShouldClearZirconVmoWithSemaphoresMutableNoStorage)
899 {
900     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_fuchsia"));
901     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_semaphore_fuchsia"));
902     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
903     RunShouldClearWithSemaphoresTest<FuchsiaTraits>(true, kMutableImageCreateFlags,
904                                                     kNoStorageImageUsageFlags, isSwiftshader(),
905                                                     enableDebugLayers());
906 }
907 
908 template <typename Traits>
runShouldDrawTest(bool isSwiftshader,bool enableDebugLayers)909 void VulkanExternalImageTest::runShouldDrawTest(bool isSwiftshader, bool enableDebugLayers)
910 {
911     ASSERT(EnsureGLExtensionEnabled(Traits::MemoryObjectExtension()));
912     ASSERT(EnsureGLExtensionEnabled(Traits::SemaphoreExtension()));
913 
914     VulkanHelper helper;
915     helper.initialize(isSwiftshader, enableDebugLayers);
916 
917     VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
918     ANGLE_SKIP_TEST_IF(!Traits::CanCreateImage(helper, format, VK_IMAGE_TYPE_2D,
919                                                VK_IMAGE_TILING_OPTIMAL, kDefaultImageCreateFlags,
920                                                kDefaultImageUsageFlags));
921     ANGLE_SKIP_TEST_IF(!Traits::CanCreateSemaphore(helper));
922 
923     VkSemaphore vkAcquireSemaphore = VK_NULL_HANDLE;
924     VkResult result                = Traits::CreateSemaphore(&helper, &vkAcquireSemaphore);
925     EXPECT_EQ(result, VK_SUCCESS);
926     EXPECT_TRUE(vkAcquireSemaphore != VK_NULL_HANDLE);
927 
928     VkSemaphore vkReleaseSemaphore = VK_NULL_HANDLE;
929     result                         = Traits::CreateSemaphore(&helper, &vkReleaseSemaphore);
930     EXPECT_EQ(result, VK_SUCCESS);
931     EXPECT_TRUE(vkReleaseSemaphore != VK_NULL_HANDLE);
932 
933     typename Traits::Handle acquireSemaphoreHandle = Traits::InvalidHandle();
934     result = Traits::ExportSemaphore(&helper, vkAcquireSemaphore, &acquireSemaphoreHandle);
935     EXPECT_EQ(result, VK_SUCCESS);
936     EXPECT_NE(acquireSemaphoreHandle, Traits::InvalidHandle());
937 
938     typename Traits::Handle releaseSemaphoreHandle = Traits::InvalidHandle();
939     result = Traits::ExportSemaphore(&helper, vkReleaseSemaphore, &releaseSemaphoreHandle);
940     EXPECT_EQ(result, VK_SUCCESS);
941     EXPECT_NE(releaseSemaphoreHandle, Traits::InvalidHandle());
942 
943     VkImage image                 = VK_NULL_HANDLE;
944     VkDeviceMemory deviceMemory   = VK_NULL_HANDLE;
945     VkDeviceSize deviceMemorySize = 0;
946 
947     VkExtent3D extent = {1, 1, 1};
948     result =
949         Traits::CreateImage2D(&helper, format, kDefaultImageCreateFlags, kDefaultImageUsageFlags,
950                               nullptr, extent, &image, &deviceMemory, &deviceMemorySize);
951     EXPECT_EQ(result, VK_SUCCESS);
952 
953     typename Traits::Handle memoryHandle = Traits::InvalidHandle();
954     result = Traits::ExportMemory(&helper, deviceMemory, &memoryHandle);
955     EXPECT_EQ(result, VK_SUCCESS);
956     EXPECT_NE(memoryHandle, Traits::InvalidHandle());
957 
958     {
959         GLMemoryObject memoryObject;
960         GLint dedicatedMemory = GL_TRUE;
961         glMemoryObjectParameterivEXT(memoryObject, GL_DEDICATED_MEMORY_OBJECT_EXT,
962                                      &dedicatedMemory);
963         Traits::ImportMemory(memoryObject, deviceMemorySize, memoryHandle);
964 
965         GLTexture texture;
966         glBindTexture(GL_TEXTURE_2D, texture);
967         glTexStorageMem2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1, memoryObject, 0);
968 
969         GLSemaphore glAcquireSemaphore;
970         Traits::ImportSemaphore(glAcquireSemaphore, acquireSemaphoreHandle);
971 
972         // Transfer ownership to GL.
973         helper.releaseImageAndSignalSemaphore(image, VK_IMAGE_LAYOUT_UNDEFINED,
974                                               VK_IMAGE_LAYOUT_GENERAL, vkAcquireSemaphore);
975 
976         const GLuint barrierTextures[] = {
977             texture,
978         };
979         constexpr uint32_t textureBarriersCount = std::extent<decltype(barrierTextures)>();
980         const GLenum textureSrcLayouts[]        = {
981             GL_LAYOUT_GENERAL_EXT,
982         };
983         constexpr uint32_t textureSrcLayoutsCount = std::extent<decltype(textureSrcLayouts)>();
984         static_assert(textureBarriersCount == textureSrcLayoutsCount,
985                       "barrierTextures and textureSrcLayouts must be the same length");
986         glWaitSemaphoreEXT(glAcquireSemaphore, 0, nullptr, textureBarriersCount, barrierTextures,
987                            textureSrcLayouts);
988 
989         GLFramebuffer framebuffer;
990         glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
991         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
992         EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
993 
994         // Make the texture red.
995         ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
996         drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.0f);
997         EXPECT_GL_NO_ERROR();
998 
999         // Transfer ownership back to test.
1000         GLSemaphore glReleaseSemaphore;
1001         Traits::ImportSemaphore(glReleaseSemaphore, releaseSemaphoreHandle);
1002 
1003         const GLenum textureDstLayouts[] = {
1004             GL_LAYOUT_TRANSFER_SRC_EXT,
1005         };
1006         constexpr uint32_t textureDstLayoutsCount = std::extent<decltype(textureSrcLayouts)>();
1007         static_assert(textureBarriersCount == textureDstLayoutsCount,
1008                       "barrierTextures and textureDstLayouts must be the same length");
1009         glSignalSemaphoreEXT(glReleaseSemaphore, 0, nullptr, textureBarriersCount, barrierTextures,
1010                              textureDstLayouts);
1011 
1012         helper.waitSemaphoreAndAcquireImage(image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1013                                             VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1014                                             vkReleaseSemaphore);
1015 
1016         uint8_t pixels[4];
1017         VkOffset3D offset = {};
1018         helper.readPixels(image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, format, offset, extent,
1019                           pixels, sizeof(pixels));
1020 
1021         EXPECT_EQ(0xFF, pixels[0]);
1022         EXPECT_EQ(0x00, pixels[1]);
1023         EXPECT_EQ(0x00, pixels[2]);
1024         EXPECT_EQ(0xFF, pixels[3]);
1025     }
1026 
1027     EXPECT_GL_NO_ERROR();
1028 
1029     vkDeviceWaitIdle(helper.getDevice());
1030     vkDestroyImage(helper.getDevice(), image, nullptr);
1031     vkDestroySemaphore(helper.getDevice(), vkAcquireSemaphore, nullptr);
1032     vkDestroySemaphore(helper.getDevice(), vkReleaseSemaphore, nullptr);
1033     vkFreeMemory(helper.getDevice(), deviceMemory, nullptr);
1034 }
1035 
1036 // Test drawing to RGBA8 texture in opaque fd with acquire/release.
TEST_P(VulkanExternalImageTest,ShouldDrawOpaqueFdWithSemaphores)1037 TEST_P(VulkanExternalImageTest, ShouldDrawOpaqueFdWithSemaphores)
1038 {
1039     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
1040     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_semaphore_fd"));
1041 
1042     // http://anglebug.com/42263923
1043     ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
1044 
1045     runShouldDrawTest<OpaqueFdTraits>(isSwiftshader(), enableDebugLayers());
1046 }
1047 
1048 // Test drawing to RGBA8 texture in zircon vmo with acquire/release multiple times.
TEST_P(VulkanExternalImageTest,ShouldDrawZirconVmoWithSemaphores)1049 TEST_P(VulkanExternalImageTest, ShouldDrawZirconVmoWithSemaphores)
1050 {
1051     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_fuchsia"));
1052     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_semaphore_fuchsia"));
1053     runShouldDrawTest<FuchsiaTraits>(isSwiftshader(), enableDebugLayers());
1054 }
1055 
1056 template <typename Traits>
runWaitSemaphoresRetainsContentTest(bool isSwiftshader,bool enableDebugLayers)1057 void VulkanExternalImageTest::runWaitSemaphoresRetainsContentTest(bool isSwiftshader,
1058                                                                   bool enableDebugLayers)
1059 {
1060     ASSERT(EnsureGLExtensionEnabled(Traits::MemoryObjectExtension()));
1061     ASSERT(EnsureGLExtensionEnabled(Traits::SemaphoreExtension()));
1062 
1063     VulkanHelper helper;
1064     helper.initialize(isSwiftshader, enableDebugLayers);
1065 
1066     VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
1067     ANGLE_SKIP_TEST_IF(!Traits::CanCreateImage(helper, format, VK_IMAGE_TYPE_2D,
1068                                                VK_IMAGE_TILING_OPTIMAL, kDefaultImageCreateFlags,
1069                                                kDefaultImageUsageFlags));
1070     ANGLE_SKIP_TEST_IF(!Traits::CanCreateSemaphore(helper));
1071 
1072     VkSemaphore vkAcquireSemaphore = VK_NULL_HANDLE;
1073     VkResult result                = Traits::CreateSemaphore(&helper, &vkAcquireSemaphore);
1074     EXPECT_EQ(result, VK_SUCCESS);
1075     EXPECT_TRUE(vkAcquireSemaphore != VK_NULL_HANDLE);
1076 
1077     VkSemaphore vkReleaseSemaphore = VK_NULL_HANDLE;
1078     result                         = Traits::CreateSemaphore(&helper, &vkReleaseSemaphore);
1079     EXPECT_EQ(result, VK_SUCCESS);
1080     EXPECT_TRUE(vkReleaseSemaphore != VK_NULL_HANDLE);
1081 
1082     typename Traits::Handle acquireSemaphoreHandle = Traits::InvalidHandle();
1083     result = Traits::ExportSemaphore(&helper, vkAcquireSemaphore, &acquireSemaphoreHandle);
1084     EXPECT_EQ(result, VK_SUCCESS);
1085     EXPECT_NE(acquireSemaphoreHandle, Traits::InvalidHandle());
1086 
1087     typename Traits::Handle releaseSemaphoreHandle = Traits::InvalidHandle();
1088     result = Traits::ExportSemaphore(&helper, vkReleaseSemaphore, &releaseSemaphoreHandle);
1089     EXPECT_EQ(result, VK_SUCCESS);
1090     EXPECT_NE(releaseSemaphoreHandle, Traits::InvalidHandle());
1091 
1092     VkImage image                 = VK_NULL_HANDLE;
1093     VkDeviceMemory deviceMemory   = VK_NULL_HANDLE;
1094     VkDeviceSize deviceMemorySize = 0;
1095 
1096     VkExtent3D extent = {kWidth, kHeight, 1};
1097     result =
1098         Traits::CreateImage2D(&helper, format, kDefaultImageCreateFlags, kDefaultImageUsageFlags,
1099                               nullptr, extent, &image, &deviceMemory, &deviceMemorySize);
1100     EXPECT_EQ(result, VK_SUCCESS);
1101 
1102     typename Traits::Handle memoryHandle = Traits::InvalidHandle();
1103     result = Traits::ExportMemory(&helper, deviceMemory, &memoryHandle);
1104     EXPECT_EQ(result, VK_SUCCESS);
1105     EXPECT_NE(memoryHandle, Traits::InvalidHandle());
1106 
1107     {
1108         GLMemoryObject memoryObject;
1109         GLint dedicatedMemory = GL_TRUE;
1110         glMemoryObjectParameterivEXT(memoryObject, GL_DEDICATED_MEMORY_OBJECT_EXT,
1111                                      &dedicatedMemory);
1112         Traits::ImportMemory(memoryObject, deviceMemorySize, memoryHandle);
1113 
1114         GLTexture texture;
1115         glBindTexture(GL_TEXTURE_2D, texture);
1116         glTexStorageMem2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, kWidth, kHeight, memoryObject, 0);
1117 
1118         GLSemaphore glAcquireSemaphore;
1119         Traits::ImportSemaphore(glAcquireSemaphore, acquireSemaphoreHandle);
1120 
1121         // Transfer ownership to GL.
1122         helper.releaseImageAndSignalSemaphore(image, VK_IMAGE_LAYOUT_UNDEFINED,
1123                                               VK_IMAGE_LAYOUT_GENERAL, vkAcquireSemaphore);
1124 
1125         const GLuint barrierTextures[] = {
1126             texture,
1127         };
1128         constexpr uint32_t textureBarriersCount = std::extent<decltype(barrierTextures)>();
1129         const GLenum textureSrcLayouts[]        = {
1130             GL_LAYOUT_GENERAL_EXT,
1131         };
1132         constexpr uint32_t textureSrcLayoutsCount = std::extent<decltype(textureSrcLayouts)>();
1133         static_assert(textureBarriersCount == textureSrcLayoutsCount,
1134                       "barrierTextures and textureSrcLayouts must be the same length");
1135         glWaitSemaphoreEXT(glAcquireSemaphore, 0, nullptr, textureBarriersCount, barrierTextures,
1136                            textureSrcLayouts);
1137 
1138         GLFramebuffer framebuffer;
1139         glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1140         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1141         EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1142 
1143         // Make the texture red.
1144         ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
1145         glViewport(0, 0, kWidth, kHeight);
1146         drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.0f);
1147         EXPECT_GL_NO_ERROR();
1148 
1149         // Transfer ownership back to test.
1150         GLSemaphore glReleaseSemaphore;
1151         Traits::ImportSemaphore(glReleaseSemaphore, releaseSemaphoreHandle);
1152 
1153         const GLenum textureDstLayouts[] = {
1154             GL_LAYOUT_TRANSFER_SRC_EXT,
1155         };
1156         constexpr uint32_t textureDstLayoutsCount = std::extent<decltype(textureSrcLayouts)>();
1157         static_assert(textureBarriersCount == textureDstLayoutsCount,
1158                       "barrierTextures and textureDstLayouts must be the same length");
1159         glSignalSemaphoreEXT(glReleaseSemaphore, 0, nullptr, textureBarriersCount, barrierTextures,
1160                              textureDstLayouts);
1161 
1162         helper.waitSemaphoreAndAcquireImage(image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1163                                             VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1164                                             vkReleaseSemaphore);
1165 
1166         // Transfer ownership to GL again, and make sure the contents are preserved.
1167         helper.releaseImageAndSignalSemaphore(image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1168                                               VK_IMAGE_LAYOUT_GENERAL, vkAcquireSemaphore);
1169         glWaitSemaphoreEXT(glAcquireSemaphore, 0, nullptr, textureBarriersCount, barrierTextures,
1170                            textureSrcLayouts);
1171 
1172         // Blend green
1173         ANGLE_GL_PROGRAM(drawGreen, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
1174         glEnable(GL_BLEND);
1175         glBlendFunc(GL_ONE, GL_ONE);
1176         drawQuad(drawGreen, essl1_shaders::PositionAttrib(), 0.0f);
1177 
1178         // Transfer ownership back to test
1179         glSignalSemaphoreEXT(glReleaseSemaphore, 0, nullptr, textureBarriersCount, barrierTextures,
1180                              textureDstLayouts);
1181         helper.waitSemaphoreAndAcquireImage(image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1182                                             VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1183                                             vkReleaseSemaphore);
1184 
1185         uint8_t pixels[4 * kWidth * kHeight];
1186         VkOffset3D offset = {};
1187         helper.readPixels(image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, format, offset, extent,
1188                           pixels, sizeof(pixels));
1189 
1190         EXPECT_EQ(0xFF, pixels[0]);
1191         EXPECT_EQ(0xFF, pixels[1]);
1192         EXPECT_EQ(0x00, pixels[2]);
1193         EXPECT_EQ(0xFF, pixels[3]);
1194 
1195         EXPECT_EQ(0xFF, pixels[4]);
1196         EXPECT_EQ(0xFF, pixels[5]);
1197         EXPECT_EQ(0x00, pixels[6]);
1198         EXPECT_EQ(0xFF, pixels[7]);
1199     }
1200 
1201     EXPECT_GL_NO_ERROR();
1202 
1203     vkDeviceWaitIdle(helper.getDevice());
1204     vkDestroyImage(helper.getDevice(), image, nullptr);
1205     vkDestroySemaphore(helper.getDevice(), vkAcquireSemaphore, nullptr);
1206     vkDestroySemaphore(helper.getDevice(), vkReleaseSemaphore, nullptr);
1207     vkFreeMemory(helper.getDevice(), deviceMemory, nullptr);
1208 }
1209 
1210 // Test drawing to RGBA8 texture in opaque fd with acquire/release multiple times.
TEST_P(VulkanExternalImageTest,WaitSemaphoresRetainsContentOpaqueFd)1211 TEST_P(VulkanExternalImageTest, WaitSemaphoresRetainsContentOpaqueFd)
1212 {
1213     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
1214     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_semaphore_fd"));
1215 
1216     // http://anglebug.com/42263923
1217     ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
1218 
1219     runWaitSemaphoresRetainsContentTest<OpaqueFdTraits>(isSwiftshader(), enableDebugLayers());
1220 }
1221 
1222 // Test drawing to RGBA8 texture in zircon vmo with acquire/release multiple times.
TEST_P(VulkanExternalImageTest,WaitSemaphoresRetainsContentZirconVmo)1223 TEST_P(VulkanExternalImageTest, WaitSemaphoresRetainsContentZirconVmo)
1224 {
1225     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_fuchsia"));
1226     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_semaphore_fuchsia"));
1227     runWaitSemaphoresRetainsContentTest<FuchsiaTraits>(isSwiftshader(), enableDebugLayers());
1228 }
1229 
1230 // Support for Zircon handle types is mandatory on Fuchsia.
TEST_P(VulkanExternalImageTest,ShouldSupportExternalHandlesFuchsia)1231 TEST_P(VulkanExternalImageTest, ShouldSupportExternalHandlesFuchsia)
1232 {
1233     ANGLE_SKIP_TEST_IF(!IsFuchsia());
1234     EXPECT_TRUE(EnsureGLExtensionEnabled("GL_ANGLE_memory_object_fuchsia"));
1235     EXPECT_TRUE(EnsureGLExtensionEnabled("GL_ANGLE_semaphore_fuchsia"));
1236     VulkanHelper helper;
1237     helper.initialize(isSwiftshader(), enableDebugLayers());
1238     EXPECT_TRUE(helper.canCreateSemaphoreZirconEvent());
1239     EXPECT_TRUE(helper.canCreateImageZirconVmo(VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_TYPE_2D,
1240                                                VK_IMAGE_TILING_OPTIMAL, kDefaultImageCreateFlags,
1241                                                kDefaultImageUsageFlags));
1242 }
1243 
1244 template <typename Traits>
RunPreInitializedOnGLImportTest(bool useMemoryObjectFlags,VkImageTiling tiling,bool isSwiftshader,bool enableDebugLayers)1245 void RunPreInitializedOnGLImportTest(bool useMemoryObjectFlags,
1246                                      VkImageTiling tiling,
1247                                      bool isSwiftshader,
1248                                      bool enableDebugLayers)
1249 {
1250     ASSERT(EnsureGLExtensionEnabled(Traits::MemoryObjectExtension()));
1251     ASSERT(EnsureGLExtensionEnabled(Traits::SemaphoreExtension()));
1252 
1253     VkImageCreateFlags createFlags = kDefaultImageCreateFlags;
1254     VkImageUsageFlags usageFlags   = kDefaultImageUsageFlags;
1255 
1256     AdjustCreateFlags(useMemoryObjectFlags, &createFlags);
1257 
1258     VulkanHelper helper;
1259     helper.initialize(isSwiftshader, enableDebugLayers);
1260 
1261     VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
1262     ANGLE_SKIP_TEST_IF(
1263         !Traits::CanCreateImage(helper, format, VK_IMAGE_TYPE_2D, tiling, createFlags, usageFlags));
1264     ANGLE_SKIP_TEST_IF(!Traits::CanCreateSemaphore(helper));
1265 
1266     VkSemaphore vkAcquireSemaphore = VK_NULL_HANDLE;
1267     VkResult result                = Traits::CreateSemaphore(&helper, &vkAcquireSemaphore);
1268     EXPECT_EQ(result, VK_SUCCESS);
1269     EXPECT_TRUE(vkAcquireSemaphore != VK_NULL_HANDLE);
1270 
1271     VkSemaphore vkReleaseSemaphore = VK_NULL_HANDLE;
1272     result                         = Traits::CreateSemaphore(&helper, &vkReleaseSemaphore);
1273     EXPECT_EQ(result, VK_SUCCESS);
1274     EXPECT_TRUE(vkReleaseSemaphore != VK_NULL_HANDLE);
1275 
1276     typename Traits::Handle acquireSemaphoreHandle = Traits::InvalidHandle();
1277     result = Traits::ExportSemaphore(&helper, vkAcquireSemaphore, &acquireSemaphoreHandle);
1278     EXPECT_EQ(result, VK_SUCCESS);
1279     EXPECT_NE(acquireSemaphoreHandle, Traits::InvalidHandle());
1280 
1281     typename Traits::Handle releaseSemaphoreHandle = Traits::InvalidHandle();
1282     result = Traits::ExportSemaphore(&helper, vkReleaseSemaphore, &releaseSemaphoreHandle);
1283     EXPECT_EQ(result, VK_SUCCESS);
1284     EXPECT_NE(releaseSemaphoreHandle, Traits::InvalidHandle());
1285 
1286     VkImage image                 = VK_NULL_HANDLE;
1287     VkDeviceMemory deviceMemory   = VK_NULL_HANDLE;
1288     VkDeviceSize deviceMemorySize = 0;
1289 
1290     VkExtent3D extent = {kWidth, kHeight, 1};
1291     result = Traits::CreateImage2D(&helper, format, createFlags, usageFlags, nullptr, extent,
1292                                    &image, &deviceMemory, &deviceMemorySize);
1293     EXPECT_EQ(result, VK_SUCCESS);
1294 
1295     // Initialize a pixel in the image
1296     constexpr uint32_t kPixel = 0x12345678;
1297     helper.writePixels(image, VK_IMAGE_LAYOUT_UNDEFINED, VK_FORMAT_R8G8B8A8_UNORM, {0, 0, 0},
1298                        {1, 1, 1}, static_cast<const void *>(&kPixel), sizeof(kPixel));
1299 
1300     typename Traits::Handle memoryHandle = Traits::InvalidHandle();
1301     result = Traits::ExportMemory(&helper, deviceMemory, &memoryHandle);
1302     EXPECT_EQ(result, VK_SUCCESS);
1303     EXPECT_NE(memoryHandle, Traits::InvalidHandle());
1304 
1305     {
1306         GLMemoryObject memoryObject;
1307         GLint dedicatedMemory = GL_TRUE;
1308         glMemoryObjectParameterivEXT(memoryObject, GL_DEDICATED_MEMORY_OBJECT_EXT,
1309                                      &dedicatedMemory);
1310         Traits::ImportMemory(memoryObject, deviceMemorySize, memoryHandle);
1311 
1312         GLTexture texture;
1313         glBindTexture(GL_TEXTURE_2D, texture);
1314         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1315         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1316         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1317         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1318         if (tiling == VK_IMAGE_TILING_LINEAR)
1319         {
1320             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_TILING_EXT, GL_LINEAR_TILING_EXT);
1321         }
1322         if (useMemoryObjectFlags)
1323         {
1324             glTexStorageMemFlags2DANGLE(GL_TEXTURE_2D, 1, GL_RGBA8, kWidth, kHeight, memoryObject,
1325                                         0, createFlags, usageFlags, nullptr);
1326         }
1327         else
1328         {
1329             glTexStorageMem2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, kWidth, kHeight, memoryObject, 0);
1330         }
1331 
1332         GLSemaphore glAcquireSemaphore;
1333         Traits::ImportSemaphore(glAcquireSemaphore, acquireSemaphoreHandle);
1334 
1335         // Note: writePixels leaves the image in TRANSFER_DST_OPTIMAL layout.
1336         helper.releaseImageAndSignalSemaphore(image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1337                                               VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1338                                               vkAcquireSemaphore);
1339 
1340         const GLuint barrierTexture   = texture;
1341         const GLenum textureSrcLayout = GL_LAYOUT_COLOR_ATTACHMENT_EXT;
1342         glWaitSemaphoreEXT(glAcquireSemaphore, 0, nullptr, 1, &barrierTexture, &textureSrcLayout);
1343 
1344         GLFramebuffer framebuffer;
1345         glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1346         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1347 
1348         // Readback the initialized pixel, ensure it contains the value written to it.
1349         uint32_t pixel = 0u;
1350         glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel);
1351         EXPECT_EQ(pixel, kPixel);
1352         EXPECT_GL_NO_ERROR();
1353 
1354         GLSemaphore glReleaseSemaphore;
1355         Traits::ImportSemaphore(glReleaseSemaphore, releaseSemaphoreHandle);
1356 
1357         const GLenum textureDstLayout = GL_LAYOUT_TRANSFER_SRC_EXT;
1358         glSignalSemaphoreEXT(glReleaseSemaphore, 0, nullptr, 1, &barrierTexture, &textureDstLayout);
1359 
1360         helper.waitSemaphoreAndAcquireImage(image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1361                                             VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1362                                             vkReleaseSemaphore);
1363     }
1364 
1365     EXPECT_GL_NO_ERROR();
1366 
1367     vkDeviceWaitIdle(helper.getDevice());
1368     vkDestroyImage(helper.getDevice(), image, nullptr);
1369     vkDestroySemaphore(helper.getDevice(), vkAcquireSemaphore, nullptr);
1370     vkDestroySemaphore(helper.getDevice(), vkReleaseSemaphore, nullptr);
1371     vkFreeMemory(helper.getDevice(), deviceMemory, nullptr);
1372 }
1373 
1374 // Test that texture storage created from VkImage memory can be considered pre-initialized in GL.
TEST_P(VulkanExternalImageTest,PreInitializedOnGLImport)1375 TEST_P(VulkanExternalImageTest, PreInitializedOnGLImport)
1376 {
1377     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
1378     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_semaphore_fd"));
1379 
1380     RunPreInitializedOnGLImportTest<OpaqueFdTraits>(false, VK_IMAGE_TILING_OPTIMAL, isSwiftshader(),
1381                                                     enableDebugLayers());
1382 }
1383 
1384 // Test that texture storage created from VkImage memory can be considered pre-initialized in GL.
1385 // Uses linear tiling.
TEST_P(VulkanExternalImageTest,PreInitializedOnGLImportLinear)1386 TEST_P(VulkanExternalImageTest, PreInitializedOnGLImportLinear)
1387 {
1388     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
1389     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_semaphore_fd"));
1390 
1391     RunPreInitializedOnGLImportTest<OpaqueFdTraits>(false, VK_IMAGE_TILING_LINEAR, isSwiftshader(),
1392                                                     enableDebugLayers());
1393 }
1394 
1395 // Test that texture storage created from VkImage memory can be considered pre-initialized in GL,
1396 // using GL_ANGLE_memory_object_flags.
TEST_P(VulkanExternalImageTest,PreInitializedOnGLImportWithFlags)1397 TEST_P(VulkanExternalImageTest, PreInitializedOnGLImportWithFlags)
1398 {
1399     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
1400     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_semaphore_fd"));
1401     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
1402 
1403     RunPreInitializedOnGLImportTest<OpaqueFdTraits>(true, VK_IMAGE_TILING_OPTIMAL, isSwiftshader(),
1404                                                     enableDebugLayers());
1405 }
1406 
1407 // Test that texture storage created from VkImage memory can be considered pre-initialized in GL,
1408 // using GL_ANGLE_memory_object_flags.  Uses linear tiling.
TEST_P(VulkanExternalImageTest,PreInitializedOnGLImportLinearWithFlags)1409 TEST_P(VulkanExternalImageTest, PreInitializedOnGLImportLinearWithFlags)
1410 {
1411     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
1412     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_semaphore_fd"));
1413     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
1414 
1415     RunPreInitializedOnGLImportTest<OpaqueFdTraits>(true, VK_IMAGE_TILING_LINEAR, isSwiftshader(),
1416                                                     enableDebugLayers());
1417 }
1418 
1419 template <typename Traits>
RunUninitializedOnGLImportTest(bool useMemoryObjectFlags,std::function<GLenum (GLuint)> useTexture,const uint32_t * expectInVulkan,bool isSwiftshader,bool enableDebugLayers)1420 void RunUninitializedOnGLImportTest(bool useMemoryObjectFlags,
1421                                     std::function<GLenum(GLuint)> useTexture,
1422                                     const uint32_t *expectInVulkan,
1423                                     bool isSwiftshader,
1424                                     bool enableDebugLayers)
1425 {
1426     ASSERT(EnsureGLExtensionEnabled(Traits::MemoryObjectExtension()));
1427     ASSERT(EnsureGLExtensionEnabled(Traits::SemaphoreExtension()));
1428 
1429     VkImageCreateFlags createFlags = kDefaultImageCreateFlags;
1430     VkImageUsageFlags usageFlags   = kDefaultImageUsageFlags;
1431 
1432     AdjustCreateFlags(useMemoryObjectFlags, &createFlags);
1433 
1434     VulkanHelper helper;
1435     helper.initialize(isSwiftshader, enableDebugLayers);
1436 
1437     VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
1438     ANGLE_SKIP_TEST_IF(!Traits::CanCreateImage(helper, format, VK_IMAGE_TYPE_2D,
1439                                                VK_IMAGE_TILING_OPTIMAL, createFlags, usageFlags));
1440     ANGLE_SKIP_TEST_IF(!Traits::CanCreateSemaphore(helper));
1441 
1442     VkSemaphore vkAcquireSemaphore = VK_NULL_HANDLE;
1443     VkResult result                = Traits::CreateSemaphore(&helper, &vkAcquireSemaphore);
1444     EXPECT_EQ(result, VK_SUCCESS);
1445     EXPECT_TRUE(vkAcquireSemaphore != VK_NULL_HANDLE);
1446 
1447     VkSemaphore vkReleaseSemaphore = VK_NULL_HANDLE;
1448     result                         = Traits::CreateSemaphore(&helper, &vkReleaseSemaphore);
1449     EXPECT_EQ(result, VK_SUCCESS);
1450     EXPECT_TRUE(vkReleaseSemaphore != VK_NULL_HANDLE);
1451 
1452     typename Traits::Handle acquireSemaphoreHandle = Traits::InvalidHandle();
1453     result = Traits::ExportSemaphore(&helper, vkAcquireSemaphore, &acquireSemaphoreHandle);
1454     EXPECT_EQ(result, VK_SUCCESS);
1455     EXPECT_NE(acquireSemaphoreHandle, Traits::InvalidHandle());
1456 
1457     typename Traits::Handle releaseSemaphoreHandle = Traits::InvalidHandle();
1458     result = Traits::ExportSemaphore(&helper, vkReleaseSemaphore, &releaseSemaphoreHandle);
1459     EXPECT_EQ(result, VK_SUCCESS);
1460     EXPECT_NE(releaseSemaphoreHandle, Traits::InvalidHandle());
1461 
1462     VkImage image                 = VK_NULL_HANDLE;
1463     VkDeviceMemory deviceMemory   = VK_NULL_HANDLE;
1464     VkDeviceSize deviceMemorySize = 0;
1465 
1466     VkExtent3D extent = {kWidth, kHeight, 1};
1467     result = Traits::CreateImage2D(&helper, format, createFlags, usageFlags, nullptr, extent,
1468                                    &image, &deviceMemory, &deviceMemorySize);
1469     EXPECT_EQ(result, VK_SUCCESS);
1470 
1471     typename Traits::Handle memoryHandle = Traits::InvalidHandle();
1472     result = Traits::ExportMemory(&helper, deviceMemory, &memoryHandle);
1473     EXPECT_EQ(result, VK_SUCCESS);
1474     EXPECT_NE(memoryHandle, Traits::InvalidHandle());
1475 
1476     {
1477         GLMemoryObject memoryObject;
1478         GLint dedicatedMemory = GL_TRUE;
1479         glMemoryObjectParameterivEXT(memoryObject, GL_DEDICATED_MEMORY_OBJECT_EXT,
1480                                      &dedicatedMemory);
1481         Traits::ImportMemory(memoryObject, deviceMemorySize, memoryHandle);
1482 
1483         GLTexture texture;
1484         glBindTexture(GL_TEXTURE_2D, texture);
1485         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1486         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1487         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1488         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1489         if (useMemoryObjectFlags)
1490         {
1491             glTexStorageMemFlags2DANGLE(GL_TEXTURE_2D, 1, GL_RGBA8, kWidth, kHeight, memoryObject,
1492                                         0, createFlags, usageFlags, nullptr);
1493         }
1494         else
1495         {
1496             glTexStorageMem2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, kWidth, kHeight, memoryObject, 0);
1497         }
1498 
1499         GLSemaphore glAcquireSemaphore;
1500         Traits::ImportSemaphore(glAcquireSemaphore, acquireSemaphoreHandle);
1501 
1502         // Submit the semaphore without touching the image
1503         helper.signalSemaphore(vkAcquireSemaphore);
1504 
1505         const GLuint barrierTexture   = texture;
1506         const GLenum textureSrcLayout = GL_NONE;
1507         glWaitSemaphoreEXT(glAcquireSemaphore, 0, nullptr, 1, &barrierTexture, &textureSrcLayout);
1508 
1509         GLSemaphore glReleaseSemaphore;
1510         Traits::ImportSemaphore(glReleaseSemaphore, releaseSemaphoreHandle);
1511 
1512         const GLenum textureDstLayout = useTexture(texture);
1513         glSignalSemaphoreEXT(glReleaseSemaphore, 0, nullptr, 1, &barrierTexture, &textureDstLayout);
1514 
1515         const VkImageLayout imageLayout = GetPostReleaseVulkanLayout(textureDstLayout);
1516         helper.waitSemaphoreAndAcquireImage(
1517             image, imageLayout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, vkReleaseSemaphore);
1518     }
1519 
1520     EXPECT_GL_NO_ERROR();
1521 
1522     // Verify the contents of the image from the Vulkan side too if needed
1523     if (expectInVulkan != nullptr)
1524     {
1525         uint8_t pixels[4];
1526         const VkOffset3D offset     = {};
1527         const VkExtent3D readExtent = {1, 1, 1};
1528         helper.readPixels(image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_FORMAT_R8G8B8A8_UNORM,
1529                           offset, readExtent, pixels, sizeof(pixels));
1530 
1531         const uint32_t pixel = pixels[0] | pixels[1] << 8 | pixels[2] << 16 | pixels[3] << 24;
1532 
1533         EXPECT_EQ(pixel, *expectInVulkan);
1534     }
1535 
1536     vkDeviceWaitIdle(helper.getDevice());
1537     vkDestroyImage(helper.getDevice(), image, nullptr);
1538     vkDestroySemaphore(helper.getDevice(), vkAcquireSemaphore, nullptr);
1539     vkDestroySemaphore(helper.getDevice(), vkReleaseSemaphore, nullptr);
1540     vkFreeMemory(helper.getDevice(), deviceMemory, nullptr);
1541 }
1542 
1543 // Test that texture storage created from VkImage memory can be imported as uninitialized in GL.
TEST_P(VulkanExternalImageTest,UninitializedOnGLImport)1544 TEST_P(VulkanExternalImageTest, UninitializedOnGLImport)
1545 {
1546     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
1547     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_semaphore_fd"));
1548 
1549     constexpr uint32_t kExpect = 0xFF0000FF;
1550 
1551     auto render = [kExpect](GLuint texture) {
1552         GLFramebuffer framebuffer;
1553         glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1554         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1555 
1556         glClearColor(1, 0, 0, 1);
1557         glClear(GL_COLOR_BUFFER_BIT);
1558 
1559         uint32_t pixel = 0u;
1560         glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel);
1561         EXPECT_GL_NO_ERROR();
1562 
1563         EXPECT_EQ(pixel, kExpect);
1564         EXPECT_GL_NO_ERROR();
1565 
1566         return GL_LAYOUT_TRANSFER_SRC_EXT;
1567     };
1568 
1569     RunUninitializedOnGLImportTest<OpaqueFdTraits>(false, render, &kExpect, isSwiftshader(),
1570                                                    enableDebugLayers());
1571 }
1572 
1573 // Test that texture storage created from VkImage memory can be imported as uninitialized in GL and
1574 // released without being touched.
TEST_P(VulkanExternalImageTest,UninitializedOnGLImportAndExport)1575 TEST_P(VulkanExternalImageTest, UninitializedOnGLImportAndExport)
1576 {
1577     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
1578     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_semaphore_fd"));
1579 
1580     auto doNothing = [](GLuint) { return GL_NONE; };
1581 
1582     RunUninitializedOnGLImportTest<OpaqueFdTraits>(false, doNothing, nullptr, isSwiftshader(),
1583                                                    enableDebugLayers());
1584 }
1585 
1586 // Test that texture storage created from VkImage memory can be imported as uninitialized in GL and
1587 // then used as the target of a copy.
TEST_P(VulkanExternalImageTest,UninitializedOnGLImportAndCopy)1588 TEST_P(VulkanExternalImageTest, UninitializedOnGLImportAndCopy)
1589 {
1590     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
1591     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_semaphore_fd"));
1592 
1593     constexpr uint32_t kExpect = 0xFF00FF00;
1594 
1595     auto copy = [kExpect](GLuint texture) {
1596         std::vector<GLColor> initData(kWidth * kHeight, GLColor::green);
1597         glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE,
1598                         initData.data());
1599 
1600         GLFramebuffer framebuffer;
1601         glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1602         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1603 
1604         uint32_t pixel = 0u;
1605         glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel);
1606         EXPECT_GL_NO_ERROR();
1607 
1608         EXPECT_EQ(pixel, kExpect);
1609         EXPECT_GL_NO_ERROR();
1610 
1611         return GL_LAYOUT_TRANSFER_SRC_EXT;
1612     };
1613 
1614     RunUninitializedOnGLImportTest<OpaqueFdTraits>(false, copy, &kExpect, isSwiftshader(),
1615                                                    enableDebugLayers());
1616 }
1617 
1618 // Test that texture storage created from VkImage memory can be imported as uninitialized in GL and
1619 // then used as sampler.  Because the image is initialized, sampled results would be garbage, so
1620 // this test is primarily ensuring no validation errors are generated.
TEST_P(VulkanExternalImageTest,UninitializedOnGLImportAndSample)1621 TEST_P(VulkanExternalImageTest, UninitializedOnGLImportAndSample)
1622 {
1623     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
1624     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_semaphore_fd"));
1625 
1626     auto sample = [this](GLuint texture) {
1627         GLProgram program;
1628         program.makeRaster(essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
1629         drawQuad(program, std::string(essl1_shaders::PositionAttrib()), 0.0f);
1630         EXPECT_GL_NO_ERROR();
1631 
1632         return GL_LAYOUT_SHADER_READ_ONLY_EXT;
1633     };
1634 
1635     RunUninitializedOnGLImportTest<OpaqueFdTraits>(false, sample, nullptr, isSwiftshader(),
1636                                                    enableDebugLayers());
1637 }
1638 
1639 // Test that texture storage created from VkImage memory can be imported as uninitialized in GL and
1640 // then used as storage image.
TEST_P(VulkanExternalImageTestES31,UninitializedOnGLImportAndStorageWrite)1641 TEST_P(VulkanExternalImageTestES31, UninitializedOnGLImportAndStorageWrite)
1642 {
1643     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
1644     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_semaphore_fd"));
1645 
1646     constexpr uint32_t kExpect = 0xFF00FFFF;
1647 
1648     auto storageWrite = [kExpect](GLuint texture) {
1649         constexpr char kCS[] = R"(#version 310 es
1650 layout(local_size_x=8, local_size_y=8) in;
1651 layout(rgba8) uniform highp writeonly image2D img;
1652 void main()
1653 {
1654     imageStore(img, ivec2(gl_GlobalInvocationID.xy), vec4(1, 1, 0, 1));
1655 })";
1656 
1657         GLProgram program;
1658         program.makeCompute(kCS);
1659         glUseProgram(program);
1660 
1661         glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
1662         glDispatchCompute(kWidth / 8, kHeight / 8, 1);
1663         EXPECT_GL_NO_ERROR();
1664 
1665         glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1666 
1667         GLFramebuffer framebuffer;
1668         glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1669         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1670 
1671         uint32_t pixel = 0u;
1672         glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel);
1673         EXPECT_GL_NO_ERROR();
1674 
1675         EXPECT_EQ(pixel, kExpect);
1676         EXPECT_GL_NO_ERROR();
1677 
1678         return GL_LAYOUT_TRANSFER_SRC_EXT;
1679     };
1680 
1681     RunUninitializedOnGLImportTest<OpaqueFdTraits>(false, storageWrite, &kExpect, isSwiftshader(),
1682                                                    enableDebugLayers());
1683 }
1684 
1685 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(VulkanExternalImageTest);
1686 ANGLE_INSTANTIATE_TEST_ES31(VulkanExternalImageTestES31);
1687 }  // namespace angle
1688