1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-02-20 19:54:19 +01:00

[dxvk] Improve lifetime tracking logic

Reduces ref counting overhead on the CS thread a bit.
This commit is contained in:
Philip Rebohle 2024-09-25 16:34:50 +02:00 committed by Philip Rebohle
parent 7ac9918b39
commit 5263307c4a
6 changed files with 79 additions and 28 deletions

View File

@ -256,17 +256,31 @@ namespace dxvk {
* the device can guarantee that the submission has
* completed.
*/
template<DxvkAccess Access>
void trackResource(Rc<DxvkResourceAllocation>&& rc) {
m_resources.trackResource(DxvkLifetime<DxvkResourceAllocation>(std::move(rc), Access));
}
template<DxvkAccess Access>
void trackResource(const Rc<DxvkResourceAllocation>& rc) {
m_resources.trackResource(DxvkLifetime<DxvkResourceAllocation>(rc.ptr(), Access));
}
template<DxvkAccess Access, typename T>
void trackResource(Rc<T>&& rc) {
m_resources.trackResource(DxvkLifetime<DxvkResource>(std::move(rc), Access));
}
template<DxvkAccess Access, typename T>
void trackResource(const Rc<T>& rc) {
m_resources.trackResource<Access>(rc.ptr());
m_resources.trackResource(DxvkLifetime<DxvkResource>(rc.ptr(), Access));
}
template<DxvkAccess Access, typename T>
void trackResource(T* rc) {
// TODO remove this jank once things are refactored
m_resources.trackResource<Access>(rc);
m_resources.trackResource(DxvkLifetime<DxvkResource>(rc, Access));
}
/**
* \brief Tracks a GPU event
*

View File

@ -1821,7 +1821,7 @@ namespace dxvk {
Rc<DxvkResourceAllocation>&& slice) {
// Allocate new backing resource
Rc<DxvkResourceAllocation> prevAllocation = buffer->assignSlice(std::move(slice));
m_cmd->trackResource<DxvkAccess::None>(prevAllocation);
m_cmd->trackResource<DxvkAccess::None>(std::move(prevAllocation));
// We also need to update all bindings that the buffer
// may be bound to either directly or through views.

View File

@ -21,8 +21,16 @@ namespace dxvk {
DxvkLifetime() = default;
template<typename Tx>
DxvkLifetime(
T* resource,
Rc<Tx>&& resource,
DxvkAccess access)
: m_ptr(reinterpret_cast<uintptr_t>(resource.ptr()) | uintptr_t(access)) {
resource.unsafeExtract()->convertRef(DxvkAccess::None, access);
}
DxvkLifetime(
const T* resource,
DxvkAccess access)
: m_ptr(reinterpret_cast<uintptr_t>(resource) | uintptr_t(access)) {
acquire();
@ -92,37 +100,28 @@ namespace dxvk {
* device has finished using them.
*/
class DxvkLifetimeTracker {
public:
DxvkLifetimeTracker();
~DxvkLifetimeTracker();
/**
* \brief Adds a resource to track
* \param [in] rc The resource to track
* \param [in] res The resource to track
*/
template<DxvkAccess Access>
void trackResource(DxvkResource* rc) {
m_resources.emplace_back(rc, Access);
void trackResource(DxvkLifetime<DxvkResource>&& res) {
m_resources.push_back(std::move(res));
}
/**
* \brief Adds a resource allocation to track
* \param [in] rc The allocation to track
* \param [in] res The allocation to track
*/
template<DxvkAccess Access>
void trackResource(DxvkResourceAllocation* rc) {
m_allocations.emplace_back(rc, Access);
void trackResource(DxvkLifetime<DxvkResourceAllocation>&& res) {
m_allocations.push_back(std::move(res));
}
/**
* \brief Releases resources
*
* Marks all tracked resources as unused.
*/
void notify();
/**
* \brief Resets the command list
*
@ -130,12 +129,12 @@ namespace dxvk {
* the command list has completed execution.
*/
void reset();
private:
std::vector<DxvkLifetime<DxvkResource>> m_resources;
std::vector<DxvkLifetime<DxvkResourceAllocation>> m_allocations;
};
}

View File

@ -477,6 +477,21 @@ namespace dxvk {
free();
}
/**
* \brief Converts reference
*
* Decrements and increments the use counter according
* to the given access types in a single operation.
* \param [in] from Previous access type
* \param [in] to New access type
*/
force_inline void convertRef(DxvkAccess from, DxvkAccess to) {
uint64_t increment = getIncrement(to) - getIncrement(from);
if (increment)
m_useCount.fetch_add(increment, std::memory_order_acq_rel);
}
/**
* \brief Checks whether the resource is in use
*

View File

@ -76,6 +76,19 @@ namespace dxvk {
delete this;
}
/**
* \brief Converts reference type
*
* \param [in] from Old access type
* \param [in] to New access type
*/
void convertRef(DxvkAccess from, DxvkAccess to) {
uint64_t increment = getIncrement(to) - getIncrement(from);
if (increment)
m_useCount += increment;
}
/**
* \brief Checks whether resource is in use
*

View File

@ -2,6 +2,7 @@
#include <functional>
#include <ostream>
#include <utility>
namespace dxvk {
@ -106,6 +107,15 @@ namespace dxvk {
return m_object != nullptr;
}
void unsafeInsert(T* object) {
this->decRef();
m_object = object;
}
T* unsafeExtract() {
return std::exchange(m_object, nullptr);
}
private:
T* m_object = nullptr;