mirror of
https://github.com/GayPizzaSpecifications/padlab.git
synced 2025-08-02 21:00:56 +00:00
metal: fix buffer overwrite flickering
This commit is contained in:
parent
2496f9e2a3
commit
9fd2016999
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,5 +1,6 @@
|
|||||||
.idea/
|
.idea/
|
||||||
cmake-build-*/
|
cmake-build-*/
|
||||||
build/
|
build/
|
||||||
|
xcode/
|
||||||
|
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
@ -43,9 +43,11 @@
|
|||||||
id<MTLRenderPipelineState> _pso;
|
id<MTLRenderPipelineState> _pso;
|
||||||
MTLViewport _viewport;
|
MTLViewport _viewport;
|
||||||
vector_float4 _drawColourF;
|
vector_float4 _drawColourF;
|
||||||
|
dispatch_semaphore_t _inFlightSemaphore;
|
||||||
|
|
||||||
unsigned _vtxListCount, _vtxListReserve, _idxListCount, _idxListReserve;
|
unsigned _vtxListCount[3], _vtxListReserve[3], _idxListCount[3], _idxListReserve[3];
|
||||||
id<MTLBuffer> _vtxMtlBuffer, _idxMtlBuffer;
|
id<MTLBuffer> _vtxMtlBuffer[3], _idxMtlBuffer[3], *_vtxFront, *_idxFront;
|
||||||
|
int _frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id) init:(SDL_Window*)window
|
- (id) init:(SDL_Window*)window
|
||||||
@ -54,10 +56,14 @@
|
|||||||
return nil;
|
return nil;
|
||||||
|
|
||||||
self.drawColour = BLACK;
|
self.drawColour = BLACK;
|
||||||
_vtxListReserve = 0;
|
_vtxListReserve[0] = _vtxListReserve[1] = _vtxListReserve[2] = 0;
|
||||||
_idxListReserve = 0;
|
_idxListReserve[0] = _idxListReserve[1] = _idxListReserve[2] = 0;
|
||||||
_vtxMtlBuffer = nil;
|
_vtxMtlBuffer[0] = _vtxMtlBuffer[1] = _vtxMtlBuffer[2] = nil;
|
||||||
_idxMtlBuffer = nil;
|
_idxMtlBuffer[0] = _idxMtlBuffer[1] = _idxMtlBuffer[2] = nil;
|
||||||
|
_vtxFront = &_vtxMtlBuffer[0];
|
||||||
|
_idxFront = &_idxMtlBuffer[0];
|
||||||
|
_frame = 0;
|
||||||
|
|
||||||
|
|
||||||
// Create Metal view
|
// Create Metal view
|
||||||
_window = window;
|
_window = window;
|
||||||
@ -119,6 +125,9 @@
|
|||||||
// Set viewport
|
// Set viewport
|
||||||
[self setView:[self getDrawSize]];
|
[self setView:[self getDrawSize]];
|
||||||
|
|
||||||
|
// Allow up to 3 frames in-flight
|
||||||
|
_inFlightSemaphore = dispatch_semaphore_create(3);
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,10 +140,10 @@
|
|||||||
|
|
||||||
- (unsigned) resizeBuffer:(id <MTLBuffer>*)buf itemSize:(unsigned)nsz requiredNum:(unsigned)count
|
- (unsigned) resizeBuffer:(id <MTLBuffer>*)buf itemSize:(unsigned)nsz requiredNum:(unsigned)count
|
||||||
{
|
{
|
||||||
unsigned reserve;
|
unsigned long reserve;
|
||||||
if (*buf)
|
if (*buf)
|
||||||
if (count * nsz <= (reserve = [*buf length]))
|
if (count * nsz <= (reserve = [*buf length]))
|
||||||
return reserve;
|
return (unsigned)reserve;
|
||||||
|
|
||||||
// Calculate new capacity
|
// Calculate new capacity
|
||||||
unsigned newCapacity = (count + DRAWLIST_CHUNK_SIZE - 1) / DRAWLIST_CHUNK_SIZE * DRAWLIST_CHUNK_SIZE;
|
unsigned newCapacity = (count + DRAWLIST_CHUNK_SIZE - 1) / DRAWLIST_CHUNK_SIZE * DRAWLIST_CHUNK_SIZE;
|
||||||
@ -185,55 +194,57 @@
|
|||||||
{
|
{
|
||||||
_passDesc.colorAttachments[0].clearColor = MTLClearColorMake(
|
_passDesc.colorAttachments[0].clearColor = MTLClearColorMake(
|
||||||
_drawColourF[0], _drawColourF[1], _drawColourF[2], _drawColourF[3]);
|
_drawColourF[0], _drawColourF[1], _drawColourF[2], _drawColourF[3]);
|
||||||
_vtxListCount = 0;
|
_vtxListCount[_frame] = 0;
|
||||||
_idxListCount = 0;
|
_idxListCount[_frame] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) reserveVertices:(unsigned)count
|
- (void) reserveVertices:(unsigned)count
|
||||||
{
|
{
|
||||||
count += _vtxListCount;
|
count += _vtxListCount[_frame];
|
||||||
if (count * sizeof(ShaderVertex) > _vtxListReserve)
|
if (count * sizeof(ShaderVertex) > _vtxListReserve[_frame])
|
||||||
_vtxListReserve = [self resizeBuffer:&_vtxMtlBuffer itemSize:sizeof(ShaderVertex) requiredNum:count];
|
_vtxListReserve[_frame] = [self resizeBuffer:_vtxFront itemSize:sizeof(ShaderVertex) requiredNum:count];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) reserveIndices:(unsigned)count
|
- (void) reserveIndices:(unsigned)count
|
||||||
{
|
{
|
||||||
count += _idxListCount;
|
count += _idxListCount[_frame];
|
||||||
if (count * sizeof(uint16_t) > _idxListReserve)
|
if (count * sizeof(uint16_t) > _idxListReserve[_frame])
|
||||||
_idxListReserve = [self resizeBuffer:&_idxMtlBuffer itemSize:sizeof(uint16_t) requiredNum:count];
|
_idxListReserve[_frame] = [self resizeBuffer:_idxFront itemSize:sizeof(uint16_t) requiredNum:count];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (uint16_t) queueVertex:(float)x :(float)y
|
- (uint16_t) queueVertex:(float)x :(float)y
|
||||||
{
|
{
|
||||||
if (_vtxListCount * sizeof(ShaderVertex) >= _vtxListReserve)
|
if (_vtxListCount[_frame] * sizeof(ShaderVertex) >= _vtxListReserve[_frame])
|
||||||
[self reserveVertices:1];
|
[self reserveVertices:1];
|
||||||
((ShaderVertex*)_vtxMtlBuffer.contents)[_vtxListCount] = (ShaderVertex){
|
((ShaderVertex*)(*_vtxFront).contents)[_vtxListCount[_frame]] = (ShaderVertex){
|
||||||
.position = { x, y },
|
.position = { x, y },
|
||||||
.colour = _drawColourF };
|
.colour = _drawColourF };
|
||||||
return _vtxListCount++;
|
return _vtxListCount[_frame]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (uint16_t) queueIndex:(uint16_t)idx
|
- (uint16_t) queueIndex:(uint16_t)idx
|
||||||
{
|
{
|
||||||
if (_idxListCount * sizeof(uint16_t) >= _idxListReserve)
|
if (_idxListCount[_frame] * sizeof(uint16_t) >= _idxListReserve[_frame])
|
||||||
[self reserveIndices:1];
|
[self reserveIndices:1];
|
||||||
((uint16_t*)_idxMtlBuffer.contents)[_idxListCount++] = idx;
|
((uint16_t*)(*_idxFront).contents)[_idxListCount[_frame]++] = idx;
|
||||||
return idx;
|
return idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) queueIndices:(uint16_t*)idcs count:(unsigned)count
|
- (void) queueIndices:(uint16_t*)idcs count:(unsigned)count
|
||||||
{
|
{
|
||||||
if ((_idxListCount + count) * sizeof(uint16_t) >= _idxListReserve)
|
if ((_idxListCount[_frame] + count) * sizeof(uint16_t) >= _idxListReserve[_frame])
|
||||||
[self reserveIndices:count];
|
[self reserveIndices:count];
|
||||||
memcpy(&((uint16_t*)_idxMtlBuffer.contents)[_idxListCount], idcs, count * sizeof(uint16_t));
|
memcpy(&((uint16_t*)(*_idxFront).contents)[_idxListCount[_frame]], idcs, count * sizeof(uint16_t));
|
||||||
_idxListCount += count;
|
_idxListCount[_frame] += count;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) present
|
- (void) present
|
||||||
{
|
{
|
||||||
|
dispatch_semaphore_wait(_inFlightSemaphore, DISPATCH_TIME_FOREVER);
|
||||||
|
|
||||||
// Synchronise buffers
|
// Synchronise buffers
|
||||||
[_vtxMtlBuffer didModifyRange:(NSRange){ .location = 0, .length = _vtxListCount * sizeof(ShaderVertex) }];
|
[*_vtxFront didModifyRange:(NSRange){ .location = 0, .length = _vtxListCount[_frame] * sizeof(ShaderVertex) }];
|
||||||
[_idxMtlBuffer didModifyRange:(NSRange){ .location = 0, .length = _idxListCount * sizeof(uint16_t) }];
|
[*_idxFront didModifyRange:(NSRange){ .location = 0, .length = _idxListCount[_frame] * sizeof(uint16_t) }];
|
||||||
|
|
||||||
@autoreleasepool
|
@autoreleasepool
|
||||||
{
|
{
|
||||||
@ -241,29 +252,37 @@
|
|||||||
_passDesc.colorAttachments[0].texture = rt.texture;
|
_passDesc.colorAttachments[0].texture = rt.texture;
|
||||||
|
|
||||||
id<MTLCommandBuffer> cmdBuf = [_queue commandBuffer];
|
id<MTLCommandBuffer> cmdBuf = [_queue commandBuffer];
|
||||||
id<MTLRenderCommandEncoder> enc = [cmdBuf renderCommandEncoderWithDescriptor:_passDesc];
|
[cmdBuf addCompletedHandler:^(id<MTLCommandBuffer> _Nonnull _)
|
||||||
|
{
|
||||||
|
dispatch_semaphore_signal(_inFlightSemaphore);
|
||||||
|
}];
|
||||||
|
|
||||||
|
id<MTLRenderCommandEncoder> enc = [cmdBuf renderCommandEncoderWithDescriptor:_passDesc];
|
||||||
[enc setViewport:_viewport];
|
[enc setViewport:_viewport];
|
||||||
[enc setCullMode:MTLCullModeNone];
|
[enc setCullMode:MTLCullModeNone];
|
||||||
[enc setRenderPipelineState:_pso];
|
[enc setRenderPipelineState:_pso];
|
||||||
|
|
||||||
if (_vtxMtlBuffer && _idxMtlBuffer)
|
if (*_vtxFront && *_idxFront)
|
||||||
{
|
{
|
||||||
[enc setVertexBuffer:_vtxMtlBuffer offset:0 atIndex:ShaderInputIdxVerticies];
|
[enc setVertexBuffer:*_vtxFront offset:0 atIndex:ShaderInputIdxVerticies];
|
||||||
const vector_float2 viewportScale = { (float)(1.0 / _viewport.width), (float)(1.0 / _viewport.height) };
|
const vector_float2 viewportScale = { (float)(1.0 / _viewport.width), (float)(1.0 / _viewport.height) };
|
||||||
[enc setVertexBytes:&viewportScale length:sizeof(vector_float2) atIndex:ShaderInputViewportScale];
|
[enc setVertexBytes:&viewportScale length:sizeof(vector_float2) atIndex:ShaderInputViewportScale];
|
||||||
[enc drawIndexedPrimitives:MTLPrimitiveTypeLine
|
[enc drawIndexedPrimitives:MTLPrimitiveTypeLine
|
||||||
indexCount:_idxListCount indexType:MTLIndexTypeUInt16
|
indexCount:_idxListCount[_frame] indexType:MTLIndexTypeUInt16
|
||||||
indexBuffer:_idxMtlBuffer indexBufferOffset:0];
|
indexBuffer:*_idxFront indexBufferOffset:0];
|
||||||
|
|
||||||
_vtxListCount = 0;
|
_vtxListCount[_frame] = _idxListCount[_frame] = 0;
|
||||||
_idxListCount = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[enc endEncoding];
|
[enc endEncoding];
|
||||||
[cmdBuf presentDrawable:rt];
|
[cmdBuf presentDrawable:rt];
|
||||||
[cmdBuf commit];
|
[cmdBuf commit];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (++_frame == 3)
|
||||||
|
_frame = 0;
|
||||||
|
_vtxFront = &_vtxMtlBuffer[_frame];
|
||||||
|
_idxFront = &_idxMtlBuffer[_frame];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
@ -324,7 +343,7 @@ void DrawRect(int x, int y, int w, int h)
|
|||||||
[renderer reserveVertices:4];
|
[renderer reserveVertices:4];
|
||||||
vector_float2
|
vector_float2
|
||||||
f00 = { x, y }, f10 = { x + w, y },
|
f00 = { x, y }, f10 = { x + w, y },
|
||||||
f01 = { x, y + h}, f11 = { x + w, y + h };
|
f01 = { x, y + h }, f11 = { x + w, y + h };
|
||||||
uint16_t i00 = [renderer queueVertex:f00[0] :f00[1]];
|
uint16_t i00 = [renderer queueVertex:f00[0] :f00[1]];
|
||||||
uint16_t i10 = [renderer queueVertex:f10[0] :f10[1]];
|
uint16_t i10 = [renderer queueVertex:f10[0] :f10[1]];
|
||||||
uint16_t i11 = [renderer queueVertex:f11[0] :f11[1]];
|
uint16_t i11 = [renderer queueVertex:f11[0] :f11[1]];
|
||||||
|
Loading…
Reference in New Issue
Block a user