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

@ -40,7 +40,7 @@ namespace skyline {
gpuDriver = ktSettings.GetString("gpuDriver");
gpuDriverLibraryName = ktSettings.GetString("gpuDriverLibraryName");
executorSlotCount = ktSettings.GetInt<u32>("executorSlotCount");
enableTextureReadbackHack = ktSettings.GetBool("enableTextureReadbackHack");
enableFastGpuReadbackHack = ktSettings.GetBool("enableFastGpuReadbackHack");
isAudioOutputDisabled = ktSettings.GetBool("isAudioOutputDisabled");
validationLayer = ktSettings.GetBool("validationLayer");
};

View File

@ -72,7 +72,9 @@ namespace skyline {
Setting<std::string> gpuDriver; //!< The label of the GPU driver to use
Setting<std::string> gpuDriverLibraryName; //!< The name of the GPU driver library to use
Setting<u32> executorSlotCount; //!< Number of GPU executor slots that can be used concurrently
Setting<bool> enableTextureReadbackHack; //!< If the CPU texture readback skipping hack should be used
// Hacks
Setting<bool> enableFastGpuReadbackHack; //!< If the CPU texture readback skipping hack should be used
// Audio
Setting<bool> isAudioOutputDisabled; //!< Disables audio output

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;
}

View File

@ -26,7 +26,9 @@ class NativeSettings(context : Context, pref : PreferenceSettings) {
var gpuDriver : String = if (pref.gpuDriver == PreferenceSettings.SYSTEM_GPU_DRIVER) "" else pref.gpuDriver
var gpuDriverLibraryName : String = if (pref.gpuDriver == PreferenceSettings.SYSTEM_GPU_DRIVER) "" else GpuDriverHelper.getLibraryName(context, pref.gpuDriver)
var executorSlotCount : Int = pref.executorSlotCount
var enableTextureReadbackHack : Boolean = pref.enableTextureReadbackHack
// Hacks
var enableFastGpuReadbackHack : Boolean = pref.enableFastGpuReadbackHack
// Audio
var isAudioOutputDisabled : Boolean = pref.isAudioOutputDisabled

View File

@ -39,7 +39,9 @@ class PreferenceSettings @Inject constructor(@ApplicationContext private val con
// GPU
var gpuDriver by sharedPreferences(context, SYSTEM_GPU_DRIVER)
var executorSlotCount by sharedPreferences(context, 6)
var enableTextureReadbackHack by sharedPreferences(context, false)
// Hacks
var enableFastGpuReadbackHack by sharedPreferences(context, false)
// Audio
var isAudioOutputDisabled by sharedPreferences(context, false)

View File

@ -75,9 +75,11 @@
<string name="respect_display_cutout_disabled">Allow UI elements to be drawn in the cutout area</string>
<string name="executor_slot_count">Executor Slot Count</string>
<string name="executor_slot_count_desc">Maximum number of simultaneous GPU executions (Higher may sometimes perform better but will use more RAM)</string>
<string name="enable_texture_readback_hack">Enable Texture Readback Hack</string>
<string name="enable_texture_readback_hack_enabled">Texture readback hack is enabled (Will break some games but others will have higher performance)</string>
<string name="enable_texture_readback_hack_disabled">Texture readback hack is disabled (Ensures highest accuracy)</string>
<!-- Settings - Hacks -->
<string name="hacks">Hacks</string>
<string name="enable_fast_gpu_readback">Enable fast GPU readback</string>
<string name="enable_fast_gpu_readback_enabled">Fast GPU readback is enabled (Will break some games but others will have higher performance)</string>
<string name="enable_fast_gpu_readback_disabled">Fast GPU readback is disabled (Ensures highest accuracy)</string>
<!-- Settings - Audio -->
<string name="audio">Audio</string>
<string name="disable_audio_output">Disable Audio Output</string>

View File

@ -135,12 +135,16 @@
app:key="executor_slot_count"
app:title="@string/executor_slot_count"
app:showSeekBarValue="true" />
</PreferenceCategory>
<PreferenceCategory
android:key="category_hacks"
android:title="@string/hacks">
<CheckBoxPreference
android:defaultValue="false"
android:summaryOff="@string/enable_texture_readback_hack_disabled"
android:summaryOn="@string/enable_texture_readback_hack_enabled"
app:key="enable_texture_readback_hack"
app:title="@string/enable_texture_readback_hack" />
android:summaryOff="@string/enable_fast_gpu_readback_enabled"
android:summaryOn="@string/enable_fast_gpu_readback_disabled"
app:key="enable_fast_gpu_readback_hack"
app:title="@string/enable_fast_gpu_readback" />
</PreferenceCategory>
<PreferenceCategory
android:key="category_audio"