1
0
mirror of https://github.com/TomHarte/CLK.git synced 2026-03-13 02:42:08 +00:00

Attempt a line output shader.

This commit is contained in:
Thomas Harte
2026-02-04 14:41:34 -05:00
parent d5fa5d4dd4
commit 65ebcd9c99
8 changed files with 187 additions and 0 deletions

View File

@@ -1237,6 +1237,7 @@
4BF0BC722973318E00CCA2B5 /* RP5C01.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF0BC6F2973318E00CCA2B5 /* RP5C01.cpp */; };
4BF437EE209D0F7E008CBD6B /* SegmentParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF437EC209D0F7E008CBD6B /* SegmentParser.cpp */; };
4BF437EF209D0F7E008CBD6B /* SegmentParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF437EC209D0F7E008CBD6B /* SegmentParser.cpp */; };
4BF64D672F33D27B001EB900 /* LineOutputShader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF64D662F33D27B001EB900 /* LineOutputShader.cpp */; };
4BF701A026FFD32300996424 /* AmigaBlitterTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BF7019F26FFD32300996424 /* AmigaBlitterTests.mm */; };
4BF8D4C82516E27A00BBE21B /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BB8617024E22F4900A00E03 /* Accelerate.framework */; };
4BF8D4D5251C11DD00BBE21B /* 65816Storage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF8D4D4251C11DD00BBE21B /* 65816Storage.cpp */; };
@@ -2577,6 +2578,8 @@
4BF437F0209D112F008CBD6B /* Sector.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Sector.hpp; sourceTree = "<group>"; };
4BF4A2D91F534DB300B171F4 /* TargetPlatforms.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = TargetPlatforms.hpp; sourceTree = "<group>"; };
4BF52672218E752E00313227 /* ScanTarget.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ScanTarget.hpp; sourceTree = "<group>"; };
4BF64D652F33D27B001EB900 /* LineOutputShader.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = LineOutputShader.hpp; sourceTree = "<group>"; };
4BF64D662F33D27B001EB900 /* LineOutputShader.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = LineOutputShader.cpp; sourceTree = "<group>"; };
4BF6606A1F281573002CB053 /* ClockReceiver.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ClockReceiver.hpp; sourceTree = "<group>"; };
4BF7019F26FFD32300996424 /* AmigaBlitterTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = AmigaBlitterTests.mm; sourceTree = "<group>"; };
4BF8D4CD251C0C9C00BBE21B /* 65816.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = 65816.hpp; sourceTree = "<group>"; };
@@ -5411,12 +5414,14 @@
4BD235BF2F312C0C0094AFAE /* CompositionShader.cpp */,
4BD235C12F312C0C0094AFAE /* CopyShader.cpp */,
4BD235CB2F32A4C80094AFAE /* KernelShaders.cpp */,
4BF64D662F33D27B001EB900 /* LineOutputShader.cpp */,
4BD235C62F312C3A0094AFAE /* Rectangle.cpp */,
4BD235C92F32A2780094AFAE /* CommonAtrributes.hpp */,
4BD235BE2F312C0C0094AFAE /* CompositionShader.hpp */,
4BD235C02F312C0C0094AFAE /* CopyShader.hpp */,
4BD235C82F326A280094AFAE /* DirtyZone.hpp */,
4BD235CA2F32A4C80094AFAE /* KernelShaders.hpp */,
4BF64D652F33D27B001EB900 /* LineOutputShader.hpp */,
4BD235C52F312C3A0094AFAE /* Rectangle.hpp */,
);
path = Shaders;
@@ -6502,6 +6507,7 @@
4B302185208A550100773308 /* DiskII.cpp in Sources */,
42EB81292B23AAC300429AF4 /* IMD.cpp in Sources */,
4B051CB1267C1CA200CA44E8 /* Keyboard.cpp in Sources */,
4BF64D672F33D27B001EB900 /* LineOutputShader.cpp in Sources */,
4B8855A72E84D51B00E251DD /* SAA5050.cpp in Sources */,
4B0F1BB32602645900B85C66 /* StaticAnalyser.cpp in Sources */,
4B055A931FAE85B50060FFFF /* BinaryDump.cpp in Sources */,

View File

@@ -14,6 +14,7 @@
#include "Outputs/OpenGL/Shaders/CompositionShader.hpp"
#include "Outputs/OpenGL/Shaders/CopyShader.hpp"
#include "Outputs/OpenGL/Shaders/KernelShaders.hpp"
#include "Outputs/OpenGL/Shaders/LineOutputShader.hpp"
#include <algorithm>
#include <cassert>
@@ -127,6 +128,7 @@ ScanTarget::ScanTarget(const API api, const GLuint target_framebuffer, const flo
unprocessed_line_texture_(api, LineBufferWidth, LineBufferHeight, UnprocessedLineBufferTextureUnit, GL_NEAREST, false),
full_display_rectangle_(api, -1.0f, -1.0f, 2.0f, 2.0f),
scans_(scan_buffer_),
lines_(line_buffer_),
dirty_zones_(dirty_zones_buffer_) {
set_scan_buffer(scan_buffer_.data(), scan_buffer_.size());
@@ -327,8 +329,18 @@ void ScanTarget::setup_pipeline() {
dirty_zones_,
is_svideo(modals.display_type) ? CompositionTextureUnit : SeparationTextureUnit
);
line_output_shader_ = OpenGL::line_output_shader(
api_,
buffer_width, 2048,
modals.expected_vertical_lines,
modals.output_scale.x, modals.output_scale.y,
lines_,
DemodulationTextureUnit
);
} else {
demodulation_shader_.reset();
line_output_shader_.reset();
}
}

View File

@@ -164,6 +164,7 @@ private:
std::array<DirtyZone, 2> dirty_zones_buffer_{};
VertexArray scans_;
VertexArray lines_;
VertexArray dirty_zones_;
Texture source_texture_;
@@ -175,6 +176,7 @@ private:
Shader composition_shader_;
Shader separation_shader_;
Shader demodulation_shader_;
Shader line_output_shader_;
CopyShader copy_shader_;
};

View File

@@ -40,4 +40,14 @@ inline std::vector<std::string> dirty_zone_attributes() {
};
}
inline std::vector<std::string> line_attributes() {
return std::vector<std::string>{
"lineEndpoint0Position",
"lineEndpoint0CyclesSinceRetrace",
"lineEndpoint1Position",
"lineEndpoint1CyclesSinceRetrace",
"lineLine",
};
}
}

View File

@@ -0,0 +1,125 @@
//
// LineOutputShader.cpp
// Clock Signal Kiosk
//
// Created by Thomas Harte on 04/02/2026.
// Copyright © 2026 Thomas Harte. All rights reserved.
//
#include "LineOutputShader.hpp"
#include "CommonAtrributes.hpp"
#include "Outputs/ScanTargets/BufferingScanTarget.hpp"
namespace {
constexpr char vertex_shader[] = R"glsl(
uniform mediump vec2 sourceSize;
uniform highp vec2 positionScale;
uniform mediump float lineHeight;
// TODO: programmable crop should affect scaling via uniforms.
in highp vec2 lineEndpoint0Position;
in highp float lineEndpoint0CyclesSinceRetrace;
in highp vec2 lineEndpoint1Position;
in highp float lineEndpoint1CyclesSinceRetrace;
in highp float lineLine;
out mediump vec2 coordinate;
void main(void) {
float lateral = float(gl_VertexID & 1);
float longitudinal = float((gl_VertexID & 2) >> 1);
coordinate = vec2(
mix(
lineEndpoint0CyclesSinceRetrace,
lineEndpoint1CyclesSinceRetrace,
lateral
),
lineLine + 0.5
) / sourceSize;
vec2 tangent = normalize(lineEndpoint1Position - lineEndpoint0Position);
vec2 normal = vec2(tangent.y, -tangent.x);
vec2 centre =
mix(
lineEndpoint0Position,
lineEndpoint1Position,
lateral
) / positionScale;
gl_Position =
vec4(
centre + (longitudinal - 0.5) * normal,
0.0,
1.0
);
}
)glsl";
constexpr char fragment_shader[] = R"glsl(
uniform lowp sampler2D source;
in mediump vec2 coordinate;
out lowp vec4 outputColour;
void main(void) {
outputColour = texture(source, coordinate);
}
)glsl";
}
using namespace Outputs::Display;
OpenGL::Shader OpenGL::line_output_shader(
const API api,
const int source_width,
const int source_height,
const int expected_vertical_lines,
const int scale_x,
const int scale_y,
const VertexArray &vertex_array,
const GLenum source_texture_unit
) {
auto shader = OpenGL::Shader(
api,
vertex_shader,
fragment_shader,
line_attributes()
);
BufferingScanTarget::Line line;
vertex_array.bind_all();
const auto enable = [&](const std::string &name, uint16_t &element, const GLint size) {
shader.enable_vertex_attribute_with_pointer(
name,
size,
GL_UNSIGNED_SHORT,
GL_FALSE,
sizeof(line),
reinterpret_cast<void *>((reinterpret_cast<uint8_t *>(&element) - reinterpret_cast<uint8_t *>(&line))),
1
);
};
enable("lineEndpoint0Position", line.end_points[0].x, 2);
enable("lineEndpoint0CyclesSinceRetrace", line.end_points[0].cycles_since_end_of_horizontal_retrace, 1);
enable("lineEndpoint1Position", line.end_points[1].x, 2);
enable("lineEndpoin10CyclesSinceRetrace", line.end_points[1].cycles_since_end_of_horizontal_retrace, 1);
enable("lineLine", line.line, 1);
shader.set_uniform("lineHeight", 1.0f / float(expected_vertical_lines));
shader.set_uniform("positionScale", float(scale_x), float(scale_y));
shader.set_uniform("sourceSize", float(source_width), float(source_height));
shader.set_uniform("source", GLint(source_texture_unit - GL_TEXTURE0));
return shader;
}

View File

@@ -0,0 +1,30 @@
//
// LineOutputShader.hpp
// Clock Signal Kiosk
//
// Created by Thomas Harte on 04/02/2026.
// Copyright © 2026 Thomas Harte. All rights reserved.
//
#pragma once
#include "Outputs/OpenGL/Primitives/VertexArray.hpp"
#include "Outputs/OpenGL/Primitives/Shader.hpp"
namespace Outputs::Display::OpenGL {
/*!
Using `Line`s as input, draws output spans.
*/
Shader line_output_shader(
API,
int source_width,
int source_height,
int expected_vertical_lines,
int scale_x,
int scale_y,
const VertexArray &,
GLenum source_texture_unit
);
}

View File

@@ -74,6 +74,7 @@ public:
uint8_t composite_amplitude;
uint16_t line;
};
static_assert(sizeof(Line) == 20);
/// Provides additional metadata about lines; this is separate because it's unlikely to be of
/// interest to the GPU, unlike the fields in Line.

View File

@@ -166,6 +166,7 @@ set(CLK_SOURCES
Outputs/OpenGL/Shaders/CompositionShader.cpp
Outputs/OpenGL/Shaders/CopyShader.cpp
Outputs/OpenGL/Shaders/KernelShaders.cpp
Outputs/OpenGL/Shaders/LineOutputShader.cpp
Outputs/OpenGL/Shaders/Rectangle.cpp
Outputs/OpenGL/ScanTarget.cpp
Outputs/OpenGL/ScanTargetGLSLFragments.cpp