mirror of
https://github.com/love2d/love.git
synced 2026-08-16 08:11:02 +02:00
metal: fix uniform data corruption
The wrong buffer binding offset was being used in 2/3rds of frames.
This commit is contained in:
@@ -57,6 +57,8 @@ public:
|
||||
BufferUsage getMode() const { return mode; }
|
||||
size_t getUsableSize() const { return bufferSize - frameGPUReadOffset; }
|
||||
|
||||
virtual size_t getGPUReadOffset() const = 0;
|
||||
|
||||
virtual MapInfo map(size_t minsize) = 0;
|
||||
virtual size_t unmap(size_t usedsize) = 0;
|
||||
virtual void markUsed(size_t usedsize) = 0;
|
||||
|
||||
@@ -242,6 +242,7 @@ private:
|
||||
StreamBuffer *uniformBuffer;
|
||||
StreamBuffer::MapInfo uniformBufferData;
|
||||
size_t uniformBufferOffset;
|
||||
size_t uniformBufferGPUStart;
|
||||
|
||||
Buffer *defaultAttributesBuffer;
|
||||
|
||||
|
||||
@@ -280,6 +280,7 @@ Graphics::Graphics()
|
||||
, attachmentStoreActions()
|
||||
, renderBindings()
|
||||
, uniformBufferOffset(0)
|
||||
, uniformBufferGPUStart(0)
|
||||
, defaultAttributesBuffer(nullptr)
|
||||
, families()
|
||||
{ @autoreleasepool {
|
||||
@@ -1035,14 +1036,19 @@ bool Graphics::applyShaderUniforms(id<MTLComputeCommandEncoder> encoder, love::g
|
||||
if (uniformBuffer->getSize() < uniformBufferOffset + size)
|
||||
{
|
||||
size_t newsize = uniformBuffer->getSize() * 2;
|
||||
if (uniformBufferOffset > 0)
|
||||
uniformBuffer->nextFrame();
|
||||
uniformBuffer->release();
|
||||
uniformBuffer = CreateStreamBuffer(device, BUFFERUSAGE_VERTEX, newsize);
|
||||
uniformBuffer = CreateStreamBuffer(device, BUFFERUSAGE_UNIFORM, newsize);
|
||||
uniformBufferData = {};
|
||||
uniformBufferOffset = 0;
|
||||
}
|
||||
|
||||
if (uniformBufferData.data == nullptr)
|
||||
{
|
||||
uniformBufferData = uniformBuffer->map(uniformBuffer->getSize());
|
||||
uniformBufferGPUStart = uniformBuffer->getGPUReadOffset();
|
||||
}
|
||||
|
||||
memcpy(uniformBufferData.data + uniformBufferOffset, bufferdata, size);
|
||||
|
||||
@@ -1050,7 +1056,7 @@ bool Graphics::applyShaderUniforms(id<MTLComputeCommandEncoder> encoder, love::g
|
||||
int uniformindex = Shader::getUniformBufferBinding();
|
||||
|
||||
auto &bindings = renderBindings;
|
||||
setBuffer(encoder, bindings, uniformindex, buffer, uniformBufferOffset);
|
||||
setBuffer(encoder, bindings, uniformindex, buffer, uniformBufferGPUStart + uniformBufferOffset);
|
||||
|
||||
uniformBufferOffset += alignUp(size, alignment);
|
||||
|
||||
@@ -1141,14 +1147,19 @@ void Graphics::applyShaderUniforms(id<MTLRenderCommandEncoder> renderEncoder, lo
|
||||
if (uniformBuffer->getSize() < uniformBufferOffset + size)
|
||||
{
|
||||
size_t newsize = uniformBuffer->getSize() * 2;
|
||||
if (uniformBufferOffset > 0)
|
||||
uniformBuffer->nextFrame();
|
||||
uniformBuffer->release();
|
||||
uniformBuffer = CreateStreamBuffer(device, BUFFERUSAGE_VERTEX, newsize);
|
||||
uniformBuffer = CreateStreamBuffer(device, BUFFERUSAGE_UNIFORM, newsize);
|
||||
uniformBufferData = {};
|
||||
uniformBufferOffset = 0;
|
||||
}
|
||||
|
||||
if (uniformBufferData.data == nullptr)
|
||||
{
|
||||
uniformBufferData = uniformBuffer->map(uniformBuffer->getSize());
|
||||
uniformBufferGPUStart = uniformBuffer->getGPUReadOffset();
|
||||
}
|
||||
|
||||
memcpy(uniformBufferData.data + uniformBufferOffset, bufferdata, size);
|
||||
|
||||
@@ -1156,8 +1167,8 @@ void Graphics::applyShaderUniforms(id<MTLRenderCommandEncoder> renderEncoder, lo
|
||||
int uniformindex = Shader::getUniformBufferBinding();
|
||||
|
||||
auto &bindings = renderBindings;
|
||||
setBuffer(renderEncoder, bindings, SHADERSTAGE_VERTEX, uniformindex, buffer, uniformBufferOffset);
|
||||
setBuffer(renderEncoder, bindings, SHADERSTAGE_PIXEL, uniformindex, buffer, uniformBufferOffset);
|
||||
setBuffer(renderEncoder, bindings, SHADERSTAGE_VERTEX, uniformindex, buffer, uniformBufferGPUStart + uniformBufferOffset);
|
||||
setBuffer(renderEncoder, bindings, SHADERSTAGE_PIXEL, uniformindex, buffer, uniformBufferGPUStart + uniformBufferOffset);
|
||||
|
||||
uniformBufferOffset += alignUp(size, alignment);
|
||||
|
||||
|
||||
@@ -67,6 +67,11 @@ public:
|
||||
}
|
||||
}}
|
||||
|
||||
size_t getGPUReadOffset() const override
|
||||
{
|
||||
return (frameIndex * bufferSize) + frameGPUReadOffset;
|
||||
}
|
||||
|
||||
MapInfo map(size_t /*minsize*/) override
|
||||
{
|
||||
// Make sure this frame's section of the buffer is done being used.
|
||||
|
||||
@@ -63,6 +63,11 @@ public:
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
size_t getGPUReadOffset() const override
|
||||
{
|
||||
return (size_t) data;
|
||||
}
|
||||
|
||||
MapInfo map(size_t /*minsize*/) override
|
||||
{
|
||||
return MapInfo(data, bufferSize);
|
||||
@@ -111,6 +116,11 @@ public:
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
size_t getGPUReadOffset() const override
|
||||
{
|
||||
return frameGPUReadOffset;
|
||||
}
|
||||
|
||||
MapInfo map(size_t /*minsize*/) override
|
||||
{
|
||||
if (orphan)
|
||||
@@ -192,6 +202,11 @@ public:
|
||||
|
||||
virtual ~StreamBufferSync() {}
|
||||
|
||||
size_t getGPUReadOffset() const override
|
||||
{
|
||||
return (frameIndex * bufferSize) + frameGPUReadOffset;
|
||||
}
|
||||
|
||||
void nextFrame() override
|
||||
{
|
||||
// Insert a GPU fence for this frame's section of the data, we'll wait
|
||||
|
||||
@@ -96,6 +96,11 @@ ptrdiff_t StreamBuffer::getHandle() const
|
||||
return (ptrdiff_t) buffer;
|
||||
}
|
||||
|
||||
size_t getGPUReadOffset() const override
|
||||
{
|
||||
return (frameIndex * bufferSize) + frameGPUReadOffset;
|
||||
}
|
||||
|
||||
love::graphics::StreamBuffer::MapInfo StreamBuffer::map(size_t /*minsize*/)
|
||||
{
|
||||
// TODO: do we also need to wait until a fence is complete, here?
|
||||
|
||||
Reference in New Issue
Block a user