summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar bunnei2023-06-11 11:33:48 -0700
committerGravatar GitHub2023-06-11 11:33:48 -0700
commit569f8d3b44301e40bcfe3bf42bcae5ae6c45ab02 (patch)
tree16c3458c1802d223ff078046ca03a573b7e8f538 /src
parentMerge pull request #10713 from t895/gradle-updates (diff)
parentCombine vertex/transform feedback buffer binding into a single call (diff)
downloadyuzu-569f8d3b44301e40bcfe3bf42bcae5ae6c45ab02.tar.gz
yuzu-569f8d3b44301e40bcfe3bf42bcae5ae6c45ab02.tar.xz
yuzu-569f8d3b44301e40bcfe3bf42bcae5ae6c45ab02.zip
Merge pull request #10668 from Kelebek1/reduce_vertex_bindings
Combine vertex/transform feedback buffer binding into a single call
Diffstat (limited to 'src')
-rw-r--r--src/video_core/buffer_cache/buffer_cache.h82
-rw-r--r--src/video_core/buffer_cache/buffer_cache_base.h11
-rw-r--r--src/video_core/renderer_opengl/gl_buffer_cache.cpp18
-rw-r--r--src/video_core/renderer_opengl/gl_buffer_cache.h4
-rw-r--r--src/video_core/renderer_vulkan/vk_buffer_cache.cpp54
-rw-r--r--src/video_core/renderer_vulkan/vk_buffer_cache.h3
6 files changed, 148 insertions, 24 deletions
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h
index 2f281b370..251a4a880 100644
--- a/src/video_core/buffer_cache/buffer_cache.h
+++ b/src/video_core/buffer_cache/buffer_cache.h
@@ -715,20 +715,38 @@ void BufferCache<P>::BindHostIndexBuffer() {
715 715
716template <class P> 716template <class P>
717void BufferCache<P>::BindHostVertexBuffers() { 717void BufferCache<P>::BindHostVertexBuffers() {
718 HostBindings host_bindings;
719 bool any_valid{false};
718 auto& flags = maxwell3d->dirty.flags; 720 auto& flags = maxwell3d->dirty.flags;
719 for (u32 index = 0; index < NUM_VERTEX_BUFFERS; ++index) { 721 for (u32 index = 0; index < NUM_VERTEX_BUFFERS; ++index) {
720 const Binding& binding = channel_state->vertex_buffers[index];
721 Buffer& buffer = slot_buffers[binding.buffer_id];
722 TouchBuffer(buffer, binding.buffer_id);
723 SynchronizeBuffer(buffer, binding.cpu_addr, binding.size);
724 if (!flags[Dirty::VertexBuffer0 + index]) { 722 if (!flags[Dirty::VertexBuffer0 + index]) {
725 continue; 723 continue;
726 } 724 }
727 flags[Dirty::VertexBuffer0 + index] = false; 725 host_bindings.min_index = std::min(host_bindings.min_index, index);
726 host_bindings.max_index = std::max(host_bindings.max_index, index);
727 any_valid = true;
728 }
728 729
729 const u32 stride = maxwell3d->regs.vertex_streams[index].stride; 730 if (any_valid) {
730 const u32 offset = buffer.Offset(binding.cpu_addr); 731 host_bindings.max_index++;
731 runtime.BindVertexBuffer(index, buffer, offset, binding.size, stride); 732 for (u32 index = host_bindings.min_index; index < host_bindings.max_index; index++) {
733 flags[Dirty::VertexBuffer0 + index] = false;
734
735 const Binding& binding = channel_state->vertex_buffers[index];
736 Buffer& buffer = slot_buffers[binding.buffer_id];
737
738 TouchBuffer(buffer, binding.buffer_id);
739 SynchronizeBuffer(buffer, binding.cpu_addr, binding.size);
740
741 const u32 stride = maxwell3d->regs.vertex_streams[index].stride;
742 const u32 offset = buffer.Offset(binding.cpu_addr);
743
744 host_bindings.buffers.push_back(reinterpret_cast<void*>(&buffer));
745 host_bindings.offsets.push_back(offset);
746 host_bindings.sizes.push_back(binding.size);
747 host_bindings.strides.push_back(stride);
748 }
749 runtime.BindVertexBuffers(host_bindings);
732 } 750 }
733} 751}
734 752
@@ -882,15 +900,25 @@ void BufferCache<P>::BindHostTransformFeedbackBuffers() {
882 if (maxwell3d->regs.transform_feedback_enabled == 0) { 900 if (maxwell3d->regs.transform_feedback_enabled == 0) {
883 return; 901 return;
884 } 902 }
903 HostBindings host_bindings;
885 for (u32 index = 0; index < NUM_TRANSFORM_FEEDBACK_BUFFERS; ++index) { 904 for (u32 index = 0; index < NUM_TRANSFORM_FEEDBACK_BUFFERS; ++index) {
886 const Binding& binding = channel_state->transform_feedback_buffers[index]; 905 const Binding& binding = channel_state->transform_feedback_buffers[index];
906 if (maxwell3d->regs.transform_feedback.controls[index].varying_count == 0 &&
907 maxwell3d->regs.transform_feedback.controls[index].stride == 0) {
908 break;
909 }
887 Buffer& buffer = slot_buffers[binding.buffer_id]; 910 Buffer& buffer = slot_buffers[binding.buffer_id];
888 TouchBuffer(buffer, binding.buffer_id); 911 TouchBuffer(buffer, binding.buffer_id);
889 const u32 size = binding.size; 912 const u32 size = binding.size;
890 SynchronizeBuffer(buffer, binding.cpu_addr, size); 913 SynchronizeBuffer(buffer, binding.cpu_addr, size);
891 914
892 const u32 offset = buffer.Offset(binding.cpu_addr); 915 const u32 offset = buffer.Offset(binding.cpu_addr);
893 runtime.BindTransformFeedbackBuffer(index, buffer, offset, size); 916 host_bindings.buffers.push_back(reinterpret_cast<void*>(&buffer));
917 host_bindings.offsets.push_back(offset);
918 host_bindings.sizes.push_back(binding.size);
919 }
920 if (host_bindings.buffers.size() > 0) {
921 runtime.BindTransformFeedbackBuffers(host_bindings);
894 } 922 }
895} 923}
896 924
@@ -1616,6 +1644,8 @@ void BufferCache<P>::DownloadBufferMemory(Buffer& buffer, VAddr cpu_addr, u64 si
1616 1644
1617template <class P> 1645template <class P>
1618void BufferCache<P>::DeleteBuffer(BufferId buffer_id, bool do_not_mark) { 1646void BufferCache<P>::DeleteBuffer(BufferId buffer_id, bool do_not_mark) {
1647 bool dirty_index{false};
1648 boost::container::small_vector<u64, NUM_VERTEX_BUFFERS> dirty_vertex_buffers;
1619 const auto scalar_replace = [buffer_id](Binding& binding) { 1649 const auto scalar_replace = [buffer_id](Binding& binding) {
1620 if (binding.buffer_id == buffer_id) { 1650 if (binding.buffer_id == buffer_id) {
1621 binding.buffer_id = BufferId{}; 1651 binding.buffer_id = BufferId{};
@@ -1624,8 +1654,19 @@ void BufferCache<P>::DeleteBuffer(BufferId buffer_id, bool do_not_mark) {
1624 const auto replace = [scalar_replace](std::span<Binding> bindings) { 1654 const auto replace = [scalar_replace](std::span<Binding> bindings) {
1625 std::ranges::for_each(bindings, scalar_replace); 1655 std::ranges::for_each(bindings, scalar_replace);
1626 }; 1656 };
1627 scalar_replace(channel_state->index_buffer); 1657
1628 replace(channel_state->vertex_buffers); 1658 if (channel_state->index_buffer.buffer_id == buffer_id) {
1659 channel_state->index_buffer.buffer_id = BufferId{};
1660 dirty_index = true;
1661 }
1662
1663 for (u32 index = 0; index < channel_state->vertex_buffers.size(); index++) {
1664 auto& binding = channel_state->vertex_buffers[index];
1665 if (binding.buffer_id == buffer_id) {
1666 binding.buffer_id = BufferId{};
1667 dirty_vertex_buffers.push_back(index);
1668 }
1669 }
1629 std::ranges::for_each(channel_state->uniform_buffers, replace); 1670 std::ranges::for_each(channel_state->uniform_buffers, replace);
1630 std::ranges::for_each(channel_state->storage_buffers, replace); 1671 std::ranges::for_each(channel_state->storage_buffers, replace);
1631 replace(channel_state->transform_feedback_buffers); 1672 replace(channel_state->transform_feedback_buffers);
@@ -1642,20 +1683,21 @@ void BufferCache<P>::DeleteBuffer(BufferId buffer_id, bool do_not_mark) {
1642 delayed_destruction_ring.Push(std::move(slot_buffers[buffer_id])); 1683 delayed_destruction_ring.Push(std::move(slot_buffers[buffer_id]));
1643 slot_buffers.erase(buffer_id); 1684 slot_buffers.erase(buffer_id);
1644 1685
1645 NotifyBufferDeletion();
1646}
1647
1648template <class P>
1649void BufferCache<P>::NotifyBufferDeletion() {
1650 if constexpr (HAS_PERSISTENT_UNIFORM_BUFFER_BINDINGS) { 1686 if constexpr (HAS_PERSISTENT_UNIFORM_BUFFER_BINDINGS) {
1651 channel_state->dirty_uniform_buffers.fill(~u32{0}); 1687 channel_state->dirty_uniform_buffers.fill(~u32{0});
1652 channel_state->uniform_buffer_binding_sizes.fill({}); 1688 channel_state->uniform_buffer_binding_sizes.fill({});
1653 } 1689 }
1690
1654 auto& flags = maxwell3d->dirty.flags; 1691 auto& flags = maxwell3d->dirty.flags;
1655 flags[Dirty::IndexBuffer] = true; 1692 if (dirty_index) {
1656 flags[Dirty::VertexBuffers] = true; 1693 flags[Dirty::IndexBuffer] = true;
1657 for (u32 index = 0; index < NUM_VERTEX_BUFFERS; ++index) { 1694 }
1658 flags[Dirty::VertexBuffer0 + index] = true; 1695
1696 if (dirty_vertex_buffers.size() > 0) {
1697 flags[Dirty::VertexBuffers] = true;
1698 for (auto index : dirty_vertex_buffers) {
1699 flags[Dirty::VertexBuffer0 + index] = true;
1700 }
1659 } 1701 }
1660 channel_state->has_deleted_buffers = true; 1702 channel_state->has_deleted_buffers = true;
1661} 1703}
diff --git a/src/video_core/buffer_cache/buffer_cache_base.h b/src/video_core/buffer_cache/buffer_cache_base.h
index 60a1f285e..cf359e241 100644
--- a/src/video_core/buffer_cache/buffer_cache_base.h
+++ b/src/video_core/buffer_cache/buffer_cache_base.h
@@ -105,6 +105,15 @@ static constexpr Binding NULL_BINDING{
105 .buffer_id = NULL_BUFFER_ID, 105 .buffer_id = NULL_BUFFER_ID,
106}; 106};
107 107
108struct HostBindings {
109 boost::container::small_vector<void*, NUM_VERTEX_BUFFERS> buffers;
110 boost::container::small_vector<u64, NUM_VERTEX_BUFFERS> offsets;
111 boost::container::small_vector<u64, NUM_VERTEX_BUFFERS> sizes;
112 boost::container::small_vector<u64, NUM_VERTEX_BUFFERS> strides;
113 u32 min_index{NUM_VERTEX_BUFFERS};
114 u32 max_index{0};
115};
116
108class BufferCacheChannelInfo : public ChannelInfo { 117class BufferCacheChannelInfo : public ChannelInfo {
109public: 118public:
110 BufferCacheChannelInfo() = delete; 119 BufferCacheChannelInfo() = delete;
@@ -519,8 +528,6 @@ private:
519 528
520 void DeleteBuffer(BufferId buffer_id, bool do_not_mark = false); 529 void DeleteBuffer(BufferId buffer_id, bool do_not_mark = false);
521 530
522 void NotifyBufferDeletion();
523
524 [[nodiscard]] Binding StorageBufferBinding(GPUVAddr ssbo_addr, u32 cbuf_index, 531 [[nodiscard]] Binding StorageBufferBinding(GPUVAddr ssbo_addr, u32 cbuf_index,
525 bool is_written) const; 532 bool is_written) const;
526 533
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.cpp b/src/video_core/renderer_opengl/gl_buffer_cache.cpp
index c419714d4..0cc546a3a 100644
--- a/src/video_core/renderer_opengl/gl_buffer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_buffer_cache.cpp
@@ -232,6 +232,15 @@ void BufferCacheRuntime::BindVertexBuffer(u32 index, Buffer& buffer, u32 offset,
232 } 232 }
233} 233}
234 234
235void BufferCacheRuntime::BindVertexBuffers(VideoCommon::HostBindings& bindings) {
236 for (u32 index = 0; index < bindings.buffers.size(); index++) {
237 BindVertexBuffer(
238 bindings.min_index + index, *reinterpret_cast<Buffer*>(bindings.buffers[index]),
239 static_cast<u32>(bindings.offsets[index]), static_cast<u32>(bindings.sizes[index]),
240 static_cast<u32>(bindings.strides[index]));
241 }
242}
243
235void BufferCacheRuntime::BindUniformBuffer(size_t stage, u32 binding_index, Buffer& buffer, 244void BufferCacheRuntime::BindUniformBuffer(size_t stage, u32 binding_index, Buffer& buffer,
236 u32 offset, u32 size) { 245 u32 offset, u32 size) {
237 if (use_assembly_shaders) { 246 if (use_assembly_shaders) {
@@ -320,6 +329,15 @@ void BufferCacheRuntime::BindTransformFeedbackBuffer(u32 index, Buffer& buffer,
320 static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(size)); 329 static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(size));
321} 330}
322 331
332void BufferCacheRuntime::BindTransformFeedbackBuffers(VideoCommon::HostBindings& bindings) {
333 for (u32 index = 0; index < bindings.buffers.size(); index++) {
334 glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, index,
335 reinterpret_cast<Buffer*>(bindings.buffers[index])->Handle(),
336 static_cast<GLintptr>(bindings.offsets[index]),
337 static_cast<GLsizeiptr>(bindings.sizes[index]));
338 }
339}
340
323void BufferCacheRuntime::BindTextureBuffer(Buffer& buffer, u32 offset, u32 size, 341void BufferCacheRuntime::BindTextureBuffer(Buffer& buffer, u32 offset, u32 size,
324 PixelFormat format) { 342 PixelFormat format) {
325 *texture_handles++ = buffer.View(offset, size, format); 343 *texture_handles++ = buffer.View(offset, size, format);
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.h b/src/video_core/renderer_opengl/gl_buffer_cache.h
index a24991585..e4e000284 100644
--- a/src/video_core/renderer_opengl/gl_buffer_cache.h
+++ b/src/video_core/renderer_opengl/gl_buffer_cache.h
@@ -7,7 +7,7 @@
7#include <span> 7#include <span>
8 8
9#include "common/common_types.h" 9#include "common/common_types.h"
10#include "video_core/buffer_cache/buffer_cache.h" 10#include "video_core/buffer_cache/buffer_cache_base.h"
11#include "video_core/buffer_cache/memory_tracker_base.h" 11#include "video_core/buffer_cache/memory_tracker_base.h"
12#include "video_core/rasterizer_interface.h" 12#include "video_core/rasterizer_interface.h"
13#include "video_core/renderer_opengl/gl_device.h" 13#include "video_core/renderer_opengl/gl_device.h"
@@ -87,6 +87,7 @@ public:
87 void BindIndexBuffer(Buffer& buffer, u32 offset, u32 size); 87 void BindIndexBuffer(Buffer& buffer, u32 offset, u32 size);
88 88
89 void BindVertexBuffer(u32 index, Buffer& buffer, u32 offset, u32 size, u32 stride); 89 void BindVertexBuffer(u32 index, Buffer& buffer, u32 offset, u32 size, u32 stride);
90 void BindVertexBuffers(VideoCommon::HostBindings& bindings);
90 91
91 void BindUniformBuffer(size_t stage, u32 binding_index, Buffer& buffer, u32 offset, u32 size); 92 void BindUniformBuffer(size_t stage, u32 binding_index, Buffer& buffer, u32 offset, u32 size);
92 93
@@ -99,6 +100,7 @@ public:
99 bool is_written); 100 bool is_written);
100 101
101 void BindTransformFeedbackBuffer(u32 index, Buffer& buffer, u32 offset, u32 size); 102 void BindTransformFeedbackBuffer(u32 index, Buffer& buffer, u32 offset, u32 size);
103 void BindTransformFeedbackBuffers(VideoCommon::HostBindings& bindings);
102 104
103 void BindTextureBuffer(Buffer& buffer, u32 offset, u32 size, 105 void BindTextureBuffer(Buffer& buffer, u32 offset, u32 size,
104 VideoCore::Surface::PixelFormat format); 106 VideoCore::Surface::PixelFormat format);
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
index daa128399..d72d99899 100644
--- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
@@ -7,7 +7,6 @@
7#include <span> 7#include <span>
8#include <vector> 8#include <vector>
9 9
10#include "video_core/buffer_cache/buffer_cache.h"
11#include "video_core/renderer_vulkan/maxwell_to_vk.h" 10#include "video_core/renderer_vulkan/maxwell_to_vk.h"
12#include "video_core/renderer_vulkan/vk_buffer_cache.h" 11#include "video_core/renderer_vulkan/vk_buffer_cache.h"
13#include "video_core/renderer_vulkan/vk_scheduler.h" 12#include "video_core/renderer_vulkan/vk_scheduler.h"
@@ -502,6 +501,40 @@ void BufferCacheRuntime::BindVertexBuffer(u32 index, VkBuffer buffer, u32 offset
502 } 501 }
503} 502}
504 503
504void BufferCacheRuntime::BindVertexBuffers(VideoCommon::HostBindings& bindings) {
505 boost::container::small_vector<VkBuffer, 32> buffer_handles;
506 for (u32 index = 0; index < bindings.buffers.size(); index++) {
507 auto& buffer = *reinterpret_cast<Buffer*>(bindings.buffers[index]);
508 auto handle = buffer.Handle();
509 if (handle == VK_NULL_HANDLE) {
510 bindings.offsets[index] = 0;
511 bindings.sizes[index] = VK_WHOLE_SIZE;
512 if (!device.HasNullDescriptor()) {
513 ReserveNullBuffer();
514 handle = *null_buffer;
515 }
516 }
517 buffer_handles.push_back(handle);
518 }
519 if (device.IsExtExtendedDynamicStateSupported()) {
520 scheduler.Record([bindings = bindings,
521 buffer_handles = buffer_handles](vk::CommandBuffer cmdbuf) {
522 cmdbuf.BindVertexBuffers2EXT(
523 bindings.min_index, bindings.max_index - bindings.min_index, buffer_handles.data(),
524 reinterpret_cast<const VkDeviceSize*>(bindings.offsets.data()),
525 reinterpret_cast<const VkDeviceSize*>(bindings.sizes.data()),
526 reinterpret_cast<const VkDeviceSize*>(bindings.strides.data()));
527 });
528 } else {
529 scheduler.Record([bindings = bindings,
530 buffer_handles = buffer_handles](vk::CommandBuffer cmdbuf) {
531 cmdbuf.BindVertexBuffers(
532 bindings.min_index, bindings.max_index - bindings.min_index, buffer_handles.data(),
533 reinterpret_cast<const VkDeviceSize*>(bindings.offsets.data()));
534 });
535 }
536}
537
505void BufferCacheRuntime::BindTransformFeedbackBuffer(u32 index, VkBuffer buffer, u32 offset, 538void BufferCacheRuntime::BindTransformFeedbackBuffer(u32 index, VkBuffer buffer, u32 offset,
506 u32 size) { 539 u32 size) {
507 if (!device.IsExtTransformFeedbackSupported()) { 540 if (!device.IsExtTransformFeedbackSupported()) {
@@ -523,6 +556,25 @@ void BufferCacheRuntime::BindTransformFeedbackBuffer(u32 index, VkBuffer buffer,
523 }); 556 });
524} 557}
525 558
559void BufferCacheRuntime::BindTransformFeedbackBuffers(VideoCommon::HostBindings& bindings) {
560 if (!device.IsExtTransformFeedbackSupported()) {
561 // Already logged in the rasterizer
562 return;
563 }
564 boost::container::small_vector<VkBuffer, 4> buffer_handles;
565 for (u32 index = 0; index < bindings.buffers.size(); index++) {
566 auto& buffer = *reinterpret_cast<Buffer*>(bindings.buffers[index]);
567 buffer_handles.push_back(buffer.Handle());
568 }
569 scheduler.Record(
570 [bindings = bindings, buffer_handles = buffer_handles](vk::CommandBuffer cmdbuf) {
571 cmdbuf.BindTransformFeedbackBuffersEXT(
572 0, static_cast<u32>(buffer_handles.size()), buffer_handles.data(),
573 reinterpret_cast<const VkDeviceSize*>(bindings.offsets.data()),
574 reinterpret_cast<const VkDeviceSize*>(bindings.sizes.data()));
575 });
576}
577
526void BufferCacheRuntime::ReserveNullBuffer() { 578void BufferCacheRuntime::ReserveNullBuffer() {
527 if (null_buffer) { 579 if (null_buffer) {
528 return; 580 return;
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.h b/src/video_core/renderer_vulkan/vk_buffer_cache.h
index 92b4f7859..92d3e9f32 100644
--- a/src/video_core/renderer_vulkan/vk_buffer_cache.h
+++ b/src/video_core/renderer_vulkan/vk_buffer_cache.h
@@ -18,6 +18,7 @@ namespace Vulkan {
18class Device; 18class Device;
19class DescriptorPool; 19class DescriptorPool;
20class Scheduler; 20class Scheduler;
21struct HostVertexBinding;
21 22
22class BufferCacheRuntime; 23class BufferCacheRuntime;
23 24
@@ -96,8 +97,10 @@ public:
96 void BindQuadIndexBuffer(PrimitiveTopology topology, u32 first, u32 count); 97 void BindQuadIndexBuffer(PrimitiveTopology topology, u32 first, u32 count);
97 98
98 void BindVertexBuffer(u32 index, VkBuffer buffer, u32 offset, u32 size, u32 stride); 99 void BindVertexBuffer(u32 index, VkBuffer buffer, u32 offset, u32 size, u32 stride);
100 void BindVertexBuffers(VideoCommon::HostBindings& bindings);
99 101
100 void BindTransformFeedbackBuffer(u32 index, VkBuffer buffer, u32 offset, u32 size); 102 void BindTransformFeedbackBuffer(u32 index, VkBuffer buffer, u32 offset, u32 size);
103 void BindTransformFeedbackBuffers(VideoCommon::HostBindings& bindings);
101 104
102 std::span<u8> BindMappedUniformBuffer([[maybe_unused]] size_t stage, 105 std::span<u8> BindMappedUniformBuffer([[maybe_unused]] size_t stage,
103 [[maybe_unused]] u32 binding_index, u32 size) { 106 [[maybe_unused]] u32 binding_index, u32 size) {