diff options
| author | 2023-06-11 11:33:48 -0700 | |
|---|---|---|
| committer | 2023-06-11 11:33:48 -0700 | |
| commit | 569f8d3b44301e40bcfe3bf42bcae5ae6c45ab02 (patch) | |
| tree | 16c3458c1802d223ff078046ca03a573b7e8f538 /src | |
| parent | Merge pull request #10713 from t895/gradle-updates (diff) | |
| parent | Combine vertex/transform feedback buffer binding into a single call (diff) | |
| download | yuzu-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.h | 82 | ||||
| -rw-r--r-- | src/video_core/buffer_cache/buffer_cache_base.h | 11 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_buffer_cache.cpp | 18 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_buffer_cache.h | 4 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_buffer_cache.cpp | 54 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_buffer_cache.h | 3 |
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 | ||
| 716 | template <class P> | 716 | template <class P> |
| 717 | void BufferCache<P>::BindHostVertexBuffers() { | 717 | void 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 | ||
| 1617 | template <class P> | 1645 | template <class P> |
| 1618 | void BufferCache<P>::DeleteBuffer(BufferId buffer_id, bool do_not_mark) { | 1646 | void 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 | |||
| 1648 | template <class P> | ||
| 1649 | void 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 | ||
| 108 | struct 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 | |||
| 108 | class BufferCacheChannelInfo : public ChannelInfo { | 117 | class BufferCacheChannelInfo : public ChannelInfo { |
| 109 | public: | 118 | public: |
| 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 | ||
| 235 | void 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 | |||
| 235 | void BufferCacheRuntime::BindUniformBuffer(size_t stage, u32 binding_index, Buffer& buffer, | 244 | void 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 | ||
| 332 | void 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 | |||
| 323 | void BufferCacheRuntime::BindTextureBuffer(Buffer& buffer, u32 offset, u32 size, | 341 | void 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 | ||
| 504 | void 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 | |||
| 505 | void BufferCacheRuntime::BindTransformFeedbackBuffer(u32 index, VkBuffer buffer, u32 offset, | 538 | void 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 | ||
| 559 | void 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 | |||
| 526 | void BufferCacheRuntime::ReserveNullBuffer() { | 578 | void 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 { | |||
| 18 | class Device; | 18 | class Device; |
| 19 | class DescriptorPool; | 19 | class DescriptorPool; |
| 20 | class Scheduler; | 20 | class Scheduler; |
| 21 | struct HostVertexBinding; | ||
| 21 | 22 | ||
| 22 | class BufferCacheRuntime; | 23 | class 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) { |