mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-27 01:55:28 +03:00
Fix deadlock on settings in PresentationEngine
after callback
Accessing the settings class during the execution of the `OnChangedCallback` results in a deadlock, as accesses to values are protected by a mutex. Instead, we now keep a local copy of the relevant settings and update those with the new value.
This commit is contained in:
parent
fc9b34846c
commit
dba191d2dc
@ -29,7 +29,9 @@ namespace skyline::gpu {
|
||||
presentationTrack{static_cast<u64>(trace::TrackIds::Presentation), perfetto::ProcessTrack::Current()},
|
||||
vsyncEvent{std::make_shared<kernel::type::KEvent>(state, true)},
|
||||
choreographerThread{&PresentationEngine::ChoreographerThread, this},
|
||||
presentationThread{&PresentationEngine::PresentationThread, this} {
|
||||
presentationThread{&PresentationEngine::PresentationThread, this},
|
||||
forceTripleBuffering{*state.settings->forceTripleBuffering},
|
||||
disableFrameThrottling{*state.settings->disableFrameThrottling} {
|
||||
auto desc{presentationTrack.Serialize()};
|
||||
desc.set_name("Presentation");
|
||||
perfetto::TrackEvent::SetTrackDescriptor(presentationTrack, desc);
|
||||
@ -203,7 +205,7 @@ namespace skyline::gpu {
|
||||
}); // We don't care about suboptimal images as they are caused by not respecting the transform hint, we handle transformations externally
|
||||
}
|
||||
|
||||
timestamp = (timestamp && !*state.settings->disableFrameThrottling) ? timestamp : getMonotonicNsNow(); // We tie FPS to the submission time rather than presentation timestamp, if we don't have the presentation timestamp available or if frame throttling is disabled as we want the maximum measured FPS to not be restricted to the refresh rate
|
||||
timestamp = (timestamp && !disableFrameThrottling) ? timestamp : getMonotonicNsNow(); // We tie FPS to the submission time rather than presentation timestamp, if we don't have the presentation timestamp available or if frame throttling is disabled as we want the maximum measured FPS to not be restricted to the refresh rate
|
||||
if (frameTimestamp) {
|
||||
i64 sampleWeight{Fps ? Fps : 1}; //!< The weight of each sample in calculating the average, we want to roughly average the past second
|
||||
|
||||
@ -281,7 +283,7 @@ namespace skyline::gpu {
|
||||
}
|
||||
|
||||
void PresentationEngine::UpdateSwapchain(texture::Format format, texture::Dimensions extent) {
|
||||
auto minImageCount{std::max(vkSurfaceCapabilities.minImageCount, *state.settings->forceTripleBuffering ? 3U : 2U)};
|
||||
auto minImageCount{std::max(vkSurfaceCapabilities.minImageCount, forceTripleBuffering ? 3U : 2U)};
|
||||
if (minImageCount > MaxSwapchainImageCount)
|
||||
throw exception("Requesting swapchain with higher image count ({}) than maximum slot count ({})", minImageCount, MaxSwapchainImageCount);
|
||||
|
||||
@ -305,7 +307,7 @@ namespace skyline::gpu {
|
||||
if ((capabilities.supportedUsageFlags & presentUsage) != presentUsage)
|
||||
throw exception("Swapchain doesn't support image usage '{}': {}", vk::to_string(presentUsage), vk::to_string(capabilities.supportedUsageFlags));
|
||||
|
||||
auto requestedMode{*state.settings->disableFrameThrottling ? vk::PresentModeKHR::eMailbox : vk::PresentModeKHR::eFifo};
|
||||
auto requestedMode{disableFrameThrottling ? vk::PresentModeKHR::eMailbox : vk::PresentModeKHR::eFifo};
|
||||
auto modes{gpu.vkPhysicalDevice.getSurfacePresentModesKHR(**vkSurface)};
|
||||
if (std::find(modes.begin(), modes.end(), requestedMode) == modes.end())
|
||||
throw exception("Swapchain doesn't support present mode: {}", vk::to_string(requestedMode));
|
||||
@ -342,9 +344,11 @@ namespace skyline::gpu {
|
||||
swapchainImageCount = vkImages.size();
|
||||
}
|
||||
|
||||
void PresentationEngine::OnDisableFrameThrottlingChanged(const bool &value) {
|
||||
void PresentationEngine::OnDisableFrameThrottlingChanged(const bool value) {
|
||||
std::scoped_lock guard{mutex};
|
||||
|
||||
disableFrameThrottling = value;
|
||||
|
||||
if (vkSurface && swapchainExtent && swapchainFormat)
|
||||
UpdateSwapchain(swapchainFormat, swapchainExtent);
|
||||
}
|
||||
|
@ -46,6 +46,9 @@ namespace skyline::gpu {
|
||||
size_t frameIndex{}; //!< The index of the next semaphore/fence to be used for acquiring swapchain images
|
||||
size_t swapchainImageCount{}; //!< The number of images in the current swapchain
|
||||
|
||||
bool forceTripleBuffering{}; //!< If the presentation engine should always triple buffer even if the swapchain supports double buffering
|
||||
bool disableFrameThrottling{}; //!< Allow the guest to submit frames without any blocking calls
|
||||
|
||||
i64 frameTimestamp{}; //!< The timestamp of the last frame being shown in nanoseconds
|
||||
i64 averageFrametimeNs{}; //!< The average time between frames in nanoseconds
|
||||
i64 averageFrametimeDeviationNs{}; //!< The average deviation of frametimes in nanoseconds
|
||||
@ -108,7 +111,7 @@ namespace skyline::gpu {
|
||||
/**
|
||||
* @brief Handles DisableFrameThrottling setting changed event
|
||||
*/
|
||||
void OnDisableFrameThrottlingChanged(const bool &value);
|
||||
void OnDisableFrameThrottlingChanged(const bool value);
|
||||
|
||||
public:
|
||||
PresentationEngine(const DeviceState &state, GPU &gpu);
|
||||
|
Loading…
Reference in New Issue
Block a user