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:
parent
7ac9918b39
commit
5263307c4a
@ -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
|
||||
*
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -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
|
||||
*
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user