1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-17 13:29:02 +00:00
CLK/Outputs/CRT/Internals/ArrayBuilder.cpp

123 lines
2.8 KiB
C++
Raw Normal View History

//
// ArrayBuilder.cpp
// Clock Signal
//
// Created by Thomas Harte on 17/11/2016.
// Copyright © 2016 Thomas Harte. All rights reserved.
//
#include "ArrayBuilder.hpp"
using namespace Outputs::CRT;
ArrayBuilder::ArrayBuilder(size_t input_size, size_t output_size) :
output_(output_size),
input_(input_size)
{}
ArrayBuilder::Buffer::Buffer(size_t size) :
allocated_data(0), completed_data(0)
{
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)size, NULL, GL_STREAM_DRAW);
data.resize(size);
}
ArrayBuilder::Buffer::~Buffer()
{
glDeleteBuffers(1, &buffer);
}
uint8_t *ArrayBuilder::get_input_storage(size_t size)
{
return input_.get_storage(size);
}
uint8_t *ArrayBuilder::get_output_storage(size_t size)
{
return output_.get_storage(size);
}
void ArrayBuilder::flush()
{
// TODO: don't flush anything if either buffer was exhausted
buffer_mutex_.lock();
input_.flush();
output_.flush();
buffer_mutex_.unlock();
}
void ArrayBuilder::bind_input()
{
input_.bind();
}
void ArrayBuilder::bind_output()
{
output_.bind();
}
ArrayBuilder::Submission ArrayBuilder::submit()
{
ArrayBuilder::Submission submission;
buffer_mutex_.lock();
submission.input_size = input_.submit();
submission.output_size = output_.submit();
buffer_mutex_.unlock();
// TODO: if either buffer was exhausted, reset both
return submission;
}
uint8_t *ArrayBuilder::Buffer::get_storage(size_t size)
{
if(allocated_data + size > data.size()) return nullptr;
uint8_t *pointer = &data[allocated_data];
vended_pointer = allocated_data;
allocated_data += size;
return pointer;
}
void ArrayBuilder::Buffer::flush()
{
// Ordinarily this just requires the completed data count to be bumped up
// to the current allocated data value. However if the amount of allocated
// data is now less than the completed data then that implies a submission
// occurred while the pointer previously vended by get_storage was in use.
// So copy whatever is danging back to the start and make amends.
if(completed_data < allocated_data)
completed_data = allocated_data;
else
{
completed_data = allocated_data - vended_pointer;
allocated_data = completed_data;
memcpy(data.data(), &data[vended_pointer], completed_data);
}
}
size_t ArrayBuilder::Buffer::submit()
{
size_t length = completed_data;
glBindBuffer(GL_ARRAY_BUFFER, buffer);
uint8_t *destination = (uint8_t *)glMapBufferRange(GL_ARRAY_BUFFER, 0, (GLsizeiptr)length, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_FLUSH_EXPLICIT_BIT);
memcpy(destination, data.data(), length);
glFlushMappedBufferRange(GL_ARRAY_BUFFER, 0, (GLsizeiptr)length);
glUnmapBuffer(GL_ARRAY_BUFFER);
completed_data = 0;
return length;
}
void ArrayBuilder::Buffer::bind()
{
glBindBuffer(GL_ARRAY_BUFFER, buffer);
}
void ArrayBuilder::Buffer::reset()
{
completed_data = allocated_data = 0;
}