1
0
mirror of https://github.com/EduApps-CDG/OpenDX synced 2024-12-30 09:45:37 +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. * completed.
*/ */
void trackResource(Rc<DxvkResource> rc) { 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() { void DxvkLifetimeTracker::reset() {
for (const auto& resource : m_resources) for (const auto& resource : m_resources)
resource->release(); resource.first->release(resource.second);
m_resources.clear(); m_resources.clear();
} }

View File

@ -25,9 +25,10 @@ namespace dxvk {
* \brief Adds a resource to track * \brief Adds a resource to track
* \param [in] rc The resource to track * \param [in] rc The resource to track
*/ */
template<DxvkAccess Access>
void trackResource(Rc<DxvkResource>&& rc) { void trackResource(Rc<DxvkResource>&& rc) {
rc->acquire(); rc->acquire(Access);
m_resources.emplace_back(std::move(rc)); m_resources.emplace_back(std::move(rc), Access);
} }
/** /**
@ -40,7 +41,7 @@ namespace dxvk {
private: 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 { enum class DxvkAccess {
Read = 0, Read = 0,
Write = 1, Write = 1,
None = 2,
}; };
using DxvkAccessFlags = Flags<DxvkAccess>; using DxvkAccessFlags = Flags<DxvkAccess>;
@ -19,22 +20,63 @@ namespace dxvk {
* is recorded, it will be marked as 'in use'. * is recorded, it will be marked as 'in use'.
*/ */
class DxvkResource : public RcObject { 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: public:
virtual ~DxvkResource(); 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: private:
std::atomic<uint32_t> m_useCount = { 0u }; std::atomic<uint32_t> m_useCount = { 0u };
static constexpr uint32_t getIncrement(DxvkAccess access) {
return access == DxvkAccess::Write
? UseCountIncrementW
: UseCountIncrementR;
}
}; };
} }