1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-01-12 15:31:09 +00:00

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.
This commit is contained in:
Thomas Harte 2020-08-08 17:27:32 -04:00
parent edf41b06fd
commit bdcf266e45
3 changed files with 40 additions and 30 deletions

View File

@ -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);
}

View File

@ -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;

View File

@ -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;