From ef3b91d3aaf8470b486ab42a2bcbd4555a6d5488 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 8 May 2016 19:42:33 -0400 Subject: [PATCH] Made an attempt to get formal on synchronisation. --- Outputs/CRT/Internals/CRTConstants.hpp | 2 +- Outputs/CRT/Internals/CRTOpenGL.cpp | 56 ++++++++++++-------------- Outputs/CRT/Internals/CRTOpenGL.hpp | 10 +++-- 3 files changed, 33 insertions(+), 35 deletions(-) diff --git a/Outputs/CRT/Internals/CRTConstants.hpp b/Outputs/CRT/Internals/CRTConstants.hpp index 1b83ce9b2..421274c05 100644 --- a/Outputs/CRT/Internals/CRTConstants.hpp +++ b/Outputs/CRT/Internals/CRTConstants.hpp @@ -41,7 +41,7 @@ const GLsizei IntermediateBufferHeight = 512; // Some internal buffer sizes const GLsizeiptr OutputVertexBufferDataSize = 6 * 8 * 312; // a multiple of 6 * OutputVertexSize -const GLsizeiptr SourceVertexBufferDataSize = 2 * 16 * 312; // a multiple of 2 * SourceVertexSize +const GLsizeiptr SourceVertexBufferDataSize = 2 * 16 * 312; // a multiple of 2 * SourceVertexSize } } diff --git a/Outputs/CRT/Internals/CRTOpenGL.cpp b/Outputs/CRT/Internals/CRTOpenGL.cpp index 5e2652ac6..a336e15ac 100644 --- a/Outputs/CRT/Internals/CRTOpenGL.cpp +++ b/Outputs/CRT/Internals/CRTOpenGL.cpp @@ -80,6 +80,18 @@ static inline void drawArrayRanges(GLenum mode, GLsizei vertex_size, int number_ } } +static void submitArrayData(GLuint buffer, uint8_t *source, int number_of_ranges, Range *ranges) +{ + glBindBuffer(GL_ARRAY_BUFFER, buffer); + for(int c = 0; c < number_of_ranges; c++) + { + uint8_t *data = (uint8_t *)glMapBufferRange(GL_ARRAY_BUFFER, ranges[c].location, ranges[c].length, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_FLUSH_EXPLICIT_BIT); + memcpy(data, &source[ranges[c].location], (size_t)ranges[c].length); + glFlushMappedBufferRange(GL_ARRAY_BUFFER, ranges[c].location, ranges[c].length); + glUnmapBuffer(GL_ARRAY_BUFFER); + } +} + using namespace Outputs::CRT; namespace { @@ -98,8 +110,8 @@ OpenGLOutputBuilder::OpenGLOutputBuilder(unsigned int buffer_depth) : _cleared_composite_output_y(0), _composite_shader(nullptr), _rgb_shader(nullptr), - _output_buffer_data(nullptr), - _source_buffer_data(nullptr), + _output_buffer_data(new uint8_t[OutputVertexBufferDataSize]), + _source_buffer_data(new uint8_t[SourceVertexBufferDataSize]), _output_buffer_data_pointer(0), _drawn_output_buffer_data_pointer(0), _source_buffer_data_pointer(0), @@ -136,9 +148,6 @@ OpenGLOutputBuilder::OpenGLOutputBuilder(unsigned int buffer_depth) : glBindBuffer(GL_ARRAY_BUFFER, output_array_buffer); glBufferData(GL_ARRAY_BUFFER, OutputVertexBufferDataSize, NULL, GL_STREAM_DRAW); - // map that buffer too, for any CRT activity that may occur before the first draw - _output_buffer_data = (uint8_t *)glMapBufferRange(GL_ARRAY_BUFFER, 0, OutputVertexBufferDataSize, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_FLUSH_EXPLICIT_BIT); - // create the source vertex array glGenVertexArrays(1, &source_vertex_array); @@ -146,15 +155,12 @@ OpenGLOutputBuilder::OpenGLOutputBuilder(unsigned int buffer_depth) : glGenBuffers(1, &source_array_buffer); glBindBuffer(GL_ARRAY_BUFFER, source_array_buffer); glBufferData(GL_ARRAY_BUFFER, SourceVertexBufferDataSize, NULL, GL_STREAM_DRAW); - - // map that buffer too, for any CRT activity that may occur before the first draw - _source_buffer_data = (uint8_t *)glMapBufferRange(GL_ARRAY_BUFFER, 0, SourceVertexBufferDataSize, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_FLUSH_EXPLICIT_BIT); } OpenGLOutputBuilder::~OpenGLOutputBuilder() { - glUnmapBuffer(GL_ARRAY_BUFFER); - glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); +// glUnmapBuffer(GL_ARRAY_BUFFER); +// glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); glDeleteTextures(1, &textureName); glDeleteBuffers(1, &output_array_buffer); glDeleteBuffers(1, &source_array_buffer); @@ -207,23 +213,19 @@ void OpenGLOutputBuilder::draw_frame(unsigned int output_width, unsigned int out _drawn_source_buffer_data_pointer = _source_buffer_data_pointer; _drawn_output_buffer_data_pointer = _output_buffer_data_pointer; - glFinish(); + // drawing commands having been issued, reclaim the array buffer pointer +// glBindBuffer(GL_ARRAY_BUFFER, output_array_buffer); +// +// glBindBuffer(GL_ARRAY_BUFFER, source_array_buffer); +// _source_buffer_data = (uint8_t *)glMapBufferRange(GL_ARRAY_BUFFER, 0, SourceVertexBufferDataSize, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_FLUSH_EXPLICIT_BIT); + + glClientWaitSync(_fence, GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED); // release the mapping, giving up on trying to draw if data has been lost - glBindBuffer(GL_ARRAY_BUFFER, output_array_buffer); - for(int c = 0; c < number_of_output_drawing_zones; c++) - { - glFlushMappedBufferRange(GL_ARRAY_BUFFER, output_drawing_zones[c].location, output_drawing_zones[c].length); - } - glUnmapBuffer(GL_ARRAY_BUFFER); + submitArrayData(output_array_buffer, _output_buffer_data.get(), number_of_output_drawing_zones, output_drawing_zones); // bind and flush the source array buffer - glBindBuffer(GL_ARRAY_BUFFER, source_array_buffer); - for(int c = 0; c < number_of_source_drawing_zones; c++) - { - glFlushMappedBufferRange(GL_ARRAY_BUFFER, source_drawing_zones[c].location, source_drawing_zones[c].length); - } - glUnmapBuffer(GL_ARRAY_BUFFER); + submitArrayData(source_array_buffer, _source_buffer_data.get(), number_of_source_drawing_zones, source_drawing_zones); // make sure there's a target to draw to if(!framebuffer || framebuffer->get_height() != output_height || framebuffer->get_width() != output_width) @@ -345,13 +347,7 @@ void OpenGLOutputBuilder::draw_frame(unsigned int output_width, unsigned int out framebuffer->draw((float)output_width / (float)output_height); - // drawing commands having been issued, reclaim the array buffer pointer - glBindBuffer(GL_ARRAY_BUFFER, output_array_buffer); - _output_buffer_data = (uint8_t *)glMapBufferRange(GL_ARRAY_BUFFER, 0, OutputVertexBufferDataSize, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_FLUSH_EXPLICIT_BIT); - - glBindBuffer(GL_ARRAY_BUFFER, source_array_buffer); - _source_buffer_data = (uint8_t *)glMapBufferRange(GL_ARRAY_BUFFER, 0, SourceVertexBufferDataSize, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_FLUSH_EXPLICIT_BIT); - + _fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); _output_mutex->unlock(); } diff --git a/Outputs/CRT/Internals/CRTOpenGL.hpp b/Outputs/CRT/Internals/CRTOpenGL.hpp index 701e11e8c..903e7c501 100644 --- a/Outputs/CRT/Internals/CRTOpenGL.hpp +++ b/Outputs/CRT/Internals/CRTOpenGL.hpp @@ -108,7 +108,7 @@ class OpenGLOutputBuilder { { if(_source_buffer_data_pointer == _drawn_source_buffer_data_pointer + SourceVertexBufferDataSize) return nullptr; _output_mutex->lock(); - return &_source_buffer_data[_source_buffer_data_pointer % SourceVertexBufferDataSize]; + return &_source_buffer_data.get()[_source_buffer_data_pointer % SourceVertexBufferDataSize]; } inline void complete_source_run() @@ -126,7 +126,7 @@ class OpenGLOutputBuilder { { if(_output_buffer_data_pointer == _drawn_output_buffer_data_pointer + OutputVertexBufferDataSize) return nullptr; _output_mutex->lock(); - return &_output_buffer_data[_output_buffer_data_pointer % OutputVertexBufferDataSize]; + return &_output_buffer_data.get()[_output_buffer_data_pointer % OutputVertexBufferDataSize]; } inline void complete_output_run(GLsizei vertices_written) @@ -194,13 +194,15 @@ class OpenGLOutputBuilder { void set_output_device(OutputDevice output_device); void set_timing(unsigned int input_frequency, unsigned int cycles_per_line, unsigned int height_of_display, unsigned int horizontal_scan_period, unsigned int vertical_scan_period, unsigned int vertical_period_divider); - uint8_t *_source_buffer_data; + std::unique_ptr _source_buffer_data; GLsizei _source_buffer_data_pointer; GLsizei _drawn_source_buffer_data_pointer; - uint8_t *_output_buffer_data; + std::unique_ptr _output_buffer_data; GLsizei _output_buffer_data_pointer; GLsizei _drawn_output_buffer_data_pointer; + + GLsync _fence; }; }