From 6719572b3b3aee497ee43e424bd75aded1a9eb45 Mon Sep 17 00:00:00 2001 From: Billy Laws Date: Sun, 9 Oct 2022 12:57:59 +0100 Subject: [PATCH] Keep track of how often textures/buffers are locked on the CPU For the upcoming preserve attachment optimisation, which will keep buffers/textures locked on the GPU between executions, we don't want to preserve any which are frequently locked on the CPU as that would result in lots of needless waiting for a resource to be unlocked by the GPU when it occasionally frees all preserve attachments when it could have been done much sooner. By checking if a resource has ever been locked on the CPU and using that to choose whether we preserve it we can avoid such waiting. --- app/src/main/cpp/skyline/gpu/buffer.cpp | 7 ++++++- app/src/main/cpp/skyline/gpu/buffer.h | 10 ++++++++++ app/src/main/cpp/skyline/gpu/texture/texture.cpp | 8 +++++++- app/src/main/cpp/skyline/gpu/texture/texture.h | 10 ++++++++++ 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/app/src/main/cpp/skyline/gpu/buffer.cpp b/app/src/main/cpp/skyline/gpu/buffer.cpp index f48e7a9c..42862bbc 100644 --- a/app/src/main/cpp/skyline/gpu/buffer.cpp +++ b/app/src/main/cpp/skyline/gpu/buffer.cpp @@ -331,6 +331,7 @@ namespace skyline::gpu { void Buffer::lock() { mutex.lock(); + accumulatedCpuLockCounter++; } bool Buffer::LockWithTag(ContextTag pTag) { @@ -349,7 +350,11 @@ namespace skyline::gpu { } bool Buffer::try_lock() { - return mutex.try_lock(); + if (mutex.try_lock()) { + accumulatedCpuLockCounter++; + return true; + } + return false; } BufferDelegate::BufferDelegate(Buffer *buffer) : buffer{buffer} {} diff --git a/app/src/main/cpp/skyline/gpu/buffer.h b/app/src/main/cpp/skyline/gpu/buffer.h index e4374657..f2d94461 100644 --- a/app/src/main/cpp/skyline/gpu/buffer.h +++ b/app/src/main/cpp/skyline/gpu/buffer.h @@ -89,6 +89,9 @@ namespace skyline::gpu { int megaBufferTableShift; //!< Shift to apply to buffer offsets to get their megabuffer table index std::vector megaBufferTable; //!< Table of megabuffer allocations for regions of the buffer + static constexpr size_t FrequentlyLockedThreshold{2}; //!< Threshold for the number of times a buffer can be locked (not from context locks, only normal) before it should be considered frequently locked + size_t accumulatedCpuLockCounter{}; //!< Number of times buffer has been locked through non-ContextLocks + private: BufferDelegate *delegate; @@ -214,6 +217,13 @@ namespace skyline::gpu { return SequencedCpuBackingWritesBlocked(); } + /** + * @return If the buffer is frequently locked by threads using non-ContextLocks + */ + bool FrequentlyLocked() { + return accumulatedCpuLockCounter >= FrequentlyLockedThreshold; + } + /** * @brief Waits on a fence cycle if it exists till it's signalled and resets it after * @note The buffer **must** be locked prior to calling this diff --git a/app/src/main/cpp/skyline/gpu/texture/texture.cpp b/app/src/main/cpp/skyline/gpu/texture/texture.cpp index c306132c..ac442107 100644 --- a/app/src/main/cpp/skyline/gpu/texture/texture.cpp +++ b/app/src/main/cpp/skyline/gpu/texture/texture.cpp @@ -614,6 +614,7 @@ namespace skyline::gpu { void Texture::lock() { mutex.lock(); + accumulatedCpuLockCounter++; } bool Texture::LockWithTag(ContextTag pTag) { @@ -631,7 +632,12 @@ namespace skyline::gpu { } bool Texture::try_lock() { - return mutex.try_lock(); + if (mutex.try_lock()) { + accumulatedCpuLockCounter++; + return true; + } + + return false; } bool Texture::WaitOnBacking() { diff --git a/app/src/main/cpp/skyline/gpu/texture/texture.h b/app/src/main/cpp/skyline/gpu/texture/texture.h index fefb9040..000a2122 100644 --- a/app/src/main/cpp/skyline/gpu/texture/texture.h +++ b/app/src/main/cpp/skyline/gpu/texture/texture.h @@ -423,6 +423,9 @@ namespace skyline::gpu { */ boost::container::small_vector GetBufferImageCopies(); + static constexpr size_t FrequentlyLockedThreshold{2}; //!< Threshold for the number of times a texture can be locked (not from context locks, only normal) before it should be considered frequently locked + size_t accumulatedCpuLockCounter{}; + public: std::shared_ptr cycle; //!< A fence cycle for when any host operation mutating the texture has completed, it must be waited on prior to any mutations to the backing std::optional guest; @@ -555,5 +558,12 @@ namespace skyline::gpu { .levelCount = VK_REMAINING_MIP_LEVELS, .layerCount = VK_REMAINING_ARRAY_LAYERS, }); + + /** + * @return If the texture is frequently locked by threads using non-ContextLocks + */ + bool FrequentlyLocked() { + return accumulatedCpuLockCounter >= FrequentlyLockedThreshold; + } }; }