diff options
6 files changed, 105 insertions, 38 deletions
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt index 744c8acae9..2418003904 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt @@ -25,6 +25,7 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting { RENDERER_ASYNCHRONOUS_SHADERS("use_asynchronous_shaders"), RENDERER_REACTIVE_FLUSHING("use_reactive_flushing"), ENABLE_BUFFER_HISTORY("enable_buffer_history"), + USE_OPTIMIZED_VERTEX_BUFFERS("use_optimized_vertex_buffers"), SYNC_MEMORY_OPERATIONS("sync_memory_operations"), BUFFER_REORDER_DISABLE("disable_buffer_reorder"), RENDERER_DEBUG("debug"), diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt index 7f212e2cca..a8bd44983b 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt @@ -797,6 +797,13 @@ abstract class SettingsItem( ) put( SwitchSetting( + BooleanSetting.USE_OPTIMIZED_VERTEX_BUFFERS, + titleId = R.string.use_optimized_vertex_buffers, + descriptionId = R.string.use_optimized_vertex_buffers_description + ) + ) + put( + SwitchSetting( BooleanSetting.SYNC_MEMORY_OPERATIONS, titleId = R.string.sync_memory_operations, descriptionId = R.string.sync_memory_operations_description diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt index 8f3c28c7a8..332617804e 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt @@ -278,6 +278,7 @@ class SettingsFragmentPresenter( add(BooleanSetting.RENDERER_FORCE_MAX_CLOCK.key) add(BooleanSetting.RENDERER_REACTIVE_FLUSHING.key) add(BooleanSetting.ENABLE_BUFFER_HISTORY.key) + add(BooleanSetting.USE_OPTIMIZED_VERTEX_BUFFERS.key) add(HeaderSetting(R.string.hacks)) diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index a34d75d7cb..fc1334863d 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -500,7 +500,8 @@ <string name="renderer_reactive_flushing_description">Improves rendering accuracy in some games at the cost of performance.</string> <string name="enable_buffer_history">Enable buffer history</string> <string name="enable_buffer_history_description">Enables access to previous buffer states. This option may improve rendering quality and performance consistency in some games.</string> - + <string name="use_optimized_vertex_buffers">Optimized Vertex Buffers</string> + <string name="use_optimized_vertex_buffers_description">Enables optimized vertex buffer binding for improved performance. Requires Mesa 26.0+ Turnip drivers. Will crash on older drivers.</string> <string name="hacks">Hacks</string> diff --git a/src/common/settings.h b/src/common/settings.h index 984ae6cc64..1aff6cc74d 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -519,6 +519,16 @@ struct Values { true, true}; +#ifdef ANDROID + SwitchableSetting<bool> use_optimized_vertex_buffers{linkage, + false, + "use_optimized_vertex_buffers", + Category::RendererAdvanced, + Specialization::Default, + true, + true}; +#endif + // Renderer Hacks // SwitchableSetting<GpuOverclock> fast_gpu_time{linkage, GpuOverclock::Medium, diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 7b92edecaa..014b4a318e 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -805,47 +805,94 @@ void BufferCache<P>::UpdateVertexBufferSlot(u32 index, const Binding& binding) { template <class P> void BufferCache<P>::BindHostVertexBuffers() { - auto& flags = maxwell3d->dirty.flags; - u32 enabled_mask = enabled_vertex_buffers_mask; - HostBindings<Buffer> bindings{}; - u32 last_index = std::numeric_limits<u32>::max(); - const auto flush_bindings = [&]() { - if (bindings.buffers.empty()) { - return; - } - bindings.max_index = bindings.min_index + static_cast<u32>(bindings.buffers.size()); - runtime.BindVertexBuffers(bindings); - bindings = HostBindings<Buffer>{}; - last_index = std::numeric_limits<u32>::max(); - }; - while (enabled_mask != 0) { - const u32 index = std::countr_zero(enabled_mask); - enabled_mask &= (enabled_mask - 1); - const Binding& binding = VertexBufferSlot(index); - Buffer& buffer = slot_buffers[binding.buffer_id]; - TouchBuffer(buffer, binding.buffer_id); - SynchronizeBuffer(buffer, binding.device_addr, binding.size); - if (!flags[Dirty::VertexBuffer0 + index]) { - flush_bindings(); - continue; + +#ifdef ANDROID + const bool use_optimized_vertex_buffers = Settings::values.use_optimized_vertex_buffers.GetValue(); +#else + constexpr bool use_optimized_vertex_buffers = true; +#endif + + if (use_optimized_vertex_buffers) { + auto& flags = maxwell3d->dirty.flags; + u32 enabled_mask = enabled_vertex_buffers_mask; + HostBindings<Buffer> bindings{}; + u32 last_index = std::numeric_limits<u32>::max(); + const auto flush_bindings = [&]() { + if (bindings.buffers.empty()) { + return; + } + bindings.max_index = bindings.min_index + static_cast<u32>(bindings.buffers.size()); + runtime.BindVertexBuffers(bindings); + bindings = HostBindings<Buffer>{}; + last_index = std::numeric_limits<u32>::max(); + }; + while (enabled_mask != 0) { + const u32 index = std::countr_zero(enabled_mask); + enabled_mask &= (enabled_mask - 1); + const Binding& binding = VertexBufferSlot(index); + Buffer& buffer = slot_buffers[binding.buffer_id]; + TouchBuffer(buffer, binding.buffer_id); + SynchronizeBuffer(buffer, binding.device_addr, binding.size); + if (!flags[Dirty::VertexBuffer0 + index]) { + flush_bindings(); + continue; + } + flags[Dirty::VertexBuffer0 + index] = false; + const u32 stride = maxwell3d->regs.vertex_streams[index].stride; + const u32 offset = buffer.Offset(binding.device_addr); + buffer.MarkUsage(offset, binding.size); + if (!bindings.buffers.empty() && index != last_index + 1) { + flush_bindings(); + } + if (bindings.buffers.empty()) { + bindings.min_index = index; + } + bindings.buffers.push_back(&buffer); + bindings.offsets.push_back(offset); + bindings.sizes.push_back(binding.size); + bindings.strides.push_back(stride); + last_index = index; } - flags[Dirty::VertexBuffer0 + index] = false; - const u32 stride = maxwell3d->regs.vertex_streams[index].stride; - const u32 offset = buffer.Offset(binding.device_addr); - buffer.MarkUsage(offset, binding.size); - if (!bindings.buffers.empty() && index != last_index + 1) { - flush_bindings(); + flush_bindings(); + } else { + HostBindings<typename P::Buffer> host_bindings; + bool any_valid{false}; + auto& flags = maxwell3d->dirty.flags; + for (u32 index = 0; index < NUM_VERTEX_BUFFERS; ++index) { + const Binding& binding = channel_state->vertex_buffers[index]; + Buffer& buffer = slot_buffers[binding.buffer_id]; + TouchBuffer(buffer, binding.buffer_id); + SynchronizeBuffer(buffer, binding.device_addr, binding.size); + if (!flags[Dirty::VertexBuffer0 + index]) { + continue; + } + flags[Dirty::VertexBuffer0 + index] = false; + + host_bindings.min_index = (std::min)(host_bindings.min_index, index); + host_bindings.max_index = (std::max)(host_bindings.max_index, index); + any_valid = true; } - if (bindings.buffers.empty()) { - bindings.min_index = index; + + if (any_valid) { + host_bindings.max_index++; + for (u32 index = host_bindings.min_index; index < host_bindings.max_index; index++) { + flags[Dirty::VertexBuffer0 + index] = false; + + const Binding& binding = channel_state->vertex_buffers[index]; + Buffer& buffer = slot_buffers[binding.buffer_id]; + + const u32 stride = maxwell3d->regs.vertex_streams[index].stride; + const u32 offset = buffer.Offset(binding.device_addr); + buffer.MarkUsage(offset, binding.size); + + host_bindings.buffers.push_back(&buffer); + host_bindings.offsets.push_back(offset); + host_bindings.sizes.push_back(binding.size); + host_bindings.strides.push_back(stride); + } + runtime.BindVertexBuffers(host_bindings); } - bindings.buffers.push_back(&buffer); - bindings.offsets.push_back(offset); - bindings.sizes.push_back(binding.size); - bindings.strides.push_back(stride); - last_index = index; } - flush_bindings(); } template <class P> |
