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

[dxvk] Implement read/write tracking in lifetime tracker

This way we will be able to more accurately determine how a
resource is going to be used by the GPU, and we can also cut
unnecessary atomic operations for non-resource objects.
This commit is contained in:
Philip Rebohle 2019-09-19 19:35:52 +02:00
parent 136ad3e4c9
commit 63183141bc
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
4 changed files with 54 additions and 11 deletions

View File

@ -147,7 +147,7 @@ namespace dxvk {
* completed.
*/
void trackResource(Rc<DxvkResource> rc) {
m_resources.trackResource(std::move(rc));
m_resources.trackResource<DxvkAccess::Write>(std::move(rc));
}
/**

View File

@ -8,7 +8,7 @@ namespace dxvk {
void DxvkLifetimeTracker::reset() {
for (const auto& resource : m_resources)
resource->release();
resource.first->release(resource.second);
m_resources.clear();
}

View File

@ -25,9 +25,10 @@ namespace dxvk {
* \brief Adds a resource to track
* \param [in] rc The resource to track
*/
template<DxvkAccess Access>
void trackResource(Rc<DxvkResource>&& rc) {
rc->acquire();
m_resources.emplace_back(std::move(rc));
rc->acquire(Access);
m_resources.emplace_back(std::move(rc), Access);
}
/**
@ -40,7 +41,7 @@ namespace dxvk {
private:
std::vector<Rc<DxvkResource>> m_resources;
std::vector<std::pair<Rc<DxvkResource>, DxvkAccess>> m_resources;
};

View File

@ -7,6 +7,7 @@ namespace dxvk {
enum class DxvkAccess {
Read = 0,
Write = 1,
None = 2,
};
using DxvkAccessFlags = Flags<DxvkAccess>;
@ -19,22 +20,63 @@ namespace dxvk {
* is recorded, it will be marked as 'in use'.
*/
class DxvkResource : public RcObject {
constexpr static uint32_t UseCountIncrementW = 1 << 18;
constexpr static uint32_t UseCountIncrementR = 1;
constexpr static uint32_t UseCountMaskW = ~(UseCountIncrementW - 1);
constexpr static uint32_t UseCountMaskR = ~(UseCountIncrementR - 1);
public:
virtual ~DxvkResource();
bool isInUse() const {
return m_useCount.load() != 0;
/**
* \brief Checks whether resource is in use
*
* Returns \c true if there are pending accesses to
* the resource by the GPU matching the given access
* type. Note that checking for reads will also return
* \c true if the resource is being written to.
* \param [in] access Access type to check for
* \returns \c true if the resource is in use
*/
bool isInUse(DxvkAccess access = DxvkAccess::Read) const {
uint32_t mask = access == DxvkAccess::Write
? UseCountMaskW
: UseCountMaskR;
return m_useCount.load() & mask;
}
void acquire() { m_useCount += 1; }
void release() { m_useCount -= 1; }
/**
* \brief Acquires resource
*
* Increments use count for the given access type.
* \param Access Resource access type
*/
void acquire(DxvkAccess access) {
if (access != DxvkAccess::None)
m_useCount += getIncrement(access);
}
/**
* \brief Releases resource
*
* Decrements use count for the given access type.
* \param Access Resource access type
*/
void release(DxvkAccess access) {
if (access != DxvkAccess::None)
m_useCount -= getIncrement(access);
}
private:
std::atomic<uint32_t> m_useCount = { 0u };
static constexpr uint32_t getIncrement(DxvkAccess access) {
return access == DxvkAccess::Write
? UseCountIncrementW
: UseCountIncrementR;
}
};
}