From d54b937ab6668ad8b0801933377b4c30cf69be2b Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Fri, 21 Aug 2020 21:11:25 -0400 Subject: [PATCH] Starts trying to do actual composite processing. --- .../Clock Signal/ScanTarget/CSScanTarget.mm | 21 ++++++++++++--- .../Clock Signal/ScanTarget/ScanTarget.metal | 27 +++++++++++++++++++ 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/OSBindings/Mac/Clock Signal/ScanTarget/CSScanTarget.mm b/OSBindings/Mac/Clock Signal/ScanTarget/CSScanTarget.mm index 8dd3c08e4..e64723934 100644 --- a/OSBindings/Mac/Clock Signal/ScanTarget/CSScanTarget.mm +++ b/OSBindings/Mac/Clock Signal/ScanTarget/CSScanTarget.mm @@ -8,9 +8,12 @@ #import "CSScanTarget.h" -#include #import + +#include + #include "BufferingScanTarget.hpp" +#include "FIRFilter.hpp" namespace { @@ -22,6 +25,7 @@ struct Uniforms { simd::float3x3 fromRGB; float zoom; simd::float2 offset; + float firCoefficients[8]; }; constexpr size_t NumBufferedScans = 2048; @@ -355,9 +359,8 @@ using BufferingScanTarget = Outputs::Display::BufferingScanTarget; #endif // Build the composition pipeline if one is in use. + const bool isSVideoOutput = modals.display_type == Outputs::Display::DisplayType::SVideo; if(_isUsingCompositionPipeline) { - const bool isSVideoOutput = modals.display_type == Outputs::Display::DisplayType::SVideo; - pipelineDescriptor.colorAttachments[0].pixelFormat = _compositionTexture.pixelFormat; pipelineDescriptor.vertexFunction = [library newFunctionWithName:@"scanToComposition"]; pipelineDescriptor.fragmentFunction = @@ -371,6 +374,15 @@ using BufferingScanTarget = Outputs::Display::BufferingScanTarget; _compositionRenderPass.colorAttachments[0].storeAction = MTLStoreActionStore; // TODO: set proper clear colour for S-Video. + + // TODO: work out fir coefficients, for real. + const float cyclesPerLine = float(modals.cycles_per_line); + const float colourCyclesPerLine = float(modals.colour_cycle_numerator) / float(modals.colour_cycle_denominator); + SignalProcessing::FIRFilter filter(15, cyclesPerLine, 0.0f, 16.0f * cyclesPerLine / colourCyclesPerLine); + + float *const firCoefficients = uniforms()->firCoefficients; + const auto calculatedCoefficients = filter.get_coefficients(); + memcpy(firCoefficients, calculatedCoefficients.data(), calculatedCoefficients.size() * sizeof(float)); } // Build the output pipeline. @@ -378,7 +390,8 @@ using BufferingScanTarget = Outputs::Display::BufferingScanTarget; pipelineDescriptor.vertexFunction = [library newFunctionWithName:_isUsingCompositionPipeline ? @"lineToDisplay" : @"scanToDisplay"]; if(_isUsingCompositionPipeline) { - pipelineDescriptor.fragmentFunction = [library newFunctionWithName:@"sampleRed8Green8Blue8"]; + // TODO! + pipelineDescriptor.fragmentFunction = [library newFunctionWithName:@"convertComposite"]; } else { const bool isRGBOutput = modals.display_type == Outputs::Display::DisplayType::RGB; pipelineDescriptor.fragmentFunction = diff --git a/OSBindings/Mac/Clock Signal/ScanTarget/ScanTarget.metal b/OSBindings/Mac/Clock Signal/ScanTarget/ScanTarget.metal index 3e0ed2cd5..0308260d0 100644 --- a/OSBindings/Mac/Clock Signal/ScanTarget/ScanTarget.metal +++ b/OSBindings/Mac/Clock Signal/ScanTarget/ScanTarget.metal @@ -30,6 +30,10 @@ struct Uniforms { // Provides zoom and offset to scale the source data. float zoom; float2 offset; + + // Describes the FIR filter in use; it'll be 15 coefficients but they're + // symmetrical around the centre. + float firCoefficients[8]; }; namespace { @@ -311,3 +315,26 @@ fragment float4 copyFragment(CopyInterpolator vert [[stage_in]], texture2d texture [[texture(0)]], constant Uniforms &uniforms [[buffer(0)]]) { + const float3 colour = + uniforms.firCoefficients[0] * texture.sample(standardSampler, vert.textureCoordinates - float2(7.0, 0.0)).rgb + + uniforms.firCoefficients[1] * texture.sample(standardSampler, vert.textureCoordinates - float2(6.0, 0.0)).rgb + + uniforms.firCoefficients[2] * texture.sample(standardSampler, vert.textureCoordinates - float2(5.0, 0.0)).rgb + + uniforms.firCoefficients[3] * texture.sample(standardSampler, vert.textureCoordinates - float2(4.0, 0.0)).rgb + + uniforms.firCoefficients[4] * texture.sample(standardSampler, vert.textureCoordinates - float2(3.0, 0.0)).rgb + + uniforms.firCoefficients[5] * texture.sample(standardSampler, vert.textureCoordinates - float2(2.0, 0.0)).rgb + + uniforms.firCoefficients[6] * texture.sample(standardSampler, vert.textureCoordinates - float2(1.0, 0.0)).rgb + + uniforms.firCoefficients[7] * texture.sample(standardSampler, vert.textureCoordinates).rgb + + uniforms.firCoefficients[6] * texture.sample(standardSampler, vert.textureCoordinates + float2(1.0, 0.0)).rgb + + uniforms.firCoefficients[5] * texture.sample(standardSampler, vert.textureCoordinates + float2(2.0, 0.0)).rgb + + uniforms.firCoefficients[4] * texture.sample(standardSampler, vert.textureCoordinates + float2(3.0, 0.0)).rgb + + uniforms.firCoefficients[3] * texture.sample(standardSampler, vert.textureCoordinates + float2(4.0, 0.0)).rgb + + uniforms.firCoefficients[2] * texture.sample(standardSampler, vert.textureCoordinates + float2(5.0, 0.0)).rgb + + uniforms.firCoefficients[1] * texture.sample(standardSampler, vert.textureCoordinates + float2(6.0, 0.0)).rgb + + uniforms.firCoefficients[0] * texture.sample(standardSampler, vert.textureCoordinates + float2(7.0, 0.0)).rgb; + + return float4(colour, 1.0); +}