aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt1
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt7
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt1
-rw-r--r--src/android/app/src/main/res/values/strings.xml3
-rw-r--r--src/common/settings.h10
-rw-r--r--src/video_core/buffer_cache/buffer_cache.h121
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>