mirror of
https://github.com/cemu-project/Cemu.git
synced 2024-11-29 20:44:18 +01:00
implement vertex stride workaround
This commit is contained in:
parent
82dcbd98a6
commit
ac651eba77
@ -1,6 +1,7 @@
|
|||||||
#include "Cafe/HW/Latte/Renderer/Metal/MetalCommon.h"
|
#include "Cafe/HW/Latte/Renderer/Metal/MetalCommon.h"
|
||||||
#include "Cafe/HW/Latte/Renderer/Metal/MetalMemoryManager.h"
|
#include "Cafe/HW/Latte/Renderer/Metal/MetalMemoryManager.h"
|
||||||
#include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h"
|
#include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h"
|
||||||
|
#include "Metal/MTLResource.hpp"
|
||||||
|
|
||||||
const size_t BUFFER_ALLOCATION_SIZE = 8 * 1024 * 1024;
|
const size_t BUFFER_ALLOCATION_SIZE = 8 * 1024 * 1024;
|
||||||
|
|
||||||
@ -79,7 +80,7 @@ MetalVertexBufferCache::~MetalVertexBufferCache()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MetalRestridedBufferRange MetalVertexBufferCache::RestrideBufferIfNeeded(uint32 bufferIndex, size_t stride)
|
MetalRestridedBufferRange MetalVertexBufferCache::RestrideBufferIfNeeded(MTL::Buffer* bufferCache, uint32 bufferIndex, size_t stride)
|
||||||
{
|
{
|
||||||
auto vertexBufferRange = m_bufferRanges[bufferIndex];
|
auto vertexBufferRange = m_bufferRanges[bufferIndex];
|
||||||
auto& restrideInfo = vertexBufferRange->restrideInfo;
|
auto& restrideInfo = vertexBufferRange->restrideInfo;
|
||||||
@ -87,20 +88,27 @@ MetalRestridedBufferRange MetalVertexBufferCache::RestrideBufferIfNeeded(uint32
|
|||||||
if (stride % 4 == 0)
|
if (stride % 4 == 0)
|
||||||
{
|
{
|
||||||
// No restride needed
|
// No restride needed
|
||||||
return {nullptr, vertexBufferRange->offset};
|
return {bufferCache, vertexBufferRange->offset};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (restrideInfo.memoryInvalidated || stride != restrideInfo.lastStride)
|
if (restrideInfo.memoryInvalidated || stride != restrideInfo.lastStride)
|
||||||
{
|
{
|
||||||
// TODO: restride
|
// TODO: use compute/void vertex function instead
|
||||||
throw std::runtime_error("restride needed");
|
size_t newStride = align(stride, 4);
|
||||||
|
size_t newSize = vertexBufferRange->size / stride * newStride;
|
||||||
|
restrideInfo.buffer = m_mtlr->GetDevice()->newBuffer(newSize, MTL::StorageModeShared);
|
||||||
|
|
||||||
restrideInfo.memoryInvalidated = false;
|
uint8* oldPtr = (uint8*)bufferCache->contents() + vertexBufferRange->offset;
|
||||||
restrideInfo.lastStride = stride;
|
uint8* newPtr = (uint8*)restrideInfo.buffer->contents();
|
||||||
|
|
||||||
|
for (size_t elem = 0; elem < vertexBufferRange->size / stride; elem++)
|
||||||
|
{
|
||||||
|
memcpy(newPtr + elem * newStride, oldPtr + elem * stride, stride);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: remove
|
restrideInfo.memoryInvalidated = false;
|
||||||
throw std::runtime_error("restride unimplemented");
|
restrideInfo.lastStride = newStride;
|
||||||
|
}
|
||||||
|
|
||||||
return {restrideInfo.buffer, 0};
|
return {restrideInfo.buffer, 0};
|
||||||
}
|
}
|
||||||
|
@ -97,7 +97,7 @@ public:
|
|||||||
range = nullptr;
|
range = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
MetalRestridedBufferRange RestrideBufferIfNeeded(uint32 bufferIndex, size_t stride);
|
MetalRestridedBufferRange RestrideBufferIfNeeded(MTL::Buffer* bufferCache, uint32 bufferIndex, size_t stride);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class MetalRenderer* m_mtlr;
|
class MetalRenderer* m_mtlr;
|
||||||
@ -159,13 +159,7 @@ public:
|
|||||||
|
|
||||||
MetalRestridedBufferRange RestrideBufferIfNeeded(uint32 bufferIndex, size_t stride)
|
MetalRestridedBufferRange RestrideBufferIfNeeded(uint32 bufferIndex, size_t stride)
|
||||||
{
|
{
|
||||||
auto range = m_vertexBufferCache.RestrideBufferIfNeeded(bufferIndex, stride);
|
return m_vertexBufferCache.RestrideBufferIfNeeded(m_bufferCache, bufferIndex, stride);
|
||||||
if (!range.buffer)
|
|
||||||
{
|
|
||||||
range.buffer = m_bufferCache;
|
|
||||||
}
|
|
||||||
|
|
||||||
return range;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -63,6 +63,13 @@ MTL::RenderPipelineState* MetalPipelineCache::GetPipelineState(const LatteFetchS
|
|||||||
uint32 bufferStride = (LatteGPUState.contextNew.GetRawView()[bufferBaseRegisterIndex + 2] >> 11) & 0xFFFF;
|
uint32 bufferStride = (LatteGPUState.contextNew.GetRawView()[bufferBaseRegisterIndex + 2] >> 11) & 0xFFFF;
|
||||||
bufferStride = align(bufferStride, 4);
|
bufferStride = align(bufferStride, 4);
|
||||||
|
|
||||||
|
// HACK
|
||||||
|
if (bufferStride == 0)
|
||||||
|
{
|
||||||
|
debug_printf("vertex buffer %u has a vertex stride of 0 bytes, using 4 bytes instead\n", bufferIndex);
|
||||||
|
bufferStride = 4;
|
||||||
|
}
|
||||||
|
|
||||||
auto layout = vertexDescriptor->layouts()->object(GET_MTL_VERTEX_BUFFER_INDEX(bufferIndex));
|
auto layout = vertexDescriptor->layouts()->object(GET_MTL_VERTEX_BUFFER_INDEX(bufferIndex));
|
||||||
layout->setStride(bufferStride);
|
layout->setStride(bufferStride);
|
||||||
if (!fetchType.has_value() || fetchType == LatteConst::VertexFetchType2::VERTEX_DATA)
|
if (!fetchType.has_value() || fetchType == LatteConst::VertexFetchType2::VERTEX_DATA)
|
||||||
|
Loading…
Reference in New Issue
Block a user