buffer_cache: Use buffer methods instead of cache virtual methods

This commit is contained in:
ReinUsesLisp 2020-06-19 20:47:48 -03:00
parent 39c97f1b65
commit 32a2dcd415
5 changed files with 90 additions and 99 deletions

View file

@ -269,15 +269,6 @@ protected:
virtual std::shared_ptr<Buffer> CreateBlock(VAddr cpu_addr, std::size_t size) = 0; 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) { virtual BufferInfo ConstBufferUpload(const void* raw_pointer, std::size_t size) {
return {}; return {};
} }
@ -339,11 +330,11 @@ private:
const VAddr cpu_addr_end = cpu_addr + size; const VAddr cpu_addr_end = cpu_addr + size;
if (memory_manager.IsGranularRange(gpu_addr, size)) { if (memory_manager.IsGranularRange(gpu_addr, size)) {
u8* host_ptr = memory_manager.GetPointer(gpu_addr); 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 { } else {
staging_buffer.resize(size); staging_buffer.resize(size);
memory_manager.ReadBlockUnsafe(gpu_addr, staging_buffer.data(), 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)); return Register(MapInterval(cpu_addr, cpu_addr_end, gpu_addr));
} }
@ -402,7 +393,7 @@ private:
} }
staging_buffer.resize(size); staging_buffer.resize(size);
system.Memory().ReadBlockUnsafe(interval.lower(), staging_buffer.data(), 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; const std::size_t size = map->end - map->start;
staging_buffer.resize(size); 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); system.Memory().WriteBlockUnsafe(map->start, staging_buffer.data(), size);
map->MarkAsModified(false, 0); map->MarkAsModified(false, 0);
} }
@ -467,7 +458,7 @@ private:
const std::size_t new_size = old_size + BLOCK_PAGE_SIZE; const std::size_t new_size = old_size + BLOCK_PAGE_SIZE;
const VAddr cpu_addr = buffer->CpuAddr(); const VAddr cpu_addr = buffer->CpuAddr();
std::shared_ptr<Buffer> new_buffer = CreateBlock(cpu_addr, new_size); 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)); QueueDestruction(std::move(buffer));
const VAddr cpu_addr_end = cpu_addr + new_size - 1; 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; const std::size_t new_size = size_1 + size_2;
std::shared_ptr<Buffer> new_buffer = CreateBlock(new_addr, new_size); std::shared_ptr<Buffer> new_buffer = CreateBlock(new_addr, new_size);
CopyBlock(*first, *new_buffer, 0, new_buffer->Offset(first_addr), size_1); new_buffer->CopyFrom(*first, 0, new_buffer->Offset(first_addr), size_1);
CopyBlock(*second, *new_buffer, 0, new_buffer->Offset(second_addr), size_2); new_buffer->CopyFrom(*second, 0, new_buffer->Offset(second_addr), size_2);
QueueDestruction(std::move(first)); QueueDestruction(std::move(first));
QueueDestruction(std::move(second)); QueueDestruction(std::move(second));

View file

@ -34,6 +34,24 @@ Buffer::Buffer(const Device& device, VAddr cpu_addr, std::size_t size)
Buffer::~Buffer() = default; 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, OGLBufferCache::OGLBufferCache(RasterizerOpenGL& rasterizer, Core::System& system,
const Device& device_, std::size_t stream_size) const Device& device_, std::size_t stream_size)
: GenericBufferCache{rasterizer, system, : GenericBufferCache{rasterizer, system,
@ -62,26 +80,6 @@ OGLBufferCache::BufferInfo OGLBufferCache::GetEmptyBuffer(std::size_t) {
return {0, 0, 0}; 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, OGLBufferCache::BufferInfo OGLBufferCache::ConstBufferUpload(const void* raw_pointer,
std::size_t size) { std::size_t size) {
DEBUG_ASSERT(cbuf_cursor < std::size(cbufs)); DEBUG_ASSERT(cbuf_cursor < std::size(cbufs));

View file

@ -28,6 +28,13 @@ public:
explicit Buffer(const Device& device, VAddr cpu_addr, std::size_t size); explicit Buffer(const Device& device, VAddr cpu_addr, std::size_t size);
~Buffer(); ~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 { GLuint Handle() const noexcept {
return gl_buffer.handle; return gl_buffer.handle;
} }
@ -57,15 +64,6 @@ public:
protected: protected:
std::shared_ptr<Buffer> CreateBlock(VAddr cpu_addr, std::size_t size) override; 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; BufferInfo ConstBufferUpload(const void* raw_pointer, std::size_t size) override;
private: private:

View file

@ -37,9 +37,9 @@ std::unique_ptr<VKStreamBuffer> CreateStreamBuffer(const VKDevice& device, VKSch
} // Anonymous namespace } // Anonymous namespace
Buffer::Buffer(const VKDevice& device, VKMemoryManager& memory_manager, VAddr cpu_addr, Buffer::Buffer(const VKDevice& device, VKMemoryManager& memory_manager, VKScheduler& scheduler_,
std::size_t size) VKStagingBufferPool& staging_pool_, VAddr cpu_addr, std::size_t size)
: VideoCommon::BufferBlock{cpu_addr, size} { : VideoCommon::BufferBlock{cpu_addr, size}, scheduler{scheduler_}, staging_pool{staging_pool_} {
VkBufferCreateInfo ci; VkBufferCreateInfo ci;
ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
ci.pNext = nullptr; ci.pNext = nullptr;
@ -56,40 +56,15 @@ Buffer::Buffer(const VKDevice& device, VKMemoryManager& memory_manager, VAddr cp
Buffer::~Buffer() = default; Buffer::~Buffer() = default;
VKBufferCache::VKBufferCache(VideoCore::RasterizerInterface& rasterizer, Core::System& system, void Buffer::Upload(std::size_t offset, std::size_t size, const u8* data) const {
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) {
const auto& staging = staging_pool.GetUnusedBuffer(size, true); const auto& staging = staging_pool.GetUnusedBuffer(size, true);
std::memcpy(staging.commit->Map(size), data, size); std::memcpy(staging.commit->Map(size), data, size);
scheduler.RequestOutsideRenderPassOperationContext(); scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([staging = *staging.handle, buffer = buffer.Handle(), offset,
size](vk::CommandBuffer cmdbuf) { const VkBuffer handle = Handle();
cmdbuf.CopyBuffer(staging, buffer, VkBufferCopy{0, offset, size}); scheduler.Record([staging = *staging.handle, handle, offset, size](vk::CommandBuffer cmdbuf) {
cmdbuf.CopyBuffer(staging, handle, VkBufferCopy{0, offset, size});
VkBufferMemoryBarrier barrier; VkBufferMemoryBarrier barrier;
barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_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.dstAccessMask = UPLOAD_ACCESS_BARRIERS;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.buffer = buffer; barrier.buffer = handle;
barrier.offset = offset; barrier.offset = offset;
barrier.size = size; barrier.size = size;
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, UPLOAD_PIPELINE_STAGE, 0, {}, 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, void Buffer::Download(std::size_t offset, std::size_t size, u8* data) const {
u8* data) {
const auto& staging = staging_pool.GetUnusedBuffer(size, true); const auto& staging = staging_pool.GetUnusedBuffer(size, true);
scheduler.RequestOutsideRenderPassOperationContext(); 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; VkBufferMemoryBarrier barrier;
barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
barrier.pNext = nullptr; 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.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.buffer = buffer; barrier.buffer = handle;
barrier.offset = offset; barrier.offset = offset;
barrier.size = size; 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_FRAGMENT_SHADER_BIT |
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT, 0, {}, barrier, {}); 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(); scheduler.Finish();
std::memcpy(data, staging.commit->Map(size), size); std::memcpy(data, staging.commit->Map(size), size);
} }
void VKBufferCache::CopyBlock(const Buffer& src, const Buffer& dst, std::size_t src_offset, void Buffer::CopyFrom(const Buffer& src, std::size_t src_offset, std::size_t dst_offset,
std::size_t dst_offset, std::size_t size) { std::size_t size) const {
scheduler.RequestOutsideRenderPassOperationContext(); 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) { size](vk::CommandBuffer cmdbuf) {
cmdbuf.CopyBuffer(src_buffer, dst_buffer, VkBufferCopy{src_offset, dst_offset, size}); 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 } // namespace Vulkan

View file

@ -25,10 +25,17 @@ class VKScheduler;
class Buffer final : public VideoCommon::BufferBlock { class Buffer final : public VideoCommon::BufferBlock {
public: public:
explicit Buffer(const VKDevice& device, VKMemoryManager& memory_manager, VAddr cpu_addr, explicit Buffer(const VKDevice& device, VKMemoryManager& memory_manager, VKScheduler& scheduler,
std::size_t size); VKStagingBufferPool& staging_pool, VAddr cpu_addr, std::size_t size);
~Buffer(); ~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 { VkBuffer Handle() const {
return *buffer.handle; return *buffer.handle;
} }
@ -38,6 +45,9 @@ public:
} }
private: private:
VKScheduler& scheduler;
VKStagingBufferPool& staging_pool;
VKBuffer buffer; VKBuffer buffer;
}; };
@ -53,15 +63,6 @@ public:
protected: protected:
std::shared_ptr<Buffer> CreateBlock(VAddr cpu_addr, std::size_t size) override; 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: private:
const VKDevice& device; const VKDevice& device;
VKMemoryManager& memory_manager; VKMemoryManager& memory_manager;