mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-07-05 14:31:17 +12:00
flush uploaded buffers
This commit is contained in:
parent
6d6c04ae3c
commit
bf93f90739
5 changed files with 42 additions and 34 deletions
|
@ -9,7 +9,7 @@ MetalBufferChunkedHeap::~MetalBufferChunkedHeap()
|
||||||
uint32 MetalBufferChunkedHeap::allocateNewChunk(uint32 chunkIndex, uint32 minimumAllocationSize)
|
uint32 MetalBufferChunkedHeap::allocateNewChunk(uint32 chunkIndex, uint32 minimumAllocationSize)
|
||||||
{
|
{
|
||||||
size_t allocationSize = std::max<size_t>(m_minimumBufferAllocationSize, minimumAllocationSize);
|
size_t allocationSize = std::max<size_t>(m_minimumBufferAllocationSize, minimumAllocationSize);
|
||||||
MTL::Buffer* buffer = m_mtlr->GetDevice()->newBuffer(allocationSize, MTL::ResourceStorageModeShared);
|
MTL::Buffer* buffer = m_mtlr->GetDevice()->newBuffer(allocationSize, m_options);
|
||||||
cemu_assert_debug(buffer);
|
cemu_assert_debug(buffer);
|
||||||
cemu_assert_debug(m_chunkBuffers.size() == chunkIndex);
|
cemu_assert_debug(m_chunkBuffers.size() == chunkIndex);
|
||||||
m_chunkBuffers.emplace_back(buffer);
|
m_chunkBuffers.emplace_back(buffer);
|
||||||
|
@ -36,7 +36,7 @@ void MetalSynchronizedRingAllocator::allocateAdditionalUploadBuffer(uint32 sizeR
|
||||||
AllocatorBuffer_t newBuffer{};
|
AllocatorBuffer_t newBuffer{};
|
||||||
newBuffer.writeIndex = 0;
|
newBuffer.writeIndex = 0;
|
||||||
newBuffer.basePtr = nullptr;
|
newBuffer.basePtr = nullptr;
|
||||||
newBuffer.mtlBuffer = m_mtlr->GetDevice()->newBuffer(bufferAllocSize, MTL::ResourceStorageModeShared);
|
newBuffer.mtlBuffer = m_mtlr->GetDevice()->newBuffer(bufferAllocSize, m_options);
|
||||||
newBuffer.basePtr = (uint8*)newBuffer.mtlBuffer->contents();
|
newBuffer.basePtr = (uint8*)newBuffer.mtlBuffer->contents();
|
||||||
newBuffer.size = bufferAllocSize;
|
newBuffer.size = bufferAllocSize;
|
||||||
newBuffer.index = (uint32)m_buffers.size();
|
newBuffer.index = (uint32)m_buffers.size();
|
||||||
|
@ -105,16 +105,10 @@ MetalSynchronizedRingAllocator::AllocatorReservation_t MetalSynchronizedRingAllo
|
||||||
|
|
||||||
void MetalSynchronizedRingAllocator::FlushReservation(AllocatorReservation_t& uploadReservation)
|
void MetalSynchronizedRingAllocator::FlushReservation(AllocatorReservation_t& uploadReservation)
|
||||||
{
|
{
|
||||||
/*
|
if (RequiresFlush())
|
||||||
cemu_assert_debug(m_bufferType == VKR_BUFFER_TYPE::STAGING); // only the staging buffer isn't coherent
|
{
|
||||||
// todo - use nonCoherentAtomSize for flush size (instead of hardcoded constant)
|
uploadReservation.mtlBuffer->didModifyRange(NS::Range(uploadReservation.bufferOffset, uploadReservation.size));
|
||||||
VkMappedMemoryRange flushedRange{};
|
}
|
||||||
flushedRange.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
|
|
||||||
flushedRange.memory = uploadReservation.vkMem;
|
|
||||||
flushedRange.offset = uploadReservation.bufferOffset;
|
|
||||||
flushedRange.size = uploadReservation.size;
|
|
||||||
vkFlushMappedMemoryRanges(m_vkr->GetLogicalDevice(), 1, &flushedRange);
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetalSynchronizedRingAllocator::CleanupBuffer(MTL::CommandBuffer* latestFinishedCommandBuffer)
|
void MetalSynchronizedRingAllocator::CleanupBuffer(MTL::CommandBuffer* latestFinishedCommandBuffer)
|
||||||
|
@ -172,9 +166,6 @@ void MetalSynchronizedRingAllocator::GetStats(uint32& numBuffers, size_t& totalB
|
||||||
|
|
||||||
/* MetalSynchronizedHeapAllocator */
|
/* MetalSynchronizedHeapAllocator */
|
||||||
|
|
||||||
MetalSynchronizedHeapAllocator::MetalSynchronizedHeapAllocator(class MetalRenderer* mtlRenderer, size_t minimumBufferAllocSize)
|
|
||||||
: m_mtlr(mtlRenderer), m_chunkedHeap(m_mtlr, minimumBufferAllocSize) {};
|
|
||||||
|
|
||||||
MetalSynchronizedHeapAllocator::AllocatorReservation* MetalSynchronizedHeapAllocator::AllocateBufferMemory(uint32 size, uint32 alignment)
|
MetalSynchronizedHeapAllocator::AllocatorReservation* MetalSynchronizedHeapAllocator::AllocateBufferMemory(uint32 size, uint32 alignment)
|
||||||
{
|
{
|
||||||
CHAddr addr = m_chunkedHeap.alloc(size, alignment);
|
CHAddr addr = m_chunkedHeap.alloc(size, alignment);
|
||||||
|
@ -202,17 +193,10 @@ void MetalSynchronizedHeapAllocator::FreeReservation(AllocatorReservation* uploa
|
||||||
|
|
||||||
void MetalSynchronizedHeapAllocator::FlushReservation(AllocatorReservation* uploadReservation)
|
void MetalSynchronizedHeapAllocator::FlushReservation(AllocatorReservation* uploadReservation)
|
||||||
{
|
{
|
||||||
/*
|
if (m_chunkedHeap.RequiresFlush())
|
||||||
if (m_chunkedHeap.RequiresFlush(uploadReservation->bufferIndex))
|
|
||||||
{
|
{
|
||||||
VkMappedMemoryRange flushedRange{};
|
uploadReservation->mtlBuffer->didModifyRange(NS::Range(uploadReservation->bufferOffset, uploadReservation->size));
|
||||||
flushedRange.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
|
|
||||||
flushedRange.memory = uploadReservation->vkMem;
|
|
||||||
flushedRange.offset = uploadReservation->bufferOffset;
|
|
||||||
flushedRange.size = uploadReservation->size;
|
|
||||||
vkFlushMappedMemoryRanges(VulkanRenderer::GetInstance()->GetLogicalDevice(), 1, &flushedRange);
|
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetalSynchronizedHeapAllocator::CleanupBuffer(MTL::CommandBuffer* latestFinishedCommandBuffer)
|
void MetalSynchronizedHeapAllocator::CleanupBuffer(MTL::CommandBuffer* latestFinishedCommandBuffer)
|
||||||
|
|
|
@ -1,15 +1,24 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h"
|
#include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h"
|
||||||
|
#include "Metal/MTLResource.hpp"
|
||||||
#include "util/ChunkedHeap/ChunkedHeap.h"
|
#include "util/ChunkedHeap/ChunkedHeap.h"
|
||||||
#include "util/helpers/MemoryPool.h"
|
#include "util/helpers/MemoryPool.h"
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
inline MTL::ResourceOptions GetResourceOptions(MTL::ResourceOptions options)
|
||||||
|
{
|
||||||
|
if (options & MTL::ResourceStorageModeShared || options & MTL::ResourceStorageModeManaged)
|
||||||
|
options |= MTL::ResourceCPUCacheModeWriteCombined;
|
||||||
|
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
class MetalBufferChunkedHeap : private ChunkedHeap<>
|
class MetalBufferChunkedHeap : private ChunkedHeap<>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MetalBufferChunkedHeap(const class MetalRenderer* mtlRenderer, size_t minimumBufferAllocationSize) : m_mtlr(mtlRenderer), m_minimumBufferAllocationSize(minimumBufferAllocationSize) { };
|
MetalBufferChunkedHeap(const class MetalRenderer* mtlRenderer, MTL::ResourceOptions options, size_t minimumBufferAllocationSize) : m_mtlr(mtlRenderer), m_options(GetResourceOptions(options)), m_minimumBufferAllocationSize(minimumBufferAllocationSize) { };
|
||||||
~MetalBufferChunkedHeap();
|
~MetalBufferChunkedHeap();
|
||||||
|
|
||||||
using ChunkedHeap::alloc;
|
using ChunkedHeap::alloc;
|
||||||
|
@ -30,6 +39,11 @@ class MetalBufferChunkedHeap : private ChunkedHeap<>
|
||||||
return m_chunkBuffers[index];
|
return m_chunkBuffers[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RequiresFlush() const
|
||||||
|
{
|
||||||
|
return m_options & MTL::ResourceStorageModeManaged;
|
||||||
|
}
|
||||||
|
|
||||||
void GetStats(uint32& numBuffers, size_t& totalBufferSize, size_t& freeBufferSize) const
|
void GetStats(uint32& numBuffers, size_t& totalBufferSize, size_t& freeBufferSize) const
|
||||||
{
|
{
|
||||||
numBuffers = m_chunkBuffers.size();
|
numBuffers = m_chunkBuffers.size();
|
||||||
|
@ -42,15 +56,17 @@ class MetalBufferChunkedHeap : private ChunkedHeap<>
|
||||||
|
|
||||||
const class MetalRenderer* m_mtlr;
|
const class MetalRenderer* m_mtlr;
|
||||||
|
|
||||||
std::vector<MTL::Buffer*> m_chunkBuffers;
|
MTL::ResourceOptions m_options;
|
||||||
size_t m_minimumBufferAllocationSize;
|
size_t m_minimumBufferAllocationSize;
|
||||||
|
|
||||||
|
std::vector<MTL::Buffer*> m_chunkBuffers;
|
||||||
};
|
};
|
||||||
|
|
||||||
// a circular ring-buffer which tracks and releases memory per command-buffer
|
// a circular ring-buffer which tracks and releases memory per command-buffer
|
||||||
class MetalSynchronizedRingAllocator
|
class MetalSynchronizedRingAllocator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MetalSynchronizedRingAllocator(class MetalRenderer* mtlRenderer, uint32 minimumBufferAllocSize) : m_mtlr(mtlRenderer), m_minimumBufferAllocSize(minimumBufferAllocSize) {};
|
MetalSynchronizedRingAllocator(class MetalRenderer* mtlRenderer, MTL::ResourceOptions options, uint32 minimumBufferAllocSize) : m_mtlr(mtlRenderer), m_options(GetResourceOptions(options)), m_minimumBufferAllocSize(minimumBufferAllocSize) {};
|
||||||
MetalSynchronizedRingAllocator(const MetalSynchronizedRingAllocator&) = delete; // disallow copy
|
MetalSynchronizedRingAllocator(const MetalSynchronizedRingAllocator&) = delete; // disallow copy
|
||||||
|
|
||||||
struct BufferSyncPoint_t
|
struct BufferSyncPoint_t
|
||||||
|
@ -88,6 +104,11 @@ public:
|
||||||
void CleanupBuffer(MTL::CommandBuffer* latestFinishedCommandBuffer);
|
void CleanupBuffer(MTL::CommandBuffer* latestFinishedCommandBuffer);
|
||||||
MTL::Buffer* GetBufferByIndex(uint32 index) const;
|
MTL::Buffer* GetBufferByIndex(uint32 index) const;
|
||||||
|
|
||||||
|
bool RequiresFlush() const
|
||||||
|
{
|
||||||
|
return m_options & MTL::ResourceStorageModeManaged;
|
||||||
|
}
|
||||||
|
|
||||||
void GetStats(uint32& numBuffers, size_t& totalBufferSize, size_t& freeBufferSize) const;
|
void GetStats(uint32& numBuffers, size_t& totalBufferSize, size_t& freeBufferSize) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -95,6 +116,8 @@ private:
|
||||||
void addUploadBufferSyncPoint(AllocatorBuffer_t& buffer, uint32 offset);
|
void addUploadBufferSyncPoint(AllocatorBuffer_t& buffer, uint32 offset);
|
||||||
|
|
||||||
const class MetalRenderer* m_mtlr;
|
const class MetalRenderer* m_mtlr;
|
||||||
|
|
||||||
|
MTL::ResourceOptions m_options;
|
||||||
const uint32 m_minimumBufferAllocSize;
|
const uint32 m_minimumBufferAllocSize;
|
||||||
|
|
||||||
std::vector<AllocatorBuffer_t> m_buffers;
|
std::vector<AllocatorBuffer_t> m_buffers;
|
||||||
|
@ -110,7 +133,7 @@ class MetalSynchronizedHeapAllocator
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MetalSynchronizedHeapAllocator(class MetalRenderer* mtlRenderer, size_t minimumBufferAllocSize);
|
MetalSynchronizedHeapAllocator(class MetalRenderer* mtlRenderer, MTL::ResourceOptions options, size_t minimumBufferAllocSize) : m_mtlr(mtlRenderer), m_chunkedHeap(m_mtlr, options, minimumBufferAllocSize) {}
|
||||||
MetalSynchronizedHeapAllocator(const MetalSynchronizedHeapAllocator&) = delete; // disallow copy
|
MetalSynchronizedHeapAllocator(const MetalSynchronizedHeapAllocator&) = delete; // disallow copy
|
||||||
|
|
||||||
struct AllocatorReservation
|
struct AllocatorReservation
|
||||||
|
|
|
@ -77,6 +77,7 @@ void MetalMemoryManager::UploadToBufferCache(const void* data, size_t offset, si
|
||||||
|
|
||||||
auto allocation = m_stagingAllocator.AllocateBufferMemory(size, 1);
|
auto allocation = m_stagingAllocator.AllocateBufferMemory(size, 1);
|
||||||
memcpy(allocation.memPtr, data, size);
|
memcpy(allocation.memPtr, data, size);
|
||||||
|
m_stagingAllocator.FlushReservation(allocation);
|
||||||
|
|
||||||
blitCommandEncoder->copyFromBuffer(allocation.mtlBuffer, allocation.bufferOffset, m_bufferCache, offset, size);
|
blitCommandEncoder->copyFromBuffer(allocation.mtlBuffer, allocation.bufferOffset, m_bufferCache, offset, size);
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
class MetalMemoryManager
|
class MetalMemoryManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MetalMemoryManager(class MetalRenderer* metalRenderer) : m_mtlr{metalRenderer}, m_stagingAllocator(m_mtlr/*, m_mtlr->GetOptimalBufferStorageMode()*/, 32u * 1024 * 1024), m_indexAllocator(m_mtlr/*, m_mtlr->GetOptimalBufferStorageMode()*/, 4u * 1024 * 1024) {}
|
MetalMemoryManager(class MetalRenderer* metalRenderer) : m_mtlr{metalRenderer}, m_stagingAllocator(m_mtlr, m_mtlr->GetOptimalBufferStorageMode(), 32u * 1024 * 1024), m_indexAllocator(m_mtlr, m_mtlr->GetOptimalBufferStorageMode(), 4u * 1024 * 1024) {}
|
||||||
~MetalMemoryManager();
|
~MetalMemoryManager();
|
||||||
|
|
||||||
MetalSynchronizedRingAllocator& GetStagingAllocator()
|
MetalSynchronizedRingAllocator& GetStagingAllocator()
|
||||||
|
|
|
@ -702,6 +702,7 @@ void MetalRenderer::texture_loadSlice(LatteTexture* hostTexture, sint32 width, s
|
||||||
// Allocate a temporary buffer
|
// Allocate a temporary buffer
|
||||||
auto& bufferAllocator = m_memoryManager->GetStagingAllocator();
|
auto& bufferAllocator = m_memoryManager->GetStagingAllocator();
|
||||||
auto allocation = bufferAllocator.AllocateBufferMemory(compressedImageSize, 1);
|
auto allocation = bufferAllocator.AllocateBufferMemory(compressedImageSize, 1);
|
||||||
|
bufferAllocator.FlushReservation(allocation);
|
||||||
|
|
||||||
// Copy the data to the temporary buffer
|
// Copy the data to the temporary buffer
|
||||||
memcpy(allocation.memPtr, pixelData, compressedImageSize);
|
memcpy(allocation.memPtr, pixelData, compressedImageSize);
|
||||||
|
@ -2092,12 +2093,11 @@ void MetalRenderer::BindStageResources(MTL::RenderCommandEncoder* renderCommandE
|
||||||
|
|
||||||
size_t size = shader->uniform.uniformRangeSize;
|
size_t size = shader->uniform.uniformRangeSize;
|
||||||
auto& bufferAllocator = m_memoryManager->GetStagingAllocator();
|
auto& bufferAllocator = m_memoryManager->GetStagingAllocator();
|
||||||
auto supportBuffer = bufferAllocator.AllocateBufferMemory(size, 1);
|
auto allocation = bufferAllocator.AllocateBufferMemory(size, 1);
|
||||||
memcpy(supportBuffer.memPtr, supportBufferData, size);
|
memcpy(allocation.memPtr, supportBufferData, size);
|
||||||
//if (!HasUnifiedMemory())
|
bufferAllocator.FlushReservation(allocation);
|
||||||
// buffer->didModifyRange(NS::Range(supportBuffer.offset, size));
|
|
||||||
|
|
||||||
SetBuffer(renderCommandEncoder, mtlShaderType, supportBuffer.mtlBuffer, supportBuffer.bufferOffset, shader->resourceMapping.uniformVarsBufferBindingPoint);
|
SetBuffer(renderCommandEncoder, mtlShaderType, allocation.mtlBuffer, allocation.bufferOffset, shader->resourceMapping.uniformVarsBufferBindingPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Uniform buffers
|
// Uniform buffers
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue