xref: /aosp_15_r20/external/angle/src/tests/gl_tests/VulkanDescriptorSetTest.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  // VulkanDescriptorSetTest:
7  //   Various tests related for Vulkan descriptor sets.
8  //
9  
10  #include "test_utils/ANGLETest.h"
11  #include "test_utils/gl_raii.h"
12  
13  #include "libANGLE/Context.h"
14  #include "libANGLE/Display.h"
15  #include "libANGLE/angletypes.h"
16  #include "libANGLE/renderer/vulkan/ContextVk.h"
17  #include "libANGLE/renderer/vulkan/ProgramVk.h"
18  #include "libANGLE/renderer/vulkan/vk_helpers.h"
19  
20  using namespace angle;
21  
22  namespace
23  {
24  
25  class VulkanDescriptorSetTest : public ANGLETest<>
26  {
27    protected:
VulkanDescriptorSetTest()28      VulkanDescriptorSetTest() {}
29  
testSetUp()30      void testSetUp() override
31      {
32          mMaxSetsPerPool = rx::vk::DynamicDescriptorPool::GetMaxSetsPerPoolForTesting();
33          mMaxSetsPerPoolMultiplier =
34              rx::vk::DynamicDescriptorPool::GetMaxSetsPerPoolMultiplierForTesting();
35      }
36  
testTearDown()37      void testTearDown() override
38      {
39          rx::vk::DynamicDescriptorPool::SetMaxSetsPerPoolForTesting(mMaxSetsPerPool);
40          rx::vk::DynamicDescriptorPool::SetMaxSetsPerPoolMultiplierForTesting(
41              mMaxSetsPerPoolMultiplier);
42      }
43  
44      static constexpr uint32_t kMaxSetsForTesting           = 1;
45      static constexpr uint32_t kMaxSetsMultiplierForTesting = 1;
46  
limitMaxSets()47      void limitMaxSets()
48      {
49          rx::vk::DynamicDescriptorPool::SetMaxSetsPerPoolForTesting(kMaxSetsForTesting);
50          rx::vk::DynamicDescriptorPool::SetMaxSetsPerPoolMultiplierForTesting(
51              kMaxSetsMultiplierForTesting);
52      }
53  
54    private:
55      uint32_t mMaxSetsPerPool;
56      uint32_t mMaxSetsPerPoolMultiplier;
57  };
58  
59  // Test atomic counter read.
TEST_P(VulkanDescriptorSetTest,AtomicCounterReadLimitedDescriptorPool)60  TEST_P(VulkanDescriptorSetTest, AtomicCounterReadLimitedDescriptorPool)
61  {
62      // Skipping test while we work on enabling atomic counter buffer support in th D3D renderer.
63      // http://anglebug.com/42260658
64      ANGLE_SKIP_TEST_IF(IsD3D11());
65  
66      // Must be before program creation to limit the descriptor pool sizes when creating the pipeline
67      // layout.
68      limitMaxSets();
69  
70      constexpr char kFS[] =
71          "#version 310 es\n"
72          "precision highp float;\n"
73          "layout(binding = 0, offset = 4) uniform atomic_uint ac;\n"
74          "out highp vec4 my_color;\n"
75          "void main()\n"
76          "{\n"
77          "    my_color = vec4(0.0);\n"
78          "    uint a1 = atomicCounter(ac);\n"
79          "    if (a1 == 3u) my_color = vec4(1.0);\n"
80          "}\n";
81  
82      ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
83  
84      glUseProgram(program);
85  
86      // The initial value of counter 'ac' is 3u.
87      unsigned int bufferData[3] = {11u, 3u, 1u};
88      GLBuffer atomicCounterBuffer;
89      glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
90      glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
91  
92      for (int i = 0; i < 5; ++i)
93      {
94          glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(bufferData), bufferData, GL_STATIC_DRAW);
95          drawQuad(program, essl31_shaders::PositionAttrib(), 0.0f);
96          ASSERT_GL_NO_ERROR();
97          EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
98      }
99  }
100  
101  class VulkanDescriptorSetLayoutDescTest : public ANGLETest<>
102  {
103    protected:
VulkanDescriptorSetLayoutDescTest()104      VulkanDescriptorSetLayoutDescTest() {}
105  
testSetUp()106      void testSetUp() override { ANGLETest::testSetUp(); }
107  
testTearDown()108      void testTearDown() override { ANGLETest::testTearDown(); }
109  
hackContext() const110      gl::Context *hackContext() const
111      {
112          egl::Display *display   = static_cast<egl::Display *>(getEGLWindow()->getDisplay());
113          gl::ContextID contextID = {
114              static_cast<GLuint>(reinterpret_cast<uintptr_t>(getEGLWindow()->getContext()))};
115          return display->getContext(contextID);
116      }
117  
hackANGLE() const118      rx::ContextVk *hackANGLE() const
119      {
120          // Hack the angle!
121          return rx::GetImplAs<rx::ContextVk>(hackContext());
122      }
123  
124      struct DescriptorSetBinding
125      {
126          uint32_t bindingIndex;
127          VkDescriptorType type;
128          uint32_t bindingCount;
129          VkShaderStageFlagBits shaderStage;
130      };
131  
132      const std::array<DescriptorSetBinding, 12> mBindings = {{
133          {0, VK_DESCRIPTOR_TYPE_SAMPLER, 1, VK_SHADER_STAGE_VERTEX_BIT},
134          {1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
135          {2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT},
136          {3, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
137          {4, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, VK_SHADER_STAGE_VERTEX_BIT},
138          {5, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
139          {6, VK_DESCRIPTOR_TYPE_SAMPLER, 1, VK_SHADER_STAGE_VERTEX_BIT},
140          {7, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
141          {8, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT},
142          {9, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
143          {10, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, VK_SHADER_STAGE_VERTEX_BIT},
144          {11, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
145      }};
146  
addBindings(const std::vector<uint32_t> & bindingIndices,rx::vk::DescriptorSetLayoutDesc * desc)147      void addBindings(const std::vector<uint32_t> &bindingIndices,
148                       rx::vk::DescriptorSetLayoutDesc *desc)
149      {
150          for (uint32_t index : bindingIndices)
151          {
152              ASSERT(index < mBindings.size());
153              const DescriptorSetBinding &binding = mBindings[index];
154              desc->addBinding(binding.bindingIndex, binding.type, binding.bindingCount,
155                               binding.shaderStage, nullptr);
156          }
157      }
158  
159      rx::vk::DescriptorSetLayoutDesc mDescriptorSetLayoutDesc;
160      rx::DescriptorSetLayoutCache mDescriptorSetLayoutCache;
161  };
162  
163  // Test basic interaction between DescriptorSetLayoutDesc and DescriptorSetLayoutCache
TEST_P(VulkanDescriptorSetLayoutDescTest,Basic)164  TEST_P(VulkanDescriptorSetLayoutDescTest, Basic)
165  {
166      const std::vector<uint32_t> bindingsPattern1 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
167      const std::vector<uint32_t> bindingsPattern2 = {0, 1};
168      const std::vector<uint32_t> bindingsPattern3 = {0, 1, 5, 9};
169  
170      angle::Result result;
171      rx::ContextVk *contextVk = hackANGLE();
172      rx::vk::DescriptorSetLayoutPtr descriptorSetLayout;
173  
174      mDescriptorSetLayoutDesc = {};
175      addBindings(bindingsPattern1, &mDescriptorSetLayoutDesc);
176      result = mDescriptorSetLayoutCache.getDescriptorSetLayout(contextVk, mDescriptorSetLayoutDesc,
177                                                                &descriptorSetLayout);
178      EXPECT_EQ(result, angle::Result::Continue);
179      EXPECT_EQ(mDescriptorSetLayoutCache.getCacheMissCount(), 1u);
180  
181      mDescriptorSetLayoutDesc = {};
182      addBindings(bindingsPattern2, &mDescriptorSetLayoutDesc);
183      result = mDescriptorSetLayoutCache.getDescriptorSetLayout(contextVk, mDescriptorSetLayoutDesc,
184                                                                &descriptorSetLayout);
185      EXPECT_EQ(result, angle::Result::Continue);
186      EXPECT_EQ(mDescriptorSetLayoutCache.getCacheMissCount(), 2u);
187  
188      mDescriptorSetLayoutDesc = {};
189      addBindings(bindingsPattern3, &mDescriptorSetLayoutDesc);
190      size_t reusedDescHash = mDescriptorSetLayoutDesc.hash();
191      result = mDescriptorSetLayoutCache.getDescriptorSetLayout(contextVk, mDescriptorSetLayoutDesc,
192                                                                &descriptorSetLayout);
193      EXPECT_EQ(result, angle::Result::Continue);
194      EXPECT_EQ(mDescriptorSetLayoutCache.getCacheMissCount(), 3u);
195  
196      rx::vk::DescriptorSetLayoutDesc desc;
197      addBindings(bindingsPattern3, &desc);
198      size_t newDescHash = desc.hash();
199      EXPECT_EQ(reusedDescHash, newDescHash);
200  
201      result =
202          mDescriptorSetLayoutCache.getDescriptorSetLayout(contextVk, desc, &descriptorSetLayout);
203      EXPECT_EQ(result, angle::Result::Continue);
204      EXPECT_EQ(mDescriptorSetLayoutCache.getCacheHitCount(), 1u);
205      EXPECT_EQ(mDescriptorSetLayoutCache.getCacheMissCount(), 3u);
206  
207      descriptorSetLayout.reset();
208      mDescriptorSetLayoutCache.destroy(contextVk->getRenderer());
209  }
210  
211  ANGLE_INSTANTIATE_TEST(VulkanDescriptorSetTest, ES31_VULKAN(), ES31_VULKAN_SWIFTSHADER());
212  ANGLE_INSTANTIATE_TEST(VulkanDescriptorSetLayoutDescTest, ES31_VULKAN());
213  
214  }  // namespace
215