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 @@ ...@@ -19,6 +19,7 @@
#include "libANGLE/renderer/vulkan/CompilerVk.h" #include "libANGLE/renderer/vulkan/CompilerVk.h"
#include "libANGLE/renderer/vulkan/ContextVk.h" #include "libANGLE/renderer/vulkan/ContextVk.h"
#include "libANGLE/renderer/vulkan/DeviceVk.h" #include "libANGLE/renderer/vulkan/DeviceVk.h"
#include "libANGLE/renderer/vulkan/DynamicDescriptorPool.h"
#include "libANGLE/renderer/vulkan/FenceNVVk.h" #include "libANGLE/renderer/vulkan/FenceNVVk.h"
#include "libANGLE/renderer/vulkan/FramebufferVk.h" #include "libANGLE/renderer/vulkan/FramebufferVk.h"
#include "libANGLE/renderer/vulkan/ImageVk.h" #include "libANGLE/renderer/vulkan/ImageVk.h"
...@@ -56,12 +57,6 @@ VkIndexType GetVkIndexType(GLenum glIndexType) ...@@ -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 kStreamingVertexDataSize = 1024 * 1024;
constexpr size_t kStreamingIndexDataSize = 1024 * 8; constexpr size_t kStreamingIndexDataSize = 1024 * 8;
...@@ -71,6 +66,7 @@ ContextVk::ContextVk(const gl::ContextState &state, RendererVk *renderer) ...@@ -71,6 +66,7 @@ ContextVk::ContextVk(const gl::ContextState &state, RendererVk *renderer)
: ContextImpl(state), : ContextImpl(state),
mRenderer(renderer), mRenderer(renderer),
mCurrentDrawMode(GL_NONE), mCurrentDrawMode(GL_NONE),
mDynamicDescriptorPool(),
mVertexArrayDirty(false), mVertexArrayDirty(false),
mTexturesDirty(false), mTexturesDirty(false),
mStreamingVertexData(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, kStreamingVertexDataSize, 1), mStreamingVertexData(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, kStreamingVertexDataSize, 1),
...@@ -88,7 +84,7 @@ void ContextVk::onDestroy(const gl::Context *context) ...@@ -88,7 +84,7 @@ void ContextVk::onDestroy(const gl::Context *context)
{ {
VkDevice device = mRenderer->getDevice(); VkDevice device = mRenderer->getDevice();
mDescriptorPool.destroy(device); mDynamicDescriptorPool.destroy(mRenderer);
mStreamingVertexData.destroy(device); mStreamingVertexData.destroy(device);
mStreamingIndexData.destroy(device); mStreamingIndexData.destroy(device);
mLineLoopHandler.destroy(device); mLineLoopHandler.destroy(device);
...@@ -96,27 +92,9 @@ void ContextVk::onDestroy(const gl::Context *context) ...@@ -96,27 +92,9 @@ void ContextVk::onDestroy(const gl::Context *context)
gl::Error ContextVk::initialize() gl::Error ContextVk::initialize()
{ {
VkDevice device = mRenderer->getDevice(); ANGLE_TRY(mDynamicDescriptorPool.init(this->getDevice(),
mRenderer->getUniformBufferDescriptorCount(),
VkDescriptorPoolSize poolSizes[2]; mRenderer->getMaxActiveTextures()));
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));
mPipelineDesc.reset(new vk::PipelineDesc()); mPipelineDesc.reset(new vk::PipelineDesc());
mPipelineDesc->initDefaults(); mPipelineDesc->initDefaults();
...@@ -885,9 +863,9 @@ gl::Error ContextVk::memoryBarrierByRegion(const gl::Context *context, GLbitfiel ...@@ -885,9 +863,9 @@ gl::Error ContextVk::memoryBarrierByRegion(const gl::Context *context, GLbitfiel
return gl::InternalError(); return gl::InternalError();
} }
vk::DescriptorPool *ContextVk::getDescriptorPool() DynamicDescriptorPool *ContextVk::getDynamicDescriptorPool()
{ {
return &mDescriptorPool; return &mDynamicDescriptorPool;
} }
const VkClearValue &ContextVk::getClearColorValue() const const VkClearValue &ContextVk::getClearColorValue() const
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <vulkan/vulkan.h> #include <vulkan/vulkan.h>
#include "libANGLE/renderer/ContextImpl.h" #include "libANGLE/renderer/ContextImpl.h"
#include "libANGLE/renderer/vulkan/DynamicDescriptorPool.h"
#include "libANGLE/renderer/vulkan/StreamingBuffer.h" #include "libANGLE/renderer/vulkan/StreamingBuffer.h"
#include "libANGLE/renderer/vulkan/vk_cache_utils.h" #include "libANGLE/renderer/vulkan/vk_cache_utils.h"
...@@ -156,7 +157,7 @@ class ContextVk : public ContextImpl ...@@ -156,7 +157,7 @@ class ContextVk : public ContextImpl
void invalidateCurrentPipeline(); void invalidateCurrentPipeline();
void onVertexArrayChange(); void onVertexArrayChange();
vk::DescriptorPool *getDescriptorPool(); DynamicDescriptorPool *getDynamicDescriptorPool();
const VkClearValue &getClearColorValue() const; const VkClearValue &getClearColorValue() const;
const VkClearValue &getClearDepthStencilValue() const; const VkClearValue &getClearDepthStencilValue() const;
...@@ -180,9 +181,9 @@ class ContextVk : public ContextImpl ...@@ -180,9 +181,9 @@ class ContextVk : public ContextImpl
// Kept in a pointer so allocations can be aligned, and structs can be portably packed. // Kept in a pointer so allocations can be aligned, and structs can be portably packed.
std::unique_ptr<vk::PipelineDesc> mPipelineDesc; std::unique_ptr<vk::PipelineDesc> mPipelineDesc;
// The descriptor pool is externally sychronized, so cannot be accessed from different threads // The dynamic descriptor pool is externally sychronized, so cannot be accessed from different
// simultaneously. Hence, we keep it in the ContextVk instead of the RendererVk. // threads simultaneously. Hence, we keep it in the ContextVk instead of the RendererVk.
vk::DescriptorPool mDescriptorPool; DynamicDescriptorPool mDynamicDescriptorPool;
// Triggers adding dependencies to the command graph. // Triggers adding dependencies to the command graph.
bool mVertexArrayDirty; 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 @@ ...@@ -13,6 +13,7 @@
#include "common/utilities.h" #include "common/utilities.h"
#include "libANGLE/Context.h" #include "libANGLE/Context.h"
#include "libANGLE/renderer/vulkan/ContextVk.h" #include "libANGLE/renderer/vulkan/ContextVk.h"
#include "libANGLE/renderer/vulkan/DynamicDescriptorPool.h"
#include "libANGLE/renderer/vulkan/GlslangWrapper.h" #include "libANGLE/renderer/vulkan/GlslangWrapper.h"
#include "libANGLE/renderer/vulkan/RendererVk.h" #include "libANGLE/renderer/vulkan/RendererVk.h"
#include "libANGLE/renderer/vulkan/TextureVk.h" #include "libANGLE/renderer/vulkan/TextureVk.h"
...@@ -194,13 +195,6 @@ vk::Error ProgramVk::reset(ContextVk *contextVk) ...@@ -194,13 +195,6 @@ vk::Error ProgramVk::reset(ContextVk *contextVk)
mVertexModuleSerial = Serial(); mVertexModuleSerial = Serial();
mFragmentModuleSerial = 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(); mDescriptorSets.clear();
mUsedDescriptorSetRange.invalidate(); mUsedDescriptorSetRange.invalidate();
mDirtyTextures = false; mDirtyTextures = false;
...@@ -661,25 +655,17 @@ vk::Error ProgramVk::initDescriptorSets(ContextVk *contextVk) ...@@ -661,25 +655,17 @@ vk::Error ProgramVk::initDescriptorSets(ContextVk *contextVk)
ASSERT(mDescriptorSets.empty()); ASSERT(mDescriptorSets.empty());
RendererVk *renderer = contextVk->getRenderer(); RendererVk *renderer = contextVk->getRenderer();
VkDevice device = contextVk->getDevice();
// Write out to a new a descriptor set. // Write out to a new a descriptor set.
// TODO(jmadill): Handle descriptor set lifetime. DynamicDescriptorPool *dynamicDescriptorPool = contextVk->getDynamicDescriptorPool();
vk::DescriptorPool *descriptorPool = contextVk->getDescriptorPool();
const auto &descriptorSetLayouts = renderer->getGraphicsDescriptorSetLayouts(); const auto &descriptorSetLayouts = renderer->getGraphicsDescriptorSetLayouts();
uint32_t descriptorSetCount = static_cast<uint32_t>(descriptorSetLayouts.size()); 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); 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(); return vk::NoError();
} }
......
...@@ -33,6 +33,9 @@ namespace rx ...@@ -33,6 +33,9 @@ namespace rx
namespace 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, VkResult VerifyExtensionsPresent(const std::vector<VkExtensionProperties> &extensionProps,
const std::vector<const char *> &enabledExtensionNames) const std::vector<const char *> &enabledExtensionNames)
...@@ -593,6 +596,18 @@ const gl::Limitations &RendererVk::getNativeLimitations() const ...@@ -593,6 +596,18 @@ const gl::Limitations &RendererVk::getNativeLimitations() const
return mNativeLimitations; 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 const vk::CommandPool &RendererVk::getCommandPool() const
{ {
return mCommandPool; return mCommandPool;
...@@ -847,10 +862,7 @@ vk::Error RendererVk::initGraphicsPipelineLayout() ...@@ -847,10 +862,7 @@ vk::Error RendererVk::initGraphicsPipelineLayout()
mGraphicsDescriptorSetLayouts.push_back(std::move(uniformLayout)); mGraphicsDescriptorSetLayouts.push_back(std::move(uniformLayout));
} }
// TODO(lucferron): expose this limitation to GL in Context Caps std::vector<VkDescriptorSetLayoutBinding> textureBindings(getMaxActiveTextures());
std::vector<VkDescriptorSetLayoutBinding> textureBindings(
std::min<size_t>(mPhysicalDeviceProperties.limits.maxPerStageDescriptorSamplers,
gl::IMPLEMENTATION_MAX_ACTIVE_TEXTURES));
// TODO(jmadill): This approach might not work well for texture arrays. // TODO(jmadill): This approach might not work well for texture arrays.
for (uint32_t textureIndex = 0; textureIndex < textureBindings.size(); ++textureIndex) for (uint32_t textureIndex = 0; textureIndex < textureBindings.size(); ++textureIndex)
......
...@@ -46,6 +46,10 @@ class RendererVk : angle::NonCopyable ...@@ -46,6 +46,10 @@ class RendererVk : angle::NonCopyable
VkInstance getInstance() const { return mInstance; } VkInstance getInstance() const { return mInstance; }
VkPhysicalDevice getPhysicalDevice() const { return mPhysicalDevice; } VkPhysicalDevice getPhysicalDevice() const { return mPhysicalDevice; }
const VkPhysicalDeviceProperties &getPhysicalDeviceProperties() const
{
return mPhysicalDeviceProperties;
}
VkQueue getQueue() const { return mQueue; } VkQueue getQueue() const { return mQueue; }
VkDevice getDevice() const { return mDevice; } VkDevice getDevice() const { return mDevice; }
...@@ -62,6 +66,8 @@ class RendererVk : angle::NonCopyable ...@@ -62,6 +66,8 @@ class RendererVk : angle::NonCopyable
const gl::TextureCapsMap &getNativeTextureCaps() const; const gl::TextureCapsMap &getNativeTextureCaps() const;
const gl::Extensions &getNativeExtensions() const; const gl::Extensions &getNativeExtensions() const;
const gl::Limitations &getNativeLimitations() const; const gl::Limitations &getNativeLimitations() const;
uint32_t getMaxActiveTextures();
uint32_t getUniformBufferDescriptorCount();
GlslangWrapper *getGlslangWrapper(); GlslangWrapper *getGlslangWrapper();
......
...@@ -756,6 +756,8 @@ ...@@ -756,6 +756,8 @@
'libANGLE/renderer/vulkan/DeviceVk.h', 'libANGLE/renderer/vulkan/DeviceVk.h',
'libANGLE/renderer/vulkan/DisplayVk.cpp', 'libANGLE/renderer/vulkan/DisplayVk.cpp',
'libANGLE/renderer/vulkan/DisplayVk.h', 'libANGLE/renderer/vulkan/DisplayVk.h',
'libANGLE/renderer/vulkan/DynamicDescriptorPool.cpp',
'libANGLE/renderer/vulkan/DynamicDescriptorPool.h',
'libANGLE/renderer/vulkan/FenceNVVk.cpp', 'libANGLE/renderer/vulkan/FenceNVVk.cpp',
'libANGLE/renderer/vulkan/FenceNVVk.h', 'libANGLE/renderer/vulkan/FenceNVVk.h',
'libANGLE/renderer/vulkan/FramebufferVk.cpp', '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