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