mirror of
https://github.com/cemu-project/Cemu.git
synced 2024-12-02 05:54:18 +01:00
optimize index buffers
This commit is contained in:
parent
0cb83d4668
commit
be8a560496
@ -1,5 +1,57 @@
|
|||||||
|
#include "Cafe/HW/Latte/Renderer/Metal/MetalMemoryManager.h"
|
||||||
#include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h"
|
#include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h"
|
||||||
|
|
||||||
|
const size_t BUFFER_ALLOCATION_SIZE = 8 * 1024 * 1024;
|
||||||
|
|
||||||
|
MetalBufferAllocation MetalBufferAllocator::GetBufferAllocation(size_t size)
|
||||||
|
{
|
||||||
|
// First, try to find a free range
|
||||||
|
for (uint32 i = 0; i < m_freeBufferRanges.size(); i++)
|
||||||
|
{
|
||||||
|
auto& range = m_freeBufferRanges[i];
|
||||||
|
if (range.size >= size)
|
||||||
|
{
|
||||||
|
MetalBufferAllocation allocation;
|
||||||
|
allocation.bufferIndex = range.bufferIndex;
|
||||||
|
allocation.bufferOffset = range.offset;
|
||||||
|
allocation.data = (uint8*)m_buffers[range.bufferIndex]->contents() + range.offset;
|
||||||
|
|
||||||
|
range.offset += size;
|
||||||
|
range.size -= size;
|
||||||
|
|
||||||
|
if (range.size == 0)
|
||||||
|
{
|
||||||
|
m_freeBufferRanges.erase(m_freeBufferRanges.begin() + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return allocation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no free range was found, allocate a new buffer
|
||||||
|
MTL::Buffer* buffer = m_mtlr->GetDevice()->newBuffer(std::max(size, BUFFER_ALLOCATION_SIZE), MTL::ResourceStorageModeShared);
|
||||||
|
|
||||||
|
MetalBufferAllocation allocation;
|
||||||
|
allocation.bufferIndex = m_buffers.size();
|
||||||
|
allocation.bufferOffset = 0;
|
||||||
|
allocation.data = buffer->contents();
|
||||||
|
|
||||||
|
m_buffers.push_back(buffer);
|
||||||
|
|
||||||
|
// If the buffer is larger than the requested size, add the remaining space to the free buffer ranges
|
||||||
|
if (size < BUFFER_ALLOCATION_SIZE)
|
||||||
|
{
|
||||||
|
MetalBufferRange range;
|
||||||
|
range.bufferIndex = allocation.bufferIndex;
|
||||||
|
range.offset = size;
|
||||||
|
range.size = BUFFER_ALLOCATION_SIZE - size;
|
||||||
|
|
||||||
|
m_freeBufferRanges.push_back(range);
|
||||||
|
}
|
||||||
|
|
||||||
|
return allocation;
|
||||||
|
}
|
||||||
|
|
||||||
void* MetalMemoryManager::GetTextureUploadBuffer(size_t size)
|
void* MetalMemoryManager::GetTextureUploadBuffer(size_t size)
|
||||||
{
|
{
|
||||||
if (m_textureUploadBuffer.size() < size)
|
if (m_textureUploadBuffer.size() < size)
|
||||||
@ -10,21 +62,6 @@ void* MetalMemoryManager::GetTextureUploadBuffer(size_t size)
|
|||||||
return m_textureUploadBuffer.data();
|
return m_textureUploadBuffer.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: optimize this
|
|
||||||
MetalBufferAllocation MetalMemoryManager::GetBufferAllocation(size_t size)
|
|
||||||
{
|
|
||||||
MTL::Buffer* buffer = m_mtlr->GetDevice()->newBuffer(size, MTL::ResourceStorageModeShared);
|
|
||||||
|
|
||||||
MetalBufferAllocation allocation;
|
|
||||||
allocation.bufferIndex = m_buffers.size();
|
|
||||||
allocation.bufferOffset = 0;
|
|
||||||
allocation.data = buffer->contents();
|
|
||||||
|
|
||||||
m_buffers.push_back(buffer);
|
|
||||||
|
|
||||||
return allocation;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MetalMemoryManager::InitBufferCache(size_t size)
|
void MetalMemoryManager::InitBufferCache(size_t size)
|
||||||
{
|
{
|
||||||
if (m_bufferCache)
|
if (m_bufferCache)
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
#include "Cafe/HW/Latte/ISA/LatteReg.h"
|
#include "Cafe/HW/Latte/ISA/LatteReg.h"
|
||||||
|
|
||||||
|
//const uint32 bufferAllocatorIndexShift = 24;
|
||||||
|
|
||||||
struct MetalBufferAllocation
|
struct MetalBufferAllocation
|
||||||
{
|
{
|
||||||
void* data;
|
void* data;
|
||||||
@ -11,16 +13,69 @@ struct MetalBufferAllocation
|
|||||||
size_t bufferOffset;
|
size_t bufferOffset;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MetalMemoryManager
|
struct MetalBufferRange
|
||||||
|
{
|
||||||
|
uint32 bufferIndex;
|
||||||
|
size_t offset;
|
||||||
|
size_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MetalBufferAllocator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MetalMemoryManager(class MetalRenderer* metalRenderer) : m_mtlr{metalRenderer} {}
|
MetalBufferAllocator(class MetalRenderer* metalRenderer) : m_mtlr{metalRenderer} {}
|
||||||
|
|
||||||
|
void ResetTemporaryBuffers()
|
||||||
|
{
|
||||||
|
m_freeBufferRanges.clear();
|
||||||
|
|
||||||
|
// Register the free ranges
|
||||||
|
for (uint32 i = 0; i < m_buffers.size(); i++)
|
||||||
|
{
|
||||||
|
m_freeBufferRanges.push_back({i, 0, m_buffers[i]->length()});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MTL::Buffer* GetBuffer(uint32 bufferIndex)
|
MTL::Buffer* GetBuffer(uint32 bufferIndex)
|
||||||
{
|
{
|
||||||
return m_buffers[bufferIndex];
|
return m_buffers[bufferIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MetalBufferAllocation GetBufferAllocation(size_t size);
|
||||||
|
|
||||||
|
private:
|
||||||
|
class MetalRenderer* m_mtlr;
|
||||||
|
|
||||||
|
std::vector<MTL::Buffer*> m_buffers;
|
||||||
|
std::vector<MetalBufferRange> m_freeBufferRanges;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MetalMemoryManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MetalMemoryManager(class MetalRenderer* metalRenderer) : m_mtlr{metalRenderer}, m_bufferAllocator(metalRenderer) {}
|
||||||
|
|
||||||
|
void ResetTemporaryBuffers()
|
||||||
|
{
|
||||||
|
m_bufferAllocator/*s[m_bufferAllocatorIndex]*/.ResetTemporaryBuffers();
|
||||||
|
//m_bufferAllocatorIndex = (m_bufferAllocatorIndex + 1) % 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
MTL::Buffer* GetBuffer(uint32 bufferIndex)
|
||||||
|
{
|
||||||
|
//uint32 bufferAllocatorIndex = (bufferIndex >> bufferAllocatorIndexShift);
|
||||||
|
|
||||||
|
return m_bufferAllocator/*s[bufferAllocatorIndex]*/.GetBuffer(bufferIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
MetalBufferAllocation GetBufferAllocation(size_t size)
|
||||||
|
{
|
||||||
|
auto allocation = m_bufferAllocator/*s[m_bufferAllocatorIndex]*/.GetBufferAllocation(size);
|
||||||
|
//allocation.bufferIndex |= (m_bufferAllocatorIndex << bufferAllocatorIndexShift);
|
||||||
|
|
||||||
|
return allocation;
|
||||||
|
}
|
||||||
|
|
||||||
MTL::Buffer* GetBufferCache()
|
MTL::Buffer* GetBufferCache()
|
||||||
{
|
{
|
||||||
return m_bufferCache;
|
return m_bufferCache;
|
||||||
@ -28,8 +83,6 @@ public:
|
|||||||
|
|
||||||
void* GetTextureUploadBuffer(size_t size);
|
void* GetTextureUploadBuffer(size_t size);
|
||||||
|
|
||||||
MetalBufferAllocation GetBufferAllocation(size_t size);
|
|
||||||
|
|
||||||
// Buffer cache
|
// Buffer cache
|
||||||
void InitBufferCache(size_t size);
|
void InitBufferCache(size_t size);
|
||||||
void UploadToBufferCache(const void* data, size_t offset, size_t size);
|
void UploadToBufferCache(const void* data, size_t offset, size_t size);
|
||||||
@ -39,6 +92,9 @@ private:
|
|||||||
class MetalRenderer* m_mtlr;
|
class MetalRenderer* m_mtlr;
|
||||||
|
|
||||||
std::vector<uint8> m_textureUploadBuffer;
|
std::vector<uint8> m_textureUploadBuffer;
|
||||||
std::vector<MTL::Buffer*> m_buffers;
|
|
||||||
|
MetalBufferAllocator m_bufferAllocator;//s[2];
|
||||||
|
//uint8 m_bufferAllocatorIndex = 0;
|
||||||
|
|
||||||
MTL::Buffer* m_bufferCache = nullptr;
|
MTL::Buffer* m_bufferCache = nullptr;
|
||||||
};
|
};
|
||||||
|
@ -456,7 +456,7 @@ void MetalRenderer::draw_beginSequence()
|
|||||||
LatteSHRC_UpdateActiveShaders();
|
LatteSHRC_UpdateActiveShaders();
|
||||||
if (LatteGPUState.activeShaderHasError)
|
if (LatteGPUState.activeShaderHasError)
|
||||||
{
|
{
|
||||||
cemuLog_logDebugOnce(LogType::Force, "Skipping drawcalls due to shader error");
|
debug_printf("Skipping drawcalls due to shader error\n");
|
||||||
m_state.skipDrawSequence = true;
|
m_state.skipDrawSequence = true;
|
||||||
cemu_assert_debug(false);
|
cemu_assert_debug(false);
|
||||||
return;
|
return;
|
||||||
@ -506,10 +506,8 @@ void MetalRenderer::draw_beginSequence()
|
|||||||
|
|
||||||
void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32 instanceCount, uint32 count, MPTR indexDataMPTR, Latte::LATTE_VGT_DMA_INDEX_TYPE::E_INDEX_TYPE indexType, bool isFirst)
|
void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32 instanceCount, uint32 count, MPTR indexDataMPTR, Latte::LATTE_VGT_DMA_INDEX_TYPE::E_INDEX_TYPE indexType, bool isFirst)
|
||||||
{
|
{
|
||||||
// TODO: uncomment
|
|
||||||
//if (m_state.skipDrawSequence)
|
//if (m_state.skipDrawSequence)
|
||||||
//{
|
//{
|
||||||
// printf("skipping draw\n");
|
|
||||||
// return;
|
// return;
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
#define MAX_MTL_TEXTURES 31
|
#define MAX_MTL_TEXTURES 31
|
||||||
|
|
||||||
struct MetalBufferRange
|
struct MetalBoundBuffer
|
||||||
{
|
{
|
||||||
bool needsRebind = false;
|
bool needsRebind = false;
|
||||||
sint32 offset = -1;
|
sint32 offset = -1;
|
||||||
@ -28,7 +28,7 @@ struct MetalState
|
|||||||
{
|
{
|
||||||
bool skipDrawSequence = false;
|
bool skipDrawSequence = false;
|
||||||
class CachedFBOMtl* activeFBO = nullptr;
|
class CachedFBOMtl* activeFBO = nullptr;
|
||||||
MetalBufferRange vertexBuffers[MAX_MTL_BUFFERS] = {{}};
|
MetalBoundBuffer vertexBuffers[MAX_MTL_BUFFERS] = {{}};
|
||||||
class LatteTextureViewMtl* textures[MAX_MTL_TEXTURES] = {nullptr};
|
class LatteTextureViewMtl* textures[MAX_MTL_TEXTURES] = {nullptr};
|
||||||
MTL::Texture* colorRenderTargets[8] = {nullptr};
|
MTL::Texture* colorRenderTargets[8] = {nullptr};
|
||||||
MTL::Texture* depthRenderTarget = nullptr;
|
MTL::Texture* depthRenderTarget = nullptr;
|
||||||
@ -333,6 +333,9 @@ private:
|
|||||||
m_commandBuffer->release();
|
m_commandBuffer->release();
|
||||||
m_commandBuffer = nullptr;
|
m_commandBuffer = nullptr;
|
||||||
|
|
||||||
|
// Reset temporary buffers
|
||||||
|
m_memoryManager->ResetTemporaryBuffers();
|
||||||
|
|
||||||
// Debug
|
// Debug
|
||||||
m_commandQueue->insertDebugCaptureBoundary();
|
m_commandQueue->insertDebugCaptureBoundary();
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#include <cmath>
|
inline const char* presentLibrarySource = \
|
||||||
const char* presentLibrarySource = \
|
|
||||||
"#include <metal_stdlib>\n" \
|
"#include <metal_stdlib>\n" \
|
||||||
"using namespace metal;\n" \
|
"using namespace metal;\n" \
|
||||||
"\n" \
|
"\n" \
|
||||||
|
Loading…
Reference in New Issue
Block a user