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/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
9 files changed, 150 insertions, 174 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 b88fce2cd..efc480d08 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.
@@ -125,16 +129,18 @@ public:
125 return std::exchange(invalidated, false); 129 return std::exchange(invalidated, false);
126 } 130 }
127 131
132 /// Function called at the end of each frame, inteded for deferred operations
128 void TickFrame() { 133 void TickFrame() {
129 ++epoch; 134 ++epoch;
135
130 while (!pending_destruction.empty()) { 136 while (!pending_destruction.empty()) {
131 // Delay at least 4 frames before destruction. 137 // Delay at least 4 frames before destruction.
132 // This is due to triple buffering happening on some drivers. 138 // This is due to triple buffering happening on some drivers.
133 static constexpr u64 epochs_to_destroy = 5; 139 static constexpr u64 epochs_to_destroy = 5;
134 if (pending_destruction.front()->GetEpoch() + epochs_to_destroy > epoch) { 140 if (pending_destruction.front()->Epoch() + epochs_to_destroy > epoch) {
135 break; 141 break;
136 } 142 }
137 pending_destruction.pop_front(); 143 pending_destruction.pop();
138 } 144 }
139 } 145 }
140 146
@@ -249,23 +255,21 @@ public:
249 255
250protected: 256protected:
251 explicit BufferCache(VideoCore::RasterizerInterface& rasterizer, Core::System& system, 257 explicit BufferCache(VideoCore::RasterizerInterface& rasterizer, Core::System& system,
252 std::unique_ptr<StreamBuffer> stream_buffer) 258 std::unique_ptr<StreamBuffer> stream_buffer_)
253 : rasterizer{rasterizer}, system{system}, stream_buffer{std::move(stream_buffer)}, 259 : rasterizer{rasterizer}, system{system}, stream_buffer{std::move(stream_buffer_)},
254 stream_buffer_handle{this->stream_buffer->GetHandle()} {} 260 stream_buffer_handle{stream_buffer->Handle()} {}
255 261
256 ~BufferCache() = default; 262 ~BufferCache() = default;
257 263
258 virtual BufferType ToHandle(const OwnerBuffer& storage) = 0; 264 virtual std::shared_ptr<Buffer> CreateBlock(VAddr cpu_addr, std::size_t size) = 0;
259 265
260 virtual OwnerBuffer CreateBlock(VAddr cpu_addr, std::size_t size) = 0; 266 virtual void UploadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size,
261
262 virtual void UploadBlockData(const OwnerBuffer& buffer, std::size_t offset, std::size_t size,
263 const u8* data) = 0; 267 const u8* data) = 0;
264 268
265 virtual void DownloadBlockData(const OwnerBuffer& buffer, std::size_t offset, std::size_t size, 269 virtual void DownloadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size,
266 u8* data) = 0; 270 u8* data) = 0;
267 271
268 virtual void CopyBlock(const OwnerBuffer& src, const OwnerBuffer& dst, std::size_t src_offset, 272 virtual void CopyBlock(const Buffer& src, const Buffer& dst, std::size_t src_offset,
269 std::size_t dst_offset, std::size_t size) = 0; 273 std::size_t dst_offset, std::size_t size) = 0;
270 274
271 virtual BufferInfo ConstBufferUpload(const void* raw_pointer, std::size_t size) { 275 virtual BufferInfo ConstBufferUpload(const void* raw_pointer, std::size_t size) {
@@ -321,7 +325,7 @@ protected:
321 } 325 }
322 326
323private: 327private:
324 MapInterval* MapAddress(const OwnerBuffer& block, GPUVAddr gpu_addr, VAddr cpu_addr, 328 MapInterval* MapAddress(const Buffer* block, GPUVAddr gpu_addr, VAddr cpu_addr,
325 std::size_t size) { 329 std::size_t size) {
326 const VectorMapInterval overlaps = GetMapsInRange(cpu_addr, size); 330 const VectorMapInterval overlaps = GetMapsInRange(cpu_addr, size);
327 if (overlaps.empty()) { 331 if (overlaps.empty()) {
@@ -329,11 +333,11 @@ private:
329 const VAddr cpu_addr_end = cpu_addr + size; 333 const VAddr cpu_addr_end = cpu_addr + size;
330 if (memory_manager.IsGranularRange(gpu_addr, size)) { 334 if (memory_manager.IsGranularRange(gpu_addr, size)) {
331 u8* host_ptr = memory_manager.GetPointer(gpu_addr); 335 u8* host_ptr = memory_manager.GetPointer(gpu_addr);
332 UploadBlockData(block, block->GetOffset(cpu_addr), size, host_ptr); 336 UploadBlockData(*block, block->Offset(cpu_addr), size, host_ptr);
333 } else { 337 } else {
334 staging_buffer.resize(size); 338 staging_buffer.resize(size);
335 memory_manager.ReadBlockUnsafe(gpu_addr, staging_buffer.data(), size); 339 memory_manager.ReadBlockUnsafe(gpu_addr, staging_buffer.data(), size);
336 UploadBlockData(block, block->GetOffset(cpu_addr), size, staging_buffer.data()); 340 UploadBlockData(*block, block->Offset(cpu_addr), size, staging_buffer.data());
337 } 341 }
338 return Register(MapInterval(cpu_addr, cpu_addr_end, gpu_addr)); 342 return Register(MapInterval(cpu_addr, cpu_addr_end, gpu_addr));
339 } 343 }
@@ -376,7 +380,7 @@ private:
376 return map; 380 return map;
377 } 381 }
378 382
379 void UpdateBlock(const OwnerBuffer& block, VAddr start, VAddr end, 383 void UpdateBlock(const Buffer* block, VAddr start, VAddr end,
380 const VectorMapInterval& overlaps) { 384 const VectorMapInterval& overlaps) {
381 const IntervalType base_interval{start, end}; 385 const IntervalType base_interval{start, end};
382 IntervalSet interval_set{}; 386 IntervalSet interval_set{};
@@ -386,13 +390,13 @@ private:
386 interval_set.subtract(subtract); 390 interval_set.subtract(subtract);
387 } 391 }
388 for (auto& interval : interval_set) { 392 for (auto& interval : interval_set) {
389 std::size_t size = interval.upper() - interval.lower(); 393 const std::size_t size = interval.upper() - interval.lower();
390 if (size > 0) { 394 if (size == 0) {
391 staging_buffer.resize(size); 395 continue;
392 system.Memory().ReadBlockUnsafe(interval.lower(), staging_buffer.data(), size);
393 UploadBlockData(block, block->GetOffset(interval.lower()), size,
394 staging_buffer.data());
395 } 396 }
397 staging_buffer.resize(size);
398 system.Memory().ReadBlockUnsafe(interval.lower(), staging_buffer.data(), size);
399 UploadBlockData(*block, block->Offset(interval.lower()), size, staging_buffer.data());
396 } 400 }
397 } 401 }
398 402
@@ -422,10 +426,14 @@ private:
422 } 426 }
423 427
424 void FlushMap(MapInterval* map) { 428 void FlushMap(MapInterval* map) {
429 const auto it = blocks.find(map->start >> BLOCK_PAGE_BITS);
430 ASSERT_OR_EXECUTE(it != blocks.end(), return;);
431
432 std::shared_ptr<Buffer> block = it->second;
433
425 const std::size_t size = map->end - map->start; 434 const std::size_t size = map->end - map->start;
426 OwnerBuffer block = blocks[map->start >> block_page_bits];
427 staging_buffer.resize(size); 435 staging_buffer.resize(size);
428 DownloadBlockData(block, block->GetOffset(map->start), size, staging_buffer.data()); 436 DownloadBlockData(*block, block->Offset(map->start), size, staging_buffer.data());
429 system.Memory().WriteBlockUnsafe(map->start, staging_buffer.data(), size); 437 system.Memory().WriteBlockUnsafe(map->start, staging_buffer.data(), size);
430 map->MarkAsModified(false, 0); 438 map->MarkAsModified(false, 0);
431 } 439 }
@@ -448,97 +456,89 @@ private:
448 buffer_offset = offset_aligned; 456 buffer_offset = offset_aligned;
449 } 457 }
450 458
451 OwnerBuffer EnlargeBlock(OwnerBuffer buffer) { 459 std::shared_ptr<Buffer> EnlargeBlock(std::shared_ptr<Buffer> buffer) {
452 const std::size_t old_size = buffer->GetSize(); 460 const std::size_t old_size = buffer->Size();
453 const std::size_t new_size = old_size + block_page_size; 461 const std::size_t new_size = old_size + BLOCK_PAGE_SIZE;
454 const VAddr cpu_addr = buffer->GetCpuAddr(); 462 const VAddr cpu_addr = buffer->CpuAddr();
455 OwnerBuffer new_buffer = CreateBlock(cpu_addr, new_size); 463 std::shared_ptr<Buffer> new_buffer = CreateBlock(cpu_addr, new_size);
456 CopyBlock(buffer, new_buffer, 0, 0, old_size); 464 CopyBlock(*buffer, *new_buffer, 0, 0, old_size);
457 buffer->SetEpoch(epoch); 465 QueueDestruction(std::move(buffer));
458 pending_destruction.push_back(buffer); 466
459 const VAddr cpu_addr_end = cpu_addr + new_size - 1; 467 const VAddr cpu_addr_end = cpu_addr + new_size - 1;
460 u64 page_start = cpu_addr >> block_page_bits; 468 const u64 page_end = cpu_addr_end >> BLOCK_PAGE_BITS;
461 const u64 page_end = cpu_addr_end >> block_page_bits; 469 for (u64 page_start = cpu_addr >> BLOCK_PAGE_BITS; page_start <= page_end; ++page_start) {
462 while (page_start <= page_end) { 470 blocks.insert_or_assign(page_start, new_buffer);
463 blocks[page_start] = new_buffer;
464 ++page_start;
465 } 471 }
472
466 return new_buffer; 473 return new_buffer;
467 } 474 }
468 475
469 OwnerBuffer MergeBlocks(OwnerBuffer first, OwnerBuffer second) { 476 std::shared_ptr<Buffer> MergeBlocks(std::shared_ptr<Buffer> first,
470 const std::size_t size_1 = first->GetSize(); 477 std::shared_ptr<Buffer> second) {
471 const std::size_t size_2 = second->GetSize(); 478 const std::size_t size_1 = first->Size();
472 const VAddr first_addr = first->GetCpuAddr(); 479 const std::size_t size_2 = second->Size();
473 const VAddr second_addr = second->GetCpuAddr(); 480 const VAddr first_addr = first->CpuAddr();
481 const VAddr second_addr = second->CpuAddr();
474 const VAddr new_addr = std::min(first_addr, second_addr); 482 const VAddr new_addr = std::min(first_addr, second_addr);
475 const std::size_t new_size = size_1 + size_2; 483 const std::size_t new_size = size_1 + size_2;
476 OwnerBuffer new_buffer = CreateBlock(new_addr, new_size); 484
477 CopyBlock(first, new_buffer, 0, new_buffer->GetOffset(first_addr), size_1); 485 std::shared_ptr<Buffer> new_buffer = CreateBlock(new_addr, new_size);
478 CopyBlock(second, new_buffer, 0, new_buffer->GetOffset(second_addr), size_2); 486 CopyBlock(*first, *new_buffer, 0, new_buffer->Offset(first_addr), size_1);
479 first->SetEpoch(epoch); 487 CopyBlock(*second, *new_buffer, 0, new_buffer->Offset(second_addr), size_2);
480 second->SetEpoch(epoch); 488 QueueDestruction(std::move(first));
481 pending_destruction.push_back(first); 489 QueueDestruction(std::move(second));
482 pending_destruction.push_back(second); 490
483 const VAddr cpu_addr_end = new_addr + new_size - 1; 491 const VAddr cpu_addr_end = new_addr + new_size - 1;
484 u64 page_start = new_addr >> block_page_bits; 492 const u64 page_end = cpu_addr_end >> BLOCK_PAGE_BITS;
485 const u64 page_end = cpu_addr_end >> block_page_bits; 493 for (u64 page_start = new_addr >> BLOCK_PAGE_BITS; page_start <= page_end; ++page_start) {
486 while (page_start <= page_end) { 494 blocks.insert_or_assign(page_start, new_buffer);
487 blocks[page_start] = new_buffer;
488 ++page_start;
489 } 495 }
490 return new_buffer; 496 return new_buffer;
491 } 497 }
492 498
493 OwnerBuffer GetBlock(const VAddr cpu_addr, const std::size_t size) { 499 Buffer* GetBlock(VAddr cpu_addr, std::size_t size) {
494 OwnerBuffer found; 500 std::shared_ptr<Buffer> found;
501
495 const VAddr cpu_addr_end = cpu_addr + size - 1; 502 const VAddr cpu_addr_end = cpu_addr + size - 1;
496 u64 page_start = cpu_addr >> block_page_bits; 503 const u64 page_end = cpu_addr_end >> BLOCK_PAGE_BITS;
497 const u64 page_end = cpu_addr_end >> block_page_bits; 504 for (u64 page_start = cpu_addr >> BLOCK_PAGE_BITS; page_start <= page_end; ++page_start) {
498 while (page_start <= page_end) {
499 auto it = blocks.find(page_start); 505 auto it = blocks.find(page_start);
500 if (it == blocks.end()) { 506 if (it == blocks.end()) {
501 if (found) { 507 if (found) {
502 found = EnlargeBlock(found); 508 found = EnlargeBlock(found);
503 } else { 509 continue;
504 const VAddr start_addr = (page_start << block_page_bits);
505 found = CreateBlock(start_addr, block_page_size);
506 blocks[page_start] = found;
507 }
508 } else {
509 if (found) {
510 if (found == it->second) {
511 ++page_start;
512 continue;
513 }
514 found = MergeBlocks(found, it->second);
515 } else {
516 found = it->second;
517 } 510 }
511 const VAddr start_addr = page_start << BLOCK_PAGE_BITS;
512 found = CreateBlock(start_addr, BLOCK_PAGE_SIZE);
513 blocks.insert_or_assign(page_start, found);
514 continue;
515 }
516 if (!found) {
517 found = it->second;
518 continue;
519 }
520 if (found != it->second) {
521 found = MergeBlocks(std::move(found), it->second);
518 } 522 }
519 ++page_start;
520 } 523 }
521 return found; 524 return found.get();
522 } 525 }
523 526
524 void MarkRegionAsWritten(const VAddr start, const VAddr end) { 527 void MarkRegionAsWritten(VAddr start, VAddr end) {
525 u64 page_start = start >> write_page_bit; 528 const u64 page_end = end >> WRITE_PAGE_BIT;
526 const u64 page_end = end >> write_page_bit; 529 for (u64 page_start = start >> WRITE_PAGE_BIT; page_start <= page_end; ++page_start) {
527 while (page_start <= page_end) {
528 auto it = written_pages.find(page_start); 530 auto it = written_pages.find(page_start);
529 if (it != written_pages.end()) { 531 if (it != written_pages.end()) {
530 it->second = it->second + 1; 532 it->second = it->second + 1;
531 } else { 533 } else {
532 written_pages[page_start] = 1; 534 written_pages.insert_or_assign(page_start, 1);
533 } 535 }
534 ++page_start;
535 } 536 }
536 } 537 }
537 538
538 void UnmarkRegionAsWritten(const VAddr start, const VAddr end) { 539 void UnmarkRegionAsWritten(VAddr start, VAddr end) {
539 u64 page_start = start >> write_page_bit; 540 const u64 page_end = end >> WRITE_PAGE_BIT;
540 const u64 page_end = end >> write_page_bit; 541 for (u64 page_start = start >> WRITE_PAGE_BIT; page_start <= page_end; ++page_start) {
541 while (page_start <= page_end) {
542 auto it = written_pages.find(page_start); 542 auto it = written_pages.find(page_start);
543 if (it != written_pages.end()) { 543 if (it != written_pages.end()) {
544 if (it->second > 1) { 544 if (it->second > 1) {
@@ -547,22 +547,24 @@ private:
547 written_pages.erase(it); 547 written_pages.erase(it);
548 } 548 }
549 } 549 }
550 ++page_start;
551 } 550 }
552 } 551 }
553 552
554 bool IsRegionWritten(const VAddr start, const VAddr end) const { 553 bool IsRegionWritten(VAddr start, VAddr end) const {
555 u64 page_start = start >> write_page_bit; 554 const u64 page_end = end >> WRITE_PAGE_BIT;
556 const u64 page_end = end >> write_page_bit; 555 for (u64 page_start = start >> WRITE_PAGE_BIT; page_start <= page_end; ++page_start) {
557 while (page_start <= page_end) {
558 if (written_pages.count(page_start) > 0) { 556 if (written_pages.count(page_start) > 0) {
559 return true; 557 return true;
560 } 558 }
561 ++page_start;
562 } 559 }
563 return false; 560 return false;
564 } 561 }
565 562
563 void QueueDestruction(std::shared_ptr<Buffer> buffer) {
564 buffer->SetEpoch(epoch);
565 pending_destruction.push(std::move(buffer));
566 }
567
566 void MarkForAsyncFlush(MapInterval* map) { 568 void MarkForAsyncFlush(MapInterval* map) {
567 if (!uncommitted_flushes) { 569 if (!uncommitted_flushes) {
568 uncommitted_flushes = std::make_shared<std::unordered_set<MapInterval*>>(); 570 uncommitted_flushes = std::make_shared<std::unordered_set<MapInterval*>>();
@@ -574,7 +576,7 @@ private:
574 Core::System& system; 576 Core::System& system;
575 577
576 std::unique_ptr<StreamBuffer> stream_buffer; 578 std::unique_ptr<StreamBuffer> stream_buffer;
577 BufferType stream_buffer_handle{}; 579 BufferType stream_buffer_handle;
578 580
579 bool invalidated = false; 581 bool invalidated = false;
580 582
@@ -586,18 +588,15 @@ private:
586 boost::intrusive::set<MapInterval, boost::intrusive::compare<MapIntervalCompare>> 588 boost::intrusive::set<MapInterval, boost::intrusive::compare<MapIntervalCompare>>
587 mapped_addresses; 589 mapped_addresses;
588 590
589 static constexpr u64 write_page_bit = 11;
590 std::unordered_map<u64, u32> written_pages; 591 std::unordered_map<u64, u32> written_pages;
592 std::unordered_map<u64, std::shared_ptr<Buffer>> blocks;
591 593
592 static constexpr u64 block_page_bits = 21; 594 std::queue<std::shared_ptr<Buffer>> pending_destruction;
593 static constexpr u64 block_page_size = 1ULL << block_page_bits;
594 std::unordered_map<u64, OwnerBuffer> blocks;
595
596 std::list<OwnerBuffer> pending_destruction;
597 u64 epoch = 0; 595 u64 epoch = 0;
598 u64 modified_ticks = 0; 596 u64 modified_ticks = 0;
599 597
600 std::vector<u8> staging_buffer; 598 std::vector<u8> staging_buffer;
599
601 std::list<MapInterval*> marked_for_unregister; 600 std::list<MapInterval*> marked_for_unregister;
602 601
603 std::shared_ptr<std::unordered_set<MapInterval*>> uncommitted_flushes; 602 std::shared_ptr<std::unordered_set<MapInterval*>> uncommitted_flushes;
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 a9e86cfc7..7168312b1 100644
--- a/src/video_core/renderer_opengl/gl_buffer_cache.h
+++ b/src/video_core/renderer_opengl/gl_buffer_cache.h
@@ -24,17 +24,12 @@ class Device;
24class OGLStreamBuffer; 24class OGLStreamBuffer;
25class RasterizerOpenGL; 25class RasterizerOpenGL;
26 26
27class CachedBufferBlock; 27class Buffer : public VideoCommon::BufferBlock {
28
29using Buffer = std::shared_ptr<CachedBufferBlock>;
30using GenericBufferCache = VideoCommon::BufferCache<Buffer, GLuint, OGLStreamBuffer>;
31
32class CachedBufferBlock : public VideoCommon::BufferBlock {
33public: 28public:
34 explicit CachedBufferBlock(VAddr cpu_addr, const std::size_t size); 29 explicit Buffer(VAddr cpu_addr, const std::size_t size);
35 ~CachedBufferBlock(); 30 ~Buffer();
36 31
37 GLuint GetHandle() const { 32 GLuint Handle() const {
38 return gl_buffer.handle; 33 return gl_buffer.handle;
39 } 34 }
40 35
@@ -42,6 +37,7 @@ private:
42 OGLBuffer gl_buffer; 37 OGLBuffer gl_buffer;
43}; 38};
44 39
40using GenericBufferCache = VideoCommon::BufferCache<Buffer, GLuint, OGLStreamBuffer>;
45class OGLBufferCache final : public GenericBufferCache { 41class OGLBufferCache final : public GenericBufferCache {
46public: 42public:
47 explicit OGLBufferCache(RasterizerOpenGL& rasterizer, Core::System& system, 43 explicit OGLBufferCache(RasterizerOpenGL& rasterizer, Core::System& system,
@@ -55,9 +51,7 @@ public:
55 } 51 }
56 52
57protected: 53protected:
58 Buffer CreateBlock(VAddr cpu_addr, std::size_t size) override; 54 std::shared_ptr<Buffer> CreateBlock(VAddr cpu_addr, std::size_t size) override;
59
60 GLuint ToHandle(const Buffer& buffer) override;
61 55
62 void UploadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size, 56 void UploadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size,
63 const u8* data) override; 57 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 a54583e7d..cb9734c10 100644
--- a/src/video_core/renderer_vulkan/vk_buffer_cache.h
+++ b/src/video_core/renderer_vulkan/vk_buffer_cache.h
@@ -24,13 +24,13 @@ class VKDevice;
24class VKMemoryManager; 24class VKMemoryManager;
25class VKScheduler; 25class VKScheduler;
26 26
27class CachedBufferBlock final : public VideoCommon::BufferBlock { 27class Buffer final : public VideoCommon::BufferBlock {
28public: 28public:
29 explicit CachedBufferBlock(const VKDevice& device, VKMemoryManager& memory_manager, 29 explicit Buffer(const VKDevice& device, VKMemoryManager& memory_manager, VAddr cpu_addr,
30 VAddr cpu_addr, std::size_t size); 30 std::size_t size);
31 ~CachedBufferBlock(); 31 ~Buffer();
32 32
33 VkBuffer GetHandle() const { 33 VkBuffer Handle() const {
34 return *buffer.handle; 34 return *buffer.handle;
35 } 35 }
36 36
@@ -38,8 +38,6 @@ private:
38 VKBuffer buffer; 38 VKBuffer buffer;
39}; 39};
40 40
41using Buffer = std::shared_ptr<CachedBufferBlock>;
42
43class VKBufferCache final : public VideoCommon::BufferCache<Buffer, VkBuffer, VKStreamBuffer> { 41class VKBufferCache final : public VideoCommon::BufferCache<Buffer, VkBuffer, VKStreamBuffer> {
44public: 42public:
45 explicit VKBufferCache(VideoCore::RasterizerInterface& rasterizer, Core::System& system, 43 explicit VKBufferCache(VideoCore::RasterizerInterface& rasterizer, Core::System& system,
@@ -50,9 +48,7 @@ public:
50 VkBuffer GetEmptyBuffer(std::size_t size) override; 48 VkBuffer GetEmptyBuffer(std::size_t size) override;
51 49
52protected: 50protected:
53 VkBuffer ToHandle(const Buffer& buffer) override; 51 std::shared_ptr<Buffer> CreateBlock(VAddr cpu_addr, std::size_t size) override;
54
55 Buffer CreateBlock(VAddr cpu_addr, std::size_t size) override;
56 52
57 void UploadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size, 53 void UploadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size,
58 const u8* data) override; 54 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