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::__anon91eea5720111::OpaqueFdTraits60 static Handle InvalidHandle() { return kInvalidFd; }
61
MemoryObjectExtensionangle::__anon91eea5720111::OpaqueFdTraits62 static const char *MemoryObjectExtension() { return "GL_EXT_memory_object_fd"; }
SemaphoreExtensionangle::__anon91eea5720111::OpaqueFdTraits63 static const char *SemaphoreExtension() { return "GL_EXT_semaphore_fd"; }
64
CanCreateSemaphoreangle::__anon91eea5720111::OpaqueFdTraits65 static bool CanCreateSemaphore(const VulkanHelper &helper)
66 {
67 return helper.canCreateSemaphoreOpaqueFd();
68 }
69
CreateSemaphoreangle::__anon91eea5720111::OpaqueFdTraits70 static VkResult CreateSemaphore(VulkanHelper *helper, VkSemaphore *semaphore)
71 {
72 return helper->createSemaphoreOpaqueFd(semaphore);
73 }
74
ExportSemaphoreangle::__anon91eea5720111::OpaqueFdTraits75 static VkResult ExportSemaphore(VulkanHelper *helper, VkSemaphore semaphore, Handle *handle)
76 {
77 return helper->exportSemaphoreOpaqueFd(semaphore, handle);
78 }
79
ImportSemaphoreangle::__anon91eea5720111::OpaqueFdTraits80 static void ImportSemaphore(GLuint semaphore, Handle handle)
81 {
82 glImportSemaphoreFdEXT(semaphore, GL_HANDLE_TYPE_OPAQUE_FD_EXT, handle);
83 }
84
CanCreateImageangle::__anon91eea5720111::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::__anon91eea5720111::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::__anon91eea5720111::OpaqueFdTraits110 static VkResult ExportMemory(VulkanHelper *helper, VkDeviceMemory deviceMemory, Handle *handle)
111 {
112 return helper->exportMemoryOpaqueFd(deviceMemory, handle);
113 }
114
ImportMemoryangle::__anon91eea5720111::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::__anon91eea5720111::FuchsiaTraits125 static Handle InvalidHandle() { return ZX_HANDLE_INVALID; }
126
MemoryObjectExtensionangle::__anon91eea5720111::FuchsiaTraits127 static const char *MemoryObjectExtension() { return "GL_ANGLE_memory_object_fuchsia"; }
SemaphoreExtensionangle::__anon91eea5720111::FuchsiaTraits128 static const char *SemaphoreExtension() { return "GL_ANGLE_semaphore_fuchsia"; }
129
CanCreateSemaphoreangle::__anon91eea5720111::FuchsiaTraits130 static bool CanCreateSemaphore(const VulkanHelper &helper)
131 {
132 return helper.canCreateSemaphoreZirconEvent();
133 }
134
CreateSemaphoreangle::__anon91eea5720111::FuchsiaTraits135 static VkResult CreateSemaphore(VulkanHelper *helper, VkSemaphore *semaphore)
136 {
137 return helper->createSemaphoreZirconEvent(semaphore);
138 }
139
ExportSemaphoreangle::__anon91eea5720111::FuchsiaTraits140 static VkResult ExportSemaphore(VulkanHelper *helper, VkSemaphore semaphore, Handle *handle)
141 {
142 return helper->exportSemaphoreZirconEvent(semaphore, handle);
143 }
144
ImportSemaphoreangle::__anon91eea5720111::FuchsiaTraits145 static void ImportSemaphore(GLuint semaphore, Handle handle)
146 {
147 glImportSemaphoreZirconHandleANGLE(semaphore, GL_HANDLE_TYPE_ZIRCON_EVENT_ANGLE, handle);
148 }
149
CanCreateImageangle::__anon91eea5720111::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::__anon91eea5720111::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::__anon91eea5720111::FuchsiaTraits175 static VkResult ExportMemory(VulkanHelper *helper, VkDeviceMemory deviceMemory, Handle *handle)
176 {
177 return helper->exportMemoryZirconVmo(deviceMemory, handle);
178 }
179
ImportMemoryangle::__anon91eea5720111::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://issuetracker.google.com/173004081
817 ANGLE_SKIP_TEST_IF(IsVulkan() && IsIntel() && IsLinux() &&
818 getEGLWindow()->isFeatureEnabled(Feature::AsyncCommandQueue));
819 // http://anglebug.com/42263923
820 ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
821
822 RunShouldClearWithSemaphoresTest<OpaqueFdTraits>(false, kDefaultImageCreateFlags,
823 kDefaultImageUsageFlags, isSwiftshader(),
824 enableDebugLayers());
825 }
826
827 // Test creating and clearing RGBA8 texture in opaque fd with acquire/release, using
828 // GL_ANGLE_memory_object_flags.
TEST_P(VulkanExternalImageTest,ShouldClearOpaqueFdWithSemaphoresWithFlags)829 TEST_P(VulkanExternalImageTest, ShouldClearOpaqueFdWithSemaphoresWithFlags)
830 {
831 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
832 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_semaphore_fd"));
833 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
834
835 // http://issuetracker.google.com/173004081
836 ANGLE_SKIP_TEST_IF(IsVulkan() && IsIntel() && IsLinux() &&
837 getEGLWindow()->isFeatureEnabled(Feature::AsyncCommandQueue));
838
839 RunShouldClearWithSemaphoresTest<OpaqueFdTraits>(true, kDefaultImageCreateFlags,
840 kDefaultImageUsageFlags, isSwiftshader(),
841 enableDebugLayers());
842 }
843
844 // Test creating and clearing RGBA8 texture without STORAGE usage in opaque fd with acquire/release.
TEST_P(VulkanExternalImageTest,ShouldClearOpaqueFdWithSemaphoresNoStorage)845 TEST_P(VulkanExternalImageTest, ShouldClearOpaqueFdWithSemaphoresNoStorage)
846 {
847 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
848 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_semaphore_fd"));
849 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
850
851 // http://issuetracker.google.com/173004081
852 ANGLE_SKIP_TEST_IF(IsVulkan() && IsIntel() && IsLinux() &&
853 getEGLWindow()->isFeatureEnabled(Feature::AsyncCommandQueue));
854
855 RunShouldClearWithSemaphoresTest<OpaqueFdTraits>(true, kDefaultImageCreateFlags,
856 kNoStorageImageUsageFlags, isSwiftshader(),
857 enableDebugLayers());
858 }
859
860 // Test creating and clearing RGBA8 texture without STORAGE usage but with MUTABLE in opaque fd with
861 // acquire/release.
TEST_P(VulkanExternalImageTest,ShouldClearOpaqueFdWithSemaphoresMutableNoStorage)862 TEST_P(VulkanExternalImageTest, ShouldClearOpaqueFdWithSemaphoresMutableNoStorage)
863 {
864 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
865 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_semaphore_fd"));
866 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
867
868 // http://issuetracker.google.com/173004081
869 ANGLE_SKIP_TEST_IF(IsVulkan() && IsIntel() && IsLinux() &&
870 getEGLWindow()->isFeatureEnabled(Feature::AsyncCommandQueue));
871
872 RunShouldClearWithSemaphoresTest<OpaqueFdTraits>(true, kMutableImageCreateFlags,
873 kNoStorageImageUsageFlags, isSwiftshader(),
874 enableDebugLayers());
875 }
876
877 // Test creating and clearing RGBA8 texture in zircon vmo with acquire/release.
TEST_P(VulkanExternalImageTest,ShouldClearZirconVmoWithSemaphores)878 TEST_P(VulkanExternalImageTest, ShouldClearZirconVmoWithSemaphores)
879 {
880 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_fuchsia"));
881 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_semaphore_fuchsia"));
882 RunShouldClearWithSemaphoresTest<FuchsiaTraits>(false, kDefaultImageCreateFlags,
883 kDefaultImageUsageFlags, isSwiftshader(),
884 enableDebugLayers());
885 }
886
887 // Test creating and clearing RGBA8 texture in zircon vmo with acquire/release, using
888 // GL_ANGLE_memory_object_flags.
TEST_P(VulkanExternalImageTest,ShouldClearZirconVmoWithSemaphoresWithFlags)889 TEST_P(VulkanExternalImageTest, ShouldClearZirconVmoWithSemaphoresWithFlags)
890 {
891 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_fuchsia"));
892 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_semaphore_fuchsia"));
893 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
894 RunShouldClearWithSemaphoresTest<FuchsiaTraits>(true, kDefaultImageCreateFlags,
895 kDefaultImageUsageFlags, isSwiftshader(),
896 enableDebugLayers());
897 }
898
899 // Test creating and clearing RGBA8 texture without STORAGE usage in zircon vmo with
900 // acquire/release.
TEST_P(VulkanExternalImageTest,ShouldClearZirconVmoWithSemaphoresNoStorage)901 TEST_P(VulkanExternalImageTest, ShouldClearZirconVmoWithSemaphoresNoStorage)
902 {
903 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_fuchsia"));
904 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_semaphore_fuchsia"));
905 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
906 RunShouldClearWithSemaphoresTest<FuchsiaTraits>(true, kDefaultImageCreateFlags,
907 kNoStorageImageUsageFlags, isSwiftshader(),
908 enableDebugLayers());
909 }
910
911 // Test creating and clearing RGBA8 texture without STORAGE usage but with MUTABLE in zircon vmo
912 // with acquire/release.
TEST_P(VulkanExternalImageTest,ShouldClearZirconVmoWithSemaphoresMutableNoStorage)913 TEST_P(VulkanExternalImageTest, ShouldClearZirconVmoWithSemaphoresMutableNoStorage)
914 {
915 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_fuchsia"));
916 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_semaphore_fuchsia"));
917 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
918 RunShouldClearWithSemaphoresTest<FuchsiaTraits>(true, kMutableImageCreateFlags,
919 kNoStorageImageUsageFlags, isSwiftshader(),
920 enableDebugLayers());
921 }
922
923 template <typename Traits>
runShouldDrawTest(bool isSwiftshader,bool enableDebugLayers)924 void VulkanExternalImageTest::runShouldDrawTest(bool isSwiftshader, bool enableDebugLayers)
925 {
926 ASSERT(EnsureGLExtensionEnabled(Traits::MemoryObjectExtension()));
927 ASSERT(EnsureGLExtensionEnabled(Traits::SemaphoreExtension()));
928
929 VulkanHelper helper;
930 helper.initialize(isSwiftshader, enableDebugLayers);
931
932 VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
933 ANGLE_SKIP_TEST_IF(!Traits::CanCreateImage(helper, format, VK_IMAGE_TYPE_2D,
934 VK_IMAGE_TILING_OPTIMAL, kDefaultImageCreateFlags,
935 kDefaultImageUsageFlags));
936 ANGLE_SKIP_TEST_IF(!Traits::CanCreateSemaphore(helper));
937
938 VkSemaphore vkAcquireSemaphore = VK_NULL_HANDLE;
939 VkResult result = Traits::CreateSemaphore(&helper, &vkAcquireSemaphore);
940 EXPECT_EQ(result, VK_SUCCESS);
941 EXPECT_TRUE(vkAcquireSemaphore != VK_NULL_HANDLE);
942
943 VkSemaphore vkReleaseSemaphore = VK_NULL_HANDLE;
944 result = Traits::CreateSemaphore(&helper, &vkReleaseSemaphore);
945 EXPECT_EQ(result, VK_SUCCESS);
946 EXPECT_TRUE(vkReleaseSemaphore != VK_NULL_HANDLE);
947
948 typename Traits::Handle acquireSemaphoreHandle = Traits::InvalidHandle();
949 result = Traits::ExportSemaphore(&helper, vkAcquireSemaphore, &acquireSemaphoreHandle);
950 EXPECT_EQ(result, VK_SUCCESS);
951 EXPECT_NE(acquireSemaphoreHandle, Traits::InvalidHandle());
952
953 typename Traits::Handle releaseSemaphoreHandle = Traits::InvalidHandle();
954 result = Traits::ExportSemaphore(&helper, vkReleaseSemaphore, &releaseSemaphoreHandle);
955 EXPECT_EQ(result, VK_SUCCESS);
956 EXPECT_NE(releaseSemaphoreHandle, Traits::InvalidHandle());
957
958 VkImage image = VK_NULL_HANDLE;
959 VkDeviceMemory deviceMemory = VK_NULL_HANDLE;
960 VkDeviceSize deviceMemorySize = 0;
961
962 VkExtent3D extent = {1, 1, 1};
963 result =
964 Traits::CreateImage2D(&helper, format, kDefaultImageCreateFlags, kDefaultImageUsageFlags,
965 nullptr, extent, &image, &deviceMemory, &deviceMemorySize);
966 EXPECT_EQ(result, VK_SUCCESS);
967
968 typename Traits::Handle memoryHandle = Traits::InvalidHandle();
969 result = Traits::ExportMemory(&helper, deviceMemory, &memoryHandle);
970 EXPECT_EQ(result, VK_SUCCESS);
971 EXPECT_NE(memoryHandle, Traits::InvalidHandle());
972
973 {
974 GLMemoryObject memoryObject;
975 GLint dedicatedMemory = GL_TRUE;
976 glMemoryObjectParameterivEXT(memoryObject, GL_DEDICATED_MEMORY_OBJECT_EXT,
977 &dedicatedMemory);
978 Traits::ImportMemory(memoryObject, deviceMemorySize, memoryHandle);
979
980 GLTexture texture;
981 glBindTexture(GL_TEXTURE_2D, texture);
982 glTexStorageMem2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, 1, 1, memoryObject, 0);
983
984 GLSemaphore glAcquireSemaphore;
985 Traits::ImportSemaphore(glAcquireSemaphore, acquireSemaphoreHandle);
986
987 // Transfer ownership to GL.
988 helper.releaseImageAndSignalSemaphore(image, VK_IMAGE_LAYOUT_UNDEFINED,
989 VK_IMAGE_LAYOUT_GENERAL, vkAcquireSemaphore);
990
991 const GLuint barrierTextures[] = {
992 texture,
993 };
994 constexpr uint32_t textureBarriersCount = std::extent<decltype(barrierTextures)>();
995 const GLenum textureSrcLayouts[] = {
996 GL_LAYOUT_GENERAL_EXT,
997 };
998 constexpr uint32_t textureSrcLayoutsCount = std::extent<decltype(textureSrcLayouts)>();
999 static_assert(textureBarriersCount == textureSrcLayoutsCount,
1000 "barrierTextures and textureSrcLayouts must be the same length");
1001 glWaitSemaphoreEXT(glAcquireSemaphore, 0, nullptr, textureBarriersCount, barrierTextures,
1002 textureSrcLayouts);
1003
1004 GLFramebuffer framebuffer;
1005 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1006 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1007 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1008
1009 // Make the texture red.
1010 ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
1011 drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.0f);
1012 EXPECT_GL_NO_ERROR();
1013
1014 // Transfer ownership back to test.
1015 GLSemaphore glReleaseSemaphore;
1016 Traits::ImportSemaphore(glReleaseSemaphore, releaseSemaphoreHandle);
1017
1018 const GLenum textureDstLayouts[] = {
1019 GL_LAYOUT_TRANSFER_SRC_EXT,
1020 };
1021 constexpr uint32_t textureDstLayoutsCount = std::extent<decltype(textureSrcLayouts)>();
1022 static_assert(textureBarriersCount == textureDstLayoutsCount,
1023 "barrierTextures and textureDstLayouts must be the same length");
1024 glSignalSemaphoreEXT(glReleaseSemaphore, 0, nullptr, textureBarriersCount, barrierTextures,
1025 textureDstLayouts);
1026
1027 helper.waitSemaphoreAndAcquireImage(image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1028 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1029 vkReleaseSemaphore);
1030
1031 uint8_t pixels[4];
1032 VkOffset3D offset = {};
1033 helper.readPixels(image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, format, offset, extent,
1034 pixels, sizeof(pixels));
1035
1036 EXPECT_EQ(0xFF, pixels[0]);
1037 EXPECT_EQ(0x00, pixels[1]);
1038 EXPECT_EQ(0x00, pixels[2]);
1039 EXPECT_EQ(0xFF, pixels[3]);
1040 }
1041
1042 EXPECT_GL_NO_ERROR();
1043
1044 vkDeviceWaitIdle(helper.getDevice());
1045 vkDestroyImage(helper.getDevice(), image, nullptr);
1046 vkDestroySemaphore(helper.getDevice(), vkAcquireSemaphore, nullptr);
1047 vkDestroySemaphore(helper.getDevice(), vkReleaseSemaphore, nullptr);
1048 vkFreeMemory(helper.getDevice(), deviceMemory, nullptr);
1049 }
1050
1051 // Test drawing to RGBA8 texture in opaque fd with acquire/release.
TEST_P(VulkanExternalImageTest,ShouldDrawOpaqueFdWithSemaphores)1052 TEST_P(VulkanExternalImageTest, ShouldDrawOpaqueFdWithSemaphores)
1053 {
1054 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
1055 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_semaphore_fd"));
1056
1057 // http://issuetracker.google.com/173004081
1058 ANGLE_SKIP_TEST_IF(IsVulkan() && IsIntel() && IsLinux() &&
1059 getEGLWindow()->isFeatureEnabled(Feature::AsyncCommandQueue));
1060 // http://anglebug.com/42263923
1061 ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
1062
1063 runShouldDrawTest<OpaqueFdTraits>(isSwiftshader(), enableDebugLayers());
1064 }
1065
1066 // Test drawing to RGBA8 texture in zircon vmo with acquire/release multiple times.
TEST_P(VulkanExternalImageTest,ShouldDrawZirconVmoWithSemaphores)1067 TEST_P(VulkanExternalImageTest, ShouldDrawZirconVmoWithSemaphores)
1068 {
1069 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_fuchsia"));
1070 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_semaphore_fuchsia"));
1071 runShouldDrawTest<FuchsiaTraits>(isSwiftshader(), enableDebugLayers());
1072 }
1073
1074 template <typename Traits>
runWaitSemaphoresRetainsContentTest(bool isSwiftshader,bool enableDebugLayers)1075 void VulkanExternalImageTest::runWaitSemaphoresRetainsContentTest(bool isSwiftshader,
1076 bool enableDebugLayers)
1077 {
1078 ASSERT(EnsureGLExtensionEnabled(Traits::MemoryObjectExtension()));
1079 ASSERT(EnsureGLExtensionEnabled(Traits::SemaphoreExtension()));
1080
1081 VulkanHelper helper;
1082 helper.initialize(isSwiftshader, enableDebugLayers);
1083
1084 VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
1085 ANGLE_SKIP_TEST_IF(!Traits::CanCreateImage(helper, format, VK_IMAGE_TYPE_2D,
1086 VK_IMAGE_TILING_OPTIMAL, kDefaultImageCreateFlags,
1087 kDefaultImageUsageFlags));
1088 ANGLE_SKIP_TEST_IF(!Traits::CanCreateSemaphore(helper));
1089
1090 VkSemaphore vkAcquireSemaphore = VK_NULL_HANDLE;
1091 VkResult result = Traits::CreateSemaphore(&helper, &vkAcquireSemaphore);
1092 EXPECT_EQ(result, VK_SUCCESS);
1093 EXPECT_TRUE(vkAcquireSemaphore != VK_NULL_HANDLE);
1094
1095 VkSemaphore vkReleaseSemaphore = VK_NULL_HANDLE;
1096 result = Traits::CreateSemaphore(&helper, &vkReleaseSemaphore);
1097 EXPECT_EQ(result, VK_SUCCESS);
1098 EXPECT_TRUE(vkReleaseSemaphore != VK_NULL_HANDLE);
1099
1100 typename Traits::Handle acquireSemaphoreHandle = Traits::InvalidHandle();
1101 result = Traits::ExportSemaphore(&helper, vkAcquireSemaphore, &acquireSemaphoreHandle);
1102 EXPECT_EQ(result, VK_SUCCESS);
1103 EXPECT_NE(acquireSemaphoreHandle, Traits::InvalidHandle());
1104
1105 typename Traits::Handle releaseSemaphoreHandle = Traits::InvalidHandle();
1106 result = Traits::ExportSemaphore(&helper, vkReleaseSemaphore, &releaseSemaphoreHandle);
1107 EXPECT_EQ(result, VK_SUCCESS);
1108 EXPECT_NE(releaseSemaphoreHandle, Traits::InvalidHandle());
1109
1110 VkImage image = VK_NULL_HANDLE;
1111 VkDeviceMemory deviceMemory = VK_NULL_HANDLE;
1112 VkDeviceSize deviceMemorySize = 0;
1113
1114 VkExtent3D extent = {kWidth, kHeight, 1};
1115 result =
1116 Traits::CreateImage2D(&helper, format, kDefaultImageCreateFlags, kDefaultImageUsageFlags,
1117 nullptr, extent, &image, &deviceMemory, &deviceMemorySize);
1118 EXPECT_EQ(result, VK_SUCCESS);
1119
1120 typename Traits::Handle memoryHandle = Traits::InvalidHandle();
1121 result = Traits::ExportMemory(&helper, deviceMemory, &memoryHandle);
1122 EXPECT_EQ(result, VK_SUCCESS);
1123 EXPECT_NE(memoryHandle, Traits::InvalidHandle());
1124
1125 {
1126 GLMemoryObject memoryObject;
1127 GLint dedicatedMemory = GL_TRUE;
1128 glMemoryObjectParameterivEXT(memoryObject, GL_DEDICATED_MEMORY_OBJECT_EXT,
1129 &dedicatedMemory);
1130 Traits::ImportMemory(memoryObject, deviceMemorySize, memoryHandle);
1131
1132 GLTexture texture;
1133 glBindTexture(GL_TEXTURE_2D, texture);
1134 glTexStorageMem2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, kWidth, kHeight, memoryObject, 0);
1135
1136 GLSemaphore glAcquireSemaphore;
1137 Traits::ImportSemaphore(glAcquireSemaphore, acquireSemaphoreHandle);
1138
1139 // Transfer ownership to GL.
1140 helper.releaseImageAndSignalSemaphore(image, VK_IMAGE_LAYOUT_UNDEFINED,
1141 VK_IMAGE_LAYOUT_GENERAL, vkAcquireSemaphore);
1142
1143 const GLuint barrierTextures[] = {
1144 texture,
1145 };
1146 constexpr uint32_t textureBarriersCount = std::extent<decltype(barrierTextures)>();
1147 const GLenum textureSrcLayouts[] = {
1148 GL_LAYOUT_GENERAL_EXT,
1149 };
1150 constexpr uint32_t textureSrcLayoutsCount = std::extent<decltype(textureSrcLayouts)>();
1151 static_assert(textureBarriersCount == textureSrcLayoutsCount,
1152 "barrierTextures and textureSrcLayouts must be the same length");
1153 glWaitSemaphoreEXT(glAcquireSemaphore, 0, nullptr, textureBarriersCount, barrierTextures,
1154 textureSrcLayouts);
1155
1156 GLFramebuffer framebuffer;
1157 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1158 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1159 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1160
1161 // Make the texture red.
1162 ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
1163 glViewport(0, 0, kWidth, kHeight);
1164 drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.0f);
1165 EXPECT_GL_NO_ERROR();
1166
1167 // Transfer ownership back to test.
1168 GLSemaphore glReleaseSemaphore;
1169 Traits::ImportSemaphore(glReleaseSemaphore, releaseSemaphoreHandle);
1170
1171 const GLenum textureDstLayouts[] = {
1172 GL_LAYOUT_TRANSFER_SRC_EXT,
1173 };
1174 constexpr uint32_t textureDstLayoutsCount = std::extent<decltype(textureSrcLayouts)>();
1175 static_assert(textureBarriersCount == textureDstLayoutsCount,
1176 "barrierTextures and textureDstLayouts must be the same length");
1177 glSignalSemaphoreEXT(glReleaseSemaphore, 0, nullptr, textureBarriersCount, barrierTextures,
1178 textureDstLayouts);
1179
1180 helper.waitSemaphoreAndAcquireImage(image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1181 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1182 vkReleaseSemaphore);
1183
1184 // Transfer ownership to GL again, and make sure the contents are preserved.
1185 helper.releaseImageAndSignalSemaphore(image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1186 VK_IMAGE_LAYOUT_GENERAL, vkAcquireSemaphore);
1187 glWaitSemaphoreEXT(glAcquireSemaphore, 0, nullptr, textureBarriersCount, barrierTextures,
1188 textureSrcLayouts);
1189
1190 // Blend green
1191 ANGLE_GL_PROGRAM(drawGreen, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
1192 glEnable(GL_BLEND);
1193 glBlendFunc(GL_ONE, GL_ONE);
1194 drawQuad(drawGreen, essl1_shaders::PositionAttrib(), 0.0f);
1195
1196 // Transfer ownership back to test
1197 glSignalSemaphoreEXT(glReleaseSemaphore, 0, nullptr, textureBarriersCount, barrierTextures,
1198 textureDstLayouts);
1199 helper.waitSemaphoreAndAcquireImage(image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1200 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1201 vkReleaseSemaphore);
1202
1203 uint8_t pixels[4 * kWidth * kHeight];
1204 VkOffset3D offset = {};
1205 helper.readPixels(image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, format, offset, extent,
1206 pixels, sizeof(pixels));
1207
1208 EXPECT_EQ(0xFF, pixels[0]);
1209 EXPECT_EQ(0xFF, pixels[1]);
1210 EXPECT_EQ(0x00, pixels[2]);
1211 EXPECT_EQ(0xFF, pixels[3]);
1212
1213 EXPECT_EQ(0xFF, pixels[4]);
1214 EXPECT_EQ(0xFF, pixels[5]);
1215 EXPECT_EQ(0x00, pixels[6]);
1216 EXPECT_EQ(0xFF, pixels[7]);
1217 }
1218
1219 EXPECT_GL_NO_ERROR();
1220
1221 vkDeviceWaitIdle(helper.getDevice());
1222 vkDestroyImage(helper.getDevice(), image, nullptr);
1223 vkDestroySemaphore(helper.getDevice(), vkAcquireSemaphore, nullptr);
1224 vkDestroySemaphore(helper.getDevice(), vkReleaseSemaphore, nullptr);
1225 vkFreeMemory(helper.getDevice(), deviceMemory, nullptr);
1226 }
1227
1228 // Test drawing to RGBA8 texture in opaque fd with acquire/release multiple times.
TEST_P(VulkanExternalImageTest,WaitSemaphoresRetainsContentOpaqueFd)1229 TEST_P(VulkanExternalImageTest, WaitSemaphoresRetainsContentOpaqueFd)
1230 {
1231 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
1232 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_semaphore_fd"));
1233
1234 // http://issuetracker.google.com/173004081
1235 ANGLE_SKIP_TEST_IF(IsVulkan() && IsIntel() && IsLinux() &&
1236 getEGLWindow()->isFeatureEnabled(Feature::AsyncCommandQueue));
1237 // http://anglebug.com/42263923
1238 ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
1239
1240 runWaitSemaphoresRetainsContentTest<OpaqueFdTraits>(isSwiftshader(), enableDebugLayers());
1241 }
1242
1243 // Test drawing to RGBA8 texture in zircon vmo with acquire/release multiple times.
TEST_P(VulkanExternalImageTest,WaitSemaphoresRetainsContentZirconVmo)1244 TEST_P(VulkanExternalImageTest, WaitSemaphoresRetainsContentZirconVmo)
1245 {
1246 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_fuchsia"));
1247 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_semaphore_fuchsia"));
1248 runWaitSemaphoresRetainsContentTest<FuchsiaTraits>(isSwiftshader(), enableDebugLayers());
1249 }
1250
1251 // Support for Zircon handle types is mandatory on Fuchsia.
TEST_P(VulkanExternalImageTest,ShouldSupportExternalHandlesFuchsia)1252 TEST_P(VulkanExternalImageTest, ShouldSupportExternalHandlesFuchsia)
1253 {
1254 ANGLE_SKIP_TEST_IF(!IsFuchsia());
1255 EXPECT_TRUE(EnsureGLExtensionEnabled("GL_ANGLE_memory_object_fuchsia"));
1256 EXPECT_TRUE(EnsureGLExtensionEnabled("GL_ANGLE_semaphore_fuchsia"));
1257 VulkanHelper helper;
1258 helper.initialize(isSwiftshader(), enableDebugLayers());
1259 EXPECT_TRUE(helper.canCreateSemaphoreZirconEvent());
1260 EXPECT_TRUE(helper.canCreateImageZirconVmo(VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_TYPE_2D,
1261 VK_IMAGE_TILING_OPTIMAL, kDefaultImageCreateFlags,
1262 kDefaultImageUsageFlags));
1263 }
1264
1265 template <typename Traits>
RunPreInitializedOnGLImportTest(bool useMemoryObjectFlags,VkImageTiling tiling,bool isSwiftshader,bool enableDebugLayers)1266 void RunPreInitializedOnGLImportTest(bool useMemoryObjectFlags,
1267 VkImageTiling tiling,
1268 bool isSwiftshader,
1269 bool enableDebugLayers)
1270 {
1271 ASSERT(EnsureGLExtensionEnabled(Traits::MemoryObjectExtension()));
1272 ASSERT(EnsureGLExtensionEnabled(Traits::SemaphoreExtension()));
1273
1274 VkImageCreateFlags createFlags = kDefaultImageCreateFlags;
1275 VkImageUsageFlags usageFlags = kDefaultImageUsageFlags;
1276
1277 AdjustCreateFlags(useMemoryObjectFlags, &createFlags);
1278
1279 VulkanHelper helper;
1280 helper.initialize(isSwiftshader, enableDebugLayers);
1281
1282 VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
1283 ANGLE_SKIP_TEST_IF(
1284 !Traits::CanCreateImage(helper, format, VK_IMAGE_TYPE_2D, tiling, createFlags, usageFlags));
1285 ANGLE_SKIP_TEST_IF(!Traits::CanCreateSemaphore(helper));
1286
1287 VkSemaphore vkAcquireSemaphore = VK_NULL_HANDLE;
1288 VkResult result = Traits::CreateSemaphore(&helper, &vkAcquireSemaphore);
1289 EXPECT_EQ(result, VK_SUCCESS);
1290 EXPECT_TRUE(vkAcquireSemaphore != VK_NULL_HANDLE);
1291
1292 VkSemaphore vkReleaseSemaphore = VK_NULL_HANDLE;
1293 result = Traits::CreateSemaphore(&helper, &vkReleaseSemaphore);
1294 EXPECT_EQ(result, VK_SUCCESS);
1295 EXPECT_TRUE(vkReleaseSemaphore != VK_NULL_HANDLE);
1296
1297 typename Traits::Handle acquireSemaphoreHandle = Traits::InvalidHandle();
1298 result = Traits::ExportSemaphore(&helper, vkAcquireSemaphore, &acquireSemaphoreHandle);
1299 EXPECT_EQ(result, VK_SUCCESS);
1300 EXPECT_NE(acquireSemaphoreHandle, Traits::InvalidHandle());
1301
1302 typename Traits::Handle releaseSemaphoreHandle = Traits::InvalidHandle();
1303 result = Traits::ExportSemaphore(&helper, vkReleaseSemaphore, &releaseSemaphoreHandle);
1304 EXPECT_EQ(result, VK_SUCCESS);
1305 EXPECT_NE(releaseSemaphoreHandle, Traits::InvalidHandle());
1306
1307 VkImage image = VK_NULL_HANDLE;
1308 VkDeviceMemory deviceMemory = VK_NULL_HANDLE;
1309 VkDeviceSize deviceMemorySize = 0;
1310
1311 VkExtent3D extent = {kWidth, kHeight, 1};
1312 result = Traits::CreateImage2D(&helper, format, createFlags, usageFlags, nullptr, extent,
1313 &image, &deviceMemory, &deviceMemorySize);
1314 EXPECT_EQ(result, VK_SUCCESS);
1315
1316 // Initialize a pixel in the image
1317 constexpr uint32_t kPixel = 0x12345678;
1318 helper.writePixels(image, VK_IMAGE_LAYOUT_UNDEFINED, VK_FORMAT_R8G8B8A8_UNORM, {0, 0, 0},
1319 {1, 1, 1}, static_cast<const void *>(&kPixel), sizeof(kPixel));
1320
1321 typename Traits::Handle memoryHandle = Traits::InvalidHandle();
1322 result = Traits::ExportMemory(&helper, deviceMemory, &memoryHandle);
1323 EXPECT_EQ(result, VK_SUCCESS);
1324 EXPECT_NE(memoryHandle, Traits::InvalidHandle());
1325
1326 {
1327 GLMemoryObject memoryObject;
1328 GLint dedicatedMemory = GL_TRUE;
1329 glMemoryObjectParameterivEXT(memoryObject, GL_DEDICATED_MEMORY_OBJECT_EXT,
1330 &dedicatedMemory);
1331 Traits::ImportMemory(memoryObject, deviceMemorySize, memoryHandle);
1332
1333 GLTexture texture;
1334 glBindTexture(GL_TEXTURE_2D, texture);
1335 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1336 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1337 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1338 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1339 if (tiling == VK_IMAGE_TILING_LINEAR)
1340 {
1341 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_TILING_EXT, GL_LINEAR_TILING_EXT);
1342 }
1343 if (useMemoryObjectFlags)
1344 {
1345 glTexStorageMemFlags2DANGLE(GL_TEXTURE_2D, 1, GL_RGBA8, kWidth, kHeight, memoryObject,
1346 0, createFlags, usageFlags, nullptr);
1347 }
1348 else
1349 {
1350 glTexStorageMem2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, kWidth, kHeight, memoryObject, 0);
1351 }
1352
1353 GLSemaphore glAcquireSemaphore;
1354 Traits::ImportSemaphore(glAcquireSemaphore, acquireSemaphoreHandle);
1355
1356 // Note: writePixels leaves the image in TRANSFER_DST_OPTIMAL layout.
1357 helper.releaseImageAndSignalSemaphore(image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1358 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1359 vkAcquireSemaphore);
1360
1361 const GLuint barrierTexture = texture;
1362 const GLenum textureSrcLayout = GL_LAYOUT_COLOR_ATTACHMENT_EXT;
1363 glWaitSemaphoreEXT(glAcquireSemaphore, 0, nullptr, 1, &barrierTexture, &textureSrcLayout);
1364
1365 GLFramebuffer framebuffer;
1366 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1367 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1368
1369 // Readback the initialized pixel, ensure it contains the value written to it.
1370 uint32_t pixel = 0u;
1371 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel);
1372 EXPECT_EQ(pixel, kPixel);
1373 EXPECT_GL_NO_ERROR();
1374
1375 GLSemaphore glReleaseSemaphore;
1376 Traits::ImportSemaphore(glReleaseSemaphore, releaseSemaphoreHandle);
1377
1378 const GLenum textureDstLayout = GL_LAYOUT_TRANSFER_SRC_EXT;
1379 glSignalSemaphoreEXT(glReleaseSemaphore, 0, nullptr, 1, &barrierTexture, &textureDstLayout);
1380
1381 helper.waitSemaphoreAndAcquireImage(image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1382 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1383 vkReleaseSemaphore);
1384 }
1385
1386 EXPECT_GL_NO_ERROR();
1387
1388 vkDeviceWaitIdle(helper.getDevice());
1389 vkDestroyImage(helper.getDevice(), image, nullptr);
1390 vkDestroySemaphore(helper.getDevice(), vkAcquireSemaphore, nullptr);
1391 vkDestroySemaphore(helper.getDevice(), vkReleaseSemaphore, nullptr);
1392 vkFreeMemory(helper.getDevice(), deviceMemory, nullptr);
1393 }
1394
1395 // Test that texture storage created from VkImage memory can be considered pre-initialized in GL.
TEST_P(VulkanExternalImageTest,PreInitializedOnGLImport)1396 TEST_P(VulkanExternalImageTest, PreInitializedOnGLImport)
1397 {
1398 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
1399 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_semaphore_fd"));
1400
1401 RunPreInitializedOnGLImportTest<OpaqueFdTraits>(false, VK_IMAGE_TILING_OPTIMAL, isSwiftshader(),
1402 enableDebugLayers());
1403 }
1404
1405 // Test that texture storage created from VkImage memory can be considered pre-initialized in GL.
1406 // Uses linear tiling.
TEST_P(VulkanExternalImageTest,PreInitializedOnGLImportLinear)1407 TEST_P(VulkanExternalImageTest, PreInitializedOnGLImportLinear)
1408 {
1409 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
1410 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_semaphore_fd"));
1411
1412 RunPreInitializedOnGLImportTest<OpaqueFdTraits>(false, VK_IMAGE_TILING_LINEAR, isSwiftshader(),
1413 enableDebugLayers());
1414 }
1415
1416 // Test that texture storage created from VkImage memory can be considered pre-initialized in GL,
1417 // using GL_ANGLE_memory_object_flags.
TEST_P(VulkanExternalImageTest,PreInitializedOnGLImportWithFlags)1418 TEST_P(VulkanExternalImageTest, PreInitializedOnGLImportWithFlags)
1419 {
1420 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
1421 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_semaphore_fd"));
1422 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
1423
1424 RunPreInitializedOnGLImportTest<OpaqueFdTraits>(true, VK_IMAGE_TILING_OPTIMAL, isSwiftshader(),
1425 enableDebugLayers());
1426 }
1427
1428 // Test that texture storage created from VkImage memory can be considered pre-initialized in GL,
1429 // using GL_ANGLE_memory_object_flags. Uses linear tiling.
TEST_P(VulkanExternalImageTest,PreInitializedOnGLImportLinearWithFlags)1430 TEST_P(VulkanExternalImageTest, PreInitializedOnGLImportLinearWithFlags)
1431 {
1432 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
1433 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_semaphore_fd"));
1434 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_memory_object_flags"));
1435
1436 RunPreInitializedOnGLImportTest<OpaqueFdTraits>(true, VK_IMAGE_TILING_LINEAR, isSwiftshader(),
1437 enableDebugLayers());
1438 }
1439
1440 template <typename Traits>
RunUninitializedOnGLImportTest(bool useMemoryObjectFlags,std::function<GLenum (GLuint)> useTexture,const uint32_t * expectInVulkan,bool isSwiftshader,bool enableDebugLayers)1441 void RunUninitializedOnGLImportTest(bool useMemoryObjectFlags,
1442 std::function<GLenum(GLuint)> useTexture,
1443 const uint32_t *expectInVulkan,
1444 bool isSwiftshader,
1445 bool enableDebugLayers)
1446 {
1447 ASSERT(EnsureGLExtensionEnabled(Traits::MemoryObjectExtension()));
1448 ASSERT(EnsureGLExtensionEnabled(Traits::SemaphoreExtension()));
1449
1450 VkImageCreateFlags createFlags = kDefaultImageCreateFlags;
1451 VkImageUsageFlags usageFlags = kDefaultImageUsageFlags;
1452
1453 AdjustCreateFlags(useMemoryObjectFlags, &createFlags);
1454
1455 VulkanHelper helper;
1456 helper.initialize(isSwiftshader, enableDebugLayers);
1457
1458 VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
1459 ANGLE_SKIP_TEST_IF(!Traits::CanCreateImage(helper, format, VK_IMAGE_TYPE_2D,
1460 VK_IMAGE_TILING_OPTIMAL, createFlags, usageFlags));
1461 ANGLE_SKIP_TEST_IF(!Traits::CanCreateSemaphore(helper));
1462
1463 VkSemaphore vkAcquireSemaphore = VK_NULL_HANDLE;
1464 VkResult result = Traits::CreateSemaphore(&helper, &vkAcquireSemaphore);
1465 EXPECT_EQ(result, VK_SUCCESS);
1466 EXPECT_TRUE(vkAcquireSemaphore != VK_NULL_HANDLE);
1467
1468 VkSemaphore vkReleaseSemaphore = VK_NULL_HANDLE;
1469 result = Traits::CreateSemaphore(&helper, &vkReleaseSemaphore);
1470 EXPECT_EQ(result, VK_SUCCESS);
1471 EXPECT_TRUE(vkReleaseSemaphore != VK_NULL_HANDLE);
1472
1473 typename Traits::Handle acquireSemaphoreHandle = Traits::InvalidHandle();
1474 result = Traits::ExportSemaphore(&helper, vkAcquireSemaphore, &acquireSemaphoreHandle);
1475 EXPECT_EQ(result, VK_SUCCESS);
1476 EXPECT_NE(acquireSemaphoreHandle, Traits::InvalidHandle());
1477
1478 typename Traits::Handle releaseSemaphoreHandle = Traits::InvalidHandle();
1479 result = Traits::ExportSemaphore(&helper, vkReleaseSemaphore, &releaseSemaphoreHandle);
1480 EXPECT_EQ(result, VK_SUCCESS);
1481 EXPECT_NE(releaseSemaphoreHandle, Traits::InvalidHandle());
1482
1483 VkImage image = VK_NULL_HANDLE;
1484 VkDeviceMemory deviceMemory = VK_NULL_HANDLE;
1485 VkDeviceSize deviceMemorySize = 0;
1486
1487 VkExtent3D extent = {kWidth, kHeight, 1};
1488 result = Traits::CreateImage2D(&helper, format, createFlags, usageFlags, nullptr, extent,
1489 &image, &deviceMemory, &deviceMemorySize);
1490 EXPECT_EQ(result, VK_SUCCESS);
1491
1492 typename Traits::Handle memoryHandle = Traits::InvalidHandle();
1493 result = Traits::ExportMemory(&helper, deviceMemory, &memoryHandle);
1494 EXPECT_EQ(result, VK_SUCCESS);
1495 EXPECT_NE(memoryHandle, Traits::InvalidHandle());
1496
1497 {
1498 GLMemoryObject memoryObject;
1499 GLint dedicatedMemory = GL_TRUE;
1500 glMemoryObjectParameterivEXT(memoryObject, GL_DEDICATED_MEMORY_OBJECT_EXT,
1501 &dedicatedMemory);
1502 Traits::ImportMemory(memoryObject, deviceMemorySize, memoryHandle);
1503
1504 GLTexture texture;
1505 glBindTexture(GL_TEXTURE_2D, texture);
1506 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1507 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1508 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1509 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1510 if (useMemoryObjectFlags)
1511 {
1512 glTexStorageMemFlags2DANGLE(GL_TEXTURE_2D, 1, GL_RGBA8, kWidth, kHeight, memoryObject,
1513 0, createFlags, usageFlags, nullptr);
1514 }
1515 else
1516 {
1517 glTexStorageMem2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, kWidth, kHeight, memoryObject, 0);
1518 }
1519
1520 GLSemaphore glAcquireSemaphore;
1521 Traits::ImportSemaphore(glAcquireSemaphore, acquireSemaphoreHandle);
1522
1523 // Submit the semaphore without touching the image
1524 helper.signalSemaphore(vkAcquireSemaphore);
1525
1526 const GLuint barrierTexture = texture;
1527 const GLenum textureSrcLayout = GL_NONE;
1528 glWaitSemaphoreEXT(glAcquireSemaphore, 0, nullptr, 1, &barrierTexture, &textureSrcLayout);
1529
1530 GLSemaphore glReleaseSemaphore;
1531 Traits::ImportSemaphore(glReleaseSemaphore, releaseSemaphoreHandle);
1532
1533 const GLenum textureDstLayout = useTexture(texture);
1534 glSignalSemaphoreEXT(glReleaseSemaphore, 0, nullptr, 1, &barrierTexture, &textureDstLayout);
1535
1536 const VkImageLayout imageLayout = GetPostReleaseVulkanLayout(textureDstLayout);
1537 helper.waitSemaphoreAndAcquireImage(
1538 image, imageLayout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, vkReleaseSemaphore);
1539 }
1540
1541 EXPECT_GL_NO_ERROR();
1542
1543 // Verify the contents of the image from the Vulkan side too if needed
1544 if (expectInVulkan != nullptr)
1545 {
1546 uint8_t pixels[4];
1547 const VkOffset3D offset = {};
1548 const VkExtent3D readExtent = {1, 1, 1};
1549 helper.readPixels(image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_FORMAT_R8G8B8A8_UNORM,
1550 offset, readExtent, pixels, sizeof(pixels));
1551
1552 const uint32_t pixel = pixels[0] | pixels[1] << 8 | pixels[2] << 16 | pixels[3] << 24;
1553
1554 EXPECT_EQ(pixel, *expectInVulkan);
1555 }
1556
1557 vkDeviceWaitIdle(helper.getDevice());
1558 vkDestroyImage(helper.getDevice(), image, nullptr);
1559 vkDestroySemaphore(helper.getDevice(), vkAcquireSemaphore, nullptr);
1560 vkDestroySemaphore(helper.getDevice(), vkReleaseSemaphore, nullptr);
1561 vkFreeMemory(helper.getDevice(), deviceMemory, nullptr);
1562 }
1563
1564 // Test that texture storage created from VkImage memory can be imported as uninitialized in GL.
TEST_P(VulkanExternalImageTest,UninitializedOnGLImport)1565 TEST_P(VulkanExternalImageTest, UninitializedOnGLImport)
1566 {
1567 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
1568 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_semaphore_fd"));
1569
1570 constexpr uint32_t kExpect = 0xFF0000FF;
1571
1572 auto render = [kExpect](GLuint texture) {
1573 GLFramebuffer framebuffer;
1574 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1575 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1576
1577 glClearColor(1, 0, 0, 1);
1578 glClear(GL_COLOR_BUFFER_BIT);
1579
1580 uint32_t pixel = 0u;
1581 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel);
1582 EXPECT_GL_NO_ERROR();
1583
1584 EXPECT_EQ(pixel, kExpect);
1585 EXPECT_GL_NO_ERROR();
1586
1587 return GL_LAYOUT_TRANSFER_SRC_EXT;
1588 };
1589
1590 RunUninitializedOnGLImportTest<OpaqueFdTraits>(false, render, &kExpect, isSwiftshader(),
1591 enableDebugLayers());
1592 }
1593
1594 // Test that texture storage created from VkImage memory can be imported as uninitialized in GL and
1595 // released without being touched.
TEST_P(VulkanExternalImageTest,UninitializedOnGLImportAndExport)1596 TEST_P(VulkanExternalImageTest, UninitializedOnGLImportAndExport)
1597 {
1598 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
1599 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_semaphore_fd"));
1600
1601 auto doNothing = [](GLuint) { return GL_NONE; };
1602
1603 RunUninitializedOnGLImportTest<OpaqueFdTraits>(false, doNothing, nullptr, isSwiftshader(),
1604 enableDebugLayers());
1605 }
1606
1607 // Test that texture storage created from VkImage memory can be imported as uninitialized in GL and
1608 // then used as the target of a copy.
TEST_P(VulkanExternalImageTest,UninitializedOnGLImportAndCopy)1609 TEST_P(VulkanExternalImageTest, UninitializedOnGLImportAndCopy)
1610 {
1611 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
1612 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_semaphore_fd"));
1613
1614 constexpr uint32_t kExpect = 0xFF00FF00;
1615
1616 auto copy = [kExpect](GLuint texture) {
1617 std::vector<GLColor> initData(kWidth * kHeight, GLColor::green);
1618 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE,
1619 initData.data());
1620
1621 GLFramebuffer framebuffer;
1622 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1623 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1624
1625 uint32_t pixel = 0u;
1626 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel);
1627 EXPECT_GL_NO_ERROR();
1628
1629 EXPECT_EQ(pixel, kExpect);
1630 EXPECT_GL_NO_ERROR();
1631
1632 return GL_LAYOUT_TRANSFER_SRC_EXT;
1633 };
1634
1635 RunUninitializedOnGLImportTest<OpaqueFdTraits>(false, copy, &kExpect, 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 sampler. Because the image is initialized, sampled results would be garbage, so
1641 // this test is primarily ensuring no validation errors are generated.
TEST_P(VulkanExternalImageTest,UninitializedOnGLImportAndSample)1642 TEST_P(VulkanExternalImageTest, UninitializedOnGLImportAndSample)
1643 {
1644 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
1645 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_semaphore_fd"));
1646
1647 auto sample = [this](GLuint texture) {
1648 GLProgram program;
1649 program.makeRaster(essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
1650 drawQuad(program, std::string(essl1_shaders::PositionAttrib()), 0.0f);
1651 EXPECT_GL_NO_ERROR();
1652
1653 return GL_LAYOUT_SHADER_READ_ONLY_EXT;
1654 };
1655
1656 RunUninitializedOnGLImportTest<OpaqueFdTraits>(false, sample, nullptr, isSwiftshader(),
1657 enableDebugLayers());
1658 }
1659
1660 // Test that texture storage created from VkImage memory can be imported as uninitialized in GL and
1661 // then used as storage image.
TEST_P(VulkanExternalImageTestES31,UninitializedOnGLImportAndStorageWrite)1662 TEST_P(VulkanExternalImageTestES31, UninitializedOnGLImportAndStorageWrite)
1663 {
1664 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object_fd"));
1665 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_semaphore_fd"));
1666
1667 constexpr uint32_t kExpect = 0xFF00FFFF;
1668
1669 auto storageWrite = [kExpect](GLuint texture) {
1670 constexpr char kCS[] = R"(#version 310 es
1671 layout(local_size_x=8, local_size_y=8) in;
1672 layout(rgba8) uniform highp writeonly image2D img;
1673 void main()
1674 {
1675 imageStore(img, ivec2(gl_GlobalInvocationID.xy), vec4(1, 1, 0, 1));
1676 })";
1677
1678 GLProgram program;
1679 program.makeCompute(kCS);
1680 glUseProgram(program);
1681
1682 glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
1683 glDispatchCompute(kWidth / 8, kHeight / 8, 1);
1684 EXPECT_GL_NO_ERROR();
1685
1686 glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
1687
1688 GLFramebuffer framebuffer;
1689 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1690 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1691
1692 uint32_t pixel = 0u;
1693 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel);
1694 EXPECT_GL_NO_ERROR();
1695
1696 EXPECT_EQ(pixel, kExpect);
1697 EXPECT_GL_NO_ERROR();
1698
1699 return GL_LAYOUT_TRANSFER_SRC_EXT;
1700 };
1701
1702 RunUninitializedOnGLImportTest<OpaqueFdTraits>(false, storageWrite, &kExpect, isSwiftshader(),
1703 enableDebugLayers());
1704 }
1705
1706 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(VulkanExternalImageTest);
1707 ANGLE_INSTANTIATE_TEST_ES31(VulkanExternalImageTestES31);
1708 } // namespace angle
1709