• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2021 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 // VulkanImageTest.cpp : Tests of EGL_ANGLE_vulkan_image & GL_ANGLE_vulkan_image extensions.
8 
9 #include "test_utils/ANGLETest.h"
10 
11 #include "common/debug.h"
12 #include "test_utils/VulkanHelper.h"
13 #include "test_utils/angle_test_instantiate.h"
14 #include "test_utils/gl_raii.h"
15 
16 namespace angle
17 {
18 
19 constexpr GLuint kWidth  = 64u;
20 constexpr GLuint kHeight = 64u;
21 constexpr GLuint kWhite  = 0xffffffff;
22 constexpr GLuint kRed    = 0xff0000ff;
23 
24 class VulkanImageTest : public ANGLETest
25 {
26   protected:
VulkanImageTest()27     VulkanImageTest() { setRobustResourceInit(true); }
28 };
29 
30 // Check extensions with Vukan backend.
TEST_P(VulkanImageTest,HasVulkanImageExtensions)31 TEST_P(VulkanImageTest, HasVulkanImageExtensions)
32 {
33     ANGLE_SKIP_TEST_IF(!IsVulkan());
34 
35     EGLWindow *window  = getEGLWindow();
36     EGLDisplay display = window->getDisplay();
37 
38     EXPECT_TRUE(IsEGLClientExtensionEnabled("EGL_EXT_device_query"));
39     EXPECT_TRUE(IsEGLDisplayExtensionEnabled(display, "EGL_ANGLE_vulkan_image"));
40     EXPECT_TRUE(IsGLExtensionEnabled("GL_ANGLE_vulkan_image"));
41 
42     EGLAttrib result = 0;
43     EXPECT_EGL_TRUE(eglQueryDisplayAttribEXT(display, EGL_DEVICE_EXT, &result));
44 
45     EGLDeviceEXT device = reinterpret_cast<EGLDeviceEXT>(result);
46     EXPECT_NE(EGL_NO_DEVICE_EXT, device);
47     EXPECT_TRUE(IsEGLDeviceExtensionEnabled(device, "EGL_ANGLE_device_vulkan"));
48 }
49 
TEST_P(VulkanImageTest,DeviceVulkan)50 TEST_P(VulkanImageTest, DeviceVulkan)
51 {
52     ANGLE_SKIP_TEST_IF(!IsVulkan());
53 
54     EGLWindow *window  = getEGLWindow();
55     EGLDisplay display = window->getDisplay();
56 
57     EGLAttrib result = 0;
58     EXPECT_EGL_TRUE(eglQueryDisplayAttribEXT(display, EGL_DEVICE_EXT, &result));
59 
60     EGLDeviceEXT device = reinterpret_cast<EGLDeviceEXT>(result);
61     EXPECT_NE(EGL_NO_DEVICE_EXT, device);
62 
63     EXPECT_EGL_TRUE(eglQueryDeviceAttribEXT(device, EGL_VULKAN_INSTANCE_ANGLE, &result));
64     VkInstance instance = reinterpret_cast<VkInstance>(result);
65     EXPECT_NE(instance, static_cast<VkInstance>(VK_NULL_HANDLE));
66 
67     EXPECT_EGL_TRUE(eglQueryDeviceAttribEXT(device, EGL_VULKAN_PHYSICAL_DEVICE_ANGLE, &result));
68     VkPhysicalDevice physical_device = reinterpret_cast<VkPhysicalDevice>(result);
69     EXPECT_NE(physical_device, static_cast<VkPhysicalDevice>(VK_NULL_HANDLE));
70 
71     EXPECT_EGL_TRUE(eglQueryDeviceAttribEXT(device, EGL_VULKAN_DEVICE_ANGLE, &result));
72     VkDevice vk_device = reinterpret_cast<VkDevice>(result);
73     EXPECT_NE(vk_device, static_cast<VkDevice>(VK_NULL_HANDLE));
74 
75     EXPECT_EGL_TRUE(eglQueryDeviceAttribEXT(device, EGL_VULKAN_QUEUE_ANGLE, &result));
76     VkQueue queue = reinterpret_cast<VkQueue>(result);
77     EXPECT_NE(queue, static_cast<VkQueue>(VK_NULL_HANDLE));
78 
79     EXPECT_EGL_TRUE(eglQueryDeviceAttribEXT(device, EGL_VULKAN_QUEUE_FAMILIY_INDEX_ANGLE, &result));
80 
81     {
82         EXPECT_EGL_TRUE(
83             eglQueryDeviceAttribEXT(device, EGL_VULKAN_DEVICE_EXTENSIONS_ANGLE, &result));
84         const char *const *extensions = reinterpret_cast<const char *const *>(result);
85         EXPECT_NE(extensions, nullptr);
86         int extension_count = 0;
87         while (extensions[extension_count])
88         {
89             extension_count++;
90         }
91         EXPECT_NE(extension_count, 0);
92     }
93 
94     {
95         EXPECT_EGL_TRUE(
96             eglQueryDeviceAttribEXT(device, EGL_VULKAN_INSTANCE_EXTENSIONS_ANGLE, &result));
97         const char *const *extensions = reinterpret_cast<const char *const *>(result);
98         EXPECT_NE(extensions, nullptr);
99         int extension_count = 0;
100         while (extensions[extension_count])
101         {
102             extension_count++;
103         }
104         EXPECT_NE(extension_count, 0);
105     }
106 
107     EXPECT_EGL_TRUE(eglQueryDeviceAttribEXT(device, EGL_VULKAN_FEATURES_ANGLE, &result));
108     const VkPhysicalDeviceFeatures2KHR *features =
109         reinterpret_cast<const VkPhysicalDeviceFeatures2KHR *>(result);
110     EXPECT_NE(features, nullptr);
111     EXPECT_EQ(features->sType, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2);
112 
113     EXPECT_EGL_TRUE(eglQueryDeviceAttribEXT(device, EGL_VULKAN_GET_INSTANCE_PROC_ADDR, &result));
114     PFN_vkGetInstanceProcAddr get_instance_proc_addr =
115         reinterpret_cast<PFN_vkGetInstanceProcAddr>(result);
116     EXPECT_NE(get_instance_proc_addr, nullptr);
117 }
118 
TEST_P(VulkanImageTest,ExportVKImage)119 TEST_P(VulkanImageTest, ExportVKImage)
120 {
121     EGLWindow *window  = getEGLWindow();
122     EGLDisplay display = window->getDisplay();
123     ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(display, "EGL_ANGLE_vulkan_image"));
124 
125     GLTexture texture;
126     glBindTexture(GL_TEXTURE_2D, texture);
127     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
128     glBindTexture(GL_TEXTURE_2D, 0);
129     EXPECT_GL_NO_ERROR();
130 
131     EGLContext context   = window->getContext();
132     EGLImageKHR eglImage = eglCreateImageKHR(
133         display, context, EGL_GL_TEXTURE_2D_KHR,
134         reinterpret_cast<EGLClientBuffer>(static_cast<uintptr_t>(texture)), nullptr);
135     EXPECT_NE(eglImage, EGL_NO_IMAGE_KHR);
136 
137     VkImage vkImage        = VK_NULL_HANDLE;
138     VkImageCreateInfo info = {};
139     EXPECT_EGL_TRUE(eglExportVkImageANGLE(display, eglImage, &vkImage, &info));
140     EXPECT_NE(vkImage, static_cast<VkImage>(VK_NULL_HANDLE));
141     EXPECT_EQ(info.sType, VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO);
142     EXPECT_EQ(info.pNext, nullptr);
143     EXPECT_EQ(info.imageType, VK_IMAGE_TYPE_2D);
144     EXPECT_EQ(info.format, VK_FORMAT_R8G8B8A8_UNORM);
145     EXPECT_EQ(info.extent.width, kWidth);
146     EXPECT_EQ(info.extent.height, kHeight);
147     EXPECT_EQ(info.extent.depth, 1u);
148     EXPECT_EQ(info.queueFamilyIndexCount, 0u);
149     EXPECT_EQ(info.pQueueFamilyIndices, nullptr);
150     EXPECT_EQ(info.initialLayout, VK_IMAGE_LAYOUT_UNDEFINED);
151 
152     EXPECT_EGL_TRUE(eglDestroyImageKHR(display, eglImage));
153 }
154 
155 // Check pixels after glTexImage2D
TEST_P(VulkanImageTest,PixelTestTexImage2D)156 TEST_P(VulkanImageTest, PixelTestTexImage2D)
157 {
158     EGLWindow *window  = getEGLWindow();
159     EGLDisplay display = window->getDisplay();
160 
161     ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(display, "EGL_ANGLE_vulkan_image"));
162 
163     VulkanHelper helper;
164     helper.initializeFromANGLE();
165 
166     constexpr GLuint kColor = 0xafbfcfdf;
167 
168     GLTexture texture;
169 
170     {
171         glBindTexture(GL_TEXTURE_2D, texture);
172         std::vector<GLuint> pixels(kWidth * kHeight, kColor);
173         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
174                      pixels.data());
175         glBindTexture(GL_TEXTURE_2D, 0);
176     }
177 
178     EGLContext context   = window->getContext();
179     EGLImageKHR eglImage = eglCreateImageKHR(
180         display, context, EGL_GL_TEXTURE_2D_KHR,
181         reinterpret_cast<EGLClientBuffer>(static_cast<uintptr_t>(texture)), nullptr);
182     EXPECT_NE(eglImage, EGL_NO_IMAGE_KHR);
183 
184     VkImage vkImage        = VK_NULL_HANDLE;
185     VkImageCreateInfo info = {};
186     EXPECT_EGL_TRUE(eglExportVkImageANGLE(display, eglImage, &vkImage, &info));
187     EXPECT_NE(vkImage, static_cast<VkImage>(VK_NULL_HANDLE));
188 
189     GLuint textures[1] = {texture};
190     GLenum layouts[1]  = {GL_NONE};
191     glReleaseTexturesANGLE(1, textures, layouts);
192     EXPECT_EQ(layouts[0], static_cast<GLenum>(GL_LAYOUT_TRANSFER_DST_EXT));
193 
194     {
195         std::vector<GLuint> pixels(kWidth * kHeight);
196         helper.readPixels(vkImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, info.format, {},
197                           info.extent, pixels.data(), pixels.size() * sizeof(GLuint));
198         EXPECT_EQ(pixels, std::vector<GLuint>(kWidth * kHeight, kColor));
199     }
200 
201     layouts[0] = GL_LAYOUT_TRANSFER_SRC_EXT;
202     glAcquireTexturesANGLE(1, textures, layouts);
203 
204     EXPECT_GL_NO_ERROR();
205     EXPECT_EGL_TRUE(eglDestroyImageKHR(display, eglImage));
206 }
207 
208 // Check pixels after glClear
TEST_P(VulkanImageTest,PixelTestClear)209 TEST_P(VulkanImageTest, PixelTestClear)
210 {
211     EGLWindow *window  = getEGLWindow();
212     EGLDisplay display = window->getDisplay();
213 
214     ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(display, "EGL_ANGLE_vulkan_image"));
215 
216     VulkanHelper helper;
217     helper.initializeFromANGLE();
218 
219     GLTexture texture;
220     glBindTexture(GL_TEXTURE_2D, texture);
221     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
222     glBindTexture(GL_TEXTURE_2D, 0);
223 
224     EGLContext context   = window->getContext();
225     EGLImageKHR eglImage = eglCreateImageKHR(
226         display, context, EGL_GL_TEXTURE_2D_KHR,
227         reinterpret_cast<EGLClientBuffer>(static_cast<uintptr_t>(texture)), nullptr);
228     EXPECT_NE(eglImage, EGL_NO_IMAGE_KHR);
229 
230     VkImage vkImage        = VK_NULL_HANDLE;
231     VkImageCreateInfo info = {};
232     EXPECT_EGL_TRUE(eglExportVkImageANGLE(display, eglImage, &vkImage, &info));
233     EXPECT_NE(vkImage, static_cast<VkImage>(VK_NULL_HANDLE));
234 
235     GLFramebuffer framebuffer;
236     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
237     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
238     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
239 
240     glViewport(0, 0, kWidth, kHeight);
241     // clear framebuffer with white color.
242     glClearColor(1.f, 1.f, 1.f, 1.f);
243     glClear(GL_COLOR_BUFFER_BIT);
244 
245     GLuint textures[1] = {texture};
246     GLenum layouts[1]  = {GL_NONE};
247     glReleaseTexturesANGLE(1, textures, layouts);
248     EXPECT_EQ(layouts[0], static_cast<GLenum>(GL_LAYOUT_TRANSFER_DST_EXT));
249 
250     std::vector<GLuint> pixels(kWidth * kHeight);
251     helper.readPixels(vkImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, info.format, {}, info.extent,
252                       pixels.data(), pixels.size() * sizeof(GLuint));
253     EXPECT_EQ(pixels, std::vector<GLuint>(kWidth * kHeight, kWhite));
254 
255     layouts[0] = GL_LAYOUT_TRANSFER_SRC_EXT;
256     glAcquireTexturesANGLE(1, textures, layouts);
257 
258     // clear framebuffer with red color.
259     glClearColor(1.f, 0.f, 0.f, 1.f);
260     glClear(GL_COLOR_BUFFER_BIT);
261 
262     glReleaseTexturesANGLE(1, textures, layouts);
263     EXPECT_EQ(layouts[0], static_cast<GLenum>(GL_LAYOUT_TRANSFER_DST_EXT));
264 
265     helper.readPixels(vkImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, info.format, {}, info.extent,
266                       pixels.data(), pixels.size() * sizeof(GLuint));
267     EXPECT_EQ(pixels, std::vector<GLuint>(kWidth * kHeight, kRed));
268 
269     layouts[0] = GL_LAYOUT_TRANSFER_SRC_EXT;
270     glAcquireTexturesANGLE(1, textures, layouts);
271 
272     EXPECT_GL_NO_ERROR();
273     EXPECT_EGL_TRUE(eglDestroyImageKHR(display, eglImage));
274     glBindFramebuffer(GL_FRAMEBUFFER, 0);
275 }
276 
277 // Check pixels after GL draw.
TEST_P(VulkanImageTest,PixelTestDrawQuad)278 TEST_P(VulkanImageTest, PixelTestDrawQuad)
279 {
280     EGLWindow *window  = getEGLWindow();
281     EGLDisplay display = window->getDisplay();
282 
283     ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(display, "EGL_ANGLE_vulkan_image"));
284 
285     VulkanHelper helper;
286     helper.initializeFromANGLE();
287 
288     GLTexture texture;
289     glBindTexture(GL_TEXTURE_2D, texture);
290     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
291     glBindTexture(GL_TEXTURE_2D, 0);
292 
293     EGLContext context   = window->getContext();
294     EGLImageKHR eglImage = eglCreateImageKHR(
295         display, context, EGL_GL_TEXTURE_2D_KHR,
296         reinterpret_cast<EGLClientBuffer>(static_cast<uintptr_t>(texture)), nullptr);
297     EXPECT_NE(eglImage, EGL_NO_IMAGE_KHR);
298 
299     GLFramebuffer framebuffer;
300     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
301     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
302     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
303 
304     glViewport(0, 0, kWidth, kHeight);
305     // clear framebuffer with black color.
306     glClearColor(0.f, 0.f, 0.f, 0.f);
307     glClear(GL_COLOR_BUFFER_BIT);
308 
309     // draw red quad
310     ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
311     drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.5f);
312 
313     GLuint textures[1] = {texture};
314     GLenum layouts[1]  = {GL_NONE};
315     glReleaseTexturesANGLE(1, textures, layouts);
316     EXPECT_EQ(layouts[0], static_cast<GLenum>(GL_LAYOUT_COLOR_ATTACHMENT_EXT));
317 
318     VkImage vkImage        = VK_NULL_HANDLE;
319     VkImageCreateInfo info = {};
320     EXPECT_EGL_TRUE(eglExportVkImageANGLE(display, eglImage, &vkImage, &info));
321     EXPECT_NE(vkImage, static_cast<VkImage>(VK_NULL_HANDLE));
322 
323     std::vector<GLuint> pixels(kWidth * kHeight);
324     helper.readPixels(vkImage, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, info.format, {},
325                       info.extent, pixels.data(), pixels.size() * sizeof(GLuint));
326     EXPECT_EQ(pixels, std::vector<GLuint>(kWidth * kHeight, kRed));
327 
328     layouts[0] = GL_LAYOUT_TRANSFER_SRC_EXT;
329     glAcquireTexturesANGLE(1, textures, layouts);
330 
331     EXPECT_GL_NO_ERROR();
332     EXPECT_EGL_TRUE(eglDestroyImageKHR(display, eglImage));
333     glBindFramebuffer(GL_FRAMEBUFFER, 0);
334 }
335 
336 // Test importing VkImage with eglCreateImageKHR
TEST_P(VulkanImageTest,ClientBuffer)337 TEST_P(VulkanImageTest, ClientBuffer)
338 {
339     EGLWindow *window  = getEGLWindow();
340     EGLDisplay display = window->getDisplay();
341 
342     ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(display, "EGL_ANGLE_vulkan_image"));
343 
344     VulkanHelper helper;
345     helper.initializeFromANGLE();
346 
347     constexpr VkImageUsageFlags kDefaultImageUsageFlags =
348         VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
349         VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT |
350         VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
351 
352     VkImage vkImage                   = VK_NULL_HANDLE;
353     VkDeviceMemory vkDeviceMemory     = VK_NULL_HANDLE;
354     VkDeviceSize deviceSize           = 0u;
355     VkImageCreateInfo imageCreateInfo = {};
356 
357     VkResult result = VK_SUCCESS;
358     result          = helper.createImage2D(VK_FORMAT_R8G8B8A8_UNORM, 0, kDefaultImageUsageFlags,
359                                   {kWidth, kHeight, 1}, &vkImage, &vkDeviceMemory, &deviceSize,
360                                   &imageCreateInfo);
361     EXPECT_EQ(result, VK_SUCCESS);
362     EXPECT_EQ(imageCreateInfo.sType, VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO);
363 
364     uint64_t info    = reinterpret_cast<uint64_t>(&imageCreateInfo);
365     EGLint attribs[] = {
366         EGL_VULKAN_IMAGE_CREATE_INFO_HI_ANGLE,
367         static_cast<EGLint>((info >> 32) & 0xffffffff),
368         EGL_VULKAN_IMAGE_CREATE_INFO_LO_ANGLE,
369         static_cast<EGLint>(info & 0xffffffff),
370         EGL_NONE,
371     };
372     EGLImageKHR eglImage = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_VULKAN_IMAGE_ANGLE,
373                                              reinterpret_cast<EGLClientBuffer>(&vkImage), attribs);
374     EXPECT_NE(eglImage, EGL_NO_IMAGE_KHR);
375 
376     GLTexture texture;
377     glBindTexture(GL_TEXTURE_2D, texture);
378     glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, eglImage);
379 
380     GLuint textures[1] = {texture};
381     GLenum layouts[1]  = {GL_NONE};
382     glAcquireTexturesANGLE(1, textures, layouts);
383 
384     GLFramebuffer framebuffer;
385     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
386     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
387     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
388 
389     glViewport(0, 0, kWidth, kHeight);
390     // clear framebuffer with white color.
391     glClearColor(1.f, 1.f, 1.f, 1.f);
392     glClear(GL_COLOR_BUFFER_BIT);
393 
394     textures[0] = texture;
395     layouts[0]  = GL_NONE;
396     glReleaseTexturesANGLE(1, textures, layouts);
397     EXPECT_EQ(layouts[0], static_cast<GLenum>(GL_LAYOUT_TRANSFER_DST_EXT));
398 
399     std::vector<GLuint> pixels(kWidth * kHeight);
400     helper.readPixels(vkImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, imageCreateInfo.format, {},
401                       imageCreateInfo.extent, pixels.data(), pixels.size() * sizeof(GLuint));
402     EXPECT_EQ(pixels, std::vector<GLuint>(kWidth * kHeight, kWhite));
403 
404     layouts[0] = GL_LAYOUT_TRANSFER_SRC_EXT;
405     glAcquireTexturesANGLE(1, textures, layouts);
406 
407     // clear framebuffer with red color.
408     glClearColor(1.f, 0.f, 0.f, 1.f);
409     glClear(GL_COLOR_BUFFER_BIT);
410 
411     glReleaseTexturesANGLE(1, textures, layouts);
412     EXPECT_EQ(layouts[0], static_cast<GLenum>(GL_LAYOUT_TRANSFER_DST_EXT));
413 
414     helper.readPixels(vkImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, imageCreateInfo.format, {},
415                       imageCreateInfo.extent, pixels.data(), pixels.size() * sizeof(GLuint));
416     EXPECT_EQ(pixels, std::vector<GLuint>(kWidth * kHeight, kRed));
417 
418     EXPECT_GL_NO_ERROR();
419     glBindFramebuffer(GL_FRAMEBUFFER, 0);
420     framebuffer.reset();
421     texture.reset();
422 
423     glFinish();
424 
425     EXPECT_EGL_TRUE(eglDestroyImageKHR(display, eglImage));
426     vkDestroyImage(helper.getDevice(), vkImage, nullptr);
427     vkFreeMemory(helper.getDevice(), vkDeviceMemory, nullptr);
428 }
429 
430 // Test that texture storage created from VkImage memory is considered pre-initialized in GL.
TEST_P(VulkanImageTest,PreInitializedOnGLImport)431 TEST_P(VulkanImageTest, PreInitializedOnGLImport)
432 {
433     ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_memory_object"));
434 
435     // http://anglebug.com/5381
436     ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
437 
438     EXPECT_TRUE(EnsureGLExtensionEnabled("GL_ANGLE_robust_resource_initialization"));
439 
440     EGLWindow *window  = getEGLWindow();
441     EGLDisplay display = window->getDisplay();
442     ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(display, "EGL_ANGLE_vulkan_image"));
443 
444     VulkanHelper helper;
445     helper.initializeFromANGLE();
446 
447     constexpr VkImageUsageFlags kDefaultImageUsageFlags =
448         VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
449         VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT |
450         VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
451 
452     ANGLE_SKIP_TEST_IF(!helper.canCreateImageOpaqueFd(VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_TYPE_2D,
453                                                       VK_IMAGE_TILING_OPTIMAL, 0,
454                                                       kDefaultImageUsageFlags) ||
455                        !helper.canCreateSemaphoreOpaqueFd());
456 
457     VkImage vkImage                 = VK_NULL_HANDLE;
458     VkDeviceMemory vkDeviceMemory   = VK_NULL_HANDLE;
459     VkDeviceSize vkDeviceMemorySize = 0u;
460 
461     VkResult result = VK_SUCCESS;
462     result = helper.createImage2DOpaqueFd(VK_FORMAT_R8G8B8A8_UNORM, 0, kDefaultImageUsageFlags,
463                                           nullptr, {kWidth, kHeight, 1}, &vkImage, &vkDeviceMemory,
464                                           &vkDeviceMemorySize);
465     EXPECT_EQ(result, VK_SUCCESS);
466 
467     constexpr uint32_t kPixel = 0x12345678;
468     helper.writePixels(vkImage, VK_IMAGE_LAYOUT_UNDEFINED, VK_FORMAT_R8G8B8A8_UNORM, {0, 0, 0},
469                        {1, 1, 1}, static_cast<const void *>(&kPixel), sizeof(kPixel));
470 
471     VkSemaphore vkSemaphore = VK_NULL_HANDLE;
472     result                  = helper.createSemaphoreOpaqueFd(&vkSemaphore);
473     EXPECT_EQ(result, VK_SUCCESS);
474 
475     // Note: writePixels leaves the image in TRANSFER_DST_OPTIMAL layout.
476     helper.releaseImageAndSignalSemaphore(vkImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
477                                           VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, vkSemaphore);
478 
479     int semfd = -1;
480     result    = helper.exportSemaphoreOpaqueFd(vkSemaphore, &semfd);
481     EXPECT_EQ(result, VK_SUCCESS);
482 
483     int memfd = -1;
484     result    = helper.exportMemoryOpaqueFd(vkDeviceMemory, &memfd);
485     EXPECT_EQ(result, VK_SUCCESS);
486 
487     GLuint semaphoreObject = 0u;
488     glGenSemaphoresEXT(1u, &semaphoreObject);
489     EXPECT_TRUE(glIsSemaphoreEXT(semaphoreObject));
490 
491     glImportSemaphoreFdEXT(semaphoreObject, GL_HANDLE_TYPE_OPAQUE_FD_EXT, semfd);
492     EXPECT_GL_NO_ERROR();
493 
494     GLuint memoryObject = 0u;
495     glCreateMemoryObjectsEXT(1u, &memoryObject);
496     EXPECT_TRUE(glIsMemoryObjectEXT(memoryObject));
497 
498     glImportMemoryFdEXT(memoryObject, vkDeviceMemorySize, GL_HANDLE_TYPE_OPAQUE_FD_EXT, memfd);
499     EXPECT_GL_NO_ERROR();
500 
501     GLuint texture = 0u;
502     glGenTextures(1u, &texture);
503     glBindTexture(GL_TEXTURE_2D, texture);
504     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
505     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
506     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
507     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
508 
509     glTexStorageMem2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8_OES, 1, 1, memoryObject, 0);
510     EXPECT_GL_NO_ERROR();
511 
512     GLenum glLayout = GL_LAYOUT_COLOR_ATTACHMENT_EXT;
513     glWaitSemaphoreEXT(semaphoreObject, 0, nullptr, 1, &texture, &glLayout);
514     EXPECT_GL_NO_ERROR();
515 
516     GLuint fbo = 0u;
517     glGenFramebuffers(1u, &fbo);
518     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
519     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
520     EXPECT_GL_NO_ERROR();
521 
522     uint32_t pixel = 0u;
523     glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel);
524     EXPECT_GL_NO_ERROR();
525 
526     EXPECT_EQ(pixel, kPixel);
527 
528     vkDestroySemaphore(helper.getDevice(), vkSemaphore, nullptr);
529     vkDestroyImage(helper.getDevice(), vkImage, nullptr);
530     vkFreeMemory(helper.getDevice(), vkDeviceMemory, nullptr);
531 }
532 
533 // Use this to select which configurations (e.g. which renderer, which GLES major version) these
534 // tests should be run against.
535 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(VulkanImageTest);
536 
537 }  // namespace angle
538