Add CommandExecutor slot count setting

This commit is contained in:
Billy Laws 2022-10-16 20:50:06 +01:00
parent 1a0819fb76
commit 576bc6f37e
9 changed files with 41 additions and 11 deletions

View File

@ -39,6 +39,7 @@ namespace skyline {
disableFrameThrottling = ktSettings.GetBool("disableFrameThrottling"); disableFrameThrottling = ktSettings.GetBool("disableFrameThrottling");
gpuDriver = ktSettings.GetString("gpuDriver"); gpuDriver = ktSettings.GetString("gpuDriver");
gpuDriverLibraryName = ktSettings.GetString("gpuDriverLibraryName"); gpuDriverLibraryName = ktSettings.GetString("gpuDriverLibraryName");
executorSlotCount = ktSettings.GetInt<u32>("executorSlotCount");
validationLayer = ktSettings.GetBool("validationLayer"); validationLayer = ktSettings.GetBool("validationLayer");
}; };
}; };

View File

@ -71,6 +71,7 @@ namespace skyline {
// GPU // GPU
Setting<std::string> gpuDriver; //!< The label of the GPU driver to use 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<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
// Debug // Debug
Setting<bool> validationLayer; //!< If the vulkan validation layer is enabled Setting<bool> validationLayer; //!< If the vulkan validation layer is enabled

View File

@ -109,8 +109,6 @@ namespace skyline::gpu {
lock.unlock(); lock.unlock();
chainedCycles.Iterate([&](const auto &cycle) { chainedCycles.Iterate([&](const auto &cycle) {
if (!cycle->Find(this))
raise(SIGTRAP);
cycle->WaitSubmit(); cycle->WaitSubmit();
}); });
lock.lock(); lock.lock();
@ -129,7 +127,7 @@ namespace skyline::gpu {
return; return;
} }
chainedCycles.Iterate([shouldDestroy, this](auto &cycle) { chainedCycles.Iterate([shouldDestroy](auto &cycle) {
cycle->Wait(shouldDestroy); cycle->Wait(shouldDestroy);
}); });

View File

@ -2,12 +2,17 @@
// Copyright © 2021 Skyline Team and Contributors (https://github.com/skyline-emu/) // Copyright © 2021 Skyline Team and Contributors (https://github.com/skyline-emu/)
#include <range/v3/view.hpp> #include <range/v3/view.hpp>
#include <common/settings.h>
#include <loader/loader.h> #include <loader/loader.h>
#include <gpu.h> #include <gpu.h>
#include "command_executor.h" #include "command_executor.h"
namespace skyline::gpu::interconnect { namespace skyline::gpu::interconnect {
CommandRecordThread::CommandRecordThread(const DeviceState &state) : state{state}, thread{&CommandRecordThread::Run, this} {} CommandRecordThread::CommandRecordThread(const DeviceState &state)
: state{state},
incoming{*state.settings->executorSlotCount},
outgoing{*state.settings->executorSlotCount},
thread{&CommandRecordThread::Run, this} {}
static vk::raii::CommandBuffer AllocateRaiiCommandBuffer(GPU &gpu, vk::raii::CommandPool &pool) { static vk::raii::CommandBuffer AllocateRaiiCommandBuffer(GPU &gpu, vk::raii::CommandPool &pool) {
return {gpu.vkDevice, (*gpu.vkDevice).allocateCommandBuffers( return {gpu.vkDevice, (*gpu.vkDevice).allocateCommandBuffers(
@ -31,6 +36,13 @@ namespace skyline::gpu::interconnect {
semaphore{gpu.vkDevice, vk::SemaphoreCreateInfo{}}, semaphore{gpu.vkDevice, vk::SemaphoreCreateInfo{}},
cycle{std::make_shared<FenceCycle>(gpu.vkDevice, *fence, *semaphore, true)} {} cycle{std::make_shared<FenceCycle>(gpu.vkDevice, *fence, *semaphore, true)} {}
CommandRecordThread::Slot::Slot(Slot &&other)
: commandPool{std::move(other.commandPool)},
commandBuffer{std::move(other.commandBuffer)},
fence{std::move(other.fence)},
semaphore{std::move(other.semaphore)},
cycle{std::move(other.cycle)} {}
std::shared_ptr<FenceCycle> CommandRecordThread::Slot::Reset(GPU &gpu) { std::shared_ptr<FenceCycle> CommandRecordThread::Slot::Reset(GPU &gpu) {
cycle->Wait(); cycle->Wait();
cycle = std::make_shared<FenceCycle>(*cycle); cycle = std::make_shared<FenceCycle>(*cycle);
@ -79,7 +91,10 @@ namespace skyline::gpu::interconnect {
void CommandRecordThread::Run() { void CommandRecordThread::Run() {
auto &gpu{*state.gpu}; auto &gpu{*state.gpu};
std::array<Slot, ActiveRecordSlots> slots{{gpu, gpu, gpu, gpu, gpu, gpu}};
std::vector<Slot> slots{};
std::generate_n(std::back_inserter(slots), *state.settings->executorSlotCount, [&] () -> Slot { return gpu; });
outgoing.AppendTranform(span<Slot>(slots), [](auto &slot) { return &slot; }); outgoing.AppendTranform(span<Slot>(slots), [](auto &slot) { return &slot; });
if (int result{pthread_setname_np(pthread_self(), "Sky-CmdRecord")}) if (int result{pthread_setname_np(pthread_self(), "Sky-CmdRecord")})
@ -116,7 +131,8 @@ namespace skyline::gpu::interconnect {
} }
CommandExecutor::CommandExecutor(const DeviceState &state) CommandExecutor::CommandExecutor(const DeviceState &state)
: gpu{*state.gpu}, : state{state},
gpu{*state.gpu},
recordThread{state}, recordThread{state},
tag{AllocateTag()} { tag{AllocateTag()} {
RotateRecordSlot(); RotateRecordSlot();
@ -401,7 +417,7 @@ namespace skyline::gpu::interconnect {
allocator->Reset(); allocator->Reset();
// Periodically clear preserve attachments just in case there are new waiters which would otherwise end up waiting forever // Periodically clear preserve attachments just in case there are new waiters which would otherwise end up waiting forever
if ((submissionNumber % CommandRecordThread::ActiveRecordSlots * 2) == 0) { if ((submissionNumber % (*state.settings->executorSlotCount * 2)) == 0) {
preserveAttachedBuffers.clear(); preserveAttachedBuffers.clear();
preserveAttachedTextures.clear(); preserveAttachedTextures.clear();
} }

View File

@ -15,7 +15,6 @@ namespace skyline::gpu::interconnect {
*/ */
class CommandRecordThread { class CommandRecordThread {
public: public:
static constexpr size_t ActiveRecordSlots{6}; //!< Maximum number of simultaneously active slots
/** /**
* @brief Single execution slot, buffered back and forth between the GPFIFO thread and the record thread * @brief Single execution slot, buffered back and forth between the GPFIFO thread and the record thread
@ -32,6 +31,8 @@ namespace skyline::gpu::interconnect {
Slot(GPU &gpu); Slot(GPU &gpu);
Slot(Slot &&other);
/** /**
* @brief Waits on the fence and resets the command buffer * @brief Waits on the fence and resets the command buffer
* @note A new fence cycle for the reset command buffer * @note A new fence cycle for the reset command buffer
@ -41,10 +42,10 @@ namespace skyline::gpu::interconnect {
private: private:
const DeviceState &state; const DeviceState &state;
std::thread thread; CircularQueue<Slot *> incoming; //!< Slots pending recording
CircularQueue<Slot *> outgoing; //!< Slots that have been submitted, may still be active on the GPU
CircularQueue<Slot *> incoming{ActiveRecordSlots}; //!< Slots pending recording std::thread thread;
CircularQueue<Slot *> outgoing{ActiveRecordSlots}; //!< Slots that have been submitted, may still be active on the GPU
void ProcessSlot(Slot *slot); void ProcessSlot(Slot *slot);
@ -70,6 +71,7 @@ namespace skyline::gpu::interconnect {
*/ */
class CommandExecutor { class CommandExecutor {
private: private:
const DeviceState &state;
GPU &gpu; GPU &gpu;
CommandRecordThread recordThread; CommandRecordThread recordThread;
CommandRecordThread::Slot *slot{}; CommandRecordThread::Slot *slot{};

View File

@ -25,6 +25,7 @@ class NativeSettings(context : Context, pref : PreferenceSettings) {
// GPU // GPU
var gpuDriver : String = if (pref.gpuDriver == PreferenceSettings.SYSTEM_GPU_DRIVER) "" else pref.gpuDriver 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 gpuDriverLibraryName : String = if (pref.gpuDriver == PreferenceSettings.SYSTEM_GPU_DRIVER) "" else GpuDriverHelper.getLibraryName(context, pref.gpuDriver)
var executorSlotCount : Int = pref.executorSlotCount
// Debug // Debug
var validationLayer : Boolean = BuildConfig.BUILD_TYPE != "release" && pref.validationLayer var validationLayer : Boolean = BuildConfig.BUILD_TYPE != "release" && pref.validationLayer

View File

@ -38,6 +38,7 @@ class PreferenceSettings @Inject constructor(@ApplicationContext private val con
// GPU // GPU
var gpuDriver by sharedPreferences(context, SYSTEM_GPU_DRIVER) var gpuDriver by sharedPreferences(context, SYSTEM_GPU_DRIVER)
var executorSlotCount by sharedPreferences(context, 6)
// Debug // Debug
var validationLayer by sharedPreferences(context, false) var validationLayer by sharedPreferences(context, false)

View File

@ -70,6 +70,8 @@
<string name="respect_display_cutout">Respect Display Cutout</string> <string name="respect_display_cutout">Respect Display Cutout</string>
<string name="respect_display_cutout_enabled">Do not draw UI elements in the cutout area</string> <string name="respect_display_cutout_enabled">Do not draw UI elements in the cutout area</string>
<string name="respect_display_cutout_disabled">Allow UI elements to be drawn in the cutout area</string> <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>
<!-- Settings - Debug --> <!-- Settings - Debug -->
<string name="debug">Debug</string> <string name="debug">Debug</string>
<string name="validation_layer">Enable validation layer</string> <string name="validation_layer">Enable validation layer</string>

View File

@ -127,6 +127,14 @@
android:summaryOn="@string/respect_display_cutout_enabled" android:summaryOn="@string/respect_display_cutout_enabled"
app:key="respect_display_cutout" app:key="respect_display_cutout"
app:title="@string/respect_display_cutout" /> app:title="@string/respect_display_cutout" />
<SeekBarPreference
android:min="1"
android:defaultValue="6"
android:max="16"
android:summary="@string/executor_slot_count_desc"
app:key="executor_slot_count"
app:title="@string/executor_slot_count"
app:showSeekBarValue="true" />
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory <PreferenceCategory
android:key="category_debug" android:key="category_debug"