1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-06 01:28:57 +00:00

At last a genuine bug fixed: was nudging the wrong amount in intermediate shaders.

This commit is contained in:
Thomas Harte 2016-05-08 16:07:36 -04:00
parent 1142c86811
commit 9485ef2c8c
10 changed files with 28 additions and 32 deletions

View File

@ -77,6 +77,11 @@ class Atari2600Document: MachineDocument {
atari2600.setState(true, forDigitalInput: input)
}
if event.keyCode == 49 {
self.runForNumberOfCycles(Int32(self.intendedCyclesPerSecond / 60))
self.openGLView.drawViewOnlyIfDirty(true)
}
if event.keyCode == 36 {
atari2600.setResetLineEnabled(true)
}

View File

@ -36,12 +36,16 @@ class MachineDocument: NSDocument, CSOpenGLViewDelegate, CSOpenGLViewResponderDe
private var cycleCountError: Int64 = 0
private var lastTime: CVTimeStamp?
private var skippedFrames = 0
// private var frameSkip = 0
private var frameSkip = 0
final func openGLView(view: CSOpenGLView, didUpdateToTime time: CVTimeStamp, didSkipPreviousUpdate : Bool, frequency : Double) {
// frameSkip = frameSkip + 1
// let modFrameSkip = frameSkip % 10
// if modFrameSkip == 0 {
// if modFrameSkip == 0 && frameSkip < 500 {
// runForNumberOfCycles(Int32(intendedCyclesPerSecond / 60))
// view.drawViewOnlyIfDirty(true)
// view.performWithGLContext({ () -> Void in
// self.openGLView(view, drawViewOnlyIfDirty: true)
// })
// }
if let lastTime = lastTime {
// perform (time passed in seconds) * (intended cycles per second), converting and

View File

@ -75,4 +75,6 @@
- (void)performWithGLContext:(nonnull dispatch_block_t)action;
- (void)drawViewOnlyIfDirty:(BOOL)onlyIfDirty;
@end

View File

@ -60,6 +60,7 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeSt
BOOL didSkip = _hasSkipped;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
[self.delegate openGLView:self didUpdateToTime:time didSkipPreviousUpdate:didSkip frequency:frequency];
[self drawViewOnlyIfDirty:YES];
OSAtomicTestAndClear(processingMask, &_updateIsOngoing);
});
_hasSkipped = NO;
@ -68,13 +69,13 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeSt
// Draw the display only if a previous draw is not still ongoing. -drawViewOnlyIfDirty: is guaranteed
// to be safe to call concurrently with -openGLView:updateToTime: so there's no need to worry about
// the above interrupting the below or vice versa.
if(!OSAtomicTestAndSet(drawingMask, &_updateIsOngoing))
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
[self drawViewOnlyIfDirty:YES];
OSAtomicTestAndClear(drawingMask, &_updateIsOngoing);
});
}
// if(!OSAtomicTestAndSet(drawingMask, &_updateIsOngoing))
// {
// dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
// [self drawViewOnlyIfDirty:YES];
// OSAtomicTestAndClear(drawingMask, &_updateIsOngoing);
// });
// }
}
- (void)invalidate
@ -134,7 +135,7 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeSt
- (void)drawRect:(NSRect)dirtyRect
{
[self drawViewOnlyIfDirty:NO];
// [self drawViewOnlyIfDirty:NO];
}
- (void)drawViewOnlyIfDirty:(BOOL)onlyIfDirty

View File

@ -141,7 +141,6 @@ void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divi
// [0/1] 3
if(next_run)
{
// printf("%d -> %d", tex_y, _openGL_output_builder->get_composite_output_y());
source_input_position_x(0) = tex_x;
source_input_position_y(0) = source_input_position_y(1) = tex_y;
source_output_position_x(0) = (uint16_t)_horizontal_flywheel->get_current_output_position();
@ -194,7 +193,6 @@ void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divi
uint8_t *next_run = _openGL_output_builder->get_next_output_run();
if(next_run)
{
// printf("{%d -> %0.2f}", _openGL_output_builder->get_composite_output_y(), (float)_vertical_flywheel->get_current_output_position() / (float)_vertical_flywheel->get_scan_period());
output_position_x(0) = output_position_x(1) = output_position_x(2) = (uint16_t)_horizontal_flywheel->get_current_output_position();
output_position_y(0) = output_position_y(1) = output_position_y(2) = (uint16_t)(_vertical_flywheel->get_current_output_position() / _vertical_flywheel_output_divider);
output_tex_x(0) = output_tex_x(1) = output_tex_x(2) = (uint16_t)_horizontal_flywheel->get_current_output_position();
@ -215,7 +213,6 @@ void CRT::advance_cycles(unsigned int number_of_cycles, unsigned int source_divi
// if this is vertical retrace then adcance a field
if(next_run_length == time_until_vertical_sync_event && next_vertical_sync_event == Flywheel::SyncEvent::EndRetrace)
{
// printf("\n!%d!\n", _openGL_output_builder->get_composite_output_y());
// TODO: eliminate the below; it's to aid with debug, aligning the top of the
// input buffer with the top of the incoming frame.
_openGL_output_builder->release_source_buffer_write_pointer();
@ -326,7 +323,6 @@ void CRT::output_data(unsigned int number_of_cycles, unsigned int source_divider
{
if(_openGL_output_builder->reduce_previous_allocation_to(number_of_cycles / source_divider))
{
// printf("[%d with %d]", (_vertical_flywheel->get_current_time() * 262) / _vertical_flywheel->get_scan_period(), _openGL_output_builder->get_last_write_y_posititon());
Scan scan {
.type = Scan::Type::Data,
.number_of_cycles = number_of_cycles,

View File

@ -33,11 +33,11 @@ const GLsizei SourceVertexSize = 16;
// These constants hold the size of the rolling buffer to which the CPU writes
const GLsizei InputBufferBuilderWidth = 2048;
const GLsizei InputBufferBuilderHeight = 1024; // 1024
const GLsizei InputBufferBuilderHeight = 512;
// This is the size of the intermediate buffers used during composite to RGB conversion
const GLsizei IntermediateBufferWidth = 2048;
const GLsizei IntermediateBufferHeight = 2048;
const GLsizei IntermediateBufferHeight = 512;
// Some internal buffer sizes
const GLsizeiptr OutputVertexBufferDataSize = 44928; // a multiple of 6 * OutputVertexSize

View File

@ -42,7 +42,7 @@ void CRTInputBufferBuilder::allocate_write_area(size_t required_length)
_write_x_position = _next_write_x_position + 1;
_write_y_position = _next_write_y_position;
// printf("#%d,%d#", _write_x_position, _write_y_position);
// printf("#%d,%d#\n", _write_x_position, _write_y_position);
_write_target_pointer = (_write_y_position * InputBufferBuilderWidth) + _write_x_position;
_next_write_x_position += required_length + 2;
}
@ -53,6 +53,7 @@ void CRTInputBufferBuilder::release_write_pointer()
if(_should_reset)
{
_next_write_x_position = _next_write_y_position = 0;
// printf("#Reset!#\n");
}
}

View File

@ -185,15 +185,6 @@ void OpenGLOutputBuilder::draw_frame(unsigned int output_width, unsigned int out
int number_of_clearing_zones = getCircularRanges(_cleared_composite_output_y, _composite_src_output_y, IntermediateBufferHeight, 1, clearing_zones);
int number_of_source_drawing_zones = getCircularRanges(_drawn_source_buffer_data_pointer, _source_buffer_data_pointer, SourceVertexBufferDataSize, 2*SourceVertexSize, source_drawing_zones);
int number_of_output_drawing_zones = getCircularRanges(_drawn_output_buffer_data_pointer, _output_buffer_data_pointer, OutputVertexBufferDataSize, 6*OutputVertexSize, output_drawing_zones);
// for(int c = 0; c < number_of_output_drawing_zones; c++)
// {
// printf("\n(%d->%d)\n", output_drawing_zones[c*2], output_drawing_zones[c*2] + output_drawing_zones[c*2 + 1]);
// }
// if(number_of_output_drawing_zones)
// printf("\n\n");
uint16_t completed_texture_y = _buffer_builder->get_and_finalise_current_line();
_composite_src_output_y %= IntermediateBufferHeight;
@ -315,8 +306,6 @@ void OpenGLOutputBuilder::draw_frame(unsigned int output_width, unsigned int out
if(number_of_output_drawing_zones)
{
// glClearColor(0.5, 0.5, 0.5, 1.0);
// glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_BLEND);
// Ensure we're back on the output framebuffer, drawing from the output array buffer
@ -336,7 +325,6 @@ void OpenGLOutputBuilder::draw_frame(unsigned int output_width, unsigned int out
{
glDrawArrays(GL_TRIANGLE_STRIP, output_drawing_zones[c*2] / OutputVertexSize, output_drawing_zones[c*2 + 1] / OutputVertexSize);
}
// glDrawArrays(GL_TRIANGLE_STRIP, 0, OutputVertexBufferDataSize / OutputVertexSize);
}
// copy framebuffer to the intended place
@ -346,7 +334,6 @@ void OpenGLOutputBuilder::draw_frame(unsigned int output_width, unsigned int out
glClear(GL_COLOR_BUFFER_BIT);
framebuffer->draw((float)output_width / (float)output_height);
// filteredYTexture->draw((float)output_width / (float)output_height);
// drawing commands having been issued, reclaim the array buffer pointer
glBindBuffer(GL_ARRAY_BUFFER, output_array_buffer);

View File

@ -57,7 +57,7 @@ class OpenGLOutputBuilder {
// the run and input data buffers
std::unique_ptr<CRTInputBufferBuilder> _buffer_builder;
std::shared_ptr<std::mutex> _output_mutex;
std::unique_ptr<std::mutex> _output_mutex;
// transient buffers indicating composite data not yet decoded
uint16_t _composite_src_output_y, _cleared_composite_output_y;

View File

@ -78,7 +78,7 @@ std::unique_ptr<IntermediateShader> IntermediateShader::make_shader(const char *
"phaseAndAmplitudeVarying.x = (phaseCyclesPerTick * (extendedOutputPosition.x - phaseTime) + phaseAndAmplitude.x) * 2.0 * 3.141592654;"
"phaseAndAmplitudeVarying.y = 0.33;" // TODO: reinstate connection with phaseAndAmplitude
"vec2 eyePosition = 2.0*(extendedOutputPosition / outputTextureSize) - vec2(1.0) + vec2(0.5)/textureSize;"
"vec2 eyePosition = 2.0*(extendedOutputPosition / outputTextureSize) - vec2(1.0) + vec2(0.5)/outputTextureSize;"
"gl_Position = vec4(eyePosition, 0.0, 1.0);"
"}", sampler_type, input_variable);