xref: /aosp_15_r20/external/angle/src/tests/gl_tests/VulkanFramebufferTest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2020 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 // VulkanFramebufferTest:
7 //   Tests to validate our Vulkan framebuffer image allocation.
8 //
9 
10 #include "test_utils/ANGLETest.h"
11 #include "test_utils/angle_test_instantiate.h"
12 // 'None' is defined as 'struct None {};' in
13 // third_party/googletest/src/googletest/include/gtest/internal/gtest-type-util.h.
14 // But 'None' is also defined as a numeric constant 0L in <X11/X.h>.
15 // So we need to include ANGLETest.h first to avoid this conflict.
16 
17 #include "libANGLE/Context.h"
18 #include "libANGLE/Display.h"
19 #include "libANGLE/angletypes.h"
20 #include "libANGLE/renderer/vulkan/ContextVk.h"
21 #include "libANGLE/renderer/vulkan/ProgramVk.h"
22 #include "libANGLE/renderer/vulkan/TextureVk.h"
23 #include "test_utils/gl_raii.h"
24 #include "util/EGLWindow.h"
25 #include "util/shader_utils.h"
26 
27 using namespace angle;
28 
29 namespace
30 {
31 
32 class VulkanFramebufferTest : public ANGLETest<>
33 {
34   protected:
hackContext() const35     gl::Context *hackContext() const
36     {
37         egl::Display *display   = static_cast<egl::Display *>(getEGLWindow()->getDisplay());
38         gl::ContextID contextID = {
39             static_cast<GLuint>(reinterpret_cast<uintptr_t>(getEGLWindow()->getContext()))};
40         return display->getContext(contextID);
41     }
42 
hackANGLE() const43     rx::ContextVk *hackANGLE() const
44     {
45         // Hack the angle!
46         return rx::GetImplAs<rx::ContextVk>(hackContext());
47     }
48 
hackTexture(GLuint handle) const49     rx::TextureVk *hackTexture(GLuint handle) const
50     {
51         // Hack the angle!
52         const gl::Context *context = hackContext();
53         const gl::Texture *texture = context->getTexture({handle});
54         return rx::vk::GetImpl(texture);
55     }
56 };
57 
58 // Test that framebuffer can be created from a mip-incomplete texture, and that its allocation only
59 // includes the framebuffer's attached mip.
TEST_P(VulkanFramebufferTest,TextureAttachmentMipIncomplete)60 TEST_P(VulkanFramebufferTest, TextureAttachmentMipIncomplete)
61 {
62     GLFramebuffer framebuffer;
63     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
64 
65     GLTexture texture;
66     glBindTexture(GL_TEXTURE_2D, texture);
67 
68     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 100, 100, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
69     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
70     glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 5, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
71 
72     // Set framebuffer to mip 0.  Framebuffer should be complete, and make the texture allocate
73     // an image of only 1 level.
74     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
75     EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
76 
77     glClearColor(0, 0, 0, 1.0f);
78     glClear(GL_COLOR_BUFFER_BIT);
79     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
80 
81     rx::TextureVk *textureVk = hackTexture(texture);
82     EXPECT_EQ(textureVk->getImage().getLevelCount(), 1u);
83 }
84 
85 // Test ensure that a R4G4B4A4 format sample only will actually uses R4G4B4A4 format instead of
86 // R8G8B8A8.
TEST_P(VulkanFramebufferTest,R4G4B4A4TextureSampleOnlyActuallyUses444Format)87 TEST_P(VulkanFramebufferTest, R4G4B4A4TextureSampleOnlyActuallyUses444Format)
88 {
89     rx::ContextVk *contextVk   = hackANGLE();
90     rx::vk::Renderer *renderer = contextVk->getRenderer();
91     angle::FormatID formatID   = angle::FormatID::R4G4B4A4_UNORM;
92 
93     // Check if R4G4B4A4_UNORM is supported format.
94     bool isTexturable = renderer->hasImageFormatFeatureBits(
95         formatID,
96         VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT);
97     ANGLE_SKIP_TEST_IF(!isTexturable);
98 
99     static constexpr GLsizei kTexWidth  = 100;
100     static constexpr GLsizei kTexHeight = 100;
101     GLTexture texture;
102     glBindTexture(GL_TEXTURE_2D, texture);
103 
104     const GLushort u16Color = 0xF00F;  // red
105     std::vector<GLushort> pixels(kTexWidth * kTexHeight, u16Color);
106     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA4, kTexWidth, kTexHeight, 0, GL_RGBA,
107                  GL_UNSIGNED_SHORT_4_4_4_4, pixels.data());
108     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
109     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
110     ANGLE_GL_PROGRAM(program, essl3_shaders::vs::Texture2DLod(), essl3_shaders::fs::Texture2DLod());
111     glUseProgram(program);
112     GLint textureLocation = glGetUniformLocation(program, essl3_shaders::Texture2DUniform());
113     ASSERT_NE(-1, textureLocation);
114     GLint lodLocation = glGetUniformLocation(program, essl3_shaders::LodUniform());
115     ASSERT_NE(-1, lodLocation);
116     glActiveTexture(GL_TEXTURE0);
117     glBindTexture(GL_TEXTURE_2D, texture);
118     glClearColor(0, 1, 0, 1);
119     glClear(GL_COLOR_BUFFER_BIT);
120     glUniform1f(lodLocation, 0);
121     drawQuad(program, essl3_shaders::PositionAttrib(), 0.5f);
122     EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 0, 255);
123     ASSERT_GL_NO_ERROR();
124 
125     rx::TextureVk *textureVk = hackTexture(texture);
126     EXPECT_EQ(textureVk->getImage().getActualFormatID(), formatID);
127 }
128 
129 ANGLE_INSTANTIATE_TEST(VulkanFramebufferTest, ES3_VULKAN());
130 
131 }  // anonymous namespace
132