diff options
| author | 2022-02-09 15:39:40 +0100 | |
|---|---|---|
| committer | 2023-01-01 16:43:57 -0500 | |
| commit | 0f89828073a541eaa2cfd985483f839bd2f97b74 (patch) | |
| tree | 3e26c71678e17ca97ec744a884f5ecb9ae2b6c5e /src/video_core/buffer_cache | |
| parent | MacroHLE: Add MultidrawIndirect HLE Macro. (diff) | |
| download | yuzu-0f89828073a541eaa2cfd985483f839bd2f97b74.tar.gz yuzu-0f89828073a541eaa2cfd985483f839bd2f97b74.tar.xz yuzu-0f89828073a541eaa2cfd985483f839bd2f97b74.zip | |
MacroHLE: Implement DrawIndexedIndirect & DrawArraysIndirect.
Diffstat (limited to 'src/video_core/buffer_cache')
| -rw-r--r-- | src/video_core/buffer_cache/buffer_cache.h | 160 |
1 files changed, 140 insertions, 20 deletions
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 99abe0edf..557227b37 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h | |||
| @@ -171,7 +171,9 @@ public: | |||
| 171 | bool is_written, bool is_image); | 171 | bool is_written, bool is_image); |
| 172 | 172 | ||
| 173 | [[nodiscard]] std::pair<Buffer*, u32> ObtainBuffer(GPUVAddr gpu_addr, u32 size, | 173 | [[nodiscard]] std::pair<Buffer*, u32> ObtainBuffer(GPUVAddr gpu_addr, u32 size, |
| 174 | bool synchronize, bool mark_as_written); | 174 | bool synchronize = true, |
| 175 | bool mark_as_written = false, | ||
| 176 | bool discard_downloads = false); | ||
| 175 | 177 | ||
| 176 | void FlushCachedWrites(); | 178 | void FlushCachedWrites(); |
| 177 | 179 | ||
| @@ -203,6 +205,14 @@ public: | |||
| 203 | /// Return true when a CPU region is modified from the CPU | 205 | /// Return true when a CPU region is modified from the CPU |
| 204 | [[nodiscard]] bool IsRegionCpuModified(VAddr addr, size_t size); | 206 | [[nodiscard]] bool IsRegionCpuModified(VAddr addr, size_t size); |
| 205 | 207 | ||
| 208 | void SetDrawIndirect(const Tegra::Engines::DrawManager::IndirectParams* current_draw_indirect_) { | ||
| 209 | current_draw_indirect = current_draw_indirect_; | ||
| 210 | } | ||
| 211 | |||
| 212 | [[nodiscard]] std::pair<Buffer*, u32> GetDrawIndirectCount(); | ||
| 213 | |||
| 214 | [[nodiscard]] std::pair<Buffer*, u32> GetDrawIndirectBuffer(); | ||
| 215 | |||
| 206 | std::mutex mutex; | 216 | std::mutex mutex; |
| 207 | Runtime& runtime; | 217 | Runtime& runtime; |
| 208 | 218 | ||
| @@ -275,6 +285,8 @@ private: | |||
| 275 | 285 | ||
| 276 | void BindHostVertexBuffers(); | 286 | void BindHostVertexBuffers(); |
| 277 | 287 | ||
| 288 | void BindHostDrawIndirectBuffers(); | ||
| 289 | |||
| 278 | void BindHostGraphicsUniformBuffers(size_t stage); | 290 | void BindHostGraphicsUniformBuffers(size_t stage); |
| 279 | 291 | ||
| 280 | void BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32 binding_index, bool needs_bind); | 292 | void BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32 binding_index, bool needs_bind); |
| @@ -301,6 +313,8 @@ private: | |||
| 301 | 313 | ||
| 302 | void UpdateVertexBuffer(u32 index); | 314 | void UpdateVertexBuffer(u32 index); |
| 303 | 315 | ||
| 316 | void UpdateDrawIndirect(); | ||
| 317 | |||
| 304 | void UpdateUniformBuffers(size_t stage); | 318 | void UpdateUniformBuffers(size_t stage); |
| 305 | 319 | ||
| 306 | void UpdateStorageBuffers(size_t stage); | 320 | void UpdateStorageBuffers(size_t stage); |
| @@ -340,6 +354,8 @@ private: | |||
| 340 | 354 | ||
| 341 | bool SynchronizeBufferImpl(Buffer& buffer, VAddr cpu_addr, u32 size); | 355 | bool SynchronizeBufferImpl(Buffer& buffer, VAddr cpu_addr, u32 size); |
| 342 | 356 | ||
| 357 | bool SynchronizeBufferNoModified(Buffer& buffer, VAddr cpu_addr, u32 size); | ||
| 358 | |||
| 343 | void UploadMemory(Buffer& buffer, u64 total_size_bytes, u64 largest_copy, | 359 | void UploadMemory(Buffer& buffer, u64 total_size_bytes, u64 largest_copy, |
| 344 | std::span<BufferCopy> copies); | 360 | std::span<BufferCopy> copies); |
| 345 | 361 | ||
| @@ -375,6 +391,8 @@ private: | |||
| 375 | SlotVector<Buffer> slot_buffers; | 391 | SlotVector<Buffer> slot_buffers; |
| 376 | DelayedDestructionRing<Buffer, 8> delayed_destruction_ring; | 392 | DelayedDestructionRing<Buffer, 8> delayed_destruction_ring; |
| 377 | 393 | ||
| 394 | const Tegra::Engines::DrawManager::IndirectParams* current_draw_indirect{}; | ||
| 395 | |||
| 378 | u32 last_index_count = 0; | 396 | u32 last_index_count = 0; |
| 379 | 397 | ||
| 380 | Binding index_buffer; | 398 | Binding index_buffer; |
| @@ -383,6 +401,8 @@ private: | |||
| 383 | std::array<std::array<Binding, NUM_STORAGE_BUFFERS>, NUM_STAGES> storage_buffers; | 401 | std::array<std::array<Binding, NUM_STORAGE_BUFFERS>, NUM_STAGES> storage_buffers; |
| 384 | std::array<std::array<TextureBufferBinding, NUM_TEXTURE_BUFFERS>, NUM_STAGES> texture_buffers; | 402 | std::array<std::array<TextureBufferBinding, NUM_TEXTURE_BUFFERS>, NUM_STAGES> texture_buffers; |
| 385 | std::array<Binding, NUM_TRANSFORM_FEEDBACK_BUFFERS> transform_feedback_buffers; | 403 | std::array<Binding, NUM_TRANSFORM_FEEDBACK_BUFFERS> transform_feedback_buffers; |
| 404 | Binding count_buffer_binding; | ||
| 405 | Binding indirect_buffer_binding; | ||
| 386 | 406 | ||
| 387 | std::array<Binding, NUM_COMPUTE_UNIFORM_BUFFERS> compute_uniform_buffers; | 407 | std::array<Binding, NUM_COMPUTE_UNIFORM_BUFFERS> compute_uniform_buffers; |
| 388 | std::array<Binding, NUM_STORAGE_BUFFERS> compute_storage_buffers; | 408 | std::array<Binding, NUM_STORAGE_BUFFERS> compute_storage_buffers; |
| @@ -422,6 +442,7 @@ private: | |||
| 422 | 442 | ||
| 423 | std::vector<BufferId> cached_write_buffer_ids; | 443 | std::vector<BufferId> cached_write_buffer_ids; |
| 424 | 444 | ||
| 445 | IntervalSet discarded_ranges; | ||
| 425 | IntervalSet uncommitted_ranges; | 446 | IntervalSet uncommitted_ranges; |
| 426 | IntervalSet common_ranges; | 447 | IntervalSet common_ranges; |
| 427 | std::deque<IntervalSet> committed_ranges; | 448 | std::deque<IntervalSet> committed_ranges; |
| @@ -579,13 +600,17 @@ bool BufferCache<P>::DMACopy(GPUVAddr src_address, GPUVAddr dest_address, u64 am | |||
| 579 | }}; | 600 | }}; |
| 580 | 601 | ||
| 581 | boost::container::small_vector<IntervalType, 4> tmp_intervals; | 602 | boost::container::small_vector<IntervalType, 4> tmp_intervals; |
| 603 | const bool is_high_accuracy = | ||
| 604 | Settings::values.gpu_accuracy.GetValue() == Settings::GPUAccuracy::High; | ||
| 582 | auto mirror = [&](VAddr base_address, VAddr base_address_end) { | 605 | auto mirror = [&](VAddr base_address, VAddr base_address_end) { |
| 583 | const u64 size = base_address_end - base_address; | 606 | const u64 size = base_address_end - base_address; |
| 584 | const VAddr diff = base_address - *cpu_src_address; | 607 | const VAddr diff = base_address - *cpu_src_address; |
| 585 | const VAddr new_base_address = *cpu_dest_address + diff; | 608 | const VAddr new_base_address = *cpu_dest_address + diff; |
| 586 | const IntervalType add_interval{new_base_address, new_base_address + size}; | 609 | const IntervalType add_interval{new_base_address, new_base_address + size}; |
| 587 | uncommitted_ranges.add(add_interval); | ||
| 588 | tmp_intervals.push_back(add_interval); | 610 | tmp_intervals.push_back(add_interval); |
| 611 | if (is_high_accuracy) { | ||
| 612 | uncommitted_ranges.add(add_interval); | ||
| 613 | } | ||
| 589 | }; | 614 | }; |
| 590 | ForEachWrittenRange(*cpu_src_address, amount, mirror); | 615 | ForEachWrittenRange(*cpu_src_address, amount, mirror); |
| 591 | // This subtraction in this order is important for overlapping copies. | 616 | // This subtraction in this order is important for overlapping copies. |
| @@ -677,6 +702,9 @@ void BufferCache<P>::BindHostGeometryBuffers(bool is_indexed) { | |||
| 677 | } | 702 | } |
| 678 | BindHostVertexBuffers(); | 703 | BindHostVertexBuffers(); |
| 679 | BindHostTransformFeedbackBuffers(); | 704 | BindHostTransformFeedbackBuffers(); |
| 705 | if (current_draw_indirect) { | ||
| 706 | BindHostDrawIndirectBuffers(); | ||
| 707 | } | ||
| 680 | } | 708 | } |
| 681 | 709 | ||
| 682 | template <class P> | 710 | template <class P> |
| @@ -796,7 +824,8 @@ void BufferCache<P>::BindComputeTextureBuffer(size_t tbo_index, GPUVAddr gpu_add | |||
| 796 | template <class P> | 824 | template <class P> |
| 797 | std::pair<typename P::Buffer*, u32> BufferCache<P>::ObtainBuffer(GPUVAddr gpu_addr, u32 size, | 825 | std::pair<typename P::Buffer*, u32> BufferCache<P>::ObtainBuffer(GPUVAddr gpu_addr, u32 size, |
| 798 | bool synchronize, | 826 | bool synchronize, |
| 799 | bool mark_as_written) { | 827 | bool mark_as_written, |
| 828 | bool discard_downloads) { | ||
| 800 | const std::optional<VAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr); | 829 | const std::optional<VAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr); |
| 801 | if (!cpu_addr) { | 830 | if (!cpu_addr) { |
| 802 | return {&slot_buffers[NULL_BUFFER_ID], 0}; | 831 | return {&slot_buffers[NULL_BUFFER_ID], 0}; |
| @@ -804,11 +833,17 @@ std::pair<typename P::Buffer*, u32> BufferCache<P>::ObtainBuffer(GPUVAddr gpu_ad | |||
| 804 | const BufferId buffer_id = FindBuffer(*cpu_addr, size); | 833 | const BufferId buffer_id = FindBuffer(*cpu_addr, size); |
| 805 | Buffer& buffer = slot_buffers[buffer_id]; | 834 | Buffer& buffer = slot_buffers[buffer_id]; |
| 806 | if (synchronize) { | 835 | if (synchronize) { |
| 807 | SynchronizeBuffer(buffer, *cpu_addr, size); | 836 | // SynchronizeBuffer(buffer, *cpu_addr, size); |
| 837 | SynchronizeBufferNoModified(buffer, *cpu_addr, size); | ||
| 808 | } | 838 | } |
| 809 | if (mark_as_written) { | 839 | if (mark_as_written) { |
| 810 | MarkWrittenBuffer(buffer_id, *cpu_addr, size); | 840 | MarkWrittenBuffer(buffer_id, *cpu_addr, size); |
| 811 | } | 841 | } |
| 842 | if (discard_downloads) { | ||
| 843 | IntervalType interval{*cpu_addr, size}; | ||
| 844 | ClearDownload(interval); | ||
| 845 | discarded_ranges.subtract(interval); | ||
| 846 | } | ||
| 812 | return {&buffer, buffer.Offset(*cpu_addr)}; | 847 | return {&buffer, buffer.Offset(*cpu_addr)}; |
| 813 | } | 848 | } |
| 814 | 849 | ||
| @@ -827,10 +862,6 @@ bool BufferCache<P>::HasUncommittedFlushes() const noexcept { | |||
| 827 | 862 | ||
| 828 | template <class P> | 863 | template <class P> |
| 829 | void BufferCache<P>::AccumulateFlushes() { | 864 | void BufferCache<P>::AccumulateFlushes() { |
| 830 | if (Settings::values.gpu_accuracy.GetValue() != Settings::GPUAccuracy::High) { | ||
| 831 | uncommitted_ranges.clear(); | ||
| 832 | return; | ||
| 833 | } | ||
| 834 | if (uncommitted_ranges.empty()) { | 865 | if (uncommitted_ranges.empty()) { |
| 835 | return; | 866 | return; |
| 836 | } | 867 | } |
| @@ -845,12 +876,15 @@ bool BufferCache<P>::ShouldWaitAsyncFlushes() const noexcept { | |||
| 845 | template <class P> | 876 | template <class P> |
| 846 | void BufferCache<P>::CommitAsyncFlushesHigh() { | 877 | void BufferCache<P>::CommitAsyncFlushesHigh() { |
| 847 | AccumulateFlushes(); | 878 | AccumulateFlushes(); |
| 879 | |||
| 880 | for (const auto& interval : discarded_ranges) { | ||
| 881 | common_ranges.subtract(interval); | ||
| 882 | } | ||
| 883 | |||
| 848 | if (committed_ranges.empty()) { | 884 | if (committed_ranges.empty()) { |
| 849 | return; | 885 | return; |
| 850 | } | 886 | } |
| 851 | MICROPROFILE_SCOPE(GPU_DownloadMemory); | 887 | MICROPROFILE_SCOPE(GPU_DownloadMemory); |
| 852 | const bool is_accuracy_normal = | ||
| 853 | Settings::values.gpu_accuracy.GetValue() == Settings::GPUAccuracy::Normal; | ||
| 854 | 888 | ||
| 855 | auto it = committed_ranges.begin(); | 889 | auto it = committed_ranges.begin(); |
| 856 | while (it != committed_ranges.end()) { | 890 | while (it != committed_ranges.end()) { |
| @@ -875,9 +909,6 @@ void BufferCache<P>::CommitAsyncFlushesHigh() { | |||
| 875 | ForEachBufferInRange(cpu_addr, size, [&](BufferId buffer_id, Buffer& buffer) { | 909 | ForEachBufferInRange(cpu_addr, size, [&](BufferId buffer_id, Buffer& buffer) { |
| 876 | buffer.ForEachDownloadRangeAndClear( | 910 | buffer.ForEachDownloadRangeAndClear( |
| 877 | cpu_addr, size, [&](u64 range_offset, u64 range_size) { | 911 | cpu_addr, size, [&](u64 range_offset, u64 range_size) { |
| 878 | if (is_accuracy_normal) { | ||
| 879 | return; | ||
| 880 | } | ||
| 881 | const VAddr buffer_addr = buffer.CpuAddr(); | 912 | const VAddr buffer_addr = buffer.CpuAddr(); |
| 882 | const auto add_download = [&](VAddr start, VAddr end) { | 913 | const auto add_download = [&](VAddr start, VAddr end) { |
| 883 | const u64 new_offset = start - buffer_addr; | 914 | const u64 new_offset = start - buffer_addr; |
| @@ -891,7 +922,7 @@ void BufferCache<P>::CommitAsyncFlushesHigh() { | |||
| 891 | buffer_id, | 922 | buffer_id, |
| 892 | }); | 923 | }); |
| 893 | // Align up to avoid cache conflicts | 924 | // Align up to avoid cache conflicts |
| 894 | constexpr u64 align = 256ULL; | 925 | constexpr u64 align = 8ULL; |
| 895 | constexpr u64 mask = ~(align - 1ULL); | 926 | constexpr u64 mask = ~(align - 1ULL); |
| 896 | total_size_bytes += (new_size + align - 1) & mask; | 927 | total_size_bytes += (new_size + align - 1) & mask; |
| 897 | largest_copy = std::max(largest_copy, new_size); | 928 | largest_copy = std::max(largest_copy, new_size); |
| @@ -942,12 +973,7 @@ void BufferCache<P>::CommitAsyncFlushesHigh() { | |||
| 942 | 973 | ||
| 943 | template <class P> | 974 | template <class P> |
| 944 | void BufferCache<P>::CommitAsyncFlushes() { | 975 | void BufferCache<P>::CommitAsyncFlushes() { |
| 945 | if (Settings::values.gpu_accuracy.GetValue() == Settings::GPUAccuracy::High) { | 976 | CommitAsyncFlushesHigh(); |
| 946 | CommitAsyncFlushesHigh(); | ||
| 947 | } else { | ||
| 948 | uncommitted_ranges.clear(); | ||
| 949 | committed_ranges.clear(); | ||
| 950 | } | ||
| 951 | } | 977 | } |
| 952 | 978 | ||
| 953 | template <class P> | 979 | template <class P> |
| @@ -1064,6 +1090,19 @@ void BufferCache<P>::BindHostVertexBuffers() { | |||
| 1064 | } | 1090 | } |
| 1065 | 1091 | ||
| 1066 | template <class P> | 1092 | template <class P> |
| 1093 | void BufferCache<P>::BindHostDrawIndirectBuffers() { | ||
| 1094 | const auto bind_buffer = [this](const Binding& binding) { | ||
| 1095 | Buffer& buffer = slot_buffers[binding.buffer_id]; | ||
| 1096 | TouchBuffer(buffer, binding.buffer_id); | ||
| 1097 | SynchronizeBuffer(buffer, binding.cpu_addr, binding.size); | ||
| 1098 | }; | ||
| 1099 | if (current_draw_indirect->include_count) { | ||
| 1100 | bind_buffer(count_buffer_binding); | ||
| 1101 | } | ||
| 1102 | bind_buffer(indirect_buffer_binding); | ||
| 1103 | } | ||
| 1104 | |||
| 1105 | template <class P> | ||
| 1067 | void BufferCache<P>::BindHostGraphicsUniformBuffers(size_t stage) { | 1106 | void BufferCache<P>::BindHostGraphicsUniformBuffers(size_t stage) { |
| 1068 | u32 dirty = ~0U; | 1107 | u32 dirty = ~0U; |
| 1069 | if constexpr (HAS_PERSISTENT_UNIFORM_BUFFER_BINDINGS) { | 1108 | if constexpr (HAS_PERSISTENT_UNIFORM_BUFFER_BINDINGS) { |
| @@ -1294,6 +1333,9 @@ void BufferCache<P>::DoUpdateGraphicsBuffers(bool is_indexed) { | |||
| 1294 | UpdateStorageBuffers(stage); | 1333 | UpdateStorageBuffers(stage); |
| 1295 | UpdateTextureBuffers(stage); | 1334 | UpdateTextureBuffers(stage); |
| 1296 | } | 1335 | } |
| 1336 | if (current_draw_indirect) { | ||
| 1337 | UpdateDrawIndirect(); | ||
| 1338 | } | ||
| 1297 | } while (has_deleted_buffers); | 1339 | } while (has_deleted_buffers); |
| 1298 | } | 1340 | } |
| 1299 | 1341 | ||
| @@ -1384,6 +1426,27 @@ void BufferCache<P>::UpdateVertexBuffer(u32 index) { | |||
| 1384 | } | 1426 | } |
| 1385 | 1427 | ||
| 1386 | template <class P> | 1428 | template <class P> |
| 1429 | void BufferCache<P>::UpdateDrawIndirect() { | ||
| 1430 | const auto update = [this](GPUVAddr gpu_addr, size_t size, Binding& binding) { | ||
| 1431 | const std::optional<VAddr> cpu_addr = gpu_memory->GpuToCpuAddress(gpu_addr); | ||
| 1432 | if (!cpu_addr) { | ||
| 1433 | binding = NULL_BINDING; | ||
| 1434 | return; | ||
| 1435 | } | ||
| 1436 | binding = Binding{ | ||
| 1437 | .cpu_addr = *cpu_addr, | ||
| 1438 | .size = static_cast<u32>(size), | ||
| 1439 | .buffer_id = FindBuffer(*cpu_addr, static_cast<u32>(size)), | ||
| 1440 | }; | ||
| 1441 | }; | ||
| 1442 | if (current_draw_indirect->include_count) { | ||
| 1443 | update(current_draw_indirect->count_start_address, sizeof(u32), count_buffer_binding); | ||
| 1444 | } | ||
| 1445 | update(current_draw_indirect->indirect_start_address, current_draw_indirect->buffer_size, | ||
| 1446 | indirect_buffer_binding); | ||
| 1447 | } | ||
| 1448 | |||
| 1449 | template <class P> | ||
| 1387 | void BufferCache<P>::UpdateUniformBuffers(size_t stage) { | 1450 | void BufferCache<P>::UpdateUniformBuffers(size_t stage) { |
| 1388 | ForEachEnabledBit(enabled_uniform_buffer_masks[stage], [&](u32 index) { | 1451 | ForEachEnabledBit(enabled_uniform_buffer_masks[stage], [&](u32 index) { |
| 1389 | Binding& binding = uniform_buffers[stage][index]; | 1452 | Binding& binding = uniform_buffers[stage][index]; |
| @@ -1705,6 +1768,51 @@ bool BufferCache<P>::SynchronizeBufferImpl(Buffer& buffer, VAddr cpu_addr, u32 s | |||
| 1705 | } | 1768 | } |
| 1706 | 1769 | ||
| 1707 | template <class P> | 1770 | template <class P> |
| 1771 | bool BufferCache<P>::SynchronizeBufferNoModified(Buffer& buffer, VAddr cpu_addr, u32 size) { | ||
| 1772 | boost::container::small_vector<BufferCopy, 4> copies; | ||
| 1773 | u64 total_size_bytes = 0; | ||
| 1774 | u64 largest_copy = 0; | ||
| 1775 | IntervalSet found_sets{}; | ||
| 1776 | auto make_copies = [&] { | ||
| 1777 | for (auto& interval : found_sets) { | ||
| 1778 | const std::size_t sub_size = interval.upper() - interval.lower(); | ||
| 1779 | const VAddr cpu_addr = interval.lower(); | ||
| 1780 | copies.push_back(BufferCopy{ | ||
| 1781 | .src_offset = total_size_bytes, | ||
| 1782 | .dst_offset = cpu_addr - buffer.CpuAddr(), | ||
| 1783 | .size = sub_size, | ||
| 1784 | }); | ||
| 1785 | total_size_bytes += sub_size; | ||
| 1786 | largest_copy = std::max(largest_copy, sub_size); | ||
| 1787 | } | ||
| 1788 | const std::span<BufferCopy> copies_span(copies.data(), copies.size()); | ||
| 1789 | UploadMemory(buffer, total_size_bytes, largest_copy, copies_span); | ||
| 1790 | }; | ||
| 1791 | buffer.ForEachUploadRange(cpu_addr, size, [&](u64 range_offset, u64 range_size) { | ||
| 1792 | const VAddr base_adr = buffer.CpuAddr() + range_offset; | ||
| 1793 | const VAddr end_adr = base_adr + range_size; | ||
| 1794 | const IntervalType add_interval{base_adr, end_adr}; | ||
| 1795 | found_sets.add(add_interval); | ||
| 1796 | }); | ||
| 1797 | if (found_sets.empty()) { | ||
| 1798 | return true; | ||
| 1799 | } | ||
| 1800 | const IntervalType search_interval{cpu_addr, cpu_addr + size}; | ||
| 1801 | auto it = common_ranges.lower_bound(search_interval); | ||
| 1802 | auto it_end = common_ranges.upper_bound(search_interval); | ||
| 1803 | if (it == common_ranges.end()) { | ||
| 1804 | make_copies(); | ||
| 1805 | return false; | ||
| 1806 | } | ||
| 1807 | while (it != it_end) { | ||
| 1808 | found_sets.subtract(*it); | ||
| 1809 | it++; | ||
| 1810 | } | ||
| 1811 | make_copies(); | ||
| 1812 | return false; | ||
| 1813 | } | ||
| 1814 | |||
| 1815 | template <class P> | ||
| 1708 | void BufferCache<P>::UploadMemory(Buffer& buffer, u64 total_size_bytes, u64 largest_copy, | 1816 | void BufferCache<P>::UploadMemory(Buffer& buffer, u64 total_size_bytes, u64 largest_copy, |
| 1709 | std::span<BufferCopy> copies) { | 1817 | std::span<BufferCopy> copies) { |
| 1710 | if constexpr (USE_MEMORY_MAPS) { | 1818 | if constexpr (USE_MEMORY_MAPS) { |
| @@ -1963,4 +2071,16 @@ bool BufferCache<P>::HasFastUniformBufferBound(size_t stage, u32 binding_index) | |||
| 1963 | } | 2071 | } |
| 1964 | } | 2072 | } |
| 1965 | 2073 | ||
| 2074 | template <class P> | ||
| 2075 | std::pair<typename BufferCache<P>::Buffer*, u32> BufferCache<P>::GetDrawIndirectCount() { | ||
| 2076 | auto& buffer = slot_buffers[count_buffer_binding.buffer_id]; | ||
| 2077 | return std::make_pair(&buffer, buffer.Offset(count_buffer_binding.cpu_addr)); | ||
| 2078 | } | ||
| 2079 | |||
| 2080 | template <class P> | ||
| 2081 | std::pair<typename BufferCache<P>::Buffer*, u32> BufferCache<P>::GetDrawIndirectBuffer() { | ||
| 2082 | auto& buffer = slot_buffers[indirect_buffer_binding.buffer_id]; | ||
| 2083 | return std::make_pair(&buffer, buffer.Offset(indirect_buffer_binding.cpu_addr)); | ||
| 2084 | } | ||
| 2085 | |||
| 1966 | } // namespace VideoCommon | 2086 | } // namespace VideoCommon |