Commit daedf4d2 by Luc Ferron Committed by Commit Bot

Vulkan: Add a DynamicDescriptorPool class.

In order to manage the life of descriptor sets better and allow allocating descriptor sets infinitely. Bug:angleproject:2392 Change-Id: Ia3c7145d85d697c04e8008e8d8839c428dd2e864 Reviewed-on: https://chromium-review.googlesource.com/966786 Commit-Queue: Luc Ferron <lucferron@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 4121799f
......@@ -19,6 +19,7 @@
#include "libANGLE/renderer/vulkan/CompilerVk.h"
#include "libANGLE/renderer/vulkan/ContextVk.h"
#include "libANGLE/renderer/vulkan/DeviceVk.h"
#include "libANGLE/renderer/vulkan/DynamicDescriptorPool.h"
#include "libANGLE/renderer/vulkan/FenceNVVk.h"
#include "libANGLE/renderer/vulkan/FramebufferVk.h"
#include "libANGLE/renderer/vulkan/ImageVk.h"
......@@ -56,12 +57,6 @@ VkIndexType GetVkIndexType(GLenum glIndexType)
}
}
enum DescriptorPoolIndex : uint8_t
{
UniformBufferPool = 0,
TexturePool = 1,
};
constexpr size_t kStreamingVertexDataSize = 1024 * 1024;
constexpr size_t kStreamingIndexDataSize = 1024 * 8;
......@@ -71,6 +66,7 @@ ContextVk::ContextVk(const gl::ContextState &state, RendererVk *renderer)
: ContextImpl(state),
mRenderer(renderer),
mCurrentDrawMode(GL_NONE),
mDynamicDescriptorPool(),
mVertexArrayDirty(false),
mTexturesDirty(false),
mStreamingVertexData(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, kStreamingVertexDataSize, 1),
......@@ -88,7 +84,7 @@ void ContextVk::onDestroy(const gl::Context *context)
{
VkDevice device = mRenderer->getDevice();
mDescriptorPool.destroy(device);
mDynamicDescriptorPool.destroy(mRenderer);
mStreamingVertexData.destroy(device);
mStreamingIndexData.destroy(device);
mLineLoopHandler.destroy(device);
......@@ -96,27 +92,9 @@ void ContextVk::onDestroy(const gl::Context *context)
gl::Error ContextVk::initialize()
{
VkDevice device = mRenderer->getDevice();
VkDescriptorPoolSize poolSizes[2];
poolSizes[UniformBufferPool].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
poolSizes[UniformBufferPool].descriptorCount = 1024;
poolSizes[TexturePool].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
poolSizes[TexturePool].descriptorCount = 1024;
VkDescriptorPoolCreateInfo descriptorPoolInfo;
descriptorPoolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
descriptorPoolInfo.pNext = nullptr;
descriptorPoolInfo.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
// TODO(jmadill): Pick non-arbitrary max.
descriptorPoolInfo.maxSets = 2048;
// Reserve pools for uniform blocks and textures.
descriptorPoolInfo.poolSizeCount = 2;
descriptorPoolInfo.pPoolSizes = poolSizes;
ANGLE_TRY(mDescriptorPool.init(device, descriptorPoolInfo));
ANGLE_TRY(mDynamicDescriptorPool.init(this->getDevice(),
mRenderer->getUniformBufferDescriptorCount(),
mRenderer->getMaxActiveTextures()));
mPipelineDesc.reset(new vk::PipelineDesc());
mPipelineDesc->initDefaults();
......@@ -885,9 +863,9 @@ gl::Error ContextVk::memoryBarrierByRegion(const gl::Context *context, GLbitfiel
return gl::InternalError();
}
vk::DescriptorPool *ContextVk::getDescriptorPool()
DynamicDescriptorPool *ContextVk::getDynamicDescriptorPool()
{
return &mDescriptorPool;
return &mDynamicDescriptorPool;
}
const VkClearValue &ContextVk::getClearColorValue() const
......
......@@ -13,6 +13,7 @@
#include <vulkan/vulkan.h>
#include "libANGLE/renderer/ContextImpl.h"
#include "libANGLE/renderer/vulkan/DynamicDescriptorPool.h"
#include "libANGLE/renderer/vulkan/StreamingBuffer.h"
#include "libANGLE/renderer/vulkan/vk_cache_utils.h"
......@@ -156,7 +157,7 @@ class ContextVk : public ContextImpl
void invalidateCurrentPipeline();
void onVertexArrayChange();
vk::DescriptorPool *getDescriptorPool();
DynamicDescriptorPool *getDynamicDescriptorPool();
const VkClearValue &getClearColorValue() const;
const VkClearValue &getClearDepthStencilValue() const;
......@@ -180,9 +181,9 @@ class ContextVk : public ContextImpl
// Kept in a pointer so allocations can be aligned, and structs can be portably packed.
std::unique_ptr<vk::PipelineDesc> mPipelineDesc;
// The descriptor pool is externally sychronized, so cannot be accessed from different threads
// simultaneously. Hence, we keep it in the ContextVk instead of the RendererVk.
vk::DescriptorPool mDescriptorPool;
// The dynamic descriptor pool is externally sychronized, so cannot be accessed from different
// threads simultaneously. Hence, we keep it in the ContextVk instead of the RendererVk.
DynamicDescriptorPool mDynamicDescriptorPool;
// Triggers adding dependencies to the command graph.
bool mVertexArrayDirty;
......
//
// Copyright 2018 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.
//
// DynamicDescriptorPool:
// Uses DescriptorPool to allocate descriptor sets as needed. If the descriptor pool
// is full, we simply allocate a new pool to keep allocating descriptor sets as needed and
// leave the renderer take care of the life time of the pools that become unused.
//
#include "DynamicDescriptorPool.h"
#include "libANGLE/renderer/vulkan/ContextVk.h"
#include "libANGLE/renderer/vulkan/RendererVk.h"
namespace rx
{
namespace
{
// TODO(jmadill): Pick non-arbitrary max.
constexpr uint32_t kMaxSets = 2048;
} // anonymous namespace
DynamicDescriptorPool::DynamicDescriptorPool()
: mCurrentAllocatedDescriptorSetCount(0),
mUniformBufferDescriptorsPerSet(0),
mCombinedImageSamplerDescriptorsPerSet(0)
{
}
DynamicDescriptorPool::~DynamicDescriptorPool()
{
}
void DynamicDescriptorPool::destroy(RendererVk *rendererVk)
{
ASSERT(mCurrentDescriptorSetPool.valid());
rendererVk->releaseResource(*this, &mCurrentDescriptorSetPool);
}
vk::Error DynamicDescriptorPool::init(const VkDevice &device,
uint32_t uniformBufferDescriptorsPerSet,
uint32_t combinedImageSamplerDescriptorsPerSet)
{
ASSERT(!mCurrentDescriptorSetPool.valid() && mCurrentAllocatedDescriptorSetCount == 0);
mUniformBufferDescriptorsPerSet = uniformBufferDescriptorsPerSet;
mCombinedImageSamplerDescriptorsPerSet = combinedImageSamplerDescriptorsPerSet;
ANGLE_TRY(allocateNewPool(device));
return vk::NoError();
}
vk::Error DynamicDescriptorPool::allocateDescriptorSets(
ContextVk *contextVk,
const VkDescriptorSetLayout *descriptorSetLayout,
uint32_t descriptorSetCount,
VkDescriptorSet *descriptorSetsOut)
{
updateQueueSerial(contextVk->getRenderer()->getCurrentQueueSerial());
if (descriptorSetCount + mCurrentAllocatedDescriptorSetCount > kMaxSets)
{
// We will bust the limit of descriptor set with this allocation so we need to get a new
// pool for it.
contextVk->getRenderer()->releaseResource(*this, &mCurrentDescriptorSetPool);
ANGLE_TRY(allocateNewPool(contextVk->getDevice()));
}
VkDescriptorSetAllocateInfo allocInfo;
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
allocInfo.pNext = nullptr;
allocInfo.descriptorPool = mCurrentDescriptorSetPool.getHandle();
allocInfo.descriptorSetCount = descriptorSetCount;
allocInfo.pSetLayouts = descriptorSetLayout;
ANGLE_TRY(mCurrentDescriptorSetPool.allocateDescriptorSets(contextVk->getDevice(), allocInfo,
descriptorSetsOut));
mCurrentAllocatedDescriptorSetCount += allocInfo.descriptorSetCount;
return vk::NoError();
}
vk::Error DynamicDescriptorPool::allocateNewPool(const VkDevice &device)
{
VkDescriptorPoolSize poolSizes[DescriptorPoolIndexCount];
poolSizes[UniformBufferIndex].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
poolSizes[UniformBufferIndex].descriptorCount =
mUniformBufferDescriptorsPerSet * kMaxSets / DescriptorPoolIndexCount;
poolSizes[TextureIndex].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
poolSizes[TextureIndex].descriptorCount =
mCombinedImageSamplerDescriptorsPerSet * kMaxSets / DescriptorPoolIndexCount;
VkDescriptorPoolCreateInfo descriptorPoolInfo;
descriptorPoolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
descriptorPoolInfo.pNext = nullptr;
descriptorPoolInfo.flags = 0;
descriptorPoolInfo.maxSets = kMaxSets;
// Reserve pools for uniform blocks and textures.
descriptorPoolInfo.poolSizeCount = DescriptorPoolIndexCount;
descriptorPoolInfo.pPoolSizes = poolSizes;
mCurrentAllocatedDescriptorSetCount = 0;
ANGLE_TRY(mCurrentDescriptorSetPool.init(device, descriptorPoolInfo));
return vk::NoError();
}
} // namespace rx
//
// Copyright 2018 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.
//
// DynamicDescriptorPool:
// Uses DescriptorPool to allocate descriptor sets as needed. If the descriptor pool
// is full, we simply allocate a new pool to keep allocating descriptor sets as needed and
// leave the renderer take care of the life time of the pools that become unused.
//
#ifndef LIBANGLE_RENDERER_VULKAN_DYNAMIC_DESCRIPTOR_POOL_H_
#define LIBANGLE_RENDERER_VULKAN_DYNAMIC_DESCRIPTOR_POOL_H_
#include "libANGLE/renderer/vulkan/vk_utils.h"
namespace rx
{
enum DescriptorPoolIndex : uint8_t
{
UniformBufferIndex = 0,
TextureIndex = 1,
DescriptorPoolIndexCount = 2
};
class DynamicDescriptorPool final : public ResourceVk
{
public:
DynamicDescriptorPool();
~DynamicDescriptorPool();
void destroy(RendererVk *rendererVk);
vk::Error init(const VkDevice &device,
uint32_t uniformBufferDescriptorsPerSet,
uint32_t combinedImageSamplerDescriptorsPerSet);
// It is an undefined behavior to pass a different descriptorSetLayout from call to call.
vk::Error allocateDescriptorSets(ContextVk *contextVk,
const VkDescriptorSetLayout *descriptorSetLayout,
uint32_t descriptorSetCount,
VkDescriptorSet *descriptorSetsOut);
private:
vk::Error allocateNewPool(const VkDevice &device);
vk::DescriptorPool mCurrentDescriptorSetPool;
size_t mCurrentAllocatedDescriptorSetCount;
uint32_t mUniformBufferDescriptorsPerSet;
uint32_t mCombinedImageSamplerDescriptorsPerSet;
};
} // namespace rx
#endif // LIBANGLE_RENDERER_VULKAN_DYNAMIC_DESCRIPTOR_POOL_H_
......@@ -13,6 +13,7 @@
#include "common/utilities.h"
#include "libANGLE/Context.h"
#include "libANGLE/renderer/vulkan/ContextVk.h"
#include "libANGLE/renderer/vulkan/DynamicDescriptorPool.h"
#include "libANGLE/renderer/vulkan/GlslangWrapper.h"
#include "libANGLE/renderer/vulkan/RendererVk.h"
#include "libANGLE/renderer/vulkan/TextureVk.h"
......@@ -194,13 +195,6 @@ vk::Error ProgramVk::reset(ContextVk *contextVk)
mVertexModuleSerial = Serial();
mFragmentModuleSerial = Serial();
// Free our descriptor set handles.
if (!mDescriptorSets.empty())
{
vk::DescriptorPool *descriptorPool = contextVk->getDescriptorPool();
ANGLE_TRY(descriptorPool->freeDescriptorSets(
device, static_cast<uint32_t>(mDescriptorSets.size()), mDescriptorSets.data()));
}
mDescriptorSets.clear();
mUsedDescriptorSetRange.invalidate();
mDirtyTextures = false;
......@@ -661,25 +655,17 @@ vk::Error ProgramVk::initDescriptorSets(ContextVk *contextVk)
ASSERT(mDescriptorSets.empty());
RendererVk *renderer = contextVk->getRenderer();
VkDevice device = contextVk->getDevice();
// Write out to a new a descriptor set.
// TODO(jmadill): Handle descriptor set lifetime.
vk::DescriptorPool *descriptorPool = contextVk->getDescriptorPool();
DynamicDescriptorPool *dynamicDescriptorPool = contextVk->getDynamicDescriptorPool();
const auto &descriptorSetLayouts = renderer->getGraphicsDescriptorSetLayouts();
uint32_t descriptorSetCount = static_cast<uint32_t>(descriptorSetLayouts.size());
VkDescriptorSetAllocateInfo allocInfo;
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
allocInfo.pNext = nullptr;
allocInfo.descriptorPool = descriptorPool->getHandle();
allocInfo.descriptorSetCount = descriptorSetCount;
allocInfo.pSetLayouts = descriptorSetLayouts[0].ptr();
mDescriptorSets.resize(descriptorSetCount, VK_NULL_HANDLE);
ANGLE_TRY(descriptorPool->allocateDescriptorSets(device, allocInfo, &mDescriptorSets[0]));
ANGLE_TRY(dynamicDescriptorPool->allocateDescriptorSets(
contextVk, descriptorSetLayouts[0].ptr(), descriptorSetCount, &mDescriptorSets[0]));
return vk::NoError();
}
......
......@@ -33,6 +33,9 @@ namespace rx
namespace
{
// We currently only allocate 2 uniform buffer per descriptor set, one for the fragment shader and
// one for the vertex shader.
constexpr size_t kUniformBufferDescriptorsPerDescriptorSet = 2;
VkResult VerifyExtensionsPresent(const std::vector<VkExtensionProperties> &extensionProps,
const std::vector<const char *> &enabledExtensionNames)
......@@ -593,6 +596,18 @@ const gl::Limitations &RendererVk::getNativeLimitations() const
return mNativeLimitations;
}
uint32_t RendererVk::getMaxActiveTextures()
{
// TODO(lucferron): expose this limitation to GL in Context Caps
return std::min<uint32_t>(mPhysicalDeviceProperties.limits.maxPerStageDescriptorSamplers,
gl::IMPLEMENTATION_MAX_ACTIVE_TEXTURES);
}
uint32_t RendererVk::getUniformBufferDescriptorCount()
{
return kUniformBufferDescriptorsPerDescriptorSet;
}
const vk::CommandPool &RendererVk::getCommandPool() const
{
return mCommandPool;
......@@ -847,10 +862,7 @@ vk::Error RendererVk::initGraphicsPipelineLayout()
mGraphicsDescriptorSetLayouts.push_back(std::move(uniformLayout));
}
// TODO(lucferron): expose this limitation to GL in Context Caps
std::vector<VkDescriptorSetLayoutBinding> textureBindings(
std::min<size_t>(mPhysicalDeviceProperties.limits.maxPerStageDescriptorSamplers,
gl::IMPLEMENTATION_MAX_ACTIVE_TEXTURES));
std::vector<VkDescriptorSetLayoutBinding> textureBindings(getMaxActiveTextures());
// TODO(jmadill): This approach might not work well for texture arrays.
for (uint32_t textureIndex = 0; textureIndex < textureBindings.size(); ++textureIndex)
......
......@@ -46,6 +46,10 @@ class RendererVk : angle::NonCopyable
VkInstance getInstance() const { return mInstance; }
VkPhysicalDevice getPhysicalDevice() const { return mPhysicalDevice; }
const VkPhysicalDeviceProperties &getPhysicalDeviceProperties() const
{
return mPhysicalDeviceProperties;
}
VkQueue getQueue() const { return mQueue; }
VkDevice getDevice() const { return mDevice; }
......@@ -62,6 +66,8 @@ class RendererVk : angle::NonCopyable
const gl::TextureCapsMap &getNativeTextureCaps() const;
const gl::Extensions &getNativeExtensions() const;
const gl::Limitations &getNativeLimitations() const;
uint32_t getMaxActiveTextures();
uint32_t getUniformBufferDescriptorCount();
GlslangWrapper *getGlslangWrapper();
......
......@@ -756,6 +756,8 @@
'libANGLE/renderer/vulkan/DeviceVk.h',
'libANGLE/renderer/vulkan/DisplayVk.cpp',
'libANGLE/renderer/vulkan/DisplayVk.h',
'libANGLE/renderer/vulkan/DynamicDescriptorPool.cpp',
'libANGLE/renderer/vulkan/DynamicDescriptorPool.h',
'libANGLE/renderer/vulkan/FenceNVVk.cpp',
'libANGLE/renderer/vulkan/FenceNVVk.h',
'libANGLE/renderer/vulkan/FramebufferVk.cpp',
......
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