Vulkan: Remove legacy resource tracker

Before the render graph was introduced we relied on a submission
resource tracker that allowed to resuse resources in the next frame.
With the introduction of the render graph we slowly migrated the
resource tracking to the render graph and eventually also moved the
whole discard pools to the submission runner.

There was still one part that 'used' the legacy resource tracker, but
actually didn't as it never reused resources. This PR removes the
resource tracker and migrate the push constants to use the render graph
to update a single buffer per shader.

Pull Request: https://projects.blender.org/blender/blender/pulls/146627
This commit is contained in:
Jeroen Bakker
2025-09-23 12:46:23 +02:00
parent c8468f5cfa
commit ddef26505b
9 changed files with 14 additions and 255 deletions

View File

@@ -249,7 +249,6 @@ set(VULKAN_SRC
vulkan/render_graph/vk_resource_state_tracker.cc
vulkan/render_graph/vk_scheduler.cc
vulkan/vk_resource_pool.cc
vulkan/vk_resource_tracker.cc
vulkan/vk_sampler.cc
vulkan/vk_samplers.cc
vulkan/vk_shader.cc
@@ -324,7 +323,6 @@ set(VULKAN_SRC
vulkan/render_graph/vk_resource_state_tracker.hh
vulkan/render_graph/vk_scheduler.hh
vulkan/vk_resource_pool.hh
vulkan/vk_resource_tracker.hh
vulkan/vk_sampler.hh
vulkan/vk_samplers.hh
vulkan/vk_shader.hh

View File

@@ -13,17 +13,13 @@
namespace blender::gpu::render_graph {
VKRenderGraph::VKRenderGraph(VKResourceStateTracker &resources) : resources_(resources)
{
submission_id.reset();
}
VKRenderGraph::VKRenderGraph(VKResourceStateTracker &resources) : resources_(resources) {}
void VKRenderGraph::reset()
{
#if 0
memstats();
#endif
submission_id.next();
links_.clear_and_shrink();
for (VKRenderGraphNode &node : nodes_) {

View File

@@ -57,7 +57,6 @@
#include "vk_command_builder.hh"
#include "vk_render_graph_links.hh"
#include "vk_resource_state_tracker.hh"
#include "vk_resource_tracker.hh"
namespace blender::gpu::render_graph {
class VKScheduler;
@@ -123,8 +122,6 @@ class VKRenderGraph : public NonCopyable {
} debug_;
public:
VKSubmissionID submission_id;
/**
* Construct a new render graph instance.
*

View File

@@ -18,7 +18,6 @@
#include "vk_buffer.hh"
#include "vk_common.hh"
#include "vk_descriptor_set_layouts.hh"
#include "vk_resource_tracker.hh"
#include "vk_uniform_buffer.hh"
namespace blender::gpu {

View File

@@ -18,7 +18,6 @@
#include "vk_buffer.hh"
#include "vk_data_conversion.hh"
#include "vk_mem_alloc.h"
#include "vk_resource_tracker.hh"
#include "vk_vertex_attribute_object.hh"
namespace blender::gpu {

View File

@@ -149,22 +149,20 @@ void VKPushConstants::update_uniform_buffer()
{
BLI_assert(layout_->storage_type_get() == StorageType::UNIFORM_BUFFER);
BLI_assert(data_ != nullptr);
VKContext &context = *VKContext::get();
std::unique_ptr<VKUniformBuffer> &uniform_buffer = tracked_resource_for(context, is_dirty_);
uniform_buffer->reset_data_uploaded();
uniform_buffer->update(data_);
is_dirty_ = false;
if (!uniform_buffer_) {
uniform_buffer_ = std::make_unique<VKUniformBuffer>(layout_->size_in_bytes(),
"push constants buffer");
}
uniform_buffer_->reset_data_uploaded();
uniform_buffer_->update(data_);
}
std::unique_ptr<VKUniformBuffer> &VKPushConstants::uniform_buffer_get()
{
BLI_assert(layout_->storage_type_get() == StorageType::UNIFORM_BUFFER);
return active_resource();
}
std::unique_ptr<VKUniformBuffer> VKPushConstants::create_resource(VKContext & /*context*/)
{
return std::make_unique<VKUniformBuffer>(layout_->size_in_bytes(), __func__);
BLI_assert(uniform_buffer_);
return uniform_buffer_;
}
} // namespace blender::gpu

View File

@@ -45,7 +45,7 @@ class VKDevice;
* It should also keep track of the submissions in order to reuse the allocated
* data.
*/
class VKPushConstants : VKResourceTracker<VKUniformBuffer> {
class VKPushConstants {
friend class VKContext;
public:
@@ -157,7 +157,9 @@ class VKPushConstants : VKResourceTracker<VKUniformBuffer> {
private:
const Layout *layout_ = nullptr;
void *data_ = nullptr;
bool is_dirty_ = false;
/** Uniform buffer used to store the push constants when they don't fit. */
std::unique_ptr<VKUniformBuffer> uniform_buffer_;
public:
VKPushConstants();
@@ -177,11 +179,6 @@ class VKPushConstants : VKResourceTracker<VKUniformBuffer> {
return *layout_;
}
/**
* Part of Resource Tracking API is called when new resource is needed.
*/
std::unique_ptr<VKUniformBuffer> create_resource(VKContext &context) override;
/**
* Get the reference to the active data.
*
@@ -231,7 +228,6 @@ class VKPushConstants : VKResourceTracker<VKUniformBuffer> {
BLI_assert_msg(push_constant_layout->offset + copy_size_in_bytes <= layout_->size_in_bytes(),
"Tried to write outside the push constant allocated memory.");
memcpy(dst, input_data, copy_size_in_bytes);
is_dirty_ = true;
return;
}
@@ -258,8 +254,6 @@ class VKPushConstants : VKResourceTracker<VKUniformBuffer> {
}
}
}
is_dirty_ = true;
}
/**

View File

@@ -1,23 +0,0 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup gpu
*/
#include "vk_resource_tracker.hh"
#include "vk_context.hh"
namespace blender::gpu {
bool VKSubmissionTracker::is_changed(const VKContext &context)
{
const VKSubmissionID &current_id = context.render_graph().submission_id;
if (last_known_id_ != current_id) {
last_known_id_ = current_id;
return true;
}
return false;
}
} // namespace blender::gpu

View File

@@ -1,199 +0,0 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup gpu
*/
#pragma once
#include "BLI_utility_mixins.hh"
#include "BLI_vector.hh"
#include "vk_common.hh"
namespace blender::gpu {
namespace render_graph {
class VKRenderGraph;
}
class VKContext;
#if (defined(__GNUC__) && __GNUC__ >= 14 && !defined(__clang__))
# pragma GCC diagnostic push
/* CPP20 compiler warnings in GCC14+.
* Must be resolved before upgrading to a newer C++, avoid noisy warnings for now. */
# pragma GCC diagnostic ignored "-Wtemplate-id-cdtor"
#endif
/**
* In vulkan multiple commands can be in flight simultaneously.
*
* These commands can share the same resources like descriptor sets
* or push constants. When between commands these resources are updated
* a new version of these resources should be created.
*
* When a resource is updated it should check the submission id of the
* command buffer. If it is different, then the resource can be reused.
* If the submission id is the same a new version of the resource to now
* intervene with other commands that uses the resource.
*
* VKSubmissionID is the identifier to keep track if a new submission is
* being recorded.
*/
struct VKSubmissionID {
friend class render_graph::VKRenderGraph;
private:
int64_t id_ = -1;
public:
VKSubmissionID() = default;
private:
/**
* Reset the submission id.
*
* This should only be called during initialization of the command buffer.
* As it leads to undesired behavior after resources are already tracking
* the submission id.
*/
void reset()
{
id_ = 0;
}
/**
* Change the submission id.
*
* Is called when submitting a command buffer to the queue. In this case resource
* known that the next time it is used that it can free its sub resources used by
* the previous submission.
*/
void next()
{
id_++;
}
public:
const VKSubmissionID &operator=(const VKSubmissionID &other)
{
id_ = other.id_;
return *this;
}
bool operator==(const VKSubmissionID &other)
{
return id_ == other.id_;
}
bool operator!=(const VKSubmissionID &other)
{
return id_ != other.id_;
}
};
/**
* Submission tracker keeps track of the last known submission id of the
* command buffer.
*/
class VKSubmissionTracker {
VKSubmissionID last_known_id_;
public:
/**
* Check if the submission_id has changed since the last time it was called
* on this VKSubmissionTracker.
*/
bool is_changed(const VKContext &context);
};
/**
* VKResourceTracker will keep track of resources.
*/
template<typename Resource> class VKResourceTracker : NonCopyable {
VKSubmissionTracker submission_tracker_;
Vector<std::unique_ptr<Resource>> tracked_resources_;
protected:
VKResourceTracker() = default;
VKResourceTracker(VKResourceTracker<Resource> &&other)
: submission_tracker_(other.submission_tracker_),
tracked_resources_(std::move(other.tracked_resources_))
{
}
VKResourceTracker<Resource> &operator=(VKResourceTracker<Resource> &&other)
{
submission_tracker_ = other.submission_tracker_;
tracked_resources_ = std::move(other.tracked_resources_);
return *this;
}
virtual ~VKResourceTracker()
{
free_tracked_resources();
}
/**
* Get a resource what can be used by the resource tracker.
*
* When a different submission was detected all previous resources
* will be freed and a new resource will be returned.
*
* When still in the same submission and we need to update the resource
* (is_dirty=true) then a new resource will be returned. Otherwise
* the previous used resource will be used.
*
* When no resources exists, a new resource will be created.
*
* The resource given back is owned by this resource tracker. And
* the resource should not be stored outside this class as it might
* be destroyed when the next submission is detected.
*/
std::unique_ptr<Resource> &tracked_resource_for(VKContext &context, const bool is_dirty)
{
if (submission_tracker_.is_changed(context)) {
free_tracked_resources();
tracked_resources_.append(create_resource(context));
}
else if (is_dirty || tracked_resources_.is_empty()) {
tracked_resources_.append(create_resource(context));
}
return active_resource();
}
/**
* Callback to create a new resource. Can be called by the `tracked_resource_for` method.
*/
virtual std::unique_ptr<Resource> create_resource(VKContext &context) = 0;
/**
* Does this instance have an active resource.
*/
bool has_active_resource()
{
return !tracked_resources_.is_empty();
}
/**
* Return the active resource of the tracker.
*/
std::unique_ptr<Resource> &active_resource()
{
BLI_assert(!tracked_resources_.is_empty());
return tracked_resources_.last();
}
private:
void free_tracked_resources()
{
tracked_resources_.clear();
}
};
#if (defined(__GNUC__) && __GNUC__ >= 14 && !defined(__clang__))
# pragma GCC diagnostic pop
#endif
} // namespace blender::gpu