Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reuse allocated descriptor sets #3002

Merged
merged 6 commits into from
Nov 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions include/mbgl/util/instrumentation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ const void* castGpuIdToTracyPtr(GpuId id) {
return reinterpret_cast<const void*>(static_cast<std::ptrdiff_t>(id));
}

#ifndef MLN_RENDER_BACKEND_OPENGL
#if !defined(MLN_RENDER_BACKEND_OPENGL) && !defined(MLN_RENDER_BACKEND_VULKAN)
#error \
"MLN_RENDER_BACKEND_OPENGL is not defined. MLN_RENDER_BACKEND_OPENGL is expected to be defined in CMake and Bazel"
"MLN_RENDER_BACKEND_OPENGL/MLN_RENDER_BACKEND_VULKAN is not defined. \
MLN_RENDER_BACKEND_OPENGL/MLN_RENDER_BACKEND_VULKAN is expected to be defined in CMake and Bazel"
#endif

#define MLN_TRACE_FUNC() ZoneScoped
Expand Down Expand Up @@ -88,14 +89,21 @@ constexpr const char* tracyConstMemoryLabel = "Constant Buffer Memory";
#undef glGetQueryObjectui64v
#undef GLint

#else // MLN_RENDER_BACKEND_OPENGL
#elif MLN_RENDER_BACKEND_VULKAN

#define MLN_END_FRAME() \
do { \
FrameMark; \
} while (0);

#else

#define MLN_TRACE_GL_CONTEXT() ((void)0)
#define MLN_TRACE_GL_ZONE(label) ((void)0)
#define MLN_TRACE_FUNC_GL() ((void)0)
#define MLN_END_FRAME() FrameMark

#endif // MLN_RENDER_BACKEND_OPENGL
#endif

#else // MLN_TRACY_ENABLE

Expand Down
2 changes: 2 additions & 0 deletions include/mbgl/vulkan/descriptor_set.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <mbgl/gfx/uniform_buffer.hpp>
#include <mbgl/vulkan/buffer_resource.hpp>
#include <span>
#include <queue>

namespace mbgl {
namespace vulkan {
Expand All @@ -21,6 +22,7 @@ struct DescriptorPoolGrowable {
struct PoolInfo {
vk::UniqueDescriptorPool pool;
uint32_t remainingSets{0};
std::queue<std::vector<vk::DescriptorSet>> unusedSets;

PoolInfo(vk::UniqueDescriptorPool&& pool_, uint32_t remainingSets_)
: pool(std::move(pool_)),
Expand Down
2 changes: 2 additions & 0 deletions include/mbgl/vulkan/texture2d.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ class Texture2D : public gfx::Texture2D {
size_t getPixelStride() const noexcept override;
size_t numChannels() const noexcept override;

bool isDirty() const { return samplerStateDirty || textureDirty; }

void create() noexcept override;

void upload() noexcept override;
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion metrics/ignores/linux-vulkan.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"render-tests/fill-extrusion-color/function": "Layer Z Fighting: https://github.com/maplibre/maplibre-native/issues/1847",
"render-tests/tilejson-bounds/default": "flaky on CI"
"render-tests/tilejson-bounds/default": "flaky on CI",
"render-tests/icon-text-fit/textFit-grid-long": "Needs to be investigated"
}
5 changes: 5 additions & 0 deletions src/mbgl/vulkan/buffer_resource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <mbgl/vulkan/context.hpp>
#include <mbgl/vulkan/renderer_backend.hpp>
#include <mbgl/util/logging.hpp>
#include <mbgl/util/instrumentation.hpp>

#include <algorithm>

Expand Down Expand Up @@ -48,6 +49,8 @@ BufferResource::BufferResource(
size(size_),
usage(usage_),
persistent(persistent_) {
MLN_TRACE_FUNC();

const auto& allocator = context.getBackend().getAllocator();

std::size_t totalSize = size;
Expand Down Expand Up @@ -141,6 +144,8 @@ BufferResource& BufferResource::operator=(BufferResource&& other) noexcept {
}

void BufferResource::update(const void* newData, std::size_t updateSize, std::size_t offset) noexcept {
MLN_TRACE_FUNC();

assert(updateSize + offset <= size);
updateSize = std::min(updateSize, size - offset);
if (updateSize <= 0) {
Expand Down
9 changes: 9 additions & 0 deletions src/mbgl/vulkan/context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ void Context::enqueueDeletion(std::function<void(Context&)>&& function) {
}

void Context::submitOneTimeCommand(const std::function<void(const vk::UniqueCommandBuffer&)>& function) const {
MLN_TRACE_FUNC();

const vk::CommandBufferAllocateInfo allocateInfo(
backend.getCommandPool().get(), vk::CommandBufferLevel::ePrimary, 1);

Expand All @@ -170,6 +172,7 @@ void Context::submitOneTimeCommand(const std::function<void(const vk::UniqueComm
}

void Context::waitFrame() const {
MLN_TRACE_FUNC();
const auto& device = backend.getDevice();
auto& frame = frameResources[frameResourceIndex];
constexpr uint64_t timeout = std::numeric_limits<uint64_t>::max();
Expand All @@ -180,6 +183,8 @@ void Context::waitFrame() const {
}
}
void Context::beginFrame() {
MLN_TRACE_FUNC();

const auto& device = backend.getDevice();
auto& renderableResource = backend.getDefaultRenderable().getResource<SurfaceRenderableResource>();
const auto& platformSurface = renderableResource.getPlatformSurface();
Expand Down Expand Up @@ -208,6 +213,7 @@ void Context::beginFrame() {
frame.runDeletionQueue(*this);

if (platformSurface) {
MLN_TRACE_ZONE(acquireNextImageKHR);
try {
const vk::ResultValue acquireImageResult = device->acquireNextImageKHR(
renderableResource.getSwapchain().get(), timeout, frame.surfaceSemaphore.get(), nullptr);
Expand Down Expand Up @@ -245,6 +251,7 @@ void Context::endFrame() {
}

void Context::submitFrame() {
MLN_TRACE_FUNC();
const auto& frame = frameResources[frameResourceIndex];
frame.commandBuffer->end();

Expand Down Expand Up @@ -626,6 +633,8 @@ const vk::UniquePipelineLayout& Context::getPushConstantPipelineLayout() {
}

void Context::FrameResources::runDeletionQueue(Context& context) {
MLN_TRACE_FUNC();

for (const auto& function : deletionQueue) function(context);

deletionQueue.clear();
Expand Down
78 changes: 61 additions & 17 deletions src/mbgl/vulkan/descriptor_set.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@
#include <mbgl/vulkan/command_encoder.hpp>
#include <mbgl/vulkan/texture2d.hpp>
#include <mbgl/util/logging.hpp>
#include <mbgl/util/instrumentation.hpp>

#include <cassert>
#include <math.h>

#define USE_DESCRIPTOR_POOL_RESET

namespace mbgl {
namespace vulkan {

Expand All @@ -19,8 +22,12 @@ DescriptorSet::~DescriptorSet() {
context.enqueueDeletion(
[type_ = type, poolIndex = descriptorPoolIndex, sets = std::move(descriptorSets)](auto& context_) mutable {
auto& poolInfo = context_.getDescriptorPool(type_).pools[poolIndex];
#ifdef USE_DESCRIPTOR_POOL_RESET
poolInfo.unusedSets.push(std::move(sets));
#else
context_.getBackend().getDevice()->freeDescriptorSets(poolInfo.pool.get(), sets);
poolInfo.remainingSets += sets.size();
#endif
});
}

Expand All @@ -34,15 +41,21 @@ void DescriptorSet::createDescriptorPool(DescriptorPoolGrowable& growablePool) {
: vk::DescriptorType::eCombinedImageSampler,
maxSets * growablePool.descriptorsPerSet};

const auto descriptorPoolInfo = vk::DescriptorPoolCreateInfo(vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet)
.setPoolSizes(size)
.setMaxSets(maxSets);
#ifdef USE_DESCRIPTOR_POOL_RESET
const auto poolFlags = vk::DescriptorPoolCreateFlags();
#else
const auto poolFlags = vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet;
#endif

const auto descriptorPoolInfo = vk::DescriptorPoolCreateInfo(poolFlags).setPoolSizes(size).setMaxSets(maxSets);

growablePool.pools.emplace_back(device->createDescriptorPoolUnique(descriptorPoolInfo), maxSets);
growablePool.currentPoolIndex = growablePool.pools.size() - 1;
};

void DescriptorSet::allocate() {
MLN_TRACE_FUNC();

if (!descriptorSets.empty()) {
return;
}
Expand All @@ -52,31 +65,55 @@ void DescriptorSet::allocate() {
auto& growablePool = context.getDescriptorPool(type);
const std::vector<vk::DescriptorSetLayout> layouts(context.getBackend().getMaxFrames(), descriptorSetLayout);

if (growablePool.currentPoolIndex == -1 || growablePool.current().remainingSets < layouts.size()) {
const auto& poolIt = std::find_if(growablePool.pools.begin(), growablePool.pools.end(), [&](const auto& p) {
return p.remainingSets >= layouts.size();
});

if (poolIt != growablePool.pools.end()) {
growablePool.currentPoolIndex = std::distance(growablePool.pools.begin(), poolIt);
} else {
createDescriptorPool(growablePool);
if (growablePool.currentPoolIndex == -1 ||
(growablePool.current().unusedSets.empty() && growablePool.current().remainingSets < layouts.size())) {
#ifdef USE_DESCRIPTOR_POOL_RESET
// find a pool that has unused allocated descriptor sets
const auto& unusedPoolIt = std::find_if(
growablePool.pools.begin(), growablePool.pools.end(), [&](const auto& p) { return !p.unusedSets.empty(); });

if (unusedPoolIt != growablePool.pools.end()) {
growablePool.currentPoolIndex = std::distance(growablePool.pools.begin(), unusedPoolIt);
} else
#endif
{
// find a pool that has available memory to allocate more descriptor sets
const auto& freePoolIt = std::find_if(growablePool.pools.begin(),
growablePool.pools.end(),
[&](const auto& p) { return p.remainingSets >= layouts.size(); });

if (freePoolIt != growablePool.pools.end()) {
growablePool.currentPoolIndex = std::distance(growablePool.pools.begin(), freePoolIt);
} else {
createDescriptorPool(growablePool);
}
}
}

descriptorPoolIndex = growablePool.currentPoolIndex;
descriptorSets = device->allocateDescriptorSets(
vk::DescriptorSetAllocateInfo().setDescriptorPool(growablePool.current().pool.get()).setSetLayouts(layouts));
growablePool.current().remainingSets -= descriptorSets.size();

markDirty(true);
#ifdef USE_DESCRIPTOR_POOL_RESET
if (!growablePool.current().unusedSets.empty()) {
descriptorSets = growablePool.current().unusedSets.front();
growablePool.current().unusedSets.pop();
} else
#endif
{
descriptorSets = device->allocateDescriptorSets(vk::DescriptorSetAllocateInfo()
.setDescriptorPool(growablePool.current().pool.get())
.setSetLayouts(layouts));
growablePool.current().remainingSets -= descriptorSets.size();
}

dirty = std::vector(descriptorSets.size(), true);
}

void DescriptorSet::markDirty(bool value) {
dirty = std::vector(descriptorSets.size(), value);
std::fill(dirty.begin(), dirty.end(), value);
}

void DescriptorSet::bind(CommandEncoder& encoder) {
MLN_TRACE_FUNC();
auto& commandBuffer = encoder.getCommandBuffer();

const uint8_t index = context.getCurrentFrameResourceIndex();
Expand All @@ -94,6 +131,8 @@ UniformDescriptorSet::UniformDescriptorSet(Context& context_, DescriptorSetType
void UniformDescriptorSet::update(const gfx::UniformBufferArray& uniforms,
uint32_t uniformStartIndex,
uint32_t descriptorBindingCount) {
MLN_TRACE_FUNC();

allocate();

const uint8_t frameIndex = context.getCurrentFrameResourceIndex();
Expand Down Expand Up @@ -127,12 +166,15 @@ void UniformDescriptorSet::update(const gfx::UniformBufferArray& uniforms,

device->updateDescriptorSets(writeDescriptorSet, nullptr);
}

dirty[frameIndex] = false;
}

ImageDescriptorSet::ImageDescriptorSet(Context& context_)
: DescriptorSet(context_, DescriptorSetType::DrawableImage) {}

void ImageDescriptorSet::update(const std::array<gfx::Texture2DPtr, shaders::maxTextureCountPerShader>& textures) {
MLN_TRACE_FUNC();
allocate();

const uint8_t frameIndex = context.getCurrentFrameResourceIndex();
Expand Down Expand Up @@ -160,6 +202,8 @@ void ImageDescriptorSet::update(const std::array<gfx::Texture2DPtr, shaders::max

device->updateDescriptorSets(writeDescriptorSet, nullptr);
}

dirty[frameIndex] = false;
}

} // namespace vulkan
Expand Down
21 changes: 21 additions & 0 deletions src/mbgl/vulkan/drawable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <mbgl/util/logging.hpp>
#include <mbgl/util/variant.hpp>
#include <mbgl/util/hash.hpp>
#include <mbgl/util/instrumentation.hpp>

#include <cassert>
#if !defined(NDEBUG)
Expand Down Expand Up @@ -129,6 +130,8 @@ void Drawable::updateVertexAttributes(gfx::VertexAttributeArrayPtr vertices,
}

void Drawable::upload(gfx::UploadPass& uploadPass_) {
MLN_TRACE_FUNC();

if (isCustom) {
return;
}
Expand Down Expand Up @@ -234,6 +237,8 @@ void Drawable::upload(gfx::UploadPass& uploadPass_) {
}

void Drawable::draw(PaintParameters& parameters) const {
MLN_TRACE_FUNC();

if (isCustom) {
return;
}
Expand Down Expand Up @@ -334,6 +339,8 @@ gfx::UniformBufferArray& Drawable::mutableUniformBuffers() {
}

void Drawable::buildVulkanInputBindings() noexcept {
MLN_TRACE_FUNC();

impl->vulkanVertexBuffers.clear();
impl->vulkanVertexOffsets.clear();

Expand Down Expand Up @@ -386,6 +393,8 @@ void Drawable::buildVulkanInputBindings() noexcept {
}

bool Drawable::bindAttributes(CommandEncoder& encoder) const noexcept {
MLN_TRACE_FUNC();

if (impl->vulkanVertexBuffers.empty()) return false;

const auto& commandBuffer = encoder.getCommandBuffer();
Expand All @@ -403,6 +412,8 @@ bool Drawable::bindAttributes(CommandEncoder& encoder) const noexcept {
}

bool Drawable::bindDescriptors(CommandEncoder& encoder) const noexcept {
MLN_TRACE_FUNC();

if (!shader) return false;

// bind uniforms
Expand All @@ -415,6 +426,15 @@ bool Drawable::bindDescriptors(CommandEncoder& encoder) const noexcept {
impl->imageDescriptorSet = std::make_unique<ImageDescriptorSet>(encoder.getContext());
}

for (const auto& texture : textures) {
if (!texture) continue;
const auto textureImpl = static_cast<const Texture2D*>(texture.get());
if (textureImpl->isDirty()) {
impl->imageDescriptorSet->markDirty(true);
break;
}
}

impl->imageDescriptorSet->update(textures);
impl->imageDescriptorSet->bind(encoder);
}
Expand All @@ -423,6 +443,7 @@ bool Drawable::bindDescriptors(CommandEncoder& encoder) const noexcept {
}

void Drawable::uploadTextures(UploadPass&) const noexcept {
MLN_TRACE_FUNC();
for (const auto& texture : textures) {
if (texture) {
texture->upload();
Expand Down
5 changes: 5 additions & 0 deletions src/mbgl/vulkan/texture2d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ Texture2D::~Texture2D() {
}

gfx::Texture2D& Texture2D::setSamplerConfiguration(const SamplerState& samplerState_) noexcept {
if (samplerState.filter == samplerState_.filter && samplerState.wrapU == samplerState_.wrapU &&
samplerState.wrapV == samplerState_.wrapV) {
return *this;
}

samplerState = samplerState_;
samplerStateDirty = true;
return *this;
Expand Down
Loading
Loading