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