Commit f12e4123 by Tim Van Patten Committed by Commit Bot

Vulkan: Match descriptor pool sizes to descriptor set layouts

When a descriptor pool is created, a list of descriptor types and counts are given to vkCreateDescriptorPool(). Later, when allocating a descriptor set from the pool, we pass along a descriptor set layout to vkAllocateDescriptorSets() which is used to determine how many of each type of descriptor (i.e. binding) to allocate from the pool. In order for our "free descriptor set" counts to be accurate for each pool, the descriptor pools need to be created with descriptor counts that match the descriptor set layout binding counts. This change fixes a bug where the descriptor set layouts were created with more bindings than the descriptor pool sizes, causing the "free descriptor set" count to be inaccurate, leading to allocating too many descriptor sets from a pool. Bug: angleproject:3570 Test: VulkanDescriptorSetTest Change-Id: I660bf02d29a1291391fb15f39e6479bf348d0f83 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2391114 Commit-Queue: Tim Van Patten <timvp@google.com> Reviewed-by: 's avatarCharlie Lao <cclao@google.com> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 58463573
...@@ -3869,9 +3869,16 @@ angle::Result ContextVk::updateDriverUniformsDescriptorSet( ...@@ -3869,9 +3869,16 @@ angle::Result ContextVk::updateDriverUniformsDescriptorSet(
} }
// Allocate a new descriptor set. // Allocate a new descriptor set.
ANGLE_TRY(mDriverUniformsDescriptorPool.allocateSets( bool newPoolAllocated;
ANGLE_TRY(mDriverUniformsDescriptorPool.allocateSetsAndGetInfo(
this, driverUniforms->descriptorSetLayout.get().ptr(), 1, this, driverUniforms->descriptorSetLayout.get().ptr(), 1,
&driverUniforms->descriptorPoolBinding, &driverUniforms->descriptorSet)); &driverUniforms->descriptorPoolBinding, &driverUniforms->descriptorSet, &newPoolAllocated));
// Clear descriptor set cache. It may no longer be valid.
if (newPoolAllocated)
{
driverUniforms->descriptorSetCache.clear();
}
// Update the driver uniform descriptor set. // Update the driver uniform descriptor set.
VkDescriptorBufferInfo &bufferInfo = allocDescriptorBufferInfo(); VkDescriptorBufferInfo &bufferInfo = allocDescriptorBufferInfo();
...@@ -4000,7 +4007,9 @@ angle::Result ContextVk::updateActiveTextures(const gl::Context *context) ...@@ -4000,7 +4007,9 @@ angle::Result ContextVk::updateActiveTextures(const gl::Context *context)
if (haveImmutableSampler) if (haveImmutableSampler)
{ {
ANGLE_TRY(mExecutable->updatePipelineLayout(context, &mActiveTextures)); // TODO(http://anglebug.com/5033): This will recreate the descriptor pools each time, which
// will likely affect performance negatively.
ANGLE_TRY(mExecutable->createPipelineLayout(context, &mActiveTextures));
invalidateCurrentGraphicsPipeline(); invalidateCurrentGraphicsPipeline();
} }
......
...@@ -139,8 +139,7 @@ class ProgramExecutableVk ...@@ -139,8 +139,7 @@ class ProgramExecutableVk
angle::Result getComputePipeline(ContextVk *contextVk, vk::PipelineAndSerial **pipelineOut); angle::Result getComputePipeline(ContextVk *contextVk, vk::PipelineAndSerial **pipelineOut);
const vk::PipelineLayout &getPipelineLayout() const { return mPipelineLayout.get(); } const vk::PipelineLayout &getPipelineLayout() const { return mPipelineLayout.get(); }
angle::Result createPipelineLayout(const gl::Context *glContext); angle::Result createPipelineLayout(const gl::Context *glContext,
angle::Result updatePipelineLayout(const gl::Context *glContext,
gl::ActiveTextureArray<vk::TextureUnit> *activeTextures); gl::ActiveTextureArray<vk::TextureUnit> *activeTextures);
angle::Result updateTexturesDescriptorSet(ContextVk *contextVk); angle::Result updateTexturesDescriptorSet(ContextVk *contextVk);
...@@ -205,20 +204,24 @@ class ProgramExecutableVk ...@@ -205,20 +204,24 @@ class ProgramExecutableVk
ContextVk *contextVk); ContextVk *contextVk);
void updateTransformFeedbackDescriptorSetImpl(const gl::ProgramState &programState, void updateTransformFeedbackDescriptorSetImpl(const gl::ProgramState &programState,
ContextVk *contextVk); ContextVk *contextVk);
void updateBuffersDescriptorSet(ContextVk *contextVk, angle::Result updateBuffersDescriptorSet(ContextVk *contextVk,
const gl::ShaderType shaderType, const gl::ShaderType shaderType,
vk::ResourceUseList *resourceUseList, vk::ResourceUseList *resourceUseList,
vk::CommandBufferHelper *commandBufferHelper, vk::CommandBufferHelper *commandBufferHelper,
const std::vector<gl::InterfaceBlock> &blocks, const std::vector<gl::InterfaceBlock> &blocks,
VkDescriptorType descriptorType); VkDescriptorType descriptorType);
void updateAtomicCounterBuffersDescriptorSet(const gl::ProgramState &programState, angle::Result updateAtomicCounterBuffersDescriptorSet(
const gl::ShaderType shaderType, const gl::ProgramState &programState,
ContextVk *contextVk, const gl::ShaderType shaderType,
vk::ResourceUseList *resourceUseList, ContextVk *contextVk,
vk::CommandBufferHelper *commandBufferHelper); vk::ResourceUseList *resourceUseList,
vk::CommandBufferHelper *commandBufferHelper);
angle::Result updateImagesDescriptorSet(const gl::ProgramExecutable &executable, angle::Result updateImagesDescriptorSet(const gl::ProgramExecutable &executable,
const gl::ShaderType shaderType, const gl::ShaderType shaderType,
ContextVk *contextVk); ContextVk *contextVk);
angle::Result initDynamicDescriptorPools(ContextVk *contextVk,
vk::DescriptorSetLayoutDesc &descriptorSetLayoutDesc,
DescriptorSetIndex descriptorSetIndex);
// Descriptor sets for uniform blocks and textures for this program. // Descriptor sets for uniform blocks and textures for this program.
vk::DescriptorSetLayoutArray<VkDescriptorSet> mDescriptorSets; vk::DescriptorSetLayoutArray<VkDescriptorSet> mDescriptorSets;
......
...@@ -92,7 +92,7 @@ angle::Result ProgramPipelineVk::link(const gl::Context *glContext, ...@@ -92,7 +92,7 @@ angle::Result ProgramPipelineVk::link(const gl::Context *glContext,
mExecutable.resolvePrecisionMismatch(mergedVaryings); mExecutable.resolvePrecisionMismatch(mergedVaryings);
} }
return mExecutable.createPipelineLayout(glContext); return mExecutable.createPipelineLayout(glContext, nullptr);
} }
size_t ProgramPipelineVk::calcUniformUpdateRequiredSpace( size_t ProgramPipelineVk::calcUniformUpdateRequiredSpace(
......
...@@ -199,7 +199,7 @@ std::unique_ptr<rx::LinkEvent> ProgramVk::load(const gl::Context *context, ...@@ -199,7 +199,7 @@ std::unique_ptr<rx::LinkEvent> ProgramVk::load(const gl::Context *context,
return std::make_unique<LinkEventDone>(status); return std::make_unique<LinkEventDone>(status);
} }
status = mExecutable.createPipelineLayout(context); status = mExecutable.createPipelineLayout(context, nullptr);
return std::make_unique<LinkEventDone>(status); return std::make_unique<LinkEventDone>(status);
} }
...@@ -295,7 +295,7 @@ std::unique_ptr<LinkEvent> ProgramVk::link(const gl::Context *context, ...@@ -295,7 +295,7 @@ std::unique_ptr<LinkEvent> ProgramVk::link(const gl::Context *context,
// TODO(jie.a.chen@intel.com): Parallelize linking. // TODO(jie.a.chen@intel.com): Parallelize linking.
// http://crbug.com/849576 // http://crbug.com/849576
status = mExecutable.createPipelineLayout(context); status = mExecutable.createPipelineLayout(context, nullptr);
return std::make_unique<LinkEventDone>(status); return std::make_unique<LinkEventDone>(status);
} }
......
...@@ -44,9 +44,6 @@ constexpr VkBufferUsageFlags kLineLoopDynamicIndirectBufferUsage = ...@@ -44,9 +44,6 @@ constexpr VkBufferUsageFlags kLineLoopDynamicIndirectBufferUsage =
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
constexpr int kLineLoopDynamicIndirectBufferInitialSize = sizeof(VkDrawIndirectCommand) * 16; constexpr int kLineLoopDynamicIndirectBufferInitialSize = sizeof(VkDrawIndirectCommand) * 16;
// This is an arbitrary max. We can change this later if necessary.
constexpr uint32_t kDefaultDescriptorPoolMaxSets = 128;
constexpr angle::PackedEnumMap<PipelineStage, VkPipelineStageFlagBits> kPipelineStageFlagBitMap = { constexpr angle::PackedEnumMap<PipelineStage, VkPipelineStageFlagBits> kPipelineStageFlagBitMap = {
{PipelineStage::TopOfPipe, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT}, {PipelineStage::TopOfPipe, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT},
{PipelineStage::DrawIndirect, VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT}, {PipelineStage::DrawIndirect, VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT},
...@@ -564,6 +561,9 @@ bool IsShaderReadOnlyLayout(const ImageMemoryBarrierData &imageLayout) ...@@ -564,6 +561,9 @@ bool IsShaderReadOnlyLayout(const ImageMemoryBarrierData &imageLayout)
} }
} // anonymous namespace } // anonymous namespace
// This is an arbitrary max. We can change this later if necessary.
uint32_t DynamicDescriptorPool::mMaxSetsPerPool = 128;
VkImageLayout ConvertImageLayoutToVkImageLayout(ImageLayout imageLayout) VkImageLayout ConvertImageLayoutToVkImageLayout(ImageLayout imageLayout)
{ {
return kImageMemoryBarrierData[imageLayout].layout; return kImageMemoryBarrierData[imageLayout].layout;
...@@ -1680,14 +1680,14 @@ bool DescriptorPoolHelper::hasCapacity(uint32_t descriptorSetCount) const ...@@ -1680,14 +1680,14 @@ bool DescriptorPoolHelper::hasCapacity(uint32_t descriptorSetCount) const
return mFreeDescriptorSets >= descriptorSetCount; return mFreeDescriptorSets >= descriptorSetCount;
} }
angle::Result DescriptorPoolHelper::init(Context *context, angle::Result DescriptorPoolHelper::init(ContextVk *contextVk,
const std::vector<VkDescriptorPoolSize> &poolSizes, const std::vector<VkDescriptorPoolSize> &poolSizes,
uint32_t maxSets) uint32_t maxSets)
{ {
if (mDescriptorPool.valid()) if (mDescriptorPool.valid())
{ {
// This could be improved by recycling the descriptor pool. // This could be improved by recycling the descriptor pool.
mDescriptorPool.destroy(context->getDevice()); mDescriptorPool.destroy(contextVk->getDevice());
} }
VkDescriptorPoolCreateInfo descriptorPoolInfo = {}; VkDescriptorPoolCreateInfo descriptorPoolInfo = {};
...@@ -1699,7 +1699,8 @@ angle::Result DescriptorPoolHelper::init(Context *context, ...@@ -1699,7 +1699,8 @@ angle::Result DescriptorPoolHelper::init(Context *context,
mFreeDescriptorSets = maxSets; mFreeDescriptorSets = maxSets;
ANGLE_VK_TRY(context, mDescriptorPool.init(context->getDevice(), descriptorPoolInfo)); ANGLE_VK_TRY(contextVk, mDescriptorPool.init(contextVk->getDevice(), descriptorPoolInfo));
return angle::Result::Continue; return angle::Result::Continue;
} }
...@@ -1729,23 +1730,25 @@ angle::Result DescriptorPoolHelper::allocateSets(ContextVk *contextVk, ...@@ -1729,23 +1730,25 @@ angle::Result DescriptorPoolHelper::allocateSets(ContextVk *contextVk,
ANGLE_VK_TRY(contextVk, mDescriptorPool.allocateDescriptorSets(contextVk->getDevice(), ANGLE_VK_TRY(contextVk, mDescriptorPool.allocateDescriptorSets(contextVk->getDevice(),
allocInfo, descriptorSetsOut)); allocInfo, descriptorSetsOut));
return angle::Result::Continue; return angle::Result::Continue;
} }
// DynamicDescriptorPool implementation. // DynamicDescriptorPool implementation.
DynamicDescriptorPool::DynamicDescriptorPool() DynamicDescriptorPool::DynamicDescriptorPool() : mCurrentPoolIndex(0) {}
: mMaxSetsPerPool(kDefaultDescriptorPoolMaxSets), mCurrentPoolIndex(0)
{}
DynamicDescriptorPool::~DynamicDescriptorPool() = default; DynamicDescriptorPool::~DynamicDescriptorPool() = default;
angle::Result DynamicDescriptorPool::init(ContextVk *contextVk, angle::Result DynamicDescriptorPool::init(ContextVk *contextVk,
const VkDescriptorPoolSize *setSizes, const VkDescriptorPoolSize *setSizes,
uint32_t setSizeCount) size_t setSizeCount)
{ {
ASSERT(setSizes);
ASSERT(setSizeCount);
ASSERT(mCurrentPoolIndex == 0); ASSERT(mCurrentPoolIndex == 0);
ASSERT(mDescriptorPools.empty() || (mDescriptorPools.size() == 1 && ASSERT(mDescriptorPools.empty() ||
mDescriptorPools[0]->get().hasCapacity(mMaxSetsPerPool))); (mDescriptorPools.size() == 1 &&
mDescriptorPools[mCurrentPoolIndex]->get().hasCapacity(mMaxSetsPerPool)));
mPoolSizes.assign(setSizes, setSizes + setSizeCount); mPoolSizes.assign(setSizes, setSizes + setSizeCount);
for (uint32_t i = 0; i < setSizeCount; ++i) for (uint32_t i = 0; i < setSizeCount; ++i)
...@@ -1754,7 +1757,8 @@ angle::Result DynamicDescriptorPool::init(ContextVk *contextVk, ...@@ -1754,7 +1757,8 @@ angle::Result DynamicDescriptorPool::init(ContextVk *contextVk,
} }
mDescriptorPools.push_back(new RefCountedDescriptorPoolHelper()); mDescriptorPools.push_back(new RefCountedDescriptorPoolHelper());
return mDescriptorPools[0]->get().init(contextVk, mPoolSizes, mMaxSetsPerPool); mCurrentPoolIndex = mDescriptorPools.size() - 1;
return mDescriptorPools[mCurrentPoolIndex]->get().init(contextVk, mPoolSizes, mMaxSetsPerPool);
} }
void DynamicDescriptorPool::destroy(VkDevice device) void DynamicDescriptorPool::destroy(VkDevice device)
...@@ -1789,6 +1793,8 @@ angle::Result DynamicDescriptorPool::allocateSetsAndGetInfo( ...@@ -1789,6 +1793,8 @@ angle::Result DynamicDescriptorPool::allocateSetsAndGetInfo(
VkDescriptorSet *descriptorSetsOut, VkDescriptorSet *descriptorSetsOut,
bool *newPoolAllocatedOut) bool *newPoolAllocatedOut)
{ {
ASSERT(!mDescriptorPools.empty());
*newPoolAllocatedOut = false; *newPoolAllocatedOut = false;
if (!bindingOut->valid() || !bindingOut->get().hasCapacity(descriptorSetCount)) if (!bindingOut->valid() || !bindingOut->get().hasCapacity(descriptorSetCount))
...@@ -1842,7 +1848,12 @@ angle::Result DynamicDescriptorPool::allocateNewPool(ContextVk *contextVk) ...@@ -1842,7 +1848,12 @@ angle::Result DynamicDescriptorPool::allocateNewPool(ContextVk *contextVk)
return mDescriptorPools[mCurrentPoolIndex]->get().init(contextVk, mPoolSizes, mMaxSetsPerPool); return mDescriptorPools[mCurrentPoolIndex]->get().init(contextVk, mPoolSizes, mMaxSetsPerPool);
} }
void DynamicDescriptorPool::setMaxSetsPerPoolForTesting(uint32_t maxSetsPerPool) uint32_t DynamicDescriptorPool::GetMaxSetsPerPoolForTesting()
{
return mMaxSetsPerPool;
}
void DynamicDescriptorPool::SetMaxSetsPerPoolForTesting(uint32_t maxSetsPerPool)
{ {
mMaxSetsPerPool = maxSetsPerPool; mMaxSetsPerPool = maxSetsPerPool;
} }
......
...@@ -252,7 +252,7 @@ class DescriptorPoolHelper ...@@ -252,7 +252,7 @@ class DescriptorPoolHelper
bool valid() { return mDescriptorPool.valid(); } bool valid() { return mDescriptorPool.valid(); }
bool hasCapacity(uint32_t descriptorSetCount) const; bool hasCapacity(uint32_t descriptorSetCount) const;
angle::Result init(Context *context, angle::Result init(ContextVk *contextVk,
const std::vector<VkDescriptorPoolSize> &poolSizes, const std::vector<VkDescriptorPoolSize> &poolSizes,
uint32_t maxSets); uint32_t maxSets);
void destroy(VkDevice device); void destroy(VkDevice device);
...@@ -287,7 +287,7 @@ class DynamicDescriptorPool final : angle::NonCopyable ...@@ -287,7 +287,7 @@ class DynamicDescriptorPool final : angle::NonCopyable
// an individual set. The pool size will be calculated accordingly. // an individual set. The pool size will be calculated accordingly.
angle::Result init(ContextVk *contextVk, angle::Result init(ContextVk *contextVk,
const VkDescriptorPoolSize *setSizes, const VkDescriptorPoolSize *setSizes,
uint32_t setSizeCount); size_t setSizeCount);
void destroy(VkDevice device); void destroy(VkDevice device);
void release(ContextVk *contextVk); void release(ContextVk *contextVk);
...@@ -314,12 +314,13 @@ class DynamicDescriptorPool final : angle::NonCopyable ...@@ -314,12 +314,13 @@ class DynamicDescriptorPool final : angle::NonCopyable
bool *newPoolAllocatedOut); bool *newPoolAllocatedOut);
// For testing only! // For testing only!
void setMaxSetsPerPoolForTesting(uint32_t maxSetsPerPool); static uint32_t GetMaxSetsPerPoolForTesting();
static void SetMaxSetsPerPoolForTesting(uint32_t maxSetsPerPool);
private: private:
angle::Result allocateNewPool(ContextVk *contextVk); angle::Result allocateNewPool(ContextVk *contextVk);
uint32_t mMaxSetsPerPool; static uint32_t mMaxSetsPerPool;
size_t mCurrentPoolIndex; size_t mCurrentPoolIndex;
std::vector<RefCountedDescriptorPoolHelper *> mDescriptorPools; std::vector<RefCountedDescriptorPoolHelper *> mDescriptorPools;
std::vector<VkDescriptorPoolSize> mPoolSizes; std::vector<VkDescriptorPoolSize> mPoolSizes;
......
...@@ -18,6 +18,7 @@ angle_white_box_tests_win_sources = [ ...@@ -18,6 +18,7 @@ angle_white_box_tests_win_sources = [
"gl_tests/ErrorMessages.cpp", "gl_tests/ErrorMessages.cpp",
] ]
angle_white_box_tests_vulkan_sources = [ angle_white_box_tests_vulkan_sources = [
"gl_tests/VulkanDescriptorSetTest.cpp",
"gl_tests/VulkanFormatTablesTest.cpp", "gl_tests/VulkanFormatTablesTest.cpp",
"gl_tests/VulkanFramebufferTest.cpp", "gl_tests/VulkanFramebufferTest.cpp",
"gl_tests/VulkanPerformanceCounterTest.cpp", "gl_tests/VulkanPerformanceCounterTest.cpp",
......
//
// Copyright 2020 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// VulkanDescriptorSetTest:
// Various tests related for Vulkan descriptor sets.
//
#include "test_utils/ANGLETest.h"
#include "test_utils/gl_raii.h"
#include "libANGLE/Context.h"
#include "libANGLE/angletypes.h"
#include "libANGLE/renderer/vulkan/ContextVk.h"
#include "libANGLE/renderer/vulkan/ProgramVk.h"
#include "libANGLE/renderer/vulkan/vk_helpers.h"
using namespace angle;
namespace
{
class VulkanDescriptorSetTest : public ANGLETest
{
protected:
VulkanDescriptorSetTest() {}
void testSetUp() override
{
mMaxSetsPerPool = rx::vk::DynamicDescriptorPool::GetMaxSetsPerPoolForTesting();
}
void testTearDown() override
{
rx::vk::DynamicDescriptorPool::SetMaxSetsPerPoolForTesting(mMaxSetsPerPool);
}
static constexpr uint32_t kMaxSetsForTesting = 1;
void limitMaxSets()
{
rx::vk::DynamicDescriptorPool::SetMaxSetsPerPoolForTesting(kMaxSetsForTesting);
}
private:
uint32_t mMaxSetsPerPool;
};
// Test atomic counter read.
TEST_P(VulkanDescriptorSetTest, AtomicCounterReadLimitedDescriptorPool)
{
// Skipping due to a bug on the Qualcomm Vulkan Android driver.
// http://anglebug.com/3726
ANGLE_SKIP_TEST_IF(IsAndroid() && IsVulkan());
// Skipping test while we work on enabling atomic counter buffer support in th D3D renderer.
// http://anglebug.com/1729
ANGLE_SKIP_TEST_IF(IsD3D11());
// Must be before program creation to limit the descriptor pool sizes when creating the pipeline
// layout.
limitMaxSets();
constexpr char kFS[] =
"#version 310 es\n"
"precision highp float;\n"
"layout(binding = 0, offset = 4) uniform atomic_uint ac;\n"
"out highp vec4 my_color;\n"
"void main()\n"
"{\n"
" my_color = vec4(0.0);\n"
" uint a1 = atomicCounter(ac);\n"
" if (a1 == 3u) my_color = vec4(1.0);\n"
"}\n";
ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
glUseProgram(program.get());
// The initial value of counter 'ac' is 3u.
unsigned int bufferData[3] = {11u, 3u, 1u};
GLBuffer atomicCounterBuffer;
glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
for (int i = 0; i < 5; ++i)
{
glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(bufferData), bufferData, GL_STATIC_DRAW);
drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.0f);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
}
}
ANGLE_INSTANTIATE_TEST(VulkanDescriptorSetTest, ES31_VULKAN(), ES31_VULKAN_SWIFTSHADER());
} // namespace
\ No newline at end of file
...@@ -39,21 +39,20 @@ class VulkanUniformUpdatesTest : public ANGLETest ...@@ -39,21 +39,20 @@ class VulkanUniformUpdatesTest : public ANGLETest
// tests. This is to ensure that the assumption that each TEST_P will recreate context. // tests. This is to ensure that the assumption that each TEST_P will recreate context.
ASSERT(mLastContext != getEGLWindow()->getContext()); ASSERT(mLastContext != getEGLWindow()->getContext());
mLastContext = getEGLWindow()->getContext(); mLastContext = getEGLWindow()->getContext();
mMaxSetsPerPool = rx::vk::DynamicDescriptorPool::GetMaxSetsPerPoolForTesting();
} }
rx::ContextVk *hackANGLE() const void testTearDown() override
{ {
// Hack the angle! rx::vk::DynamicDescriptorPool::SetMaxSetsPerPoolForTesting(mMaxSetsPerPool);
const gl::Context *context = static_cast<gl::Context *>(getEGLWindow()->getContext());
return rx::GetImplAs<rx::ContextVk>(context);
} }
rx::ProgramVk *hackProgram(GLuint handle) const rx::ContextVk *hackANGLE() const
{ {
// Hack the angle! // Hack the angle!
const gl::Context *context = static_cast<gl::Context *>(getEGLWindow()->getContext()); const gl::Context *context = static_cast<gl::Context *>(getEGLWindow()->getContext());
const gl::Program *program = context->getProgramResolveLink({handle}); return rx::GetImplAs<rx::ContextVk>(context);
return rx::vk::GetImpl(program);
} }
rx::TextureVk *hackTexture(GLuint handle) const rx::TextureVk *hackTexture(GLuint handle) const
...@@ -64,33 +63,11 @@ class VulkanUniformUpdatesTest : public ANGLETest ...@@ -64,33 +63,11 @@ class VulkanUniformUpdatesTest : public ANGLETest
return rx::vk::GetImpl(texture); return rx::vk::GetImpl(texture);
} }
static constexpr uint32_t kMaxSetsForTesting = 32; static constexpr uint32_t kMaxSetsForTesting = 1;
void limitMaxSets(GLuint program) void limitMaxSets()
{ {
rx::ContextVk *contextVk = hackANGLE(); rx::vk::DynamicDescriptorPool::SetMaxSetsPerPoolForTesting(kMaxSetsForTesting);
rx::ProgramVk *programVk = hackProgram(program);
// Force a small limit on the max sets per pool to more easily trigger a new allocation.
rx::vk::DynamicDescriptorPool *uniformPool = programVk->getDynamicDescriptorPool(
ToUnderlying(rx::DescriptorSetIndex::UniformsAndXfb));
uniformPool->setMaxSetsPerPoolForTesting(kMaxSetsForTesting);
VkDescriptorPoolSize uniformSetSize = {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
rx::kReservedDefaultUniformBindingCount};
(void)uniformPool->init(contextVk, &uniformSetSize, 1);
uint32_t textureCount =
static_cast<uint32_t>(programVk->getState().getSamplerBindings().size());
// To support the bindEmptyForUnusedDescriptorSets workaround.
textureCount = std::max(textureCount, 1u);
rx::vk::DynamicDescriptorPool *texturePool =
programVk->getDynamicDescriptorPool(ToUnderlying(rx::DescriptorSetIndex::Texture));
texturePool->setMaxSetsPerPoolForTesting(kMaxSetsForTesting);
VkDescriptorPoolSize textureSetSize = {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
textureCount};
(void)texturePool->init(contextVk, &textureSetSize, 1);
} }
static constexpr size_t kTextureStagingBufferSizeForTesting = 128; static constexpr size_t kTextureStagingBufferSizeForTesting = 128;
...@@ -103,6 +80,7 @@ class VulkanUniformUpdatesTest : public ANGLETest ...@@ -103,6 +80,7 @@ class VulkanUniformUpdatesTest : public ANGLETest
private: private:
EGLContext mLastContext; EGLContext mLastContext;
uint32_t mMaxSetsPerPool;
}; };
// This test updates a uniform until a new buffer is allocated and then make sure the uniform // This test updates a uniform until a new buffer is allocated and then make sure the uniform
...@@ -128,7 +106,7 @@ void main() ...@@ -128,7 +106,7 @@ void main()
ANGLE_GL_PROGRAM(program, kPositionUniformVertexShader, kColorUniformFragmentShader); ANGLE_GL_PROGRAM(program, kPositionUniformVertexShader, kColorUniformFragmentShader);
glUseProgram(program); glUseProgram(program);
limitMaxSets(program); limitMaxSets();
// Set a really small min size so that uniform updates often allocates a new buffer. // Set a really small min size so that uniform updates often allocates a new buffer.
rx::ContextVk *contextVk = hackANGLE(); rx::ContextVk *contextVk = hackANGLE();
...@@ -171,7 +149,7 @@ TEST_P(VulkanUniformUpdatesTest, DescriptorPoolUpdates) ...@@ -171,7 +149,7 @@ TEST_P(VulkanUniformUpdatesTest, DescriptorPoolUpdates)
glUseProgram(program); glUseProgram(program);
// Force a small limit on the max sets per pool to more easily trigger a new allocation. // Force a small limit on the max sets per pool to more easily trigger a new allocation.
limitMaxSets(program); limitMaxSets();
GLint texLoc = glGetUniformLocation(program, "tex"); GLint texLoc = glGetUniformLocation(program, "tex");
ASSERT_NE(-1, texLoc); ASSERT_NE(-1, texLoc);
...@@ -212,7 +190,7 @@ void main() ...@@ -212,7 +190,7 @@ void main()
ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), kFS); ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), kFS);
glUseProgram(program); glUseProgram(program);
limitMaxSets(program); limitMaxSets();
// Get uniform locations. // Get uniform locations.
GLint texLoc = glGetUniformLocation(program, "tex"); GLint texLoc = glGetUniformLocation(program, "tex");
...@@ -280,7 +258,7 @@ void main() ...@@ -280,7 +258,7 @@ void main()
ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), kFS); ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), kFS);
glUseProgram(program); glUseProgram(program);
limitMaxSets(program); limitMaxSets();
// Initialize large arrays of textures. // Initialize large arrays of textures.
std::vector<GLTexture> whiteTextures; std::vector<GLTexture> whiteTextures;
...@@ -369,8 +347,8 @@ void main() ...@@ -369,8 +347,8 @@ void main()
glUseProgram(program1); glUseProgram(program1);
// Force a small limit on the max sets per pool to more easily trigger a new allocation. // Force a small limit on the max sets per pool to more easily trigger a new allocation.
limitMaxSets(program1); limitMaxSets();
limitMaxSets(program2); limitMaxSets();
// Set a really small min size so that uniform updates often allocates a new buffer. // Set a really small min size so that uniform updates often allocates a new buffer.
rx::ContextVk *contextVk = hackANGLE(); rx::ContextVk *contextVk = hackANGLE();
...@@ -513,7 +491,7 @@ void main() ...@@ -513,7 +491,7 @@ void main()
ANGLE_GL_PROGRAM(program, kPositionUniformVertexShader, kColorUniformFragmentShader); ANGLE_GL_PROGRAM(program, kPositionUniformVertexShader, kColorUniformFragmentShader);
glUseProgram(program); glUseProgram(program);
limitMaxSets(program); limitMaxSets();
// Set a really small min size so that every uniform update actually allocates a new buffer. // Set a really small min size so that every uniform update actually allocates a new buffer.
rx::ContextVk *contextVk = hackANGLE(); rx::ContextVk *contextVk = hackANGLE();
...@@ -613,7 +591,7 @@ void main() ...@@ -613,7 +591,7 @@ void main()
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
glUseProgram(program); glUseProgram(program);
limitMaxSets(program); limitMaxSets();
// Set a really small min size so that every uniform update actually allocates a new buffer. // Set a really small min size so that every uniform update actually allocates a new buffer.
rx::ContextVk *contextVk = hackANGLE(); rx::ContextVk *contextVk = hackANGLE();
contextVk->setDefaultUniformBlocksMinSizeForTesting(128); contextVk->setDefaultUniformBlocksMinSizeForTesting(128);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment