From bdcf266e45ba045218cd4796d3bade14c7537235 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 8 Aug 2020 17:27:32 -0400 Subject: [PATCH] Having learnt a bit more: eliminates Metal `attribute` tags, switches to more natural expression of structs. Also thereby eliminates the need for a forced alignas(4) on various structs. --- .../Clock Signal/ScanTarget/ScanTarget.metal | 58 +++++++++++-------- Outputs/ScanTarget.hpp | 6 +- Outputs/ScanTargets/BufferingScanTarget.hpp | 6 +- 3 files changed, 40 insertions(+), 30 deletions(-) diff --git a/OSBindings/Mac/Clock Signal/ScanTarget/ScanTarget.metal b/OSBindings/Mac/Clock Signal/ScanTarget/ScanTarget.metal index dd839dbc5..b75921fde 100644 --- a/OSBindings/Mac/Clock Signal/ScanTarget/ScanTarget.metal +++ b/OSBindings/Mac/Clock Signal/ScanTarget/ScanTarget.metal @@ -12,31 +12,43 @@ using namespace metal; struct Uniforms { // This is used to scale scan positions, i.e. it provides the range // for mapping from scan-style integer positions into eye space. - int2 scale [[attribute(0)]]; + int2 scale; // This provides the intended height of a scan, in eye-coordinate terms. - float lineWidth [[attribute(1)]]; + float lineWidth; // Provides a scaling factor in order to preserve 4:3 central content. - float aspectRatioMultiplier [[attribute(2)]]; + float aspectRatioMultiplier; }; -// This is intended to match `Scan` as defined by the BufferingScanTarget. -// Fields have been combined as necessary to make them all at least four -// bytes in size, since that is the required attribute alignment in Swift. +// This is intended to match the net effect of `Scan` as defined by the BufferingScanTarget. struct Scan { - uint32_t startPosition [[attribute(0)]]; - uint32_t startOffsetAndAngle [[attribute(1)]]; - uint32_t startCycles [[attribute(2)]]; + struct EndPoint { + uint16_t position[2]; + uint16_t dataOffset; + uint16_t compositeAngle; + uint16_t cyclesSinceRetrace; + } endPoints[2]; - uint32_t endPosition [[attribute(3)]]; - uint32_t endOffsetAndAngle [[attribute(4)]]; - uint32_t endCycles [[attribute(5)]]; - - uint32_t compositeAmplitude [[attribute(6)]]; - uint32_t dataYAndLine [[attribute(7)]]; + uint8_t compositeAmplitude; + uint16_t dataY; + uint16_t line; }; +// This matches the BufferingScanTarget's `Line`. +struct Line { + struct EndPoint { + uint16_t position[2]; + uint16_t cyclesSinceRetrace; + uint16_t compositeAngle; + } endPoints[2]; + + uint16_t line; + uint8_t compositeAmplitude; +}; + + +// This is an intermediate struct, which is TEMPORARY. struct ColouredVertex { float4 position [[position]]; }; @@ -48,21 +60,21 @@ vertex ColouredVertex scanVertexMain( constant Uniforms &uniforms [[buffer(1)]], constant Scan *scans [[buffer(0)]], uint instanceID [[instance_id]], uint vertexID [[vertex_id]]) { - // Unpack start and end vertices; little-endian numbers are assumed here. + // Get start and end vertices in regular float2 form. const float2 start = float2( - float(scans[instanceID].startPosition & 0xffff) / float(uniforms.scale.x), - float(scans[instanceID].startPosition >> 16) / float(uniforms.scale.y) + float(scans[instanceID].endPoints[0].position[0]) / float(uniforms.scale.x), + float(scans[instanceID].endPoints[0].position[1]) / float(uniforms.scale.y) ); const float2 end = float2( - float(scans[instanceID].endPosition & 0xffff) / float(uniforms.scale.x), - float(scans[instanceID].endPosition >> 16) / float(uniforms.scale.y) + float(scans[instanceID].endPoints[1].position[0]) / float(uniforms.scale.x), + float(scans[instanceID].endPoints[1].position[1]) / float(uniforms.scale.y) ); // Calculate the tangent and normal. const float2 tangent = (end - start); const float2 normal = float2(-tangent.y, tangent.x) / length(tangent); - // Hence determine this quad's real shape. + // Hence determine this quad's real shape, using vertexID to pick a corner. ColouredVertex output; output.position = float4( ((start + (float(vertexID&2) * 0.5) * tangent + (float(vertexID&1) - 0.5) * normal * uniforms.lineWidth) * float2(2.0, -2.0) + float2(-1.0, 1.0)) * float2(uniforms.aspectRatioMultiplier, 1.0), @@ -72,6 +84,6 @@ vertex ColouredVertex scanVertexMain( constant Uniforms &uniforms [[buffer(1)]], return output; } -fragment float4 scanFragmentMain(ColouredVertex vert [[stage_in]]) { - return float4(1.0); +fragment half4 scanFragmentMain(ColouredVertex vert [[stage_in]]) { + return half4(1.0); } diff --git a/Outputs/ScanTarget.hpp b/Outputs/ScanTarget.hpp index 0765eef46..63be212d1 100644 --- a/Outputs/ScanTarget.hpp +++ b/Outputs/ScanTarget.hpp @@ -210,11 +210,9 @@ struct ScanTarget { /*! Defines a scan in terms of its two endpoints. - - Is guaranteed to be a multiple of four bytes in size. */ - struct alignas(4) Scan { - struct alignas(4) EndPoint { + struct Scan { + struct EndPoint { /// Provide the coordinate of this endpoint. These are fixed point, purely fractional /// numbers, relative to the scale provided in the Modals. uint16_t x, y; diff --git a/Outputs/ScanTargets/BufferingScanTarget.hpp b/Outputs/ScanTargets/BufferingScanTarget.hpp index 51a7fb6d3..85d186c68 100644 --- a/Outputs/ScanTargets/BufferingScanTarget.hpp +++ b/Outputs/ScanTargets/BufferingScanTarget.hpp @@ -50,7 +50,7 @@ class BufferingScanTarget: public Outputs::Display::ScanTarget { // Extends the definition of a Scan to include two extra fields, // completing this scan's source data and destination locations. - struct alignas(4) Scan { + struct Scan { Outputs::Display::ScanTarget::Scan scan; /// Stores the y coordinate for this scan's data within the write area texture. @@ -65,8 +65,8 @@ class BufferingScanTarget: public Outputs::Display::ScanTarget { /// Defines the boundaries of a complete line of video — a 2d start and end location, /// composite phase and amplitude (if relevant), the source line in the intermediate buffer /// plus the start and end offsets of the area that is visible from the intermediate buffer. - struct alignas(4) Line { - struct alignas(4) EndPoint { + struct Line { + struct EndPoint { uint16_t x, y; uint16_t cycles_since_end_of_horizontal_retrace; int16_t composite_angle;