summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/buffer_cache/buffer_block.h27
-rw-r--r--src/video_core/buffer_cache/buffer_cache.h199
-rw-r--r--src/video_core/macro/macro_jit_x64.h4
-rw-r--r--src/video_core/renderer_opengl/gl_buffer_cache.cpp21
-rw-r--r--src/video_core/renderer_opengl/gl_buffer_cache.h18
-rw-r--r--src/video_core/renderer_opengl/gl_stream_buffer.cpp8
-rw-r--r--src/video_core/renderer_opengl/gl_stream_buffer.h11
-rw-r--r--src/video_core/renderer_vulkan/vk_buffer_cache.cpp22
-rw-r--r--src/video_core/renderer_vulkan/vk_buffer_cache.h16
-rw-r--r--src/video_core/renderer_vulkan/vk_stream_buffer.h2
10 files changed, 152 insertions, 176 deletions
diff --git a/src/video_core/buffer_cache/buffer_block.h b/src/video_core/buffer_cache/buffer_block.h
index e35ee0b67..e64170e66 100644
--- a/src/video_core/buffer_cache/buffer_block.h
+++ b/src/video_core/buffer_cache/buffer_block.h
@@ -15,48 +15,47 @@ namespace VideoCommon {
15 15
16class BufferBlock { 16class BufferBlock {
17public: 17public:
18 bool Overlaps(const VAddr start, const VAddr end) const { 18 bool Overlaps(VAddr start, VAddr end) const {
19 return (cpu_addr < end) && (cpu_addr_end > start); 19 return (cpu_addr < end) && (cpu_addr_end > start);
20 } 20 }
21 21
22 bool IsInside(const VAddr other_start, const VAddr other_end) const { 22 bool IsInside(VAddr other_start, VAddr other_end) const {
23 return cpu_addr <= other_start && other_end <= cpu_addr_end; 23 return cpu_addr <= other_start && other_end <= cpu_addr_end;
24 } 24 }
25 25
26 std::size_t GetOffset(const VAddr in_addr) { 26 std::size_t Offset(VAddr in_addr) const {
27 return static_cast<std::size_t>(in_addr - cpu_addr); 27 return static_cast<std::size_t>(in_addr - cpu_addr);
28 } 28 }
29 29
30 VAddr GetCpuAddr() const { 30 VAddr CpuAddr() const {
31 return cpu_addr; 31 return cpu_addr;
32 } 32 }
33 33
34 VAddr GetCpuAddrEnd() const { 34 VAddr CpuAddrEnd() const {
35 return cpu_addr_end; 35 return cpu_addr_end;
36 } 36 }
37 37
38 void SetCpuAddr(const VAddr new_addr) { 38 void SetCpuAddr(VAddr new_addr) {
39 cpu_addr = new_addr; 39 cpu_addr = new_addr;
40 cpu_addr_end = new_addr + size; 40 cpu_addr_end = new_addr + size;
41 } 41 }
42 42
43 std::size_t GetSize() const { 43 std::size_t Size() const {
44 return size; 44 return size;
45 } 45 }
46 46
47 void SetEpoch(u64 new_epoch) { 47 u64 Epoch() const {
48 epoch = new_epoch; 48 return epoch;
49 } 49 }
50 50
51 u64 GetEpoch() { 51 void SetEpoch(u64 new_epoch) {
52 return epoch; 52 epoch = new_epoch;
53 } 53 }
54 54
55protected: 55protected:
56 explicit BufferBlock(VAddr cpu_addr, const std::size_t size) : size{size} { 56 explicit BufferBlock(VAddr cpu_addr_, std::size_t size_) : size{size_} {
57 SetCpuAddr(cpu_addr); 57 SetCpuAddr(cpu_addr_);
58 } 58 }
59 ~BufferBlock() = default;
60 59
61private: 60private:
62 VAddr cpu_addr{}; 61 VAddr cpu_addr{};
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h
index 77ae34339..308d8b55f 100644
--- a/src/video_core/buffer_cache/buffer_cache.h
+++ b/src/video_core/buffer_cache/buffer_cache.h
@@ -30,12 +30,16 @@
30 30
31namespace VideoCommon { 31namespace VideoCommon {
32 32
33template <typename OwnerBuffer, typename BufferType, typename StreamBuffer> 33template <typename Buffer, typename BufferType, typename StreamBuffer>
34class BufferCache { 34class BufferCache {
35 using IntervalSet = boost::icl::interval_set<VAddr>; 35 using IntervalSet = boost::icl::interval_set<VAddr>;
36 using IntervalType = typename IntervalSet::interval_type; 36 using IntervalType = typename IntervalSet::interval_type;
37 using VectorMapInterval = boost::container::small_vector<MapInterval*, 1>; 37 using VectorMapInterval = boost::container::small_vector<MapInterval*, 1>;
38 38
39 static constexpr u64 WRITE_PAGE_BIT = 11;
40 static constexpr u64 BLOCK_PAGE_BITS = 21;
41 static constexpr u64 BLOCK_PAGE_SIZE = 1ULL << BLOCK_PAGE_BITS;
42
39public: 43public:
40 using BufferInfo = std::pair<BufferType, u64>; 44 using BufferInfo = std::pair<BufferType, u64>;
41 45
@@ -82,7 +86,7 @@ public:
82 } 86 }
83 } 87 }
84 88
85 OwnerBuffer block = GetBlock(cpu_addr, size); 89 Buffer* const block = GetBlock(cpu_addr, size);
86 MapInterval* const map = MapAddress(block, gpu_addr, cpu_addr, size); 90 MapInterval* const map = MapAddress(block, gpu_addr, cpu_addr, size);
87 if (!map) { 91 if (!map) {
88 return {GetEmptyBuffer(size), 0}; 92 return {GetEmptyBuffer(size), 0};
@@ -98,7 +102,7 @@ public:
98 } 102 }
99 } 103 }
100 104
101 return {ToHandle(block), static_cast<u64>(block->GetOffset(cpu_addr))}; 105 return {block->Handle(), static_cast<u64>(block->Offset(cpu_addr))};
102 } 106 }
103 107
104 /// Uploads from a host memory. Returns the OpenGL buffer where it's located and its offset. 108 /// Uploads from a host memory. Returns the OpenGL buffer where it's located and its offset.
@@ -129,16 +133,18 @@ public:
129 stream_buffer->Unmap(buffer_offset - buffer_offset_base); 133 stream_buffer->Unmap(buffer_offset - buffer_offset_base);
130 } 134 }
131 135
136 /// Function called at the end of each frame, inteded for deferred operations
132 void TickFrame() { 137 void TickFrame() {
133 ++epoch; 138 ++epoch;
139
134 while (!pending_destruction.empty()) { 140 while (!pending_destruction.empty()) {
135 // Delay at least 4 frames before destruction. 141 // Delay at least 4 frames before destruction.
136 // This is due to triple buffering happening on some drivers. 142 // This is due to triple buffering happening on some drivers.
137 static constexpr u64 epochs_to_destroy = 5; 143 static constexpr u64 epochs_to_destroy = 5;
138 if (pending_destruction.front()->GetEpoch() + epochs_to_destroy > epoch) { 144 if (pending_destruction.front()->Epoch() + epochs_to_destroy > epoch) {
139 break; 145 break;
140 } 146 }
141 pending_destruction.pop_front(); 147 pending_destruction.pop();
142 } 148 }
143 } 149 }
144 150
@@ -253,23 +259,21 @@ public:
253 259
254protected: 260protected:
255 explicit BufferCache(VideoCore::RasterizerInterface& rasterizer, Core::System& system, 261 explicit BufferCache(VideoCore::RasterizerInterface& rasterizer, Core::System& system,
256 std::unique_ptr<StreamBuffer> stream_buffer) 262 std::unique_ptr<StreamBuffer> stream_buffer_)
257 : rasterizer{rasterizer}, system{system}, stream_buffer{std::move(stream_buffer)}, 263 : rasterizer{rasterizer}, system{system}, stream_buffer{std::move(stream_buffer_)},
258 stream_buffer_handle{this->stream_buffer->GetHandle()} {} 264 stream_buffer_handle{stream_buffer->Handle()} {}
259 265
260 ~BufferCache() = default; 266 ~BufferCache() = default;
261 267
262 virtual BufferType ToHandle(const OwnerBuffer& storage) = 0; 268 virtual std::shared_ptr<Buffer> CreateBlock(VAddr cpu_addr, std::size_t size) = 0;
263 269
264 virtual OwnerBuffer CreateBlock(VAddr cpu_addr, std::size_t size) = 0; 270 virtual void UploadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size,
265
266 virtual void UploadBlockData(const OwnerBuffer& buffer, std::size_t offset, std::size_t size,
267 const u8* data) = 0; 271 const u8* data) = 0;
268 272
269 virtual void DownloadBlockData(const OwnerBuffer& buffer, std::size_t offset, std::size_t size, 273 virtual void DownloadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size,
270 u8* data) = 0; 274 u8* data) = 0;
271 275
272 virtual void CopyBlock(const OwnerBuffer& src, const OwnerBuffer& dst, std::size_t src_offset, 276 virtual void CopyBlock(const Buffer& src, const Buffer& dst, std::size_t src_offset,
273 std::size_t dst_offset, std::size_t size) = 0; 277 std::size_t dst_offset, std::size_t size) = 0;
274 278
275 virtual BufferInfo ConstBufferUpload(const void* raw_pointer, std::size_t size) { 279 virtual BufferInfo ConstBufferUpload(const void* raw_pointer, std::size_t size) {
@@ -325,7 +329,7 @@ protected:
325 } 329 }
326 330
327private: 331private:
328 MapInterval* MapAddress(const OwnerBuffer& block, GPUVAddr gpu_addr, VAddr cpu_addr, 332 MapInterval* MapAddress(const Buffer* block, GPUVAddr gpu_addr, VAddr cpu_addr,
329 std::size_t size) { 333 std::size_t size) {
330 const VectorMapInterval overlaps = GetMapsInRange(cpu_addr, size); 334 const VectorMapInterval overlaps = GetMapsInRange(cpu_addr, size);
331 if (overlaps.empty()) { 335 if (overlaps.empty()) {
@@ -333,11 +337,11 @@ private:
333 const VAddr cpu_addr_end = cpu_addr + size; 337 const VAddr cpu_addr_end = cpu_addr + size;
334 if (memory_manager.IsGranularRange(gpu_addr, size)) { 338 if (memory_manager.IsGranularRange(gpu_addr, size)) {
335 u8* host_ptr = memory_manager.GetPointer(gpu_addr); 339 u8* host_ptr = memory_manager.GetPointer(gpu_addr);
336 UploadBlockData(block, block->GetOffset(cpu_addr), size, host_ptr); 340 UploadBlockData(*block, block->Offset(cpu_addr), size, host_ptr);
337 } else { 341 } else {
338 staging_buffer.resize(size); 342 staging_buffer.resize(size);
339 memory_manager.ReadBlockUnsafe(gpu_addr, staging_buffer.data(), size); 343 memory_manager.ReadBlockUnsafe(gpu_addr, staging_buffer.data(), size);
340 UploadBlockData(block, block->GetOffset(cpu_addr), size, staging_buffer.data()); 344 UploadBlockData(*block, block->Offset(cpu_addr), size, staging_buffer.data());
341 } 345 }
342 return Register(MapInterval(cpu_addr, cpu_addr_end, gpu_addr)); 346 return Register(MapInterval(cpu_addr, cpu_addr_end, gpu_addr));
343 } 347 }
@@ -380,7 +384,7 @@ private:
380 return map; 384 return map;
381 } 385 }
382 386
383 void UpdateBlock(const OwnerBuffer& block, VAddr start, VAddr end, 387 void UpdateBlock(const Buffer* block, VAddr start, VAddr end,
384 const VectorMapInterval& overlaps) { 388 const VectorMapInterval& overlaps) {
385 const IntervalType base_interval{start, end}; 389 const IntervalType base_interval{start, end};
386 IntervalSet interval_set{}; 390 IntervalSet interval_set{};
@@ -390,13 +394,13 @@ private:
390 interval_set.subtract(subtract); 394 interval_set.subtract(subtract);
391 } 395 }
392 for (auto& interval : interval_set) { 396 for (auto& interval : interval_set) {
393 std::size_t size = interval.upper() - interval.lower(); 397 const std::size_t size = interval.upper() - interval.lower();
394 if (size > 0) { 398 if (size == 0) {
395 staging_buffer.resize(size); 399 continue;
396 system.Memory().ReadBlockUnsafe(interval.lower(), staging_buffer.data(), size);
397 UploadBlockData(block, block->GetOffset(interval.lower()), size,
398 staging_buffer.data());
399 } 400 }
401 staging_buffer.resize(size);
402 system.Memory().ReadBlockUnsafe(interval.lower(), staging_buffer.data(), size);
403 UploadBlockData(*block, block->Offset(interval.lower()), size, staging_buffer.data());
400 } 404 }
401 } 405 }
402 406
@@ -426,10 +430,14 @@ private:
426 } 430 }
427 431
428 void FlushMap(MapInterval* map) { 432 void FlushMap(MapInterval* map) {
433 const auto it = blocks.find(map->start >> BLOCK_PAGE_BITS);
434 ASSERT_OR_EXECUTE(it != blocks.end(), return;);
435
436 std::shared_ptr<Buffer> block = it->second;
437
429 const std::size_t size = map->end - map->start; 438 const std::size_t size = map->end - map->start;
430 OwnerBuffer block = blocks[map->start >> block_page_bits];
431 staging_buffer.resize(size); 439 staging_buffer.resize(size);
432 DownloadBlockData(block, block->GetOffset(map->start), size, staging_buffer.data()); 440 DownloadBlockData(*block, block->Offset(map->start), size, staging_buffer.data());
433 system.Memory().WriteBlockUnsafe(map->start, staging_buffer.data(), size); 441 system.Memory().WriteBlockUnsafe(map->start, staging_buffer.data(), size);
434 map->MarkAsModified(false, 0); 442 map->MarkAsModified(false, 0);
435 } 443 }
@@ -452,97 +460,89 @@ private:
452 buffer_offset = offset_aligned; 460 buffer_offset = offset_aligned;
453 } 461 }
454 462
455 OwnerBuffer EnlargeBlock(OwnerBuffer buffer) { 463 std::shared_ptr<Buffer> EnlargeBlock(std::shared_ptr<Buffer> buffer) {
456 const std::size_t old_size = buffer->GetSize(); 464 const std::size_t old_size = buffer->Size();
457 const std::size_t new_size = old_size + block_page_size; 465 const std::size_t new_size = old_size + BLOCK_PAGE_SIZE;
458 const VAddr cpu_addr = buffer->GetCpuAddr(); 466 const VAddr cpu_addr = buffer->CpuAddr();
459 OwnerBuffer new_buffer = CreateBlock(cpu_addr, new_size); 467 std::shared_ptr<Buffer> new_buffer = CreateBlock(cpu_addr, new_size);
460 CopyBlock(buffer, new_buffer, 0, 0, old_size); 468 CopyBlock(*buffer, *new_buffer, 0, 0, old_size);
461 buffer->SetEpoch(epoch); 469 QueueDestruction(std::move(buffer));
462 pending_destruction.push_back(buffer); 470
463 const VAddr cpu_addr_end = cpu_addr + new_size - 1; 471 const VAddr cpu_addr_end = cpu_addr + new_size - 1;
464 u64 page_start = cpu_addr >> block_page_bits; 472 const u64 page_end = cpu_addr_end >> BLOCK_PAGE_BITS;
465 const u64 page_end = cpu_addr_end >> block_page_bits; 473 for (u64 page_start = cpu_addr >> BLOCK_PAGE_BITS; page_start <= page_end; ++page_start) {
466 while (page_start <= page_end) { 474 blocks.insert_or_assign(page_start, new_buffer);
467 blocks[page_start] = new_buffer;
468 ++page_start;
469 } 475 }
476
470 return new_buffer; 477 return new_buffer;
471 } 478 }
472 479
473 OwnerBuffer MergeBlocks(OwnerBuffer first, OwnerBuffer second) { 480 std::shared_ptr<Buffer> MergeBlocks(std::shared_ptr<Buffer> first,
474 const std::size_t size_1 = first->GetSize(); 481 std::shared_ptr<Buffer> second) {
475 const std::size_t size_2 = second->GetSize(); 482 const std::size_t size_1 = first->Size();
476 const VAddr first_addr = first->GetCpuAddr(); 483 const std::size_t size_2 = second->Size();
477 const VAddr second_addr = second->GetCpuAddr(); 484 const VAddr first_addr = first->CpuAddr();
485 const VAddr second_addr = second->CpuAddr();
478 const VAddr new_addr = std::min(first_addr, second_addr); 486 const VAddr new_addr = std::min(first_addr, second_addr);
479 const std::size_t new_size = size_1 + size_2; 487 const std::size_t new_size = size_1 + size_2;
480 OwnerBuffer new_buffer = CreateBlock(new_addr, new_size); 488
481 CopyBlock(first, new_buffer, 0, new_buffer->GetOffset(first_addr), size_1); 489 std::shared_ptr<Buffer> new_buffer = CreateBlock(new_addr, new_size);
482 CopyBlock(second, new_buffer, 0, new_buffer->GetOffset(second_addr), size_2); 490 CopyBlock(*first, *new_buffer, 0, new_buffer->Offset(first_addr), size_1);
483 first->SetEpoch(epoch); 491 CopyBlock(*second, *new_buffer, 0, new_buffer->Offset(second_addr), size_2);
484 second->SetEpoch(epoch); 492 QueueDestruction(std::move(first));
485 pending_destruction.push_back(first); 493 QueueDestruction(std::move(second));
486 pending_destruction.push_back(second); 494
487 const VAddr cpu_addr_end = new_addr + new_size - 1; 495 const VAddr cpu_addr_end = new_addr + new_size - 1;
488 u64 page_start = new_addr >> block_page_bits; 496 const u64 page_end = cpu_addr_end >> BLOCK_PAGE_BITS;
489 const u64 page_end = cpu_addr_end >> block_page_bits; 497 for (u64 page_start = new_addr >> BLOCK_PAGE_BITS; page_start <= page_end; ++page_start) {
490 while (page_start <= page_end) { 498 blocks.insert_or_assign(page_start, new_buffer);
491 blocks[page_start] = new_buffer;
492 ++page_start;
493 } 499 }
494 return new_buffer; 500 return new_buffer;
495 } 501 }
496 502
497 OwnerBuffer GetBlock(const VAddr cpu_addr, const std::size_t size) { 503 Buffer* GetBlock(VAddr cpu_addr, std::size_t size) {
498 OwnerBuffer found; 504 std::shared_ptr<Buffer> found;
505
499 const VAddr cpu_addr_end = cpu_addr + size - 1; 506 const VAddr cpu_addr_end = cpu_addr + size - 1;
500 u64 page_start = cpu_addr >> block_page_bits; 507 const u64 page_end = cpu_addr_end >> BLOCK_PAGE_BITS;
501 const u64 page_end = cpu_addr_end >> block_page_bits; 508 for (u64 page_start = cpu_addr >> BLOCK_PAGE_BITS; page_start <= page_end; ++page_start) {
502 while (page_start <= page_end) {
503 auto it = blocks.find(page_start); 509 auto it = blocks.find(page_start);
504 if (it == blocks.end()) { 510 if (it == blocks.end()) {
505 if (found) { 511 if (found) {
506 found = EnlargeBlock(found); 512 found = EnlargeBlock(found);
507 } else { 513 continue;
508 const VAddr start_addr = (page_start << block_page_bits);
509 found = CreateBlock(start_addr, block_page_size);
510 blocks[page_start] = found;
511 }
512 } else {
513 if (found) {
514 if (found == it->second) {
515 ++page_start;
516 continue;
517 }
518 found = MergeBlocks(found, it->second);
519 } else {
520 found = it->second;
521 } 514 }
515 const VAddr start_addr = page_start << BLOCK_PAGE_BITS;
516 found = CreateBlock(start_addr, BLOCK_PAGE_SIZE);
517 blocks.insert_or_assign(page_start, found);
518 continue;
519 }
520 if (!found) {
521 found = it->second;
522 continue;
523 }
524 if (found != it->second) {
525 found = MergeBlocks(std::move(found), it->second);
522 } 526 }
523 ++page_start;
524 } 527 }
525 return found; 528 return found.get();
526 } 529 }
527 530
528 void MarkRegionAsWritten(const VAddr start, const VAddr end) { 531 void MarkRegionAsWritten(VAddr start, VAddr end) {
529 u64 page_start = start >> write_page_bit; 532 const u64 page_end = end >> WRITE_PAGE_BIT;
530 const u64 page_end = end >> write_page_bit; 533 for (u64 page_start = start >> WRITE_PAGE_BIT; page_start <= page_end; ++page_start) {
531 while (page_start <= page_end) {
532 auto it = written_pages.find(page_start); 534 auto it = written_pages.find(page_start);
533 if (it != written_pages.end()) { 535 if (it != written_pages.end()) {
534 it->second = it->second + 1; 536 it->second = it->second + 1;
535 } else { 537 } else {
536 written_pages[page_start] = 1; 538 written_pages.insert_or_assign(page_start, 1);
537 } 539 }
538 ++page_start;
539 } 540 }
540 } 541 }
541 542
542 void UnmarkRegionAsWritten(const VAddr start, const VAddr end) { 543 void UnmarkRegionAsWritten(VAddr start, VAddr end) {
543 u64 page_start = start >> write_page_bit; 544 const u64 page_end = end >> WRITE_PAGE_BIT;
544 const u64 page_end = end >> write_page_bit; 545 for (u64 page_start = start >> WRITE_PAGE_BIT; page_start <= page_end; ++page_start) {
545 while (page_start <= page_end) {
546 auto it = written_pages.find(page_start); 546 auto it = written_pages.find(page_start);
547 if (it != written_pages.end()) { 547 if (it != written_pages.end()) {
548 if (it->second > 1) { 548 if (it->second > 1) {
@@ -551,22 +551,24 @@ private:
551 written_pages.erase(it); 551 written_pages.erase(it);
552 } 552 }
553 } 553 }
554 ++page_start;
555 } 554 }
556 } 555 }
557 556
558 bool IsRegionWritten(const VAddr start, const VAddr end) const { 557 bool IsRegionWritten(VAddr start, VAddr end) const {
559 u64 page_start = start >> write_page_bit; 558 const u64 page_end = end >> WRITE_PAGE_BIT;
560 const u64 page_end = end >> write_page_bit; 559 for (u64 page_start = start >> WRITE_PAGE_BIT; page_start <= page_end; ++page_start) {
561 while (page_start <= page_end) {
562 if (written_pages.count(page_start) > 0) { 560 if (written_pages.count(page_start) > 0) {
563 return true; 561 return true;
564 } 562 }
565 ++page_start;
566 } 563 }
567 return false; 564 return false;
568 } 565 }
569 566
567 void QueueDestruction(std::shared_ptr<Buffer> buffer) {
568 buffer->SetEpoch(epoch);
569 pending_destruction.push(std::move(buffer));
570 }
571
570 void MarkForAsyncFlush(MapInterval* map) { 572 void MarkForAsyncFlush(MapInterval* map) {
571 if (!uncommitted_flushes) { 573 if (!uncommitted_flushes) {
572 uncommitted_flushes = std::make_shared<std::unordered_set<MapInterval*>>(); 574 uncommitted_flushes = std::make_shared<std::unordered_set<MapInterval*>>();
@@ -578,7 +580,7 @@ private:
578 Core::System& system; 580 Core::System& system;
579 581
580 std::unique_ptr<StreamBuffer> stream_buffer; 582 std::unique_ptr<StreamBuffer> stream_buffer;
581 BufferType stream_buffer_handle{}; 583 BufferType stream_buffer_handle;
582 584
583 u8* buffer_ptr = nullptr; 585 u8* buffer_ptr = nullptr;
584 u64 buffer_offset = 0; 586 u64 buffer_offset = 0;
@@ -588,18 +590,15 @@ private:
588 boost::intrusive::set<MapInterval, boost::intrusive::compare<MapIntervalCompare>> 590 boost::intrusive::set<MapInterval, boost::intrusive::compare<MapIntervalCompare>>
589 mapped_addresses; 591 mapped_addresses;
590 592
591 static constexpr u64 write_page_bit = 11;
592 std::unordered_map<u64, u32> written_pages; 593 std::unordered_map<u64, u32> written_pages;
594 std::unordered_map<u64, std::shared_ptr<Buffer>> blocks;
593 595
594 static constexpr u64 block_page_bits = 21; 596 std::queue<std::shared_ptr<Buffer>> pending_destruction;
595 static constexpr u64 block_page_size = 1ULL << block_page_bits;
596 std::unordered_map<u64, OwnerBuffer> blocks;
597
598 std::list<OwnerBuffer> pending_destruction;
599 u64 epoch = 0; 597 u64 epoch = 0;
600 u64 modified_ticks = 0; 598 u64 modified_ticks = 0;
601 599
602 std::vector<u8> staging_buffer; 600 std::vector<u8> staging_buffer;
601
603 std::list<MapInterval*> marked_for_unregister; 602 std::list<MapInterval*> marked_for_unregister;
604 603
605 std::shared_ptr<std::unordered_set<MapInterval*>> uncommitted_flushes; 604 std::shared_ptr<std::unordered_set<MapInterval*>> uncommitted_flushes;
diff --git a/src/video_core/macro/macro_jit_x64.h b/src/video_core/macro/macro_jit_x64.h
index 21ee157cf..71f738b9a 100644
--- a/src/video_core/macro/macro_jit_x64.h
+++ b/src/video_core/macro/macro_jit_x64.h
@@ -85,8 +85,8 @@ private:
85 std::optional<Macro::Opcode> next_opcode{}; 85 std::optional<Macro::Opcode> next_opcode{};
86 ProgramType program{nullptr}; 86 ProgramType program{nullptr};
87 87
88 std::array<Xbyak::Label, MAX_CODE_SIZE> labels{}; 88 std::array<Xbyak::Label, MAX_CODE_SIZE> labels;
89 std::array<Xbyak::Label, MAX_CODE_SIZE> delay_skip{}; 89 std::array<Xbyak::Label, MAX_CODE_SIZE> delay_skip;
90 Xbyak::Label end_of_code{}; 90 Xbyak::Label end_of_code{};
91 91
92 bool is_delay_slot{}; 92 bool is_delay_slot{};
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.cpp b/src/video_core/renderer_opengl/gl_buffer_cache.cpp
index 9964ea894..ad0577a4f 100644
--- a/src/video_core/renderer_opengl/gl_buffer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_buffer_cache.cpp
@@ -22,13 +22,12 @@ using Maxwell = Tegra::Engines::Maxwell3D::Regs;
22 22
23MICROPROFILE_DEFINE(OpenGL_Buffer_Download, "OpenGL", "Buffer Download", MP_RGB(192, 192, 128)); 23MICROPROFILE_DEFINE(OpenGL_Buffer_Download, "OpenGL", "Buffer Download", MP_RGB(192, 192, 128));
24 24
25CachedBufferBlock::CachedBufferBlock(VAddr cpu_addr, const std::size_t size) 25Buffer::Buffer(VAddr cpu_addr, const std::size_t size) : VideoCommon::BufferBlock{cpu_addr, size} {
26 : VideoCommon::BufferBlock{cpu_addr, size} {
27 gl_buffer.Create(); 26 gl_buffer.Create();
28 glNamedBufferData(gl_buffer.handle, static_cast<GLsizeiptr>(size), nullptr, GL_DYNAMIC_DRAW); 27 glNamedBufferData(gl_buffer.handle, static_cast<GLsizeiptr>(size), nullptr, GL_DYNAMIC_DRAW);
29} 28}
30 29
31CachedBufferBlock::~CachedBufferBlock() = default; 30Buffer::~Buffer() = default;
32 31
33OGLBufferCache::OGLBufferCache(RasterizerOpenGL& rasterizer, Core::System& system, 32OGLBufferCache::OGLBufferCache(RasterizerOpenGL& rasterizer, Core::System& system,
34 const Device& device, std::size_t stream_size) 33 const Device& device, std::size_t stream_size)
@@ -48,12 +47,8 @@ OGLBufferCache::~OGLBufferCache() {
48 glDeleteBuffers(static_cast<GLsizei>(std::size(cbufs)), std::data(cbufs)); 47 glDeleteBuffers(static_cast<GLsizei>(std::size(cbufs)), std::data(cbufs));
49} 48}
50 49
51Buffer OGLBufferCache::CreateBlock(VAddr cpu_addr, std::size_t size) { 50std::shared_ptr<Buffer> OGLBufferCache::CreateBlock(VAddr cpu_addr, std::size_t size) {
52 return std::make_shared<CachedBufferBlock>(cpu_addr, size); 51 return std::make_shared<Buffer>(cpu_addr, size);
53}
54
55GLuint OGLBufferCache::ToHandle(const Buffer& buffer) {
56 return buffer->GetHandle();
57} 52}
58 53
59GLuint OGLBufferCache::GetEmptyBuffer(std::size_t) { 54GLuint OGLBufferCache::GetEmptyBuffer(std::size_t) {
@@ -62,7 +57,7 @@ GLuint OGLBufferCache::GetEmptyBuffer(std::size_t) {
62 57
63void OGLBufferCache::UploadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size, 58void OGLBufferCache::UploadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size,
64 const u8* data) { 59 const u8* data) {
65 glNamedBufferSubData(buffer->GetHandle(), static_cast<GLintptr>(offset), 60 glNamedBufferSubData(buffer.Handle(), static_cast<GLintptr>(offset),
66 static_cast<GLsizeiptr>(size), data); 61 static_cast<GLsizeiptr>(size), data);
67} 62}
68 63
@@ -70,20 +65,20 @@ void OGLBufferCache::DownloadBlockData(const Buffer& buffer, std::size_t offset,
70 u8* data) { 65 u8* data) {
71 MICROPROFILE_SCOPE(OpenGL_Buffer_Download); 66 MICROPROFILE_SCOPE(OpenGL_Buffer_Download);
72 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); 67 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
73 glGetNamedBufferSubData(buffer->GetHandle(), static_cast<GLintptr>(offset), 68 glGetNamedBufferSubData(buffer.Handle(), static_cast<GLintptr>(offset),
74 static_cast<GLsizeiptr>(size), data); 69 static_cast<GLsizeiptr>(size), data);
75} 70}
76 71
77void OGLBufferCache::CopyBlock(const Buffer& src, const Buffer& dst, std::size_t src_offset, 72void OGLBufferCache::CopyBlock(const Buffer& src, const Buffer& dst, std::size_t src_offset,
78 std::size_t dst_offset, std::size_t size) { 73 std::size_t dst_offset, std::size_t size) {
79 glCopyNamedBufferSubData(src->GetHandle(), dst->GetHandle(), static_cast<GLintptr>(src_offset), 74 glCopyNamedBufferSubData(src.Handle(), dst.Handle(), static_cast<GLintptr>(src_offset),
80 static_cast<GLintptr>(dst_offset), static_cast<GLsizeiptr>(size)); 75 static_cast<GLintptr>(dst_offset), static_cast<GLsizeiptr>(size));
81} 76}
82 77
83OGLBufferCache::BufferInfo OGLBufferCache::ConstBufferUpload(const void* raw_pointer, 78OGLBufferCache::BufferInfo OGLBufferCache::ConstBufferUpload(const void* raw_pointer,
84 std::size_t size) { 79 std::size_t size) {
85 DEBUG_ASSERT(cbuf_cursor < std::size(cbufs)); 80 DEBUG_ASSERT(cbuf_cursor < std::size(cbufs));
86 const GLuint& cbuf = cbufs[cbuf_cursor++]; 81 const GLuint cbuf = cbufs[cbuf_cursor++];
87 glNamedBufferSubData(cbuf, 0, static_cast<GLsizeiptr>(size), raw_pointer); 82 glNamedBufferSubData(cbuf, 0, static_cast<GLsizeiptr>(size), raw_pointer);
88 return {cbuf, 0}; 83 return {cbuf, 0};
89} 84}
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.h b/src/video_core/renderer_opengl/gl_buffer_cache.h
index 679b9b1d7..a49aaf9c4 100644
--- a/src/video_core/renderer_opengl/gl_buffer_cache.h
+++ b/src/video_core/renderer_opengl/gl_buffer_cache.h
@@ -23,17 +23,12 @@ class Device;
23class OGLStreamBuffer; 23class OGLStreamBuffer;
24class RasterizerOpenGL; 24class RasterizerOpenGL;
25 25
26class CachedBufferBlock; 26class Buffer : public VideoCommon::BufferBlock {
27
28using Buffer = std::shared_ptr<CachedBufferBlock>;
29using GenericBufferCache = VideoCommon::BufferCache<Buffer, GLuint, OGLStreamBuffer>;
30
31class CachedBufferBlock : public VideoCommon::BufferBlock {
32public: 27public:
33 explicit CachedBufferBlock(VAddr cpu_addr, const std::size_t size); 28 explicit Buffer(VAddr cpu_addr, const std::size_t size);
34 ~CachedBufferBlock(); 29 ~Buffer();
35 30
36 GLuint GetHandle() const { 31 GLuint Handle() const {
37 return gl_buffer.handle; 32 return gl_buffer.handle;
38 } 33 }
39 34
@@ -41,6 +36,7 @@ private:
41 OGLBuffer gl_buffer; 36 OGLBuffer gl_buffer;
42}; 37};
43 38
39using GenericBufferCache = VideoCommon::BufferCache<Buffer, GLuint, OGLStreamBuffer>;
44class OGLBufferCache final : public GenericBufferCache { 40class OGLBufferCache final : public GenericBufferCache {
45public: 41public:
46 explicit OGLBufferCache(RasterizerOpenGL& rasterizer, Core::System& system, 42 explicit OGLBufferCache(RasterizerOpenGL& rasterizer, Core::System& system,
@@ -54,9 +50,7 @@ public:
54 } 50 }
55 51
56protected: 52protected:
57 Buffer CreateBlock(VAddr cpu_addr, std::size_t size) override; 53 std::shared_ptr<Buffer> CreateBlock(VAddr cpu_addr, std::size_t size) override;
58
59 GLuint ToHandle(const Buffer& buffer) override;
60 54
61 void UploadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size, 55 void UploadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size,
62 const u8* data) override; 56 const u8* data) override;
diff --git a/src/video_core/renderer_opengl/gl_stream_buffer.cpp b/src/video_core/renderer_opengl/gl_stream_buffer.cpp
index 6ec328c53..932a2f69e 100644
--- a/src/video_core/renderer_opengl/gl_stream_buffer.cpp
+++ b/src/video_core/renderer_opengl/gl_stream_buffer.cpp
@@ -49,14 +49,6 @@ OGLStreamBuffer::~OGLStreamBuffer() {
49 gl_buffer.Release(); 49 gl_buffer.Release();
50} 50}
51 51
52GLuint OGLStreamBuffer::GetHandle() const {
53 return gl_buffer.handle;
54}
55
56GLsizeiptr OGLStreamBuffer::GetSize() const {
57 return buffer_size;
58}
59
60std::tuple<u8*, GLintptr, bool> OGLStreamBuffer::Map(GLsizeiptr size, GLintptr alignment) { 52std::tuple<u8*, GLintptr, bool> OGLStreamBuffer::Map(GLsizeiptr size, GLintptr alignment) {
61 ASSERT(size <= buffer_size); 53 ASSERT(size <= buffer_size);
62 ASSERT(alignment <= buffer_size); 54 ASSERT(alignment <= buffer_size);
diff --git a/src/video_core/renderer_opengl/gl_stream_buffer.h b/src/video_core/renderer_opengl/gl_stream_buffer.h
index f8383cbd4..866da3594 100644
--- a/src/video_core/renderer_opengl/gl_stream_buffer.h
+++ b/src/video_core/renderer_opengl/gl_stream_buffer.h
@@ -17,9 +17,6 @@ public:
17 bool use_persistent = true); 17 bool use_persistent = true);
18 ~OGLStreamBuffer(); 18 ~OGLStreamBuffer();
19 19
20 GLuint GetHandle() const;
21 GLsizeiptr GetSize() const;
22
23 /* 20 /*
24 * Allocates a linear chunk of memory in the GPU buffer with at least "size" bytes 21 * Allocates a linear chunk of memory in the GPU buffer with at least "size" bytes
25 * and the optional alignment requirement. 22 * and the optional alignment requirement.
@@ -32,6 +29,14 @@ public:
32 29
33 void Unmap(GLsizeiptr size); 30 void Unmap(GLsizeiptr size);
34 31
32 GLuint Handle() const {
33 return gl_buffer.handle;
34 }
35
36 GLsizeiptr Size() const {
37 return buffer_size;
38 }
39
35private: 40private:
36 OGLBuffer gl_buffer; 41 OGLBuffer gl_buffer;
37 42
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
index 5f33d9e40..1fde38328 100644
--- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp
@@ -37,8 +37,8 @@ std::unique_ptr<VKStreamBuffer> CreateStreamBuffer(const VKDevice& device, VKSch
37 37
38} // Anonymous namespace 38} // Anonymous namespace
39 39
40CachedBufferBlock::CachedBufferBlock(const VKDevice& device, VKMemoryManager& memory_manager, 40Buffer::Buffer(const VKDevice& device, VKMemoryManager& memory_manager, VAddr cpu_addr,
41 VAddr cpu_addr, std::size_t size) 41 std::size_t size)
42 : VideoCommon::BufferBlock{cpu_addr, size} { 42 : VideoCommon::BufferBlock{cpu_addr, size} {
43 VkBufferCreateInfo ci; 43 VkBufferCreateInfo ci;
44 ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; 44 ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
@@ -54,7 +54,7 @@ CachedBufferBlock::CachedBufferBlock(const VKDevice& device, VKMemoryManager& me
54 buffer.commit = memory_manager.Commit(buffer.handle, false); 54 buffer.commit = memory_manager.Commit(buffer.handle, false);
55} 55}
56 56
57CachedBufferBlock::~CachedBufferBlock() = default; 57Buffer::~Buffer() = default;
58 58
59VKBufferCache::VKBufferCache(VideoCore::RasterizerInterface& rasterizer, Core::System& system, 59VKBufferCache::VKBufferCache(VideoCore::RasterizerInterface& rasterizer, Core::System& system,
60 const VKDevice& device, VKMemoryManager& memory_manager, 60 const VKDevice& device, VKMemoryManager& memory_manager,
@@ -67,12 +67,8 @@ VKBufferCache::VKBufferCache(VideoCore::RasterizerInterface& rasterizer, Core::S
67 67
68VKBufferCache::~VKBufferCache() = default; 68VKBufferCache::~VKBufferCache() = default;
69 69
70Buffer VKBufferCache::CreateBlock(VAddr cpu_addr, std::size_t size) { 70std::shared_ptr<Buffer> VKBufferCache::CreateBlock(VAddr cpu_addr, std::size_t size) {
71 return std::make_shared<CachedBufferBlock>(device, memory_manager, cpu_addr, size); 71 return std::make_shared<Buffer>(device, memory_manager, cpu_addr, size);
72}
73
74VkBuffer VKBufferCache::ToHandle(const Buffer& buffer) {
75 return buffer->GetHandle();
76} 72}
77 73
78VkBuffer VKBufferCache::GetEmptyBuffer(std::size_t size) { 74VkBuffer VKBufferCache::GetEmptyBuffer(std::size_t size) {
@@ -91,7 +87,7 @@ void VKBufferCache::UploadBlockData(const Buffer& buffer, std::size_t offset, st
91 std::memcpy(staging.commit->Map(size), data, size); 87 std::memcpy(staging.commit->Map(size), data, size);
92 88
93 scheduler.RequestOutsideRenderPassOperationContext(); 89 scheduler.RequestOutsideRenderPassOperationContext();
94 scheduler.Record([staging = *staging.handle, buffer = buffer->GetHandle(), offset, 90 scheduler.Record([staging = *staging.handle, buffer = buffer.Handle(), offset,
95 size](vk::CommandBuffer cmdbuf) { 91 size](vk::CommandBuffer cmdbuf) {
96 cmdbuf.CopyBuffer(staging, buffer, VkBufferCopy{0, offset, size}); 92 cmdbuf.CopyBuffer(staging, buffer, VkBufferCopy{0, offset, size});
97 93
@@ -114,7 +110,7 @@ void VKBufferCache::DownloadBlockData(const Buffer& buffer, std::size_t offset,
114 u8* data) { 110 u8* data) {
115 const auto& staging = staging_pool.GetUnusedBuffer(size, true); 111 const auto& staging = staging_pool.GetUnusedBuffer(size, true);
116 scheduler.RequestOutsideRenderPassOperationContext(); 112 scheduler.RequestOutsideRenderPassOperationContext();
117 scheduler.Record([staging = *staging.handle, buffer = buffer->GetHandle(), offset, 113 scheduler.Record([staging = *staging.handle, buffer = buffer.Handle(), offset,
118 size](vk::CommandBuffer cmdbuf) { 114 size](vk::CommandBuffer cmdbuf) {
119 VkBufferMemoryBarrier barrier; 115 VkBufferMemoryBarrier barrier;
120 barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; 116 barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
@@ -141,8 +137,8 @@ void VKBufferCache::DownloadBlockData(const Buffer& buffer, std::size_t offset,
141void VKBufferCache::CopyBlock(const Buffer& src, const Buffer& dst, std::size_t src_offset, 137void VKBufferCache::CopyBlock(const Buffer& src, const Buffer& dst, std::size_t src_offset,
142 std::size_t dst_offset, std::size_t size) { 138 std::size_t dst_offset, std::size_t size) {
143 scheduler.RequestOutsideRenderPassOperationContext(); 139 scheduler.RequestOutsideRenderPassOperationContext();
144 scheduler.Record([src_buffer = src->GetHandle(), dst_buffer = dst->GetHandle(), src_offset, 140 scheduler.Record([src_buffer = src.Handle(), dst_buffer = dst.Handle(), src_offset, dst_offset,
145 dst_offset, size](vk::CommandBuffer cmdbuf) { 141 size](vk::CommandBuffer cmdbuf) {
146 cmdbuf.CopyBuffer(src_buffer, dst_buffer, VkBufferCopy{src_offset, dst_offset, size}); 142 cmdbuf.CopyBuffer(src_buffer, dst_buffer, VkBufferCopy{src_offset, dst_offset, size});
147 143
148 std::array<VkBufferMemoryBarrier, 2> barriers; 144 std::array<VkBufferMemoryBarrier, 2> barriers;
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.h b/src/video_core/renderer_vulkan/vk_buffer_cache.h
index 65cb3c8ad..9ebbef835 100644
--- a/src/video_core/renderer_vulkan/vk_buffer_cache.h
+++ b/src/video_core/renderer_vulkan/vk_buffer_cache.h
@@ -23,13 +23,13 @@ class VKDevice;
23class VKMemoryManager; 23class VKMemoryManager;
24class VKScheduler; 24class VKScheduler;
25 25
26class CachedBufferBlock final : public VideoCommon::BufferBlock { 26class Buffer final : public VideoCommon::BufferBlock {
27public: 27public:
28 explicit CachedBufferBlock(const VKDevice& device, VKMemoryManager& memory_manager, 28 explicit Buffer(const VKDevice& device, VKMemoryManager& memory_manager, VAddr cpu_addr,
29 VAddr cpu_addr, std::size_t size); 29 std::size_t size);
30 ~CachedBufferBlock(); 30 ~Buffer();
31 31
32 VkBuffer GetHandle() const { 32 VkBuffer Handle() const {
33 return *buffer.handle; 33 return *buffer.handle;
34 } 34 }
35 35
@@ -37,8 +37,6 @@ private:
37 VKBuffer buffer; 37 VKBuffer buffer;
38}; 38};
39 39
40using Buffer = std::shared_ptr<CachedBufferBlock>;
41
42class VKBufferCache final : public VideoCommon::BufferCache<Buffer, VkBuffer, VKStreamBuffer> { 40class VKBufferCache final : public VideoCommon::BufferCache<Buffer, VkBuffer, VKStreamBuffer> {
43public: 41public:
44 explicit VKBufferCache(VideoCore::RasterizerInterface& rasterizer, Core::System& system, 42 explicit VKBufferCache(VideoCore::RasterizerInterface& rasterizer, Core::System& system,
@@ -49,9 +47,7 @@ public:
49 VkBuffer GetEmptyBuffer(std::size_t size) override; 47 VkBuffer GetEmptyBuffer(std::size_t size) override;
50 48
51protected: 49protected:
52 VkBuffer ToHandle(const Buffer& buffer) override; 50 std::shared_ptr<Buffer> CreateBlock(VAddr cpu_addr, std::size_t size) override;
53
54 Buffer CreateBlock(VAddr cpu_addr, std::size_t size) override;
55 51
56 void UploadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size, 52 void UploadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size,
57 const u8* data) override; 53 const u8* data) override;
diff --git a/src/video_core/renderer_vulkan/vk_stream_buffer.h b/src/video_core/renderer_vulkan/vk_stream_buffer.h
index dfddf7ad6..c765c60a0 100644
--- a/src/video_core/renderer_vulkan/vk_stream_buffer.h
+++ b/src/video_core/renderer_vulkan/vk_stream_buffer.h
@@ -35,7 +35,7 @@ public:
35 /// Ensures that "size" bytes of memory are available to the GPU, potentially recording a copy. 35 /// Ensures that "size" bytes of memory are available to the GPU, potentially recording a copy.
36 void Unmap(u64 size); 36 void Unmap(u64 size);
37 37
38 VkBuffer GetHandle() const { 38 VkBuffer Handle() const {
39 return *buffer; 39 return *buffer;
40 } 40 }
41 41