1
0
mirror of https://github.com/TomHarte/CLK.git synced 2026-04-19 19:16:34 +00:00

Attempt full combination pipeline.

This commit is contained in:
Thomas Harte
2026-02-23 11:42:40 -05:00
parent 56246427da
commit a69b7a0884
2 changed files with 76 additions and 18 deletions
@@ -169,11 +169,13 @@ using BufferingScanTarget = Outputs::Display::BufferingScanTarget;
id<MTLCommandQueue> _commandQueue;
// Pipelines.
id<MTLRenderPipelineState> _composePipeline; // Renders to the composition texture.
id<MTLRenderPipelineState> _outputPipeline; // Draws to the frame buffer.
id<MTLRenderPipelineState> _copyPipeline; // Copies from one texture to another.
id<MTLRenderPipelineState> _supersamplePipeline; // Resamples from one texture to one that is 1/4 as large.
id<MTLRenderPipelineState> _clearPipeline; // Applies additional inter-frame clearing (cf. the stencil).
id<MTLRenderPipelineState> _composePipeline; // Renders to the composition texture.
id<MTLRenderPipelineState> _outputPipeline; // Draws to the frame buffer.
id<MTLRenderPipelineState> _copyPipeline; // Copies from one texture to another.
id<MTLRenderPipelineState> _supersampleCopyPipeline; // Resamples from one texture to one that is 1/4 as large.
id<MTLRenderPipelineState> _mixPipeline; // Combines two textures, mixing them 50:50.
id<MTLRenderPipelineState> _supersampleMixPipeline; // Resamples and combines two textures.
id<MTLRenderPipelineState> _clearPipeline; // Applies additional inter-frame clearing (cf. the stencil).
// Buffers.
id<MTLBuffer> _uniformsBuffer; // A static buffer, containing a copy of the Uniforms struct.
@@ -311,8 +313,14 @@ using BufferingScanTarget = Outputs::Display::BufferingScanTarget;
pipelineDescriptor.fragmentFunction = [library newFunctionWithName:@"copyFragment"];
_copyPipeline = [_view.device newRenderPipelineStateWithDescriptor:pipelineDescriptor error:nil];
pipelineDescriptor.fragmentFunction = [library newFunctionWithName:@"interpolateFragment"];
_supersamplePipeline = [_view.device newRenderPipelineStateWithDescriptor:pipelineDescriptor error:nil];
pipelineDescriptor.fragmentFunction = [library newFunctionWithName:@"interpolateCopyFragment"];
_supersampleCopyPipeline = [_view.device newRenderPipelineStateWithDescriptor:pipelineDescriptor error:nil];
pipelineDescriptor.fragmentFunction = [library newFunctionWithName:@"mixFragment"];
_mixPipeline = [_view.device newRenderPipelineStateWithDescriptor:pipelineDescriptor error:nil];
pipelineDescriptor.fragmentFunction = [library newFunctionWithName:@"interpolateMixFragment"];
_supersampleMixPipeline = [_view.device newRenderPipelineStateWithDescriptor:pipelineDescriptor error:nil];
pipelineDescriptor.fragmentFunction = [library newFunctionWithName:@"clearFragment"];
pipelineDescriptor.stencilAttachmentPixelFormat = MTLPixelFormatStencil8;
@@ -729,7 +737,7 @@ using BufferingScanTarget = Outputs::Display::BufferingScanTarget;
[library newFunctionWithName:_pipeline == Pipeline::DirectToDisplay ? @"scanToDisplay" : @"lineToDisplay"];
if(_pipeline != Pipeline::DirectToDisplay) {
pipelineDescriptor.fragmentFunction = [library newFunctionWithName:@"interpolateFragment"];
pipelineDescriptor.fragmentFunction = [library newFunctionWithName:@"interpolateCopyFragment"];
} else {
const bool isRGBOutput = modals.display_type == Outputs::Display::DisplayType::RGB;
pipelineDescriptor.fragmentFunction = fragment_function(
@@ -899,17 +907,39 @@ using BufferingScanTarget = Outputs::Display::BufferingScanTarget;
// Every pixel will be drawn, so don't clear or reload.
view.currentRenderPassDescriptor.colorAttachments[0].loadAction = MTLLoadActionDontCare;
id<MTLRenderCommandEncoder> encoder =
[commandBuffer renderCommandEncoderWithDescriptor:view.currentRenderPassDescriptor];
// TODO: differnet copy phase if weave deinterlacing.
[encoder setRenderPipelineState:_isUsingSupersampling ? _supersamplePipeline : _copyPipeline];
[encoder setVertexTexture:_frameBuffers[_fieldIndex] atIndex:0];
[encoder setFragmentTexture:_frameBuffers[_fieldIndex] atIndex:0];
{
id<MTLRenderCommandEncoder> encoder =
[commandBuffer renderCommandEncoderWithDescriptor:view.currentRenderPassDescriptor];
[encoder drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:4];
[encoder endEncoding];
encoder = nil;
[encoder setRenderPipelineState:
_isUsingSupersampling ?
(_isInterlaced ? _supersampleMixPipeline : _supersampleCopyPipeline) :
(_isInterlaced ? _mixPipeline : _copyPipeline)
];
[encoder setVertexTexture:_frameBuffers[0] atIndex:0];
[encoder setFragmentTexture:_frameBuffers[0] atIndex:0];
[encoder setVertexTexture:_frameBuffers[1] atIndex:1];
[encoder setFragmentTexture:_frameBuffers[1] atIndex:1];
[encoder drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:4];
[encoder endEncoding];
encoder = nil;
}
// if(_isInterlaced) {
// id<MTLRenderCommandEncoder> encoder =
// [commandBuffer renderCommandEncoderWithDescriptor:view.currentRenderPassDescriptor];
//
// [encoder setRenderPipelineState:_isUsingSupersampling ? _supersampleAddPipeline : _addPipeline];
// [encoder setVertexTexture:_frameBuffers[1] atIndex:0];
// [encoder setFragmentTexture:_frameBuffers[1] atIndex:0];
//
// [encoder drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:4];
// [encoder endEncoding];
// encoder = nil;
// }
[commandBuffer presentDrawable:view.currentDrawable];
[commandBuffer addCompletedHandler:^(id<MTLCommandBuffer> _Nonnull) {
@@ -34,13 +34,41 @@ fragment half4 copyFragment(
}
/// Bilinearly samples @c texture.
fragment half4 interpolateFragment(
fragment half4 interpolateCopyFragment(
const CopyInterpolator vert [[stage_in]],
const metal::texture2d<half> texture [[texture(0)]]
) {
return texture.sample(linearSampler, vert.textureCoordinates);
}
/// Point-samples @c texture to copy directly from source to target.
fragment half4 mixFragment(
const CopyInterpolator vert [[stage_in]],
const metal::texture2d<half> texture1 [[texture(0)]],
const metal::texture2d<half> texture2 [[texture(1)]]
) {
return
metal::mix(
texture1.sample(nearestSampler, vert.textureCoordinates),
texture2.sample(nearestSampler, vert.textureCoordinates),
0.5
);
}
/// Bilinearly samples @c texture.
fragment half4 interpolateMixFragment(
const CopyInterpolator vert [[stage_in]],
const metal::texture2d<half> texture1 [[texture(0)]],
const metal::texture2d<half> texture2 [[texture(1)]]
) {
return
metal::mix(
texture1.sample(linearSampler, vert.textureCoordinates),
texture2.sample(linearSampler, vert.textureCoordinates),
0.5
);
}
/// Fills with black.
fragment half4 clearFragment(
const constant Uniforms &uniforms [[buffer(0)]]