aboutsummaryrefslogtreecommitdiff
path: root/src/video_core/renderer_vulkan
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core/renderer_vulkan')
-rw-r--r--src/video_core/renderer_vulkan/renderer_vulkan.cpp6
-rw-r--r--src/video_core/renderer_vulkan/vk_present_manager.cpp26
-rw-r--r--src/video_core/renderer_vulkan/vk_present_manager.h10
3 files changed, 38 insertions, 4 deletions
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
index 4fd4c0233b..27ca531186 100644
--- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp
+++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
@@ -217,13 +217,15 @@ void RendererVulkan::Composite(std::span<const Tegra::FramebufferConfig> framebu
scheduler.RequestOutsideRenderPassOperationContext();
blit_swapchain.DrawToFrame(device, rasterizer, frame, framebuffers,
- render_window.GetFramebufferLayout(), swapchain.GetImageCount(),
+ render_window.GetFramebufferLayout(),
+ present_manager.SwapchainImageCount(),
swapchain.GetImageViewFormat());
#ifdef HAS_LSFG
void(frame_gen.WantedGenerations(present_manager.MaxExtraFrames()));
- frame_gen.Process(device, frame, swapchain.GetImageFormat(), GuestExtent(framebuffers));
+ frame_gen.Process(device, frame, present_manager.SwapchainImageFormat(),
+ GuestExtent(framebuffers));
const size_t generated_frames = frame_gen.GeneratedFrameCount();
for (size_t generation = 0; generation < generated_frames; ++generation) {
diff --git a/src/video_core/renderer_vulkan/vk_present_manager.cpp b/src/video_core/renderer_vulkan/vk_present_manager.cpp
index d173a3ba5f..9298764546 100644
--- a/src/video_core/renderer_vulkan/vk_present_manager.cpp
+++ b/src/video_core/renderer_vulkan/vk_present_manager.cpp
@@ -23,6 +23,7 @@ namespace Vulkan {
namespace {
constexpr size_t MAX_FRAMES_IN_FLIGHT = 7;
+constexpr u32 MAX_PRESENT_ATTEMPTS = 3;
#ifdef HAS_LSFG
static_assert(MAX_FRAMES_IN_FLIGHT <= LSFG_MAX_TARGETS);
#endif
@@ -372,12 +373,33 @@ void PresentManager::SetImageCount() {
#else
image_count = std::min<size_t>(swapchain.GetImageCount(), MAX_FRAMES_IN_FLIGHT);
#endif
+ swapchain_image_count = swapchain.GetImageCount();
+ swapchain_image_format = swapchain.GetImageFormat();
+}
+
+void PresentManager::DiscardFrame(Frame* frame) {
+ static constexpr VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+ const VkSemaphore render_ready = *frame->render_ready;
+ const VkSubmitInfo submit_info{
+ .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
+ .pNext = nullptr,
+ .waitSemaphoreCount = 1U,
+ .pWaitSemaphores = &render_ready,
+ .pWaitDstStageMask = &wait_stage,
+ .commandBufferCount = 0U,
+ .pCommandBuffers = nullptr,
+ .signalSemaphoreCount = 0U,
+ .pSignalSemaphores = nullptr,
+ };
+
+ std::scoped_lock submit_lock{scheduler.submit_mutex};
+ void(device.GetGraphicsQueue().Submit(submit_info, *frame->present_done));
}
void PresentManager::CopyToSwapchain(Frame* frame) {
bool requires_recreation = false;
- while (true) {
+ for (u32 attempt = 0; attempt < MAX_PRESENT_ATTEMPTS; ++attempt) {
try {
// Recreate surface and swapchain if needed.
if (requires_recreation) {
@@ -397,6 +419,8 @@ void PresentManager::CopyToSwapchain(Frame* frame) {
requires_recreation = true;
}
}
+
+ DiscardFrame(frame);
}
void PresentManager::CopyToSwapchainImpl(Frame* frame) {
diff --git a/src/video_core/renderer_vulkan/vk_present_manager.h b/src/video_core/renderer_vulkan/vk_present_manager.h
index 4741c55e61..ab2b76f10f 100644
--- a/src/video_core/renderer_vulkan/vk_present_manager.h
+++ b/src/video_core/renderer_vulkan/vk_present_manager.h
@@ -6,6 +6,7 @@
#pragma once
+#include <atomic>
#include <condition_variable>
#include <mutex>
#include <boost/container/deque.hpp>
@@ -68,6 +69,9 @@ public:
/// How many additional frames can be queued without stalling the render thread
[[nodiscard]] size_t MaxExtraFrames() const;
+ [[nodiscard]] std::size_t SwapchainImageCount() const { return swapchain_image_count; }
+ [[nodiscard]] VkFormat SwapchainImageFormat() const { return swapchain_image_format; }
+
private:
void PresentThread(std::stop_token token);
@@ -77,6 +81,8 @@ private:
void RecreateSwapchain(Frame* frame);
+ void DiscardFrame(Frame* frame);
+
void SetImageCount();
private:
@@ -100,7 +106,9 @@ private:
bool blit_supported;
bool storage_supported;
bool use_present_thread;
- std::size_t image_count{};
+ std::atomic<std::size_t> image_count{};
+ std::atomic<std::size_t> swapchain_image_count{};
+ std::atomic<VkFormat> swapchain_image_format{};
};
} // namespace Vulkan