mirror of
https://github.com/TomHarte/CLK.git
synced 2024-09-13 20:55:40 +00:00
As messy as it is, this use glMapBufferRange
to avoid explicit buffer submits.
This commit is contained in:
parent
ca35a7e222
commit
0d27d3bb7f
@ -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);
|
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);
|
glGenVertexArrays(1, &output_vertex_array);
|
||||||
glGenBuffers(1, &output_array_buffer);
|
glGenBuffers(1, &output_array_buffer);
|
||||||
output_vertices_per_slice = 0;
|
output_vertices_per_slice = 0;
|
||||||
|
|
||||||
prepare_composite_input_shader();
|
|
||||||
prepare_rgb_output_shader();
|
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, output_array_buffer);
|
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);
|
glBindVertexArray(output_vertex_array);
|
||||||
prepare_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
|
// check for anything to decode from composite
|
||||||
if(_composite_src_runs->number_of_vertices)
|
if(_composite_src_runs->number_of_vertices)
|
||||||
{
|
{
|
||||||
composite_input_shader_program->bind();
|
// composite_input_shader_program->bind();
|
||||||
_composite_src_runs->reset();
|
// _composite_src_runs->reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
// _output_mutex->unlock();
|
// _output_mutex->unlock();
|
||||||
@ -156,24 +160,24 @@ void OpenGLOutputBuilder::draw_frame(unsigned int output_width, unsigned int out
|
|||||||
// glGetIntegerv(GL_VIEWPORT, results);
|
// glGetIntegerv(GL_VIEWPORT, results);
|
||||||
|
|
||||||
// ensure array buffer is up to date
|
// ensure array buffer is up to date
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, output_array_buffer);
|
// glBindBuffer(GL_ARRAY_BUFFER, output_array_buffer);
|
||||||
size_t max_number_of_vertices = 0;
|
// size_t max_number_of_vertices = 0;
|
||||||
for(int c = 0; c < NumberOfFields; c++)
|
// for(int c = 0; c < NumberOfFields; c++)
|
||||||
{
|
// {
|
||||||
max_number_of_vertices = std::max(max_number_of_vertices, _run_builders[c]->number_of_vertices);
|
// 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)
|
// if(output_vertices_per_slice < max_number_of_vertices)
|
||||||
{
|
// {
|
||||||
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);
|
// glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(max_number_of_vertices * OutputVertexSize * OutputVertexSize), NULL, GL_STREAM_DRAW);
|
||||||
|
//
|
||||||
for(unsigned int c = 0; c < NumberOfFields; c++)
|
// for(unsigned int c = 0; c < NumberOfFields; c++)
|
||||||
{
|
// {
|
||||||
uint8_t *data = &_run_builders[c]->_runs[0];
|
// 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);
|
// 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;
|
// _run_builders[c]->uploaded_vertices = _run_builders[c]->number_of_vertices;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
// switch to the output shader
|
// switch to the output shader
|
||||||
if(rgb_shader_program)
|
if(rgb_shader_program)
|
||||||
@ -202,17 +206,29 @@ void OpenGLOutputBuilder::draw_frame(unsigned int output_width, unsigned int out
|
|||||||
{
|
{
|
||||||
glUniform1f(timestampBaseUniform, (GLfloat)total_age);
|
glUniform1f(timestampBaseUniform, (GLfloat)total_age);
|
||||||
|
|
||||||
if(_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];
|
// uint8_t *data = &_run_builders[run]->_runs[_run_builders[run]->uploaded_vertices * OutputVertexSize];
|
||||||
glBufferSubData(GL_ARRAY_BUFFER,
|
// glBufferSubData(GL_ARRAY_BUFFER,
|
||||||
(GLsizeiptr)(((run * output_vertices_per_slice) + _run_builders[run]->uploaded_vertices) * OutputVertexSize),
|
// (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);
|
// (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;
|
// _run_builders[run]->uploaded_vertices = _run_builders[run]->number_of_vertices;
|
||||||
}
|
// }
|
||||||
|
|
||||||
// draw this frame
|
// 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
|
// advance back in time
|
||||||
@ -549,11 +565,11 @@ void OpenGLOutputBuilder::set_output_device(OutputDevice output_device)
|
|||||||
{
|
{
|
||||||
_output_device = output_device;
|
_output_device = output_device;
|
||||||
|
|
||||||
for(int builder = 0; builder < NumberOfFields; builder++)
|
// for(int builder = 0; builder < NumberOfFields; builder++)
|
||||||
{
|
// {
|
||||||
_run_builders[builder]->reset();
|
// _run_builders[builder]->reset();
|
||||||
}
|
// }
|
||||||
_composite_src_runs->reset();
|
// _composite_src_runs->reset();
|
||||||
_composite_src_output_y = 0;
|
_composite_src_output_y = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,6 +47,9 @@ const int InputBufferBuilderHeight = 1024;
|
|||||||
const int IntermediateBufferWidth = 2048;
|
const int IntermediateBufferWidth = 2048;
|
||||||
const int IntermediateBufferHeight = 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
|
// 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
|
// 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
|
// number of historic fields that are required fully to
|
||||||
@ -136,23 +139,30 @@ class OpenGLOutputBuilder {
|
|||||||
|
|
||||||
inline uint8_t *get_next_input_run()
|
inline uint8_t *get_next_input_run()
|
||||||
{
|
{
|
||||||
_output_mutex->lock();
|
if (_output_buffer_data_pointer + 6 * InputVertexSize > buffer_size) _output_buffer_data_pointer = 0;
|
||||||
return (_output_device == Monitor) ? _run_builders[_run_write_pointer]->get_next_run(6) : _composite_src_runs->get_next_run(2);
|
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()
|
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()
|
inline uint8_t *get_next_output_run()
|
||||||
{
|
{
|
||||||
_output_mutex->lock();
|
// _output_mutex->lock();
|
||||||
return (_output_device == Monitor) ? _run_builders[_run_write_pointer]->get_next_run(6) : _composite_src_runs->get_next_run(2);
|
// 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()
|
inline void complete_output_run()
|
||||||
{
|
{
|
||||||
|
// _output_mutex->unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline OutputDevice get_output_device()
|
inline OutputDevice get_output_device()
|
||||||
@ -183,7 +193,9 @@ class OpenGLOutputBuilder {
|
|||||||
inline void increment_field()
|
inline void increment_field()
|
||||||
{
|
{
|
||||||
_run_write_pointer = (_run_write_pointer + 1)%NumberOfFields;
|
_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)
|
inline void allocate_write_area(size_t required_length)
|
||||||
@ -228,6 +240,9 @@ class OpenGLOutputBuilder {
|
|||||||
|
|
||||||
// TODO: update related uniforms
|
// TODO: update related uniforms
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t *_output_buffer_data;
|
||||||
|
size_t _output_buffer_data_pointer;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
using namespace Outputs::CRT;
|
using namespace Outputs::CRT;
|
||||||
|
|
||||||
void CRTRunBuilder::reset()
|
/*void CRTRunBuilder::reset()
|
||||||
{
|
{
|
||||||
number_of_vertices = 0;
|
number_of_vertices = 0;
|
||||||
uploaded_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;
|
return next_run;
|
||||||
}
|
}
|
||||||
|
*/
|
@ -15,24 +15,25 @@ namespace Outputs {
|
|||||||
namespace CRT {
|
namespace CRT {
|
||||||
|
|
||||||
struct CRTRunBuilder {
|
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.
|
// Resets the run builder.
|
||||||
void reset();
|
// void reset();
|
||||||
|
|
||||||
// Getter for new storage plus backing storage; in RGB mode input runs will map directly
|
// 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
|
// 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
|
// input buffer to the processing buffer, and output runs will map from the processing
|
||||||
// buffer to the screen.
|
// buffer to the screen.
|
||||||
uint8_t *get_next_run(size_t number_of_vertices);
|
// uint8_t *get_next_run(size_t number_of_vertices);
|
||||||
std::vector<uint8_t> _runs;
|
// std::vector<uint8_t> _runs;
|
||||||
|
|
||||||
// Container for total length in cycles of all contained runs.
|
// Container for total length in cycles of all contained runs.
|
||||||
uint32_t duration;
|
uint32_t duration;
|
||||||
|
size_t start;
|
||||||
|
|
||||||
// Storage for the length of run data uploaded so far; reset to zero by reset but otherwise
|
// Storage for the length of run data uploaded so far; reset to zero by reset but otherwise
|
||||||
// entrusted to the CRT to update.
|
// entrusted to the CRT to update.
|
||||||
size_t uploaded_vertices;
|
// size_t uploaded_vertices;
|
||||||
size_t number_of_vertices;
|
size_t number_of_vertices;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Loading…
Reference in New Issue
Block a user