Apply GPU readback hack to both buffers and textures

And rename as appropriate.
This commit is contained in:
Billy Laws
2022-11-18 20:48:39 +00:00
parent f358c4517e
commit 281838fde1
9 changed files with 45 additions and 13 deletions

View File

@ -5,6 +5,7 @@
#include <kernel/memory.h>
#include <kernel/types/KProcess.h>
#include <common/trace.h>
#include <common/settings.h>
#include "buffer.h"
namespace skyline::gpu {
@ -38,8 +39,14 @@ namespace skyline::gpu {
// If this mutex would cause other callbacks to be blocked then we should block on this mutex in advance
std::shared_ptr<FenceCycle> waitCycle{};
do {
if (waitCycle)
if (waitCycle) {
i64 startNs{buffer->accumulatedGuestWaitCounter > FastReadbackHackWaitCountThreshold ? util::GetTimeNs() : 0};
waitCycle->Wait();
if (startNs)
buffer->accumulatedGuestWaitTime += std::chrono::nanoseconds(util::GetTimeNs() - startNs);
buffer->accumulatedGuestWaitCounter++;
}
std::scoped_lock lock{*buffer};
if (waitCycle && buffer->cycle == waitCycle) {
@ -89,6 +96,14 @@ namespace skyline::gpu {
return true;
}
if (buffer->accumulatedGuestWaitTime > FastReadbackHackWaitTimeThreshold && *buffer->gpu.state.settings->enableFastGpuReadbackHack) {
// As opposed to skipping readback as we do for textures, with buffers we can still perform the readback but just without syncinc the GPU
// While the read data may be invalid it's still better than nothing and works in most cases
memcpy(buffer->mirror.data(), buffer->backing.data(), buffer->mirror.size());
buffer->dirtyState = DirtyState::Clean;
return true;
}
std::unique_lock lock{*buffer, std::try_to_lock};
if (!lock)
return false;

View File

@ -90,6 +90,11 @@ namespace skyline::gpu {
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
static constexpr size_t FastReadbackHackWaitCountThreshold{8}; //!< Threshold for the number of times a buffer can be waited on before it should be considered for the readback hack
static constexpr std::chrono::nanoseconds FastReadbackHackWaitTimeThreshold{constant::NsInSecond / 2}; //!< Threshold for the amount of time buffer texture can be waited on before it should be considered for the readback hack, `SkipReadbackHackWaitCountThreshold` needs to be hit before this
size_t accumulatedGuestWaitCounter{}; //!< Total number of times the buffer has been waited on
std::chrono::nanoseconds accumulatedGuestWaitTime{}; //!< Amount of time the buffer has been waited on for since the `FastReadbackHackWaitTimeThreshold`th wait on it by the guest
/**
* @brief Resets all megabuffer tracking state
*/

View File

@ -225,7 +225,7 @@ namespace skyline::gpu {
return true; // If the texture is already CPU dirty or we can transition it to being CPU dirty then we don't need to do anything
}
if (texture->accumulatedGuestWaitTime > SkipReadbackHackWaitTimeThreshold && *texture->gpu.state.settings->enableTextureReadbackHack) {
if (texture->accumulatedGuestWaitTime > SkipReadbackHackWaitTimeThreshold && *texture->gpu.state.settings->enableFastGpuReadbackHack) {
texture->dirtyState = DirtyState::Clean;
return true;
}