summaryrefslogtreecommitdiff
path: root/src/video_core/buffer_cache
diff options
context:
space:
mode:
authorGravatar Kelebek12023-06-04 21:09:57 +0100
committerGravatar Kelebek12023-06-08 12:13:27 +0100
commitace6c2318be5e8c5b2ad5f489d8144f28505d5f9 (patch)
tree0bde2e03aa840aba635109f6281215f64e99bb37 /src/video_core/buffer_cache
parentMerge pull request #10655 from Morph1984/msvc-cxx20 (diff)
downloadyuzu-ace6c2318be5e8c5b2ad5f489d8144f28505d5f9.tar.gz
yuzu-ace6c2318be5e8c5b2ad5f489d8144f28505d5f9.tar.xz
yuzu-ace6c2318be5e8c5b2ad5f489d8144f28505d5f9.zip
Combine vertex/transform feedback buffer binding into a single call
Diffstat (limited to 'src/video_core/buffer_cache')
-rw-r--r--src/video_core/buffer_cache/buffer_cache.h82
-rw-r--r--src/video_core/buffer_cache/buffer_cache_base.h11
2 files changed, 71 insertions, 22 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