mirror of
				https://git.suyu.dev/suyu/suyu.git
				synced 2025-10-31 23:06:43 +08:00 
			
		
		
		
	buffer_cache: Use buffer methods instead of cache virtual methods
This commit is contained in:
		
							parent
							
								
									39c97f1b65
								
							
						
					
					
						commit
						32a2dcd415
					
				| @ -269,15 +269,6 @@ protected: | ||||
| 
 | ||||
|     virtual std::shared_ptr<Buffer> CreateBlock(VAddr cpu_addr, std::size_t size) = 0; | ||||
| 
 | ||||
|     virtual void UploadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size, | ||||
|                                  const u8* data) = 0; | ||||
| 
 | ||||
|     virtual void DownloadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size, | ||||
|                                    u8* data) = 0; | ||||
| 
 | ||||
|     virtual void CopyBlock(const Buffer& src, const Buffer& dst, std::size_t src_offset, | ||||
|                            std::size_t dst_offset, std::size_t size) = 0; | ||||
| 
 | ||||
|     virtual BufferInfo ConstBufferUpload(const void* raw_pointer, std::size_t size) { | ||||
|         return {}; | ||||
|     } | ||||
| @ -339,11 +330,11 @@ private: | ||||
|             const VAddr cpu_addr_end = cpu_addr + size; | ||||
|             if (memory_manager.IsGranularRange(gpu_addr, size)) { | ||||
|                 u8* host_ptr = memory_manager.GetPointer(gpu_addr); | ||||
|                 UploadBlockData(*block, block->Offset(cpu_addr), size, host_ptr); | ||||
|                 block->Upload(block->Offset(cpu_addr), size, host_ptr); | ||||
|             } else { | ||||
|                 staging_buffer.resize(size); | ||||
|                 memory_manager.ReadBlockUnsafe(gpu_addr, staging_buffer.data(), size); | ||||
|                 UploadBlockData(*block, block->Offset(cpu_addr), size, staging_buffer.data()); | ||||
|                 block->Upload(block->Offset(cpu_addr), size, staging_buffer.data()); | ||||
|             } | ||||
|             return Register(MapInterval(cpu_addr, cpu_addr_end, gpu_addr)); | ||||
|         } | ||||
| @ -402,7 +393,7 @@ private: | ||||
|             } | ||||
|             staging_buffer.resize(size); | ||||
|             system.Memory().ReadBlockUnsafe(interval.lower(), staging_buffer.data(), size); | ||||
|             UploadBlockData(*block, block->Offset(interval.lower()), size, staging_buffer.data()); | ||||
|             block->Upload(block->Offset(interval.lower()), size, staging_buffer.data()); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @ -439,7 +430,7 @@ private: | ||||
| 
 | ||||
|         const std::size_t size = map->end - map->start; | ||||
|         staging_buffer.resize(size); | ||||
|         DownloadBlockData(*block, block->Offset(map->start), size, staging_buffer.data()); | ||||
|         block->Download(block->Offset(map->start), size, staging_buffer.data()); | ||||
|         system.Memory().WriteBlockUnsafe(map->start, staging_buffer.data(), size); | ||||
|         map->MarkAsModified(false, 0); | ||||
|     } | ||||
| @ -467,7 +458,7 @@ private: | ||||
|         const std::size_t new_size = old_size + BLOCK_PAGE_SIZE; | ||||
|         const VAddr cpu_addr = buffer->CpuAddr(); | ||||
|         std::shared_ptr<Buffer> new_buffer = CreateBlock(cpu_addr, new_size); | ||||
|         CopyBlock(*buffer, *new_buffer, 0, 0, old_size); | ||||
|         new_buffer->CopyFrom(*buffer, 0, 0, old_size); | ||||
|         QueueDestruction(std::move(buffer)); | ||||
| 
 | ||||
|         const VAddr cpu_addr_end = cpu_addr + new_size - 1; | ||||
| @ -489,8 +480,8 @@ private: | ||||
|         const std::size_t new_size = size_1 + size_2; | ||||
| 
 | ||||
|         std::shared_ptr<Buffer> new_buffer = CreateBlock(new_addr, new_size); | ||||
|         CopyBlock(*first, *new_buffer, 0, new_buffer->Offset(first_addr), size_1); | ||||
|         CopyBlock(*second, *new_buffer, 0, new_buffer->Offset(second_addr), size_2); | ||||
|         new_buffer->CopyFrom(*first, 0, new_buffer->Offset(first_addr), size_1); | ||||
|         new_buffer->CopyFrom(*second, 0, new_buffer->Offset(second_addr), size_2); | ||||
|         QueueDestruction(std::move(first)); | ||||
|         QueueDestruction(std::move(second)); | ||||
| 
 | ||||
|  | ||||
| @ -34,6 +34,24 @@ Buffer::Buffer(const Device& device, VAddr cpu_addr, std::size_t size) | ||||
| 
 | ||||
| Buffer::~Buffer() = default; | ||||
| 
 | ||||
| void Buffer::Upload(std::size_t offset, std::size_t size, const u8* data) const { | ||||
|     glNamedBufferSubData(Handle(), static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(size), | ||||
|                          data); | ||||
| } | ||||
| 
 | ||||
| void Buffer::Download(std::size_t offset, std::size_t size, u8* data) const { | ||||
|     MICROPROFILE_SCOPE(OpenGL_Buffer_Download); | ||||
|     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); | ||||
|     glGetNamedBufferSubData(Handle(), static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(size), | ||||
|                             data); | ||||
| } | ||||
| 
 | ||||
| void Buffer::CopyFrom(const Buffer& src, std::size_t src_offset, std::size_t dst_offset, | ||||
|                       std::size_t size) const { | ||||
|     glCopyNamedBufferSubData(src.Handle(), Handle(), static_cast<GLintptr>(src_offset), | ||||
|                              static_cast<GLintptr>(dst_offset), static_cast<GLsizeiptr>(size)); | ||||
| } | ||||
| 
 | ||||
| OGLBufferCache::OGLBufferCache(RasterizerOpenGL& rasterizer, Core::System& system, | ||||
|                                const Device& device_, std::size_t stream_size) | ||||
|     : GenericBufferCache{rasterizer, system, | ||||
| @ -62,26 +80,6 @@ OGLBufferCache::BufferInfo OGLBufferCache::GetEmptyBuffer(std::size_t) { | ||||
|     return {0, 0, 0}; | ||||
| } | ||||
| 
 | ||||
| void OGLBufferCache::UploadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size, | ||||
|                                      const u8* data) { | ||||
|     glNamedBufferSubData(buffer.Handle(), static_cast<GLintptr>(offset), | ||||
|                          static_cast<GLsizeiptr>(size), data); | ||||
| } | ||||
| 
 | ||||
| void OGLBufferCache::DownloadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size, | ||||
|                                        u8* data) { | ||||
|     MICROPROFILE_SCOPE(OpenGL_Buffer_Download); | ||||
|     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); | ||||
|     glGetNamedBufferSubData(buffer.Handle(), static_cast<GLintptr>(offset), | ||||
|                             static_cast<GLsizeiptr>(size), data); | ||||
| } | ||||
| 
 | ||||
| void OGLBufferCache::CopyBlock(const Buffer& src, const Buffer& dst, std::size_t src_offset, | ||||
|                                std::size_t dst_offset, std::size_t size) { | ||||
|     glCopyNamedBufferSubData(src.Handle(), dst.Handle(), static_cast<GLintptr>(src_offset), | ||||
|                              static_cast<GLintptr>(dst_offset), static_cast<GLsizeiptr>(size)); | ||||
| } | ||||
| 
 | ||||
| OGLBufferCache::BufferInfo OGLBufferCache::ConstBufferUpload(const void* raw_pointer, | ||||
|                                                              std::size_t size) { | ||||
|     DEBUG_ASSERT(cbuf_cursor < std::size(cbufs)); | ||||
|  | ||||
| @ -28,6 +28,13 @@ public: | ||||
|     explicit Buffer(const Device& device, VAddr cpu_addr, std::size_t size); | ||||
|     ~Buffer(); | ||||
| 
 | ||||
|     void Upload(std::size_t offset, std::size_t size, const u8* data) const; | ||||
| 
 | ||||
|     void Download(std::size_t offset, std::size_t size, u8* data) const; | ||||
| 
 | ||||
|     void CopyFrom(const Buffer& src, std::size_t src_offset, std::size_t dst_offset, | ||||
|                   std::size_t size) const; | ||||
| 
 | ||||
|     GLuint Handle() const noexcept { | ||||
|         return gl_buffer.handle; | ||||
|     } | ||||
| @ -57,15 +64,6 @@ public: | ||||
| protected: | ||||
|     std::shared_ptr<Buffer> CreateBlock(VAddr cpu_addr, std::size_t size) override; | ||||
| 
 | ||||
|     void UploadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size, | ||||
|                          const u8* data) override; | ||||
| 
 | ||||
|     void DownloadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size, | ||||
|                            u8* data) override; | ||||
| 
 | ||||
|     void CopyBlock(const Buffer& src, const Buffer& dst, std::size_t src_offset, | ||||
|                    std::size_t dst_offset, std::size_t size) override; | ||||
| 
 | ||||
|     BufferInfo ConstBufferUpload(const void* raw_pointer, std::size_t size) override; | ||||
| 
 | ||||
| private: | ||||
|  | ||||
| @ -37,9 +37,9 @@ std::unique_ptr<VKStreamBuffer> CreateStreamBuffer(const VKDevice& device, VKSch | ||||
| 
 | ||||
| } // Anonymous namespace
 | ||||
| 
 | ||||
| Buffer::Buffer(const VKDevice& device, VKMemoryManager& memory_manager, VAddr cpu_addr, | ||||
|                std::size_t size) | ||||
|     : VideoCommon::BufferBlock{cpu_addr, size} { | ||||
| Buffer::Buffer(const VKDevice& device, VKMemoryManager& memory_manager, VKScheduler& scheduler_, | ||||
|                VKStagingBufferPool& staging_pool_, VAddr cpu_addr, std::size_t size) | ||||
|     : VideoCommon::BufferBlock{cpu_addr, size}, scheduler{scheduler_}, staging_pool{staging_pool_} { | ||||
|     VkBufferCreateInfo ci; | ||||
|     ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; | ||||
|     ci.pNext = nullptr; | ||||
| @ -56,40 +56,15 @@ Buffer::Buffer(const VKDevice& device, VKMemoryManager& memory_manager, VAddr cp | ||||
| 
 | ||||
| Buffer::~Buffer() = default; | ||||
| 
 | ||||
| VKBufferCache::VKBufferCache(VideoCore::RasterizerInterface& rasterizer, Core::System& system, | ||||
|                              const VKDevice& device, VKMemoryManager& memory_manager, | ||||
|                              VKScheduler& scheduler, VKStagingBufferPool& staging_pool) | ||||
|     : VideoCommon::BufferCache<Buffer, VkBuffer, VKStreamBuffer>{rasterizer, system, | ||||
|                                                                  CreateStreamBuffer(device, | ||||
|                                                                                     scheduler)}, | ||||
|       device{device}, memory_manager{memory_manager}, scheduler{scheduler}, staging_pool{ | ||||
|                                                                                 staging_pool} {} | ||||
| 
 | ||||
| VKBufferCache::~VKBufferCache() = default; | ||||
| 
 | ||||
| std::shared_ptr<Buffer> VKBufferCache::CreateBlock(VAddr cpu_addr, std::size_t size) { | ||||
|     return std::make_shared<Buffer>(device, memory_manager, cpu_addr, size); | ||||
| } | ||||
| 
 | ||||
| VKBufferCache::BufferInfo VKBufferCache::GetEmptyBuffer(std::size_t size) { | ||||
|     size = std::max(size, std::size_t(4)); | ||||
|     const auto& empty = staging_pool.GetUnusedBuffer(size, false); | ||||
|     scheduler.RequestOutsideRenderPassOperationContext(); | ||||
|     scheduler.Record([size, buffer = *empty.handle](vk::CommandBuffer cmdbuf) { | ||||
|         cmdbuf.FillBuffer(buffer, 0, size, 0); | ||||
|     }); | ||||
|     return {*empty.handle, 0, 0}; | ||||
| } | ||||
| 
 | ||||
| void VKBufferCache::UploadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size, | ||||
|                                     const u8* data) { | ||||
| void Buffer::Upload(std::size_t offset, std::size_t size, const u8* data) const { | ||||
|     const auto& staging = staging_pool.GetUnusedBuffer(size, true); | ||||
|     std::memcpy(staging.commit->Map(size), data, size); | ||||
| 
 | ||||
|     scheduler.RequestOutsideRenderPassOperationContext(); | ||||
|     scheduler.Record([staging = *staging.handle, buffer = buffer.Handle(), offset, | ||||
|                       size](vk::CommandBuffer cmdbuf) { | ||||
|         cmdbuf.CopyBuffer(staging, buffer, VkBufferCopy{0, offset, size}); | ||||
| 
 | ||||
|     const VkBuffer handle = Handle(); | ||||
|     scheduler.Record([staging = *staging.handle, handle, offset, size](vk::CommandBuffer cmdbuf) { | ||||
|         cmdbuf.CopyBuffer(staging, handle, VkBufferCopy{0, offset, size}); | ||||
| 
 | ||||
|         VkBufferMemoryBarrier barrier; | ||||
|         barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; | ||||
| @ -98,7 +73,7 @@ void VKBufferCache::UploadBlockData(const Buffer& buffer, std::size_t offset, st | ||||
|         barrier.dstAccessMask = UPLOAD_ACCESS_BARRIERS; | ||||
|         barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; | ||||
|         barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; | ||||
|         barrier.buffer = buffer; | ||||
|         barrier.buffer = handle; | ||||
|         barrier.offset = offset; | ||||
|         barrier.size = size; | ||||
|         cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, UPLOAD_PIPELINE_STAGE, 0, {}, | ||||
| @ -106,12 +81,12 @@ void VKBufferCache::UploadBlockData(const Buffer& buffer, std::size_t offset, st | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| void VKBufferCache::DownloadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size, | ||||
|                                       u8* data) { | ||||
| void Buffer::Download(std::size_t offset, std::size_t size, u8* data) const { | ||||
|     const auto& staging = staging_pool.GetUnusedBuffer(size, true); | ||||
|     scheduler.RequestOutsideRenderPassOperationContext(); | ||||
|     scheduler.Record([staging = *staging.handle, buffer = buffer.Handle(), offset, | ||||
|                       size](vk::CommandBuffer cmdbuf) { | ||||
| 
 | ||||
|     const VkBuffer handle = Handle(); | ||||
|     scheduler.Record([staging = *staging.handle, handle, offset, size](vk::CommandBuffer cmdbuf) { | ||||
|         VkBufferMemoryBarrier barrier; | ||||
|         barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; | ||||
|         barrier.pNext = nullptr; | ||||
| @ -119,7 +94,7 @@ void VKBufferCache::DownloadBlockData(const Buffer& buffer, std::size_t offset, | ||||
|         barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; | ||||
|         barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; | ||||
|         barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; | ||||
|         barrier.buffer = buffer; | ||||
|         barrier.buffer = handle; | ||||
|         barrier.offset = offset; | ||||
|         barrier.size = size; | ||||
| 
 | ||||
| @ -127,17 +102,19 @@ void VKBufferCache::DownloadBlockData(const Buffer& buffer, std::size_t offset, | ||||
|                                    VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | | ||||
|                                    VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, | ||||
|                                VK_PIPELINE_STAGE_TRANSFER_BIT, 0, {}, barrier, {}); | ||||
|         cmdbuf.CopyBuffer(buffer, staging, VkBufferCopy{offset, 0, size}); | ||||
|         cmdbuf.CopyBuffer(handle, staging, VkBufferCopy{offset, 0, size}); | ||||
|     }); | ||||
|     scheduler.Finish(); | ||||
| 
 | ||||
|     std::memcpy(data, staging.commit->Map(size), size); | ||||
| } | ||||
| 
 | ||||
| void VKBufferCache::CopyBlock(const Buffer& src, const Buffer& dst, std::size_t src_offset, | ||||
|                               std::size_t dst_offset, std::size_t size) { | ||||
| void Buffer::CopyFrom(const Buffer& src, std::size_t src_offset, std::size_t dst_offset, | ||||
|                       std::size_t size) const { | ||||
|     scheduler.RequestOutsideRenderPassOperationContext(); | ||||
|     scheduler.Record([src_buffer = src.Handle(), dst_buffer = dst.Handle(), src_offset, dst_offset, | ||||
| 
 | ||||
|     const VkBuffer dst_buffer = Handle(); | ||||
|     scheduler.Record([src_buffer = src.Handle(), dst_buffer, src_offset, dst_offset, | ||||
|                       size](vk::CommandBuffer cmdbuf) { | ||||
|         cmdbuf.CopyBuffer(src_buffer, dst_buffer, VkBufferCopy{src_offset, dst_offset, size}); | ||||
| 
 | ||||
| @ -165,4 +142,30 @@ void VKBufferCache::CopyBlock(const Buffer& src, const Buffer& dst, std::size_t | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| VKBufferCache::VKBufferCache(VideoCore::RasterizerInterface& rasterizer, Core::System& system, | ||||
|                              const VKDevice& device, VKMemoryManager& memory_manager, | ||||
|                              VKScheduler& scheduler, VKStagingBufferPool& staging_pool) | ||||
|     : VideoCommon::BufferCache<Buffer, VkBuffer, VKStreamBuffer>{rasterizer, system, | ||||
|                                                                  CreateStreamBuffer(device, | ||||
|                                                                                     scheduler)}, | ||||
|       device{device}, memory_manager{memory_manager}, scheduler{scheduler}, staging_pool{ | ||||
|                                                                                 staging_pool} {} | ||||
| 
 | ||||
| VKBufferCache::~VKBufferCache() = default; | ||||
| 
 | ||||
| std::shared_ptr<Buffer> VKBufferCache::CreateBlock(VAddr cpu_addr, std::size_t size) { | ||||
|     return std::make_shared<Buffer>(device, memory_manager, scheduler, staging_pool, cpu_addr, | ||||
|                                     size); | ||||
| } | ||||
| 
 | ||||
| VKBufferCache::BufferInfo VKBufferCache::GetEmptyBuffer(std::size_t size) { | ||||
|     size = std::max(size, std::size_t(4)); | ||||
|     const auto& empty = staging_pool.GetUnusedBuffer(size, false); | ||||
|     scheduler.RequestOutsideRenderPassOperationContext(); | ||||
|     scheduler.Record([size, buffer = *empty.handle](vk::CommandBuffer cmdbuf) { | ||||
|         cmdbuf.FillBuffer(buffer, 0, size, 0); | ||||
|     }); | ||||
|     return {*empty.handle, 0, 0}; | ||||
| } | ||||
| 
 | ||||
| } // namespace Vulkan
 | ||||
|  | ||||
| @ -25,10 +25,17 @@ class VKScheduler; | ||||
| 
 | ||||
| class Buffer final : public VideoCommon::BufferBlock { | ||||
| public: | ||||
|     explicit Buffer(const VKDevice& device, VKMemoryManager& memory_manager, VAddr cpu_addr, | ||||
|                     std::size_t size); | ||||
|     explicit Buffer(const VKDevice& device, VKMemoryManager& memory_manager, VKScheduler& scheduler, | ||||
|                     VKStagingBufferPool& staging_pool, VAddr cpu_addr, std::size_t size); | ||||
|     ~Buffer(); | ||||
| 
 | ||||
|     void Upload(std::size_t offset, std::size_t size, const u8* data) const; | ||||
| 
 | ||||
|     void Download(std::size_t offset, std::size_t size, u8* data) const; | ||||
| 
 | ||||
|     void CopyFrom(const Buffer& src, std::size_t src_offset, std::size_t dst_offset, | ||||
|                   std::size_t size) const; | ||||
| 
 | ||||
|     VkBuffer Handle() const { | ||||
|         return *buffer.handle; | ||||
|     } | ||||
| @ -38,6 +45,9 @@ public: | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     VKScheduler& scheduler; | ||||
|     VKStagingBufferPool& staging_pool; | ||||
| 
 | ||||
|     VKBuffer buffer; | ||||
| }; | ||||
| 
 | ||||
| @ -53,15 +63,6 @@ public: | ||||
| protected: | ||||
|     std::shared_ptr<Buffer> CreateBlock(VAddr cpu_addr, std::size_t size) override; | ||||
| 
 | ||||
|     void UploadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size, | ||||
|                          const u8* data) override; | ||||
| 
 | ||||
|     void DownloadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size, | ||||
|                            u8* data) override; | ||||
| 
 | ||||
|     void CopyBlock(const Buffer& src, const Buffer& dst, std::size_t src_offset, | ||||
|                    std::size_t dst_offset, std::size_t size) override; | ||||
| 
 | ||||
| private: | ||||
|     const VKDevice& device; | ||||
|     VKMemoryManager& memory_manager; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user