From 0d27d3bb7f7a49a43fe190770ece67ebd65e2019 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Wed, 16 Mar 2016 22:29:22 -0400 Subject: [PATCH] As messy as it is, this use `glMapBufferRange` to avoid explicit buffer submits. --- Outputs/CRT/Internals/CRTOpenGL.cpp | 90 +++++++++++++++---------- Outputs/CRT/Internals/CRTOpenGL.hpp | 27 ++++++-- Outputs/CRT/Internals/CRTRunBuilder.cpp | 3 +- Outputs/CRT/Internals/CRTRunBuilder.hpp | 11 +-- 4 files changed, 82 insertions(+), 49 deletions(-) diff --git a/Outputs/CRT/Internals/CRTOpenGL.cpp b/Outputs/CRT/Internals/CRTOpenGL.cpp index 3d9ddcddf..320827d76 100644 --- a/Outputs/CRT/Internals/CRTOpenGL.cpp +++ b/Outputs/CRT/Internals/CRTOpenGL.cpp @@ -82,14 +82,18 @@ void OpenGLOutputBuilder::draw_frame(unsigned int output_width, unsigned int out glTexImage2D(GL_TEXTURE_2D, 0, (GLint)format, InputBufferBuilderWidth, InputBufferBuilderHeight, 0, format, GL_UNSIGNED_BYTE, _buffer_builder->buffers[buffer].data); } + prepare_composite_input_shader(); + prepare_rgb_output_shader(); + glGenVertexArrays(1, &output_vertex_array); glGenBuffers(1, &output_array_buffer); output_vertices_per_slice = 0; - prepare_composite_input_shader(); - prepare_rgb_output_shader(); - glBindBuffer(GL_ARRAY_BUFFER, output_array_buffer); + + glBufferData(GL_ARRAY_BUFFER, buffer_size, NULL, GL_STREAM_DRAW); + _output_buffer_data = (uint8_t *)glMapBufferRange(GL_ARRAY_BUFFER, 0, buffer_size, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT); + _output_buffer_data_pointer = 0; glBindVertexArray(output_vertex_array); prepare_output_vertex_array(); @@ -144,8 +148,8 @@ void OpenGLOutputBuilder::draw_frame(unsigned int output_width, unsigned int out // check for anything to decode from composite if(_composite_src_runs->number_of_vertices) { - composite_input_shader_program->bind(); - _composite_src_runs->reset(); +// composite_input_shader_program->bind(); +// _composite_src_runs->reset(); } // _output_mutex->unlock(); @@ -156,24 +160,24 @@ void OpenGLOutputBuilder::draw_frame(unsigned int output_width, unsigned int out // glGetIntegerv(GL_VIEWPORT, results); // ensure array buffer is up to date - glBindBuffer(GL_ARRAY_BUFFER, output_array_buffer); - size_t max_number_of_vertices = 0; - for(int c = 0; c < NumberOfFields; c++) - { - max_number_of_vertices = std::max(max_number_of_vertices, _run_builders[c]->number_of_vertices); - } - if(output_vertices_per_slice < max_number_of_vertices) - { - output_vertices_per_slice = max_number_of_vertices; - glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(max_number_of_vertices * OutputVertexSize * OutputVertexSize), NULL, GL_STREAM_DRAW); - - for(unsigned int c = 0; c < NumberOfFields; c++) - { - uint8_t *data = &_run_builders[c]->_runs[0]; - glBufferSubData(GL_ARRAY_BUFFER, (GLsizeiptr)(c * output_vertices_per_slice * OutputVertexSize), (GLsizeiptr)(_run_builders[c]->number_of_vertices * OutputVertexSize), data); - _run_builders[c]->uploaded_vertices = _run_builders[c]->number_of_vertices; - } - } +// glBindBuffer(GL_ARRAY_BUFFER, output_array_buffer); +// size_t max_number_of_vertices = 0; +// for(int c = 0; c < NumberOfFields; c++) +// { +// max_number_of_vertices = std::max(max_number_of_vertices, _run_builders[c]->number_of_vertices); +// } +// if(output_vertices_per_slice < max_number_of_vertices) +// { +// output_vertices_per_slice = max_number_of_vertices; +// glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(max_number_of_vertices * OutputVertexSize * OutputVertexSize), NULL, GL_STREAM_DRAW); +// +// for(unsigned int c = 0; c < NumberOfFields; c++) +// { +// uint8_t *data = &_run_builders[c]->_runs[0]; +// glBufferSubData(GL_ARRAY_BUFFER, (GLsizeiptr)(c * output_vertices_per_slice * OutputVertexSize), (GLsizeiptr)(_run_builders[c]->number_of_vertices * OutputVertexSize), data); +// _run_builders[c]->uploaded_vertices = _run_builders[c]->number_of_vertices; +// } +// } // switch to the output shader if(rgb_shader_program) @@ -202,17 +206,29 @@ void OpenGLOutputBuilder::draw_frame(unsigned int output_width, unsigned int out { glUniform1f(timestampBaseUniform, (GLfloat)total_age); - if(_run_builders[run]->uploaded_vertices != _run_builders[run]->number_of_vertices) - { - uint8_t *data = &_run_builders[run]->_runs[_run_builders[run]->uploaded_vertices * OutputVertexSize]; - glBufferSubData(GL_ARRAY_BUFFER, - (GLsizeiptr)(((run * output_vertices_per_slice) + _run_builders[run]->uploaded_vertices) * OutputVertexSize), - (GLsizeiptr)((_run_builders[run]->number_of_vertices - _run_builders[run]->uploaded_vertices) * OutputVertexSize), data); - _run_builders[run]->uploaded_vertices = _run_builders[run]->number_of_vertices; - } +// if(_run_builders[run]->uploaded_vertices != _run_builders[run]->number_of_vertices) +// { +// uint8_t *data = &_run_builders[run]->_runs[_run_builders[run]->uploaded_vertices * OutputVertexSize]; +// glBufferSubData(GL_ARRAY_BUFFER, +// (GLsizeiptr)(((run * output_vertices_per_slice) + _run_builders[run]->uploaded_vertices) * OutputVertexSize), +// (GLsizeiptr)((_run_builders[run]->number_of_vertices - _run_builders[run]->uploaded_vertices) * OutputVertexSize), data); +// _run_builders[run]->uploaded_vertices = _run_builders[run]->number_of_vertices; +// } // draw this frame - glDrawArrays(GL_TRIANGLE_STRIP, (GLint)(run * output_vertices_per_slice), (GLsizei)_run_builders[run]->number_of_vertices); +// glDrawArrays(GL_TRIANGLE_STRIP, (GLint)(run * output_vertices_per_slice), (GLsizei)_run_builders[run]->number_of_vertices); + + GLsizei count = (GLsizei)_run_builders[run]->number_of_vertices; + GLsizei max_count = (GLsizei)((buffer_size - _run_builders[run]->start) / InputVertexSize); + if(count < max_count) + { + glDrawArrays(GL_TRIANGLE_STRIP, (GLint)(_run_builders[run]->start / InputVertexSize), count); + } + else + { + glDrawArrays(GL_TRIANGLE_STRIP, (GLint)(_run_builders[run]->start / InputVertexSize), max_count); + glDrawArrays(GL_TRIANGLE_STRIP, 0, count - max_count); + } } // advance back in time @@ -549,11 +565,11 @@ void OpenGLOutputBuilder::set_output_device(OutputDevice output_device) { _output_device = output_device; - for(int builder = 0; builder < NumberOfFields; builder++) - { - _run_builders[builder]->reset(); - } - _composite_src_runs->reset(); +// for(int builder = 0; builder < NumberOfFields; builder++) +// { +// _run_builders[builder]->reset(); +// } +// _composite_src_runs->reset(); _composite_src_output_y = 0; } } diff --git a/Outputs/CRT/Internals/CRTOpenGL.hpp b/Outputs/CRT/Internals/CRTOpenGL.hpp index 0acd9f680..f2697cc1b 100644 --- a/Outputs/CRT/Internals/CRTOpenGL.hpp +++ b/Outputs/CRT/Internals/CRTOpenGL.hpp @@ -47,6 +47,9 @@ const int InputBufferBuilderHeight = 1024; const int IntermediateBufferWidth = 2048; const int IntermediateBufferHeight = 2048; +const GLsizeiptr buffer_size = (GLsizeiptr)(312 * 6 * 6 * OutputVertexSize); + + // Runs are divided discretely by vertical syncs in order to put a usable bounds on the uniform used to track // run age; that therefore creates a discrete number of fields that are stored. This number should be the // number of historic fields that are required fully to @@ -136,23 +139,30 @@ class OpenGLOutputBuilder { inline uint8_t *get_next_input_run() { - _output_mutex->lock(); - return (_output_device == Monitor) ? _run_builders[_run_write_pointer]->get_next_run(6) : _composite_src_runs->get_next_run(2); + if (_output_buffer_data_pointer + 6 * InputVertexSize > buffer_size) _output_buffer_data_pointer = 0; + uint8_t *pointer = &_output_buffer_data[_output_buffer_data_pointer]; + _output_buffer_data_pointer += 6 * InputVertexSize; + return pointer; +// _output_mutex->lock(); +// return (_output_device == Monitor) ? _run_builders[_run_write_pointer]->get_next_run(6) : _composite_src_runs->get_next_run(2); } inline void complete_input_run() { - _output_mutex->unlock(); + _run_builders[_run_write_pointer]->number_of_vertices += 6; +// _output_mutex->unlock(); } inline uint8_t *get_next_output_run() { - _output_mutex->lock(); - return (_output_device == Monitor) ? _run_builders[_run_write_pointer]->get_next_run(6) : _composite_src_runs->get_next_run(2); +// _output_mutex->lock(); +// return (_output_device == Monitor) ? _run_builders[_run_write_pointer]->get_next_run(6) : _composite_src_runs->get_next_run(2); + return nullptr; } inline void complete_output_run() { +// _output_mutex->unlock(); } inline OutputDevice get_output_device() @@ -183,7 +193,9 @@ class OpenGLOutputBuilder { inline void increment_field() { _run_write_pointer = (_run_write_pointer + 1)%NumberOfFields; - _run_builders[_run_write_pointer]->reset(); + _run_builders[_run_write_pointer]->start = _output_buffer_data_pointer; + _run_builders[_run_write_pointer]->duration = 0; + _run_builders[_run_write_pointer]->number_of_vertices = 0; } inline void allocate_write_area(size_t required_length) @@ -228,6 +240,9 @@ class OpenGLOutputBuilder { // TODO: update related uniforms } + + uint8_t *_output_buffer_data; + size_t _output_buffer_data_pointer; }; } diff --git a/Outputs/CRT/Internals/CRTRunBuilder.cpp b/Outputs/CRT/Internals/CRTRunBuilder.cpp index b67356eb3..9d6df1384 100644 --- a/Outputs/CRT/Internals/CRTRunBuilder.cpp +++ b/Outputs/CRT/Internals/CRTRunBuilder.cpp @@ -11,7 +11,7 @@ using namespace Outputs::CRT; -void CRTRunBuilder::reset() +/*void CRTRunBuilder::reset() { number_of_vertices = 0; uploaded_vertices = 0; @@ -31,3 +31,4 @@ uint8_t *CRTRunBuilder::get_next_run(size_t number_of_vertices_in_run) return next_run; } +*/ \ No newline at end of file diff --git a/Outputs/CRT/Internals/CRTRunBuilder.hpp b/Outputs/CRT/Internals/CRTRunBuilder.hpp index f5969a304..db7020647 100644 --- a/Outputs/CRT/Internals/CRTRunBuilder.hpp +++ b/Outputs/CRT/Internals/CRTRunBuilder.hpp @@ -15,24 +15,25 @@ namespace Outputs { namespace CRT { struct CRTRunBuilder { - CRTRunBuilder(size_t vertex_size) : _vertex_size(vertex_size) { reset(); } + CRTRunBuilder(size_t vertex_size) : _vertex_size(vertex_size), duration(0), start(0), number_of_vertices(0) {} // reset(); // Resets the run builder. - void reset(); +// void reset(); // Getter for new storage plus backing storage; in RGB mode input runs will map directly // from the input buffer to the screen. In composite mode input runs will map from the // input buffer to the processing buffer, and output runs will map from the processing // buffer to the screen. - uint8_t *get_next_run(size_t number_of_vertices); - std::vector _runs; +// uint8_t *get_next_run(size_t number_of_vertices); +// std::vector _runs; // Container for total length in cycles of all contained runs. uint32_t duration; + size_t start; // Storage for the length of run data uploaded so far; reset to zero by reset but otherwise // entrusted to the CRT to update. - size_t uploaded_vertices; +// size_t uploaded_vertices; size_t number_of_vertices; private: