Compare commits

..

4 Commits

Author SHA1 Message Date
lizzie 0538d96031 2026-09-05 05:55:38
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-05 05:55:38 +00:00
lizzie 904b4e77d6 2026-09-05 05:53:11
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-05 05:53:11 +00:00
lizzie 0c2801b6d3 2026-09-04 23:59:41
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-04 23:59:41 +00:00
lizzie ba82ca04d8 2026-09-04 23:57:52
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-09-04 23:57:52 +00:00
14 changed files with 118 additions and 91 deletions
+11 -13
View File
@@ -4,17 +4,16 @@
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include <thread> #include <chrono>
#include <fmt/ranges.h> #include <fmt/ranges.h>
#include <math.h> #include <math.h>
#include "common/param_package.h" #include "common/param_package.h"
#include "common/settings.h" #include "common/settings.h"
#include "common/thread.h" #include "common/steady_clock.h"
#include "input_common/drivers/mouse.h" #include "input_common/drivers/mouse.h"
namespace InputCommon { namespace InputCommon {
constexpr int update_time = 10;
constexpr float default_panning_sensitivity = 0.0010f; constexpr float default_panning_sensitivity = 0.0010f;
constexpr float default_stick_sensitivity = 0.0006f; constexpr float default_stick_sensitivity = 0.0006f;
constexpr float default_deadzone_counterweight = 0.01f; constexpr float default_deadzone_counterweight = 0.01f;
@@ -74,7 +73,7 @@ Mouse::Mouse(std::string input_engine_) : InputEngine(std::move(input_engine_))
last_motion_change = {}; last_motion_change = {};
} }
void Mouse::UpdateStickInput() { void Mouse::UpdateStickInput(Common::SteadyClock::time_point timestamp) {
if (!IsMousePanningEnabled()) { if (!IsMousePanningEnabled()) {
return; return;
} }
@@ -100,12 +99,9 @@ void Mouse::UpdateStickInput() {
last_mouse_change *= clamped_decay; last_mouse_change *= clamped_decay;
} }
void Mouse::UpdateMotionInput() { void Mouse::UpdateMotionInput(Common::SteadyClock::time_point timestamp) {
const float sensitivity = const float sensitivity = IsMousePanningEnabled() ? default_motion_panning_sensitivity : default_motion_sensitivity;
IsMousePanningEnabled() ? default_motion_panning_sensitivity : default_motion_sensitivity; const float rotation_velocity = std::sqrt(last_motion_change.x * last_motion_change.x + last_motion_change.y * last_motion_change.y);
const float rotation_velocity = std::sqrt(last_motion_change.x * last_motion_change.x +
last_motion_change.y * last_motion_change.y);
// Clamp rotation speed // Clamp rotation speed
if (rotation_velocity > maximum_rotation_speed / sensitivity) { if (rotation_velocity > maximum_rotation_speed / sensitivity) {
@@ -121,7 +117,7 @@ void Mouse::UpdateMotionInput() {
.accel_x = 0, .accel_x = 0,
.accel_y = 0, .accel_y = 0,
.accel_z = 0, .accel_z = 0,
.delta_timestamp = update_time * 1000, .delta_timestamp = u64(std::chrono::duration_cast<std::chrono::microseconds>(timestamp - last_notify_timestamp).count()),
}; };
if (IsMousePanningEnabled()) { if (IsMousePanningEnabled()) {
@@ -177,8 +173,10 @@ void Mouse::Move(int x, int y, int center_x, int center_y) {
} }
void Mouse::NotifyChanged() { void Mouse::NotifyChanged() {
UpdateStickInput(); auto const timestamp = Common::SteadyClock::Now();
UpdateMotionInput(); UpdateStickInput(timestamp);
UpdateMotionInput(timestamp);
last_notify_timestamp = Common::SteadyClock::Now();
} }
void Mouse::MouseMove(f32 touch_x, f32 touch_y) { void Mouse::MouseMove(f32 touch_x, f32 touch_y) {
+10 -7
View File
@@ -7,7 +7,9 @@
#pragma once #pragma once
#include <thread> #include <thread>
#include <chrono>
#include "common/steady_clock.h"
#include "common/polyfill_thread.h" #include "common/polyfill_thread.h"
#include "common/vector_math.h" #include "common/vector_math.h"
#include "input_common/input_engine.h" #include "input_common/input_engine.h"
@@ -101,17 +103,18 @@ public:
Common::Input::ButtonNames GetUIName(const Common::ParamPackage& params) const override; Common::Input::ButtonNames GetUIName(const Common::ParamPackage& params) const override;
private: private:
void UpdateStickInput(); void UpdateStickInput(Common::SteadyClock::time_point timestamp);
void UpdateMotionInput(); void UpdateMotionInput(Common::SteadyClock::time_point timestamp);
bool IsMousePanningEnabled(); bool IsMousePanningEnabled();
Common::Input::ButtonNames GetUIButtonName(const Common::ParamPackage& params) const; Common::Input::ButtonNames GetUIButtonName(const Common::ParamPackage& params) const;
Common::Vec2<int> mouse_origin; Common::Vec2<int> mouse_origin{};
Common::Vec2<int> last_mouse_position; Common::Vec2<int> last_mouse_position{};
Common::Vec2<float> last_mouse_change; Common::Vec2<float> last_mouse_change{};
Common::Vec3<float> last_motion_change; Common::Vec3<float> last_motion_change{};
Common::Vec2<int> wheel_position; Common::Vec2<int> wheel_position{};
Common::SteadyClock::time_point last_notify_timestamp{};
bool button_pressed = false; bool button_pressed = false;
}; };
@@ -148,11 +148,11 @@ BufferCacheRuntime::BufferCacheRuntime(const Device& device_,
} }
StagingBufferMap BufferCacheRuntime::UploadStagingBuffer(size_t size) { StagingBufferMap BufferCacheRuntime::UploadStagingBuffer(size_t size) {
return staging_buffer_pool.RequestUploadBuffer(device, size); return staging_buffer_pool.RequestUploadBuffer(size);
} }
StagingBufferMap BufferCacheRuntime::DownloadStagingBuffer(size_t size, bool deferred) { StagingBufferMap BufferCacheRuntime::DownloadStagingBuffer(size_t size, bool deferred) {
return staging_buffer_pool.RequestDownloadBuffer(device, size, deferred); return staging_buffer_pool.RequestDownloadBuffer(size, deferred);
} }
void BufferCacheRuntime::FreeDeferredStagingBuffer(StagingBufferMap& buffer) { void BufferCacheRuntime::FreeDeferredStagingBuffer(StagingBufferMap& buffer) {
@@ -557,11 +557,11 @@ void TextureCacheRuntime::Finish() {
} }
StagingBufferMap TextureCacheRuntime::UploadStagingBuffer(size_t size, bool deferred) { StagingBufferMap TextureCacheRuntime::UploadStagingBuffer(size_t size, bool deferred) {
return staging_buffer_pool.RequestUploadBuffer(device, size); return staging_buffer_pool.RequestUploadBuffer(size);
} }
StagingBufferMap TextureCacheRuntime::DownloadStagingBuffer(size_t size, bool deferred) { StagingBufferMap TextureCacheRuntime::DownloadStagingBuffer(size_t size, bool deferred) {
return staging_buffer_pool.RequestDownloadBuffer(device, size, deferred); return staging_buffer_pool.RequestDownloadBuffer(size, deferred);
} }
void TextureCacheRuntime::FreeDeferredStagingBuffer(StagingBufferMap& buffer) { void TextureCacheRuntime::FreeDeferredStagingBuffer(StagingBufferMap& buffer) {
@@ -192,7 +192,7 @@ public:
if (host_visible) { if (host_visible) {
return StagingBufferRef{}; return StagingBufferRef{};
} }
return staging_pool.Request(device, size_bytes, MemoryUsage::Upload); return staging_pool.Request(size_bytes, MemoryUsage::Upload);
}(); }();
u8* staging_data = host_visible ? buffer.Mapped().data() : staging.mapped_span.data(); u8* staging_data = host_visible ? buffer.Mapped().data() : staging.mapped_span.data();
@@ -366,11 +366,11 @@ BufferCacheRuntime::BufferCacheRuntime(const Device& device_, MemoryAllocator& m
} }
StagingBufferRef BufferCacheRuntime::UploadStagingBuffer(size_t size) { StagingBufferRef BufferCacheRuntime::UploadStagingBuffer(size_t size) {
return staging_pool.Request(device, size, MemoryUsage::Upload); return staging_pool.Request(size, MemoryUsage::Upload);
} }
StagingBufferRef BufferCacheRuntime::DownloadStagingBuffer(size_t size, bool deferred) { StagingBufferRef BufferCacheRuntime::DownloadStagingBuffer(size_t size, bool deferred) {
return staging_pool.Request(device, size, MemoryUsage::Download, deferred); return staging_pool.Request(size, MemoryUsage::Download, deferred);
} }
VkFormat BufferCacheRuntime::TexelBufferFormat(VideoCore::Surface::PixelFormat format) const { VkFormat BufferCacheRuntime::TexelBufferFormat(VideoCore::Surface::PixelFormat format) const {
@@ -149,7 +149,7 @@ public:
std::span<u8> BindMappedUniformBuffer([[maybe_unused]] size_t stage, std::span<u8> BindMappedUniformBuffer([[maybe_unused]] size_t stage,
[[maybe_unused]] u32 binding_index, [[maybe_unused]] u32 binding_index,
u32 size) { u32 size) {
const StagingBufferRef ref = staging_pool.Request(device, size, MemoryUsage::Upload); const StagingBufferRef ref = staging_pool.Request(size, MemoryUsage::Upload);
guest_descriptor_queue.AddBuffer(ref.buffer, ref.device_address, guest_descriptor_queue.AddBuffer(ref.buffer, ref.device_address,
static_cast<u32>(ref.offset), size); static_cast<u32>(ref.offset), size);
return ref.mapped_span; return ref.mapped_span;
@@ -287,7 +287,7 @@ Uint8Pass::~Uint8Pass() = default;
std::pair<VkBuffer, VkDeviceSize> Uint8Pass::Assemble(u32 num_vertices, VkBuffer src_buffer, std::pair<VkBuffer, VkDeviceSize> Uint8Pass::Assemble(u32 num_vertices, VkBuffer src_buffer,
u32 src_offset) { u32 src_offset) {
const u32 staging_size = static_cast<u32>(num_vertices * sizeof(u16)); const u32 staging_size = static_cast<u32>(num_vertices * sizeof(u16));
const auto staging = staging_buffer_pool.Request(device, staging_size, MemoryUsage::DeviceLocal); const auto staging = staging_buffer_pool.Request(staging_size, MemoryUsage::DeviceLocal);
compute_pass_descriptor_queue.Acquire(scheduler, 2); compute_pass_descriptor_queue.Acquire(scheduler, 2);
compute_pass_descriptor_queue.AddBuffer(src_buffer, src_offset, num_vertices); compute_pass_descriptor_queue.AddBuffer(src_buffer, src_offset, num_vertices);
@@ -345,7 +345,7 @@ std::pair<VkBuffer, VkDeviceSize> QuadIndexedPass::Assemble(
const u32 num_tri_vertices = (is_strip ? (num_vertices - 2) / 2 : num_vertices / 4) * 6; const u32 num_tri_vertices = (is_strip ? (num_vertices - 2) / 2 : num_vertices / 4) * 6;
const std::size_t staging_size = num_tri_vertices * sizeof(u32); const std::size_t staging_size = num_tri_vertices * sizeof(u32);
const auto staging = staging_buffer_pool.Request(device, staging_size, MemoryUsage::DeviceLocal); const auto staging = staging_buffer_pool.Request(staging_size, MemoryUsage::DeviceLocal);
compute_pass_descriptor_queue.Acquire(scheduler, 2); compute_pass_descriptor_queue.Acquire(scheduler, 2);
compute_pass_descriptor_queue.AddBuffer(src_buffer, src_offset, input_size); compute_pass_descriptor_queue.AddBuffer(src_buffer, src_offset, input_size);
@@ -852,7 +852,7 @@ public:
void PushUnsyncedQueries() override { void PushUnsyncedQueries() override {
CloseCounter(); CloseCounter();
auto staging_ref = staging_pool.Request(device, auto staging_ref = staging_pool.Request(
pending_flush_queries.size() * TFBQueryBank::QUERY_SIZE, MemoryUsage::Download, true); pending_flush_queries.size() * TFBQueryBank::QUERY_SIZE, MemoryUsage::Download, true);
size_t offset_base = staging_ref.offset; size_t offset_base = staging_ref.offset;
for (auto q : pending_flush_queries) { for (auto q : pending_flush_queries) {
@@ -1657,7 +1657,7 @@ void QueryCacheRuntime::SyncValues(std::span<SyncValuesType> values, VkBuffer ba
impl->copies_setup.clear(); impl->copies_setup.clear();
impl->copies_setup.resize(impl->little_cache.size()); impl->copies_setup.resize(impl->little_cache.size());
if constexpr (SyncValuesType::GeneratesBaseBuffer) { if constexpr (SyncValuesType::GeneratesBaseBuffer) {
ref = impl->staging_pool.Request(impl->device, total_size, MemoryUsage::Upload); ref = impl->staging_pool.Request(total_size, MemoryUsage::Upload);
size_t current_offset = ref.offset; size_t current_offset = ref.offset;
size_t accumulated_size = 0; size_t accumulated_size = 0;
for (size_t i = 0; i < values.size(); i++) { for (size_t i = 0; i < values.size(); i++) {
@@ -25,14 +25,29 @@ namespace {
using namespace Common::Literals; using namespace Common::Literals;
size_t GetStreamBufferSize(const Device& device, size_t max_stream_buffer_size, size_t max_alignment) { // Maximum potential alignment of a Vulkan buffer
constexpr VkDeviceSize MAX_ALIGNMENT = 256;
// Stream buffer size in bytes
// *NIX drivers are more sensitive to increased buffers for streaming.
// Windows ones however, can intake bigger buffers and generally do not OOM.
// - GTX 960 on Windows will not OOM with 256mib
// - GT 1030 on ^NIX will OOM with 256mib
#if defined(__FreeBSD__)
constexpr VkDeviceSize MAX_STREAM_BUFFER_SIZE = 128_MiB;
#else
constexpr VkDeviceSize MAX_STREAM_BUFFER_SIZE = 256_MiB;
#endif
size_t GetStreamBufferSize(const Device& device) {
if (!device.HasDebuggingToolAttached()) { if (!device.HasDebuggingToolAttached()) {
return max_stream_buffer_size; return MAX_STREAM_BUFFER_SIZE;
} }
VkDeviceSize size{0}; VkDeviceSize size{0};
bool has_device_local_host_visible_heap{}; bool has_device_local_host_visible_heap{};
ForEachDeviceLocalHostVisibleHeap(device, [&size, &has_device_local_host_visible_heap](size_t index, VkMemoryHeap& heap) { ForEachDeviceLocalHostVisibleHeap(device, [&size, &has_device_local_host_visible_heap](
size_t index, VkMemoryHeap& heap) {
has_device_local_host_visible_heap = true; has_device_local_host_visible_heap = true;
size = (std::max)(size, heap.size); size = (std::max)(size, heap.size);
}); });
@@ -40,27 +55,28 @@ size_t GetStreamBufferSize(const Device& device, size_t max_stream_buffer_size,
// If rebar is not supported, cut the max heap size to 40%. This will allow 2 captures to be // If rebar is not supported, cut the max heap size to 40%. This will allow 2 captures to be
// loaded at the same time in RenderDoc. If rebar is supported, this shouldn't be an issue // loaded at the same time in RenderDoc. If rebar is supported, this shouldn't be an issue
// as the heap will be much larger. // as the heap will be much larger.
if (size <= max_stream_buffer_size) { if (size <= MAX_STREAM_BUFFER_SIZE) {
size = size * 40 / 100; size = size * 40 / 100;
} }
} else { } else {
size = max_stream_buffer_size; size = MAX_STREAM_BUFFER_SIZE;
} }
return (std::min)(Common::AlignUp(size, max_alignment), max_stream_buffer_size); return (std::min)(Common::AlignUp(size, MAX_ALIGNMENT), MAX_STREAM_BUFFER_SIZE);
} }
} // Anonymous namespace } // Anonymous namespace
StagingBufferPool::StagingBufferPool(const Device& device, MemoryAllocator& memory_allocator_, Scheduler& scheduler_) StagingBufferPool::StagingBufferPool(const Device& device_, MemoryAllocator& memory_allocator_,
: memory_allocator{memory_allocator_}, scheduler{scheduler_} Scheduler& scheduler_)
, stream_buffer_size{GetStreamBufferSize(device, 256_MiB, 256)} : device{device_}, memory_allocator{memory_allocator_}, scheduler{scheduler_},
{ stream_buffer_size{GetStreamBufferSize(device)}, region_size{stream_buffer_size /
StagingBufferPool::NUM_SYNCS} {
VkBufferCreateInfo stream_ci = { VkBufferCreateInfo stream_ci = {
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.pNext = nullptr, .pNext = nullptr,
.flags = 0, .flags = 0,
.size = stream_buffer_size, .size = stream_buffer_size,
.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT |
| VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE, .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
.queueFamilyIndexCount = 0, .queueFamilyIndexCount = 0,
.pQueueFamilyIndices = nullptr, .pQueueFamilyIndices = nullptr,
@@ -71,20 +87,7 @@ StagingBufferPool::StagingBufferPool(const Device& device, MemoryAllocator& memo
if (device.IsBufferDeviceAddressSupported()) { if (device.IsBufferDeviceAddressSupported()) {
stream_ci.usage |= VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; stream_ci.usage |= VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
} }
// *BSD drivers are more sensitive to increased buffers for streaming. stream_buffer = memory_allocator.CreateBuffer(stream_ci, MemoryUsage::Stream);
// Windows ones however, can intake bigger buffers and generally do not OOM.
// - GTX 960 on Windows will not OOM with 256mib
// - GT 1030 on ^BSD will OOM with 256mib
// This doesn't seem to be, however, universally true
try {
stream_buffer = memory_allocator.CreateBuffer(stream_ci, MemoryUsage::Stream);
} catch (vk::Exception& e) {
LOG_ERROR(Render_Vulkan, "Can't fit {} bytes buffer, halving", stream_ci.size);
stream_buffer_size = GetStreamBufferSize(device, 128_MiB, 256);
stream_ci.size = stream_buffer_size;
stream_buffer = memory_allocator.CreateBuffer(stream_ci, MemoryUsage::Stream);
}
region_size = stream_buffer_size / StagingBufferPool::NUM_SYNCS;
if (device.HasDebuggingToolAttached()) { if (device.HasDebuggingToolAttached()) {
stream_buffer.SetObjectNameEXT("Stream Buffer"); stream_buffer.SetObjectNameEXT("Stream Buffer");
} }
@@ -97,10 +100,11 @@ StagingBufferPool::StagingBufferPool(const Device& device, MemoryAllocator& memo
StagingBufferPool::~StagingBufferPool() = default; StagingBufferPool::~StagingBufferPool() = default;
StagingBufferRef StagingBufferPool::Request(const Device& device, size_t size, MemoryUsage usage, bool deferred) { StagingBufferRef StagingBufferPool::Request(size_t size, MemoryUsage usage, bool deferred) {
return (!deferred && usage == MemoryUsage::Upload && size <= region_size) if (!deferred && usage == MemoryUsage::Upload && size <= region_size) {
? GetStreamBuffer(device, size) return GetStreamBuffer(size);
: GetStagingBuffer(device, size, usage, deferred); }
return GetStagingBuffer(size, usage, deferred);
} }
void StagingBufferPool::FreeDeferred(StagingBufferRef& ref) { void StagingBufferPool::FreeDeferred(StagingBufferRef& ref) {
@@ -123,10 +127,11 @@ void StagingBufferPool::TickFrame() {
ReleaseCache(MemoryUsage::Download); ReleaseCache(MemoryUsage::Download);
} }
StagingBufferRef StagingBufferPool::GetStreamBuffer(const Device& device, size_t size) { StagingBufferRef StagingBufferPool::GetStreamBuffer(size_t size) {
if (AreRegionsActive(Region(free_iterator) + 1, (std::min)(Region(iterator + size) + 1, NUM_SYNCS))) { if (AreRegionsActive(Region(free_iterator) + 1,
(std::min)(Region(iterator + size) + 1, NUM_SYNCS))) {
// Avoid waiting for the previous usages to be free // Avoid waiting for the previous usages to be free
return GetStagingBuffer(device, size, MemoryUsage::Upload); return GetStagingBuffer(size, MemoryUsage::Upload);
} }
const u64 current_tick = scheduler.CurrentTick(); const u64 current_tick = scheduler.CurrentTick();
std::fill(sync_ticks.begin() + Region(used_iterator), sync_ticks.begin() + Region(iterator), std::fill(sync_ticks.begin() + Region(used_iterator), sync_ticks.begin() + Region(iterator),
@@ -135,14 +140,15 @@ StagingBufferRef StagingBufferPool::GetStreamBuffer(const Device& device, size_t
free_iterator = (std::max)(free_iterator, iterator + size); free_iterator = (std::max)(free_iterator, iterator + size);
if (iterator + size >= stream_buffer_size) { if (iterator + size >= stream_buffer_size) {
std::fill(sync_ticks.begin() + Region(used_iterator), sync_ticks.begin() + NUM_SYNCS, current_tick); std::fill(sync_ticks.begin() + Region(used_iterator), sync_ticks.begin() + NUM_SYNCS,
current_tick);
used_iterator = 0; used_iterator = 0;
iterator = 0; iterator = 0;
free_iterator = size; free_iterator = size;
if (AreRegionsActive(0, Region(size) + 1)) { if (AreRegionsActive(0, Region(size) + 1)) {
// Avoid waiting for the previous usages to be free // Avoid waiting for the previous usages to be free
return GetStagingBuffer(device, size, MemoryUsage::Upload); return GetStagingBuffer(size, MemoryUsage::Upload);
} }
} }
const size_t offset = iterator; const size_t offset = iterator;
@@ -150,7 +156,7 @@ StagingBufferRef StagingBufferPool::GetStreamBuffer(const Device& device, size_t
return StagingBufferRef{ return StagingBufferRef{
.buffer = *stream_buffer, .buffer = *stream_buffer,
.device_address = stream_buffer_address, .device_address = stream_buffer_address,
.offset = VkDeviceSize(offset), .offset = static_cast<VkDeviceSize>(offset),
.mapped_span = stream_pointer.subspan(offset, size), .mapped_span = stream_pointer.subspan(offset, size),
.usage{}, .usage{},
.log2_level{}, .log2_level{},
@@ -160,18 +166,21 @@ StagingBufferRef StagingBufferPool::GetStreamBuffer(const Device& device, size_t
bool StagingBufferPool::AreRegionsActive(size_t region_begin, size_t region_end) const { bool StagingBufferPool::AreRegionsActive(size_t region_begin, size_t region_end) const {
const u64 gpu_tick = scheduler.GetMasterSemaphore().KnownGpuTick(); const u64 gpu_tick = scheduler.GetMasterSemaphore().KnownGpuTick();
return std::any_of(sync_ticks.begin() + region_begin, sync_ticks.begin() + region_end, [gpu_tick](u64 sync_tick) { return std::any_of(sync_ticks.begin() + region_begin, sync_ticks.begin() + region_end,
return gpu_tick < sync_tick; [gpu_tick](u64 sync_tick) { return gpu_tick < sync_tick; });
});
}; };
StagingBufferRef StagingBufferPool::GetStagingBuffer(const Device& device, size_t size, MemoryUsage usage, bool deferred) { StagingBufferRef StagingBufferPool::GetStagingBuffer(size_t size, MemoryUsage usage,
if (const std::optional<StagingBufferRef> ref = TryGetReservedBuffer(size, usage, deferred)) bool deferred) {
if (const std::optional<StagingBufferRef> ref = TryGetReservedBuffer(size, usage, deferred)) {
return *ref; return *ref;
return CreateStagingBuffer(device, size, usage, deferred); }
return CreateStagingBuffer(size, usage, deferred);
} }
std::optional<StagingBufferRef> StagingBufferPool::TryGetReservedBuffer(size_t size, MemoryUsage usage, bool deferred) { std::optional<StagingBufferRef> StagingBufferPool::TryGetReservedBuffer(size_t size,
MemoryUsage usage,
bool deferred) {
StagingBuffers& cache_level = GetCache(usage)[Common::Log2Ceil(size)]; StagingBuffers& cache_level = GetCache(usage)[Common::Log2Ceil(size)];
const auto is_free = [this](const StagingBuffer& entry) { const auto is_free = [this](const StagingBuffer& entry) {
@@ -193,7 +202,7 @@ std::optional<StagingBufferRef> StagingBufferPool::TryGetReservedBuffer(size_t s
return it->Ref(); return it->Ref();
} }
StagingBufferRef StagingBufferPool::CreateStagingBuffer(const Device& device, size_t size, MemoryUsage usage, bool deferred) { StagingBufferRef StagingBufferPool::CreateStagingBuffer(size_t size, MemoryUsage usage, bool deferred) {
auto const log2_size = Common::Log2Ceil<u32>(u32(size)); auto const log2_size = Common::Log2Ceil<u32>(u32(size));
VkBufferCreateInfo buffer_ci = { VkBufferCreateInfo buffer_ci = {
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
@@ -33,10 +33,11 @@ class StagingBufferPool {
public: public:
static constexpr size_t NUM_SYNCS = 16; static constexpr size_t NUM_SYNCS = 16;
explicit StagingBufferPool(const Device& device, MemoryAllocator& memory_allocator, Scheduler& scheduler); explicit StagingBufferPool(const Device& device, MemoryAllocator& memory_allocator,
Scheduler& scheduler);
~StagingBufferPool(); ~StagingBufferPool();
StagingBufferRef Request(const Device& device, size_t size, MemoryUsage usage, bool deferred = false); StagingBufferRef Request(size_t size, MemoryUsage usage, bool deferred = false);
void FreeDeferred(StagingBufferRef& ref); void FreeDeferred(StagingBufferRef& ref);
[[nodiscard]] VkBuffer StreamBuf() const noexcept { [[nodiscard]] VkBuffer StreamBuf() const noexcept {
@@ -83,18 +84,27 @@ private:
static constexpr size_t NUM_LEVELS = sizeof(size_t) * CHAR_BIT; static constexpr size_t NUM_LEVELS = sizeof(size_t) * CHAR_BIT;
using StagingBuffersCache = std::array<StagingBuffers, NUM_LEVELS>; using StagingBuffersCache = std::array<StagingBuffers, NUM_LEVELS>;
StagingBufferRef GetStreamBuffer(const Device& device, size_t size); StagingBufferRef GetStreamBuffer(size_t size);
bool AreRegionsActive(size_t region_begin, size_t region_end) const; bool AreRegionsActive(size_t region_begin, size_t region_end) const;
StagingBufferRef GetStagingBuffer(const Device& device, size_t size, MemoryUsage usage, bool deferred = false);
std::optional<StagingBufferRef> TryGetReservedBuffer(size_t size, MemoryUsage usage, bool deferred); StagingBufferRef GetStagingBuffer(size_t size, MemoryUsage usage, bool deferred = false);
StagingBufferRef CreateStagingBuffer(const Device& device, size_t size, MemoryUsage usage, bool deferred);
std::optional<StagingBufferRef> TryGetReservedBuffer(size_t size, MemoryUsage usage,
bool deferred);
StagingBufferRef CreateStagingBuffer(size_t size, MemoryUsage usage, bool deferred);
StagingBuffersCache& GetCache(MemoryUsage usage); StagingBuffersCache& GetCache(MemoryUsage usage);
void ReleaseCache(MemoryUsage usage); void ReleaseCache(MemoryUsage usage);
void ReleaseLevel(StagingBuffersCache& cache, size_t log2); void ReleaseLevel(StagingBuffersCache& cache, size_t log2);
size_t Region(size_t iter) const noexcept { size_t Region(size_t iter) const noexcept {
return iter / region_size; return iter / region_size;
} }
const Device& device;
MemoryAllocator& memory_allocator; MemoryAllocator& memory_allocator;
Scheduler& scheduler; Scheduler& scheduler;
@@ -975,11 +975,11 @@ void TextureCacheRuntime::Finish() {
} }
StagingBufferRef TextureCacheRuntime::UploadStagingBuffer(size_t size, bool deferred) { StagingBufferRef TextureCacheRuntime::UploadStagingBuffer(size_t size, bool deferred) {
return staging_buffer_pool.Request(device, size, MemoryUsage::Upload, deferred); return staging_buffer_pool.Request(size, MemoryUsage::Upload, deferred);
} }
StagingBufferRef TextureCacheRuntime::DownloadStagingBuffer(size_t size, bool deferred) { StagingBufferRef TextureCacheRuntime::DownloadStagingBuffer(size_t size, bool deferred) {
return staging_buffer_pool.Request(device, size, MemoryUsage::Download, deferred); return staging_buffer_pool.Request(size, MemoryUsage::Download, deferred);
} }
void TextureCacheRuntime::FreeDeferredStagingBuffer(StagingBufferRef& ref) { void TextureCacheRuntime::FreeDeferredStagingBuffer(StagingBufferRef& ref) {
+5 -7
View File
@@ -538,6 +538,7 @@ void GRenderWindow::mouseReleaseEvent(QMouseEvent* event) {
} }
void GRenderWindow::ConstrainMouse() { void GRenderWindow::ConstrainMouse() {
input_subsystem->GetMouse()->NotifyChanged(); // required to reset mouse once it's no longer moved
if (QtCommon::emu_thread == nullptr || !Settings::values.mouse_panning) { if (QtCommon::emu_thread == nullptr || !Settings::values.mouse_panning) {
mouse_constrain_timer.stop(); mouse_constrain_timer.stop();
return; return;
@@ -552,15 +553,12 @@ void GRenderWindow::ConstrainMouse() {
const auto pos = mapFromGlobal(QCursor::pos()); const auto pos = mapFromGlobal(QCursor::pos());
const int new_pos_x = std::clamp(pos.x(), 0, width()); const int new_pos_x = std::clamp(pos.x(), 0, width());
const int new_pos_y = std::clamp(pos.y(), 0, height()); const int new_pos_y = std::clamp(pos.y(), 0, height());
QCursor::setPos(mapToGlobal(QPoint{new_pos_x, new_pos_y})); QCursor::setPos(mapToGlobal(QPoint{new_pos_x, new_pos_y}));
return; } else {
const int center_x = width() / 2;
const int center_y = height() / 2;
QCursor::setPos(mapToGlobal(QPoint{center_x, center_y}));
} }
const int center_x = width() / 2;
const int center_y = height() / 2;
QCursor::setPos(mapToGlobal(QPoint{center_x, center_y}));
} }
void GRenderWindow::wheelEvent(QWheelEvent* event) { void GRenderWindow::wheelEvent(QWheelEvent* event) {
@@ -37,10 +37,16 @@ EmuWindow_SDL3::EmuWindow_SDL3(InputCommon::InputSubsystem* input_subsystem_, Co
SDL_SetWindowTitle(this_->render_window, title.c_str()); SDL_SetWindowTitle(this_->render_window, title.c_str());
return 2000; return 2000;
}, this); }, this);
mouse_timer = SDL_AddTimer(100, [](void *userdata, SDL_TimerID, Uint32) -> Uint32 {
auto* this_ = (EmuWindow_SDL3*)userdata;
this_->input_subsystem->GetMouse()->NotifyChanged();
return 100;
}, this);
} }
EmuWindow_SDL3::~EmuWindow_SDL3() { EmuWindow_SDL3::~EmuWindow_SDL3() {
SDL_RemoveTimer(titlebar_timer); SDL_RemoveTimer(titlebar_timer);
SDL_RemoveTimer(mouse_timer);
system.HIDCore().UnloadInputDevices(); system.HIDCore().UnloadInputDevices();
input_subsystem->Shutdown(); input_subsystem->Shutdown();
SDL_Quit(); SDL_Quit();
@@ -84,6 +84,9 @@ protected:
/// Periodic changer of titlebar (independent of event loop) /// Periodic changer of titlebar (independent of event loop)
SDL_TimerID titlebar_timer; SDL_TimerID titlebar_timer;
// Mouse resetter once it
SDL_TimerID mouse_timer;
/// Is the window still open? /// Is the window still open?
bool is_open = true; bool is_open = true;