1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-02-19 07:31:15 +00:00

Makes thread safe.

This commit is contained in:
Thomas Harte 2020-08-15 21:52:55 -04:00
parent 645c29f853
commit 512c0079a9

View File

@ -99,6 +99,14 @@ using BufferingScanTarget = Outputs::Display::BufferingScanTarget;
// Set initial aspect-ratio multiplier. // Set initial aspect-ratio multiplier.
_view = view; _view = view;
[self mtkView:view drawableSizeWillChange:view.drawableSize]; [self mtkView:view drawableSizeWillChange:view.drawableSize];
// Generate copy pipeline.
id<MTLLibrary> library = [_view.device newDefaultLibrary];
MTLRenderPipelineDescriptor *const pipelineDescriptor = [[MTLRenderPipelineDescriptor alloc] init];
pipelineDescriptor.colorAttachments[0].pixelFormat = _view.colorPixelFormat;
pipelineDescriptor.vertexFunction = [library newFunctionWithName:@"copyVertex"];
pipelineDescriptor.fragmentFunction = [library newFunctionWithName:@"copyFragment"];
_copyPipeline = [_view.device newRenderPipelineStateWithDescriptor:pipelineDescriptor error:nil];
} }
return self; return self;
@ -119,20 +127,22 @@ using BufferingScanTarget = Outputs::Display::BufferingScanTarget;
// TODO: attach a stencil buffer. // TODO: attach a stencil buffer.
// Generate a framebuffer and a pipeline that targets it. @synchronized(self) {
MTLTextureDescriptor *const textureDescriptor = [MTLTextureDescriptor // Generate a framebuffer and a pipeline that targets it.
texture2DDescriptorWithPixelFormat:view.colorPixelFormat MTLTextureDescriptor *const textureDescriptor = [MTLTextureDescriptor
width:NSUInteger(size.width * view.layer.contentsScale) texture2DDescriptorWithPixelFormat:view.colorPixelFormat
height:NSUInteger(size.height * view.layer.contentsScale) width:NSUInteger(size.width * view.layer.contentsScale)
mipmapped:NO]; height:NSUInteger(size.height * view.layer.contentsScale)
textureDescriptor.usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead; mipmapped:NO];
textureDescriptor.resourceOptions = MTLResourceStorageModePrivate; textureDescriptor.usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead;
_frameBuffer = [view.device newTextureWithDescriptor:textureDescriptor]; textureDescriptor.resourceOptions = MTLResourceStorageModePrivate;
_frameBuffer = [view.device newTextureWithDescriptor:textureDescriptor];
_frameBufferRenderPass = [[MTLRenderPassDescriptor alloc] init]; _frameBufferRenderPass = [[MTLRenderPassDescriptor alloc] init];
_frameBufferRenderPass.colorAttachments[0].texture = _frameBuffer; _frameBufferRenderPass.colorAttachments[0].texture = _frameBuffer;
_frameBufferRenderPass.colorAttachments[0].loadAction = MTLLoadActionLoad; _frameBufferRenderPass.colorAttachments[0].loadAction = MTLLoadActionLoad;
_frameBufferRenderPass.colorAttachments[0].storeAction = MTLStoreActionStore; _frameBufferRenderPass.colorAttachments[0].storeAction = MTLStoreActionStore;
}
} }
- (void)setAspectRatio { - (void)setAspectRatio {
@ -248,17 +258,6 @@ using BufferingScanTarget = Outputs::Display::BufferingScanTarget;
pipelineDescriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha; pipelineDescriptor.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
_scanPipeline = [_view.device newRenderPipelineStateWithDescriptor:pipelineDescriptor error:nil]; _scanPipeline = [_view.device newRenderPipelineStateWithDescriptor:pipelineDescriptor error:nil];
//
// Generate copy pipeline.
//
pipelineDescriptor = [[MTLRenderPipelineDescriptor alloc] init];
pipelineDescriptor.colorAttachments[0].pixelFormat = _view.colorPixelFormat;
pipelineDescriptor.vertexFunction = [library newFunctionWithName:@"copyVertex"];
pipelineDescriptor.fragmentFunction = [library newFunctionWithName:@"copyFragment"];
_copyPipeline = [_view.device newRenderPipelineStateWithDescriptor:pipelineDescriptor error:nil];
} }
- (void)checkModals { - (void)checkModals {
@ -271,64 +270,64 @@ using BufferingScanTarget = Outputs::Display::BufferingScanTarget;
}); });
} }
//- (void)updateFrameBuffer {
//}
- (void)updateFrameBuffer { - (void)updateFrameBuffer {
[self checkModals]; [self checkModals];
if(!_frameBufferRenderPass) return;
// Generate a command encoder for the view. @synchronized(self) {
id<MTLCommandBuffer> commandBuffer = [_commandQueue commandBuffer]; if(!_frameBufferRenderPass) return;
id<MTLRenderCommandEncoder> encoder = [commandBuffer renderCommandEncoderWithDescriptor:_frameBufferRenderPass];
// Drawing. Just scans. // Generate a command encoder for the view.
[encoder setRenderPipelineState:_scanPipeline]; id<MTLCommandBuffer> commandBuffer = [_commandQueue commandBuffer];
id<MTLRenderCommandEncoder> encoder = [commandBuffer renderCommandEncoderWithDescriptor:_frameBufferRenderPass];
[encoder setFragmentTexture:_writeAreaTexture atIndex:0]; // Drawing. Just scans.
[encoder setVertexBuffer:_scansBuffer offset:0 atIndex:0]; [encoder setRenderPipelineState:_scanPipeline];
[encoder setVertexBuffer:_uniformsBuffer offset:0 atIndex:1];
[encoder setFragmentBuffer:_uniformsBuffer offset:0 atIndex:0];
const auto outputArea = _scanTarget.get_output_area(); [encoder setFragmentTexture:_writeAreaTexture atIndex:0];
[encoder setVertexBuffer:_scansBuffer offset:0 atIndex:0];
[encoder setVertexBuffer:_uniformsBuffer offset:0 atIndex:1];
[encoder setFragmentBuffer:_uniformsBuffer offset:0 atIndex:0];
// Ensure texture changes are noted. const auto outputArea = _scanTarget.get_output_area();
const auto writeAreaModificationStart = size_t(outputArea.start.write_area_x + outputArea.start.write_area_y * 2048) * _bytesPerInputPixel;
const auto writeAreaModificationEnd = size_t(outputArea.end.write_area_x + outputArea.end.write_area_y * 2048) * _bytesPerInputPixel; // Ensure texture changes are noted.
if(writeAreaModificationStart != writeAreaModificationEnd) { const auto writeAreaModificationStart = size_t(outputArea.start.write_area_x + outputArea.start.write_area_y * 2048) * _bytesPerInputPixel;
if(writeAreaModificationStart < writeAreaModificationEnd) { const auto writeAreaModificationEnd = size_t(outputArea.end.write_area_x + outputArea.end.write_area_y * 2048) * _bytesPerInputPixel;
[_writeAreaBuffer didModifyRange:NSMakeRange(writeAreaModificationStart, writeAreaModificationEnd - writeAreaModificationStart)]; if(writeAreaModificationStart != writeAreaModificationEnd) {
} else { if(writeAreaModificationStart < writeAreaModificationEnd) {
[_writeAreaBuffer didModifyRange:NSMakeRange(writeAreaModificationStart, _totalTextureBytes - writeAreaModificationStart)]; [_writeAreaBuffer didModifyRange:NSMakeRange(writeAreaModificationStart, writeAreaModificationEnd - writeAreaModificationStart)];
if(writeAreaModificationEnd) { } else {
[_writeAreaBuffer didModifyRange:NSMakeRange(0, writeAreaModificationEnd)]; [_writeAreaBuffer didModifyRange:NSMakeRange(writeAreaModificationStart, _totalTextureBytes - writeAreaModificationStart)];
if(writeAreaModificationEnd) {
[_writeAreaBuffer didModifyRange:NSMakeRange(0, writeAreaModificationEnd)];
}
}
}
// TEMPORARY: just draw the scans.
if(outputArea.start.scan != outputArea.end.scan) {
if(outputArea.start.scan < outputArea.end.scan) {
[encoder drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:4 instanceCount:outputArea.end.scan - outputArea.start.scan baseInstance:outputArea.start.scan];
} else {
[encoder drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:4 instanceCount:NumBufferedScans - outputArea.start.scan baseInstance:outputArea.start.scan];
if(outputArea.end.scan) {
[encoder drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:4 instanceCount:outputArea.end.scan];
}
} }
} }
// Complete encoding.
[encoder endEncoding];
// Add a callback to update the buffer.
[commandBuffer addCompletedHandler:^(id<MTLCommandBuffer> _Nonnull) {
self->_scanTarget.complete_output_area(outputArea);
}];
// Commit the drawing.
[commandBuffer commit];
} }
// TEMPORARY: just draw the scans.
if(outputArea.start.scan != outputArea.end.scan) {
if(outputArea.start.scan < outputArea.end.scan) {
[encoder drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:4 instanceCount:outputArea.end.scan - outputArea.start.scan baseInstance:outputArea.start.scan];
} else {
[encoder drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:4 instanceCount:NumBufferedScans - outputArea.start.scan baseInstance:outputArea.start.scan];
if(outputArea.end.scan) {
[encoder drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:4 instanceCount:outputArea.end.scan];
}
}
}
// Complete encoding.
[encoder endEncoding];
// Add a callback to update the buffer.
[commandBuffer addCompletedHandler:^(id<MTLCommandBuffer> _Nonnull) {
self->_scanTarget.complete_output_area(outputArea);
}];
// Commit the drawing.
[commandBuffer commit];
} }
/*! /*!
@ -337,9 +336,6 @@ using BufferingScanTarget = Outputs::Display::BufferingScanTarget;
@discussion Called on the delegate when it is asked to render into the view @discussion Called on the delegate when it is asked to render into the view
*/ */
- (void)drawInMTKView:(nonnull MTKView *)view { - (void)drawInMTKView:(nonnull MTKView *)view {
[self checkModals];
// [self updateFrameBuffer];
// Schedule a copy from the current framebuffer to the view; blitting is unavailable as the target is a framebuffer texture. // Schedule a copy from the current framebuffer to the view; blitting is unavailable as the target is a framebuffer texture.
id<MTLCommandBuffer> commandBuffer = [_commandQueue commandBuffer]; id<MTLCommandBuffer> commandBuffer = [_commandQueue commandBuffer];
id<MTLRenderCommandEncoder> encoder = [commandBuffer renderCommandEncoderWithDescriptor:view.currentRenderPassDescriptor]; id<MTLRenderCommandEncoder> encoder = [commandBuffer renderCommandEncoderWithDescriptor:view.currentRenderPassDescriptor];