• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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