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

Made an attempt to get formal on synchronisation.

This commit is contained in:
Thomas Harte 2016-05-08 19:42:33 -04:00
parent dd469fe83a
commit ef3b91d3aa
3 changed files with 33 additions and 35 deletions

View File

@ -41,7 +41,7 @@ const GLsizei IntermediateBufferHeight = 512;
// Some internal buffer sizes // Some internal buffer sizes
const GLsizeiptr OutputVertexBufferDataSize = 6 * 8 * 312; // a multiple of 6 * OutputVertexSize 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
} }
} }

View File

@ -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; using namespace Outputs::CRT;
namespace { namespace {
@ -98,8 +110,8 @@ OpenGLOutputBuilder::OpenGLOutputBuilder(unsigned int buffer_depth) :
_cleared_composite_output_y(0), _cleared_composite_output_y(0),
_composite_shader(nullptr), _composite_shader(nullptr),
_rgb_shader(nullptr), _rgb_shader(nullptr),
_output_buffer_data(nullptr), _output_buffer_data(new uint8_t[OutputVertexBufferDataSize]),
_source_buffer_data(nullptr), _source_buffer_data(new uint8_t[SourceVertexBufferDataSize]),
_output_buffer_data_pointer(0), _output_buffer_data_pointer(0),
_drawn_output_buffer_data_pointer(0), _drawn_output_buffer_data_pointer(0),
_source_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); glBindBuffer(GL_ARRAY_BUFFER, output_array_buffer);
glBufferData(GL_ARRAY_BUFFER, OutputVertexBufferDataSize, NULL, GL_STREAM_DRAW); 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 // create the source vertex array
glGenVertexArrays(1, &source_vertex_array); glGenVertexArrays(1, &source_vertex_array);
@ -146,15 +155,12 @@ OpenGLOutputBuilder::OpenGLOutputBuilder(unsigned int buffer_depth) :
glGenBuffers(1, &source_array_buffer); glGenBuffers(1, &source_array_buffer);
glBindBuffer(GL_ARRAY_BUFFER, source_array_buffer); glBindBuffer(GL_ARRAY_BUFFER, source_array_buffer);
glBufferData(GL_ARRAY_BUFFER, SourceVertexBufferDataSize, NULL, GL_STREAM_DRAW); 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() OpenGLOutputBuilder::~OpenGLOutputBuilder()
{ {
glUnmapBuffer(GL_ARRAY_BUFFER); // glUnmapBuffer(GL_ARRAY_BUFFER);
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); // glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
glDeleteTextures(1, &textureName); glDeleteTextures(1, &textureName);
glDeleteBuffers(1, &output_array_buffer); glDeleteBuffers(1, &output_array_buffer);
glDeleteBuffers(1, &source_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_source_buffer_data_pointer = _source_buffer_data_pointer;
_drawn_output_buffer_data_pointer = _output_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 // release the mapping, giving up on trying to draw if data has been lost
glBindBuffer(GL_ARRAY_BUFFER, output_array_buffer); submitArrayData(output_array_buffer, _output_buffer_data.get(), number_of_output_drawing_zones, output_drawing_zones);
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);
// bind and flush the source array buffer // bind and flush the source array buffer
glBindBuffer(GL_ARRAY_BUFFER, source_array_buffer); submitArrayData(source_array_buffer, _source_buffer_data.get(), number_of_source_drawing_zones, source_drawing_zones);
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);
// make sure there's a target to draw to // make sure there's a target to draw to
if(!framebuffer || framebuffer->get_height() != output_height || framebuffer->get_width() != output_width) 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); framebuffer->draw((float)output_width / (float)output_height);
// drawing commands having been issued, reclaim the array buffer pointer _fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
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);
_output_mutex->unlock(); _output_mutex->unlock();
} }

View File

@ -108,7 +108,7 @@ class OpenGLOutputBuilder {
{ {
if(_source_buffer_data_pointer == _drawn_source_buffer_data_pointer + SourceVertexBufferDataSize) return nullptr; if(_source_buffer_data_pointer == _drawn_source_buffer_data_pointer + SourceVertexBufferDataSize) return nullptr;
_output_mutex->lock(); _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() inline void complete_source_run()
@ -126,7 +126,7 @@ class OpenGLOutputBuilder {
{ {
if(_output_buffer_data_pointer == _drawn_output_buffer_data_pointer + OutputVertexBufferDataSize) return nullptr; if(_output_buffer_data_pointer == _drawn_output_buffer_data_pointer + OutputVertexBufferDataSize) return nullptr;
_output_mutex->lock(); _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) inline void complete_output_run(GLsizei vertices_written)
@ -194,13 +194,15 @@ class OpenGLOutputBuilder {
void set_output_device(OutputDevice output_device); 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); 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<uint8_t> _source_buffer_data;
GLsizei _source_buffer_data_pointer; GLsizei _source_buffer_data_pointer;
GLsizei _drawn_source_buffer_data_pointer; GLsizei _drawn_source_buffer_data_pointer;
uint8_t *_output_buffer_data; std::unique_ptr<uint8_t> _output_buffer_data;
GLsizei _output_buffer_data_pointer; GLsizei _output_buffer_data_pointer;
GLsizei _drawn_output_buffer_data_pointer; GLsizei _drawn_output_buffer_data_pointer;
GLsync _fence;
}; };
} }