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