mirror of
https://github.com/cemu-project/Cemu.git
synced 2024-11-29 20:44:18 +01:00
use managed storage mode when dedicated memory
This commit is contained in:
parent
269e072139
commit
485a652c85
@ -769,7 +769,7 @@ void LatteIndices_decode(const void* indexData, LatteIndexType indexType, uint32
|
|||||||
// recalculate index range but filter out primitive restart index
|
// recalculate index range but filter out primitive restart index
|
||||||
LatteIndices_alternativeCalculateIndexMinMax(indexData, indexType, count, indexMin, indexMax);
|
LatteIndices_alternativeCalculateIndexMinMax(indexData, indexType, count, indexMin, indexMax);
|
||||||
}
|
}
|
||||||
g_renderer->indexData_uploadIndexMemory(indexBufferOffset, indexOutputSize);
|
g_renderer->indexData_uploadIndexMemory(indexBufferIndex, indexBufferOffset, indexOutputSize);
|
||||||
// update cache
|
// update cache
|
||||||
LatteIndexCache.lastPtr = indexData;
|
LatteIndexCache.lastPtr = indexData;
|
||||||
LatteIndexCache.lastCount = count;
|
LatteIndexCache.lastCount = count;
|
||||||
|
@ -9,7 +9,7 @@ LatteTextureMtl::LatteTextureMtl(class MetalRenderer* mtlRenderer, Latte::E_DIM
|
|||||||
: LatteTexture(dim, physAddress, physMipAddress, format, width, height, depth, pitch, mipLevels, swizzle, tileMode, isDepth), m_mtlr(mtlRenderer), m_format(format), m_isDepth(isDepth)
|
: LatteTexture(dim, physAddress, physMipAddress, format, width, height, depth, pitch, mipLevels, swizzle, tileMode, isDepth), m_mtlr(mtlRenderer), m_format(format), m_isDepth(isDepth)
|
||||||
{
|
{
|
||||||
MTL::TextureDescriptor* desc = MTL::TextureDescriptor::alloc()->init();
|
MTL::TextureDescriptor* desc = MTL::TextureDescriptor::alloc()->init();
|
||||||
desc->setStorageMode(MTL::StorageModeShared); // TODO: use private?
|
desc->setStorageMode(m_mtlr->GetOptimalStorageMode());
|
||||||
|
|
||||||
sint32 effectiveBaseWidth = width;
|
sint32 effectiveBaseWidth = width;
|
||||||
sint32 effectiveBaseHeight = height;
|
sint32 effectiveBaseHeight = height;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h"
|
#include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h"
|
||||||
|
#include "Metal/MTLResource.hpp"
|
||||||
|
|
||||||
struct MetalBufferRange
|
struct MetalBufferRange
|
||||||
{
|
{
|
||||||
@ -13,7 +14,7 @@ template<typename BufferT>
|
|||||||
class MetalBufferAllocator
|
class MetalBufferAllocator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MetalBufferAllocator(class MetalRenderer* metalRenderer) : m_mtlr{metalRenderer} {}
|
MetalBufferAllocator(class MetalRenderer* metalRenderer, MTL::ResourceOptions storageMode) : m_mtlr{metalRenderer}, m_storageMode{storageMode} {}
|
||||||
|
|
||||||
~MetalBufferAllocator()
|
~MetalBufferAllocator()
|
||||||
{
|
{
|
||||||
@ -68,7 +69,7 @@ public:
|
|||||||
|
|
||||||
// If no free range was found, allocate a new buffer
|
// If no free range was found, allocate a new buffer
|
||||||
m_allocationSize = std::max(m_allocationSize, size);
|
m_allocationSize = std::max(m_allocationSize, size);
|
||||||
MTL::Buffer* buffer = m_mtlr->GetDevice()->newBuffer(m_allocationSize, MTL::ResourceStorageModeShared);
|
MTL::Buffer* buffer = m_mtlr->GetDevice()->newBuffer(m_allocationSize, m_storageMode);
|
||||||
#ifdef CEMU_DEBUG_ASSERT
|
#ifdef CEMU_DEBUG_ASSERT
|
||||||
buffer->setLabel(GetLabel("Buffer from buffer allocator", buffer));
|
buffer->setLabel(GetLabel("Buffer from buffer allocator", buffer));
|
||||||
#endif
|
#endif
|
||||||
@ -124,6 +125,7 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
class MetalRenderer* m_mtlr;
|
class MetalRenderer* m_mtlr;
|
||||||
|
MTL::ResourceOptions m_storageMode;
|
||||||
|
|
||||||
size_t m_allocationSize = 8 * 1024 * 1024;
|
size_t m_allocationSize = 8 * 1024 * 1024;
|
||||||
|
|
||||||
@ -147,7 +149,7 @@ struct MetalSyncedBuffer
|
|||||||
class MetalTemporaryBufferAllocator : public MetalBufferAllocator<MetalSyncedBuffer>
|
class MetalTemporaryBufferAllocator : public MetalBufferAllocator<MetalSyncedBuffer>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MetalTemporaryBufferAllocator(class MetalRenderer* metalRenderer) : MetalBufferAllocator<MetalSyncedBuffer>(metalRenderer) {}
|
MetalTemporaryBufferAllocator(class MetalRenderer* metalRenderer) : MetalBufferAllocator<MetalSyncedBuffer>(metalRenderer, metalRenderer->GetOptimalResourceStorageMode()) {}
|
||||||
|
|
||||||
void SetActiveCommandBuffer(MTL::CommandBuffer* commandBuffer)
|
void SetActiveCommandBuffer(MTL::CommandBuffer* commandBuffer)
|
||||||
{
|
{
|
||||||
|
@ -132,7 +132,7 @@ void MetalMemoryManager::InitBufferCache(size_t size)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_bufferCache = m_mtlr->GetDevice()->newBuffer(size, MTL::ResourceStorageModeShared);
|
m_bufferCache = m_mtlr->GetDevice()->newBuffer(size, m_mtlr->GetOptimalResourceStorageMode());
|
||||||
#ifdef CEMU_DEBUG_ASSERT
|
#ifdef CEMU_DEBUG_ASSERT
|
||||||
m_bufferCache->setLabel(GetLabel("Buffer cache", m_bufferCache));
|
m_bufferCache->setLabel(GetLabel("Buffer cache", m_bufferCache));
|
||||||
#endif
|
#endif
|
||||||
@ -152,6 +152,8 @@ void MetalMemoryManager::UploadToBufferCache(const void* data, size_t offset, si
|
|||||||
}
|
}
|
||||||
|
|
||||||
memcpy((uint8*)m_bufferCache->contents() + offset, data, size);
|
memcpy((uint8*)m_bufferCache->contents() + offset, data, size);
|
||||||
|
if (!m_mtlr->HasUnifiedMemory())
|
||||||
|
m_bufferCache->didModifyRange(NS::Range(offset, size));
|
||||||
|
|
||||||
// Notify vertex buffer cache about the change
|
// Notify vertex buffer cache about the change
|
||||||
m_vertexBufferCache.MemoryRangeChanged(offset, size);
|
m_vertexBufferCache.MemoryRangeChanged(offset, size);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Cafe/HW/Latte/Renderer/Metal/MetalBufferAllocator.h"
|
#include "Cafe/HW/Latte/Renderer/Metal/MetalBufferAllocator.h"
|
||||||
|
#include "Metal/MTLResource.hpp"
|
||||||
|
|
||||||
struct MetalRestridedBufferRange
|
struct MetalRestridedBufferRange
|
||||||
{
|
{
|
||||||
@ -57,7 +58,7 @@ private:
|
|||||||
class MetalMemoryManager
|
class MetalMemoryManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MetalMemoryManager(class MetalRenderer* metalRenderer) : m_mtlr{metalRenderer}, m_bufferAllocator(metalRenderer), m_framePersistentBufferAllocator(metalRenderer), m_tempBufferAllocator(metalRenderer), m_vertexBufferCache(metalRenderer, m_framePersistentBufferAllocator) {}
|
MetalMemoryManager(class MetalRenderer* metalRenderer) : m_mtlr{metalRenderer}, m_bufferAllocator(metalRenderer, m_mtlr->GetOptimalResourceStorageMode()), m_framePersistentBufferAllocator(metalRenderer, MTL::ResourceStorageModePrivate), m_tempBufferAllocator(metalRenderer), m_vertexBufferCache(metalRenderer, m_framePersistentBufferAllocator) {}
|
||||||
~MetalMemoryManager();
|
~MetalMemoryManager();
|
||||||
|
|
||||||
// Pipelines
|
// Pipelines
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "Cafe/HW/Latte/Core/LatteIndices.h"
|
#include "Cafe/HW/Latte/Core/LatteIndices.h"
|
||||||
#include "Cemu/Logging/CemuDebugLogging.h"
|
#include "Cemu/Logging/CemuDebugLogging.h"
|
||||||
#include "Common/precompiled.h"
|
#include "Common/precompiled.h"
|
||||||
|
#include "Metal/MTLResource.hpp"
|
||||||
#include "gui/guiWrapper.h"
|
#include "gui/guiWrapper.h"
|
||||||
|
|
||||||
#define COMMIT_TRESHOLD 256
|
#define COMMIT_TRESHOLD 256
|
||||||
@ -31,6 +32,9 @@ MetalRenderer::MetalRenderer()
|
|||||||
m_device = MTL::CreateSystemDefaultDevice();
|
m_device = MTL::CreateSystemDefaultDevice();
|
||||||
m_commandQueue = m_device->newCommandQueue();
|
m_commandQueue = m_device->newCommandQueue();
|
||||||
|
|
||||||
|
// Feature support
|
||||||
|
m_hasUnifiedMemory = m_device->hasUnifiedMemory();
|
||||||
|
|
||||||
// Resources
|
// Resources
|
||||||
MTL::SamplerDescriptor* samplerDescriptor = MTL::SamplerDescriptor::alloc()->init();
|
MTL::SamplerDescriptor* samplerDescriptor = MTL::SamplerDescriptor::alloc()->init();
|
||||||
#ifdef CEMU_DEBUG_ASSERT
|
#ifdef CEMU_DEBUG_ASSERT
|
||||||
@ -75,7 +79,7 @@ MetalRenderer::MetalRenderer()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Transform feedback
|
// Transform feedback
|
||||||
m_xfbRingBuffer = m_device->newBuffer(LatteStreamout_GetRingBufferSize(), MTL::StorageModeShared);
|
m_xfbRingBuffer = m_device->newBuffer(LatteStreamout_GetRingBufferSize(), MTL::ResourceStorageModePrivate);
|
||||||
#ifdef CEMU_DEBUG_ASSERT
|
#ifdef CEMU_DEBUG_ASSERT
|
||||||
m_xfbRingBuffer->setLabel(GetLabel("Transform feedback buffer", m_xfbRingBuffer));
|
m_xfbRingBuffer->setLabel(GetLabel("Transform feedback buffer", m_xfbRingBuffer));
|
||||||
#endif
|
#endif
|
||||||
@ -991,9 +995,11 @@ void* MetalRenderer::indexData_reserveIndexMemory(uint32 size, uint32& offset, u
|
|||||||
return allocation.data;
|
return allocation.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetalRenderer::indexData_uploadIndexMemory(uint32 offset, uint32 size)
|
void MetalRenderer::indexData_uploadIndexMemory(uint32 bufferIndex, uint32 offset, uint32 size)
|
||||||
{
|
{
|
||||||
// Do nothing, since the buffer has shared storage mode
|
auto buffer = m_memoryManager->GetTemporaryBufferAllocator().GetBuffer(bufferIndex);
|
||||||
|
if (!HasUnifiedMemory())
|
||||||
|
buffer->didModifyRange(NS::Range(offset, size));
|
||||||
}
|
}
|
||||||
|
|
||||||
MTL::CommandBuffer* MetalRenderer::GetCommandBuffer()
|
MTL::CommandBuffer* MetalRenderer::GetCommandBuffer()
|
||||||
@ -1495,18 +1501,21 @@ void MetalRenderer::BindStageResources(MTL::RenderCommandEncoder* renderCommandE
|
|||||||
size_t size = shader->uniform.uniformRangeSize;
|
size_t size = shader->uniform.uniformRangeSize;
|
||||||
auto supportBuffer = bufferAllocator.GetBufferAllocation(size);
|
auto supportBuffer = bufferAllocator.GetBufferAllocation(size);
|
||||||
memcpy(supportBuffer.data, supportBufferData, size);
|
memcpy(supportBuffer.data, supportBufferData, size);
|
||||||
|
auto buffer = bufferAllocator.GetBuffer(supportBuffer.bufferIndex);
|
||||||
|
if (!HasUnifiedMemory())
|
||||||
|
buffer->didModifyRange(NS::Range(supportBuffer.offset, size));
|
||||||
|
|
||||||
switch (shader->shaderType)
|
switch (shader->shaderType)
|
||||||
{
|
{
|
||||||
case LatteConst::ShaderType::Vertex:
|
case LatteConst::ShaderType::Vertex:
|
||||||
{
|
{
|
||||||
renderCommandEncoder->setVertexBuffer(bufferAllocator.GetBuffer(supportBuffer.bufferIndex), supportBuffer.offset, MTL_SUPPORT_BUFFER_BINDING);
|
renderCommandEncoder->setVertexBuffer(buffer, supportBuffer.offset, MTL_SUPPORT_BUFFER_BINDING);
|
||||||
//renderCommandEncoder->setVertexBytes(supportBufferData, sizeof(supportBufferData), MTL_SUPPORT_BUFFER_BINDING);
|
//renderCommandEncoder->setVertexBytes(supportBufferData, sizeof(supportBufferData), MTL_SUPPORT_BUFFER_BINDING);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LatteConst::ShaderType::Pixel:
|
case LatteConst::ShaderType::Pixel:
|
||||||
{
|
{
|
||||||
renderCommandEncoder->setFragmentBuffer(bufferAllocator.GetBuffer(supportBuffer.bufferIndex), supportBuffer.offset, MTL_SUPPORT_BUFFER_BINDING);
|
renderCommandEncoder->setFragmentBuffer(buffer, supportBuffer.offset, MTL_SUPPORT_BUFFER_BINDING);
|
||||||
//renderCommandEncoder->setFragmentBytes(supportBufferData, sizeof(supportBufferData), MTL_SUPPORT_BUFFER_BINDING);
|
//renderCommandEncoder->setFragmentBytes(supportBufferData, sizeof(supportBufferData), MTL_SUPPORT_BUFFER_BINDING);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "Cafe/HW/Latte/Renderer/Renderer.h"
|
#include "Cafe/HW/Latte/Renderer/Renderer.h"
|
||||||
|
|
||||||
#include "Cafe/HW/Latte/Renderer/Metal/MetalCommon.h"
|
#include "Cafe/HW/Latte/Renderer/Metal/MetalCommon.h"
|
||||||
|
#include "Metal/MTLResource.hpp"
|
||||||
|
|
||||||
struct MetalBufferAllocation
|
struct MetalBufferAllocation
|
||||||
{
|
{
|
||||||
@ -269,7 +270,7 @@ public:
|
|||||||
|
|
||||||
// index
|
// index
|
||||||
void* indexData_reserveIndexMemory(uint32 size, uint32& offset, uint32& bufferIndex) override;
|
void* indexData_reserveIndexMemory(uint32 size, uint32& offset, uint32& bufferIndex) override;
|
||||||
void indexData_uploadIndexMemory(uint32 offset, uint32 size) override;
|
void indexData_uploadIndexMemory(uint32 bufferIndex, uint32 offset, uint32 size) override;
|
||||||
|
|
||||||
// occlusion queries
|
// occlusion queries
|
||||||
LatteQueryObject* occlusionQuery_create() override {
|
LatteQueryObject* occlusionQuery_create() override {
|
||||||
@ -348,7 +349,22 @@ public:
|
|||||||
void ClearColorTextureInternal(MTL::Texture* mtlTexture, sint32 sliceIndex, sint32 mipIndex, float r, float g, float b, float a);
|
void ClearColorTextureInternal(MTL::Texture* mtlTexture, sint32 sliceIndex, sint32 mipIndex, float r, float g, float b, float a);
|
||||||
|
|
||||||
// Getters
|
// Getters
|
||||||
MTL::Buffer* GetTextureReadbackBuffer()
|
bool HasUnifiedMemory() const
|
||||||
|
{
|
||||||
|
return m_hasUnifiedMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
MTL::StorageMode GetOptimalStorageMode() const
|
||||||
|
{
|
||||||
|
return (m_hasUnifiedMemory ? MTL::StorageModeShared : MTL::StorageModeManaged);
|
||||||
|
}
|
||||||
|
|
||||||
|
MTL::ResourceOptions GetOptimalResourceStorageMode() const
|
||||||
|
{
|
||||||
|
return (m_hasUnifiedMemory ? MTL::ResourceStorageModeShared : MTL::ResourceStorageModeManaged);
|
||||||
|
}
|
||||||
|
|
||||||
|
MTL::Buffer* GetTextureReadbackBuffer() const
|
||||||
{
|
{
|
||||||
return m_readbackBuffer;
|
return m_readbackBuffer;
|
||||||
}
|
}
|
||||||
@ -357,15 +373,19 @@ private:
|
|||||||
CA::MetalLayer* m_metalLayer;
|
CA::MetalLayer* m_metalLayer;
|
||||||
float m_layerScaleX, m_layerScaleY;
|
float m_layerScaleX, m_layerScaleY;
|
||||||
|
|
||||||
|
// Metal objects
|
||||||
|
MTL::Device* m_device;
|
||||||
|
MTL::CommandQueue* m_commandQueue;
|
||||||
|
|
||||||
|
// Feature support
|
||||||
|
bool m_hasUnifiedMemory;
|
||||||
|
|
||||||
|
// Managers and caches
|
||||||
class MetalMemoryManager* m_memoryManager;
|
class MetalMemoryManager* m_memoryManager;
|
||||||
class MetalPipelineCache* m_pipelineCache;
|
class MetalPipelineCache* m_pipelineCache;
|
||||||
class MetalDepthStencilCache* m_depthStencilCache;
|
class MetalDepthStencilCache* m_depthStencilCache;
|
||||||
class MetalSamplerCache* m_samplerCache;
|
class MetalSamplerCache* m_samplerCache;
|
||||||
|
|
||||||
// Metal objects
|
|
||||||
MTL::Device* m_device;
|
|
||||||
MTL::CommandQueue* m_commandQueue;
|
|
||||||
|
|
||||||
// Pipelines
|
// Pipelines
|
||||||
MTL::RenderPipelineState* m_presentPipelineLinear;
|
MTL::RenderPipelineState* m_presentPipelineLinear;
|
||||||
MTL::RenderPipelineState* m_presentPipelineSRGB;
|
MTL::RenderPipelineState* m_presentPipelineSRGB;
|
||||||
|
@ -109,7 +109,7 @@ public:
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void indexData_uploadIndexMemory(uint32 offset, uint32 size) override
|
void indexData_uploadIndexMemory(uint32 bufferIndex, uint32 offset, uint32 size) override
|
||||||
{
|
{
|
||||||
assert_dbg();
|
assert_dbg();
|
||||||
}
|
}
|
||||||
|
@ -141,7 +141,7 @@ public:
|
|||||||
|
|
||||||
// index
|
// index
|
||||||
virtual void* indexData_reserveIndexMemory(uint32 size, uint32& offset, uint32& bufferIndex) = 0;
|
virtual void* indexData_reserveIndexMemory(uint32 size, uint32& offset, uint32& bufferIndex) = 0;
|
||||||
virtual void indexData_uploadIndexMemory(uint32 offset, uint32 size) = 0;
|
virtual void indexData_uploadIndexMemory(uint32 bufferIndex, uint32 offset, uint32 size) = 0;
|
||||||
|
|
||||||
// occlusion queries
|
// occlusion queries
|
||||||
virtual LatteQueryObject* occlusionQuery_create() = 0;
|
virtual LatteQueryObject* occlusionQuery_create() = 0;
|
||||||
|
@ -328,7 +328,7 @@ public:
|
|||||||
RendererShader* shader_create(RendererShader::ShaderType type, uint64 baseHash, uint64 auxHash, const std::string& source, bool isGameShader, bool isGfxPackShader) override;
|
RendererShader* shader_create(RendererShader::ShaderType type, uint64 baseHash, uint64 auxHash, const std::string& source, bool isGameShader, bool isGfxPackShader) override;
|
||||||
|
|
||||||
void* indexData_reserveIndexMemory(uint32 size, uint32& offset, uint32& bufferIndex) override;
|
void* indexData_reserveIndexMemory(uint32 size, uint32& offset, uint32& bufferIndex) override;
|
||||||
void indexData_uploadIndexMemory(uint32 offset, uint32 size) override;
|
void indexData_uploadIndexMemory(uint32 bufferIndex, uint32 offset, uint32 size) override;
|
||||||
|
|
||||||
// externally callable
|
// externally callable
|
||||||
void GetTextureFormatInfoVK(Latte::E_GX2SURFFMT format, bool isDepth, Latte::E_DIM dim, sint32 width, sint32 height, FormatInfoVK* formatInfoOut);
|
void GetTextureFormatInfoVK(Latte::E_GX2SURFFMT format, bool isDepth, Latte::E_DIM dim, sint32 width, sint32 height, FormatInfoVK* formatInfoOut);
|
||||||
|
@ -366,7 +366,7 @@ void* VulkanRenderer::indexData_reserveIndexMemory(uint32 size, uint32& offset,
|
|||||||
return resv.memPtr;
|
return resv.memPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanRenderer::indexData_uploadIndexMemory(uint32 offset, uint32 size)
|
void VulkanRenderer::indexData_uploadIndexMemory(uint32 bufferIndex, uint32 offset, uint32 size)
|
||||||
{
|
{
|
||||||
// does nothing since the index buffer memory is coherent
|
// does nothing since the index buffer memory is coherent
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user