mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-26 09:29:45 +00:00
Reduces draw/update contention.
This won't yet have any effect on either port owing to the way they handle contexts, but here it is.
This commit is contained in:
parent
24fb95291a
commit
6f7dd10d95
@ -101,29 +101,31 @@ ScanTarget::ScanTarget(GLuint target_framebuffer, float output_gamma) :
|
|||||||
test_gl(glBlendFunc, GL_SRC_ALPHA, GL_CONSTANT_COLOR);
|
test_gl(glBlendFunc, GL_SRC_ALPHA, GL_CONSTANT_COLOR);
|
||||||
test_gl(glBlendColor, 0.4f, 0.4f, 0.4f, 1.0f);
|
test_gl(glBlendColor, 0.4f, 0.4f, 0.4f, 1.0f);
|
||||||
|
|
||||||
is_drawing_.clear();
|
// Establish initial state for the two atomic flags.
|
||||||
|
is_updating_.clear();
|
||||||
|
is_drawing_to_accumulation_buffer_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
ScanTarget::~ScanTarget() {
|
ScanTarget::~ScanTarget() {
|
||||||
while(is_drawing_.test_and_set());
|
while(is_updating_.test_and_set());
|
||||||
glDeleteBuffers(1, &scan_buffer_name_);
|
glDeleteBuffers(1, &scan_buffer_name_);
|
||||||
glDeleteTextures(1, &write_area_texture_name_);
|
glDeleteTextures(1, &write_area_texture_name_);
|
||||||
glDeleteVertexArrays(1, &scan_vertex_array_);
|
glDeleteVertexArrays(1, &scan_vertex_array_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScanTarget::set_target_framebuffer(GLuint target_framebuffer) {
|
void ScanTarget::set_target_framebuffer(GLuint target_framebuffer) {
|
||||||
while(is_drawing_.test_and_set());
|
while(is_updating_.test_and_set());
|
||||||
target_framebuffer_ = target_framebuffer;
|
target_framebuffer_ = target_framebuffer;
|
||||||
is_drawing_.clear();
|
is_updating_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScanTarget::set_modals(Modals modals) {
|
void ScanTarget::set_modals(Modals modals) {
|
||||||
// Don't change the modals while drawing is ongoing; a previous set might be
|
// Don't change the modals while drawing is ongoing; a previous set might be
|
||||||
// in the process of being established.
|
// in the process of being established.
|
||||||
while(is_drawing_.test_and_set());
|
while(is_updating_.test_and_set());
|
||||||
modals_ = modals;
|
modals_ = modals;
|
||||||
modals_are_dirty_ = true;
|
modals_are_dirty_ = true;
|
||||||
is_drawing_.clear();
|
is_updating_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
Outputs::Display::ScanTarget::Scan *ScanTarget::begin_scan() {
|
Outputs::Display::ScanTarget::Scan *ScanTarget::begin_scan() {
|
||||||
@ -410,7 +412,7 @@ void ScanTarget::update(int output_width, int output_height) {
|
|||||||
|
|
||||||
// Spin until the is-drawing flag is reset; the wait sync above will deal
|
// Spin until the is-drawing flag is reset; the wait sync above will deal
|
||||||
// with instances where waiting is inappropriate.
|
// with instances where waiting is inappropriate.
|
||||||
while(is_drawing_.test_and_set());
|
while(is_updating_.test_and_set());
|
||||||
|
|
||||||
// Establish the pipeline if necessary.
|
// Establish the pipeline if necessary.
|
||||||
const bool did_setup_pipeline = modals_are_dirty_;
|
const bool did_setup_pipeline = modals_are_dirty_;
|
||||||
@ -568,6 +570,9 @@ void ScanTarget::update(int output_width, int output_height) {
|
|||||||
const int framebuffer_height = std::max(output_height / resolution_reduction_level_, std::min(540, output_height));
|
const int framebuffer_height = std::max(output_height / resolution_reduction_level_, std::min(540, output_height));
|
||||||
const int proportional_width = (framebuffer_height * 4) / 3;
|
const int proportional_width = (framebuffer_height * 4) / 3;
|
||||||
const bool did_create_accumulation_texture = !accumulation_texture_ || ( (accumulation_texture_->get_width() != proportional_width || accumulation_texture_->get_height() != framebuffer_height));
|
const bool did_create_accumulation_texture = !accumulation_texture_ || ( (accumulation_texture_->get_width() != proportional_width || accumulation_texture_->get_height() != framebuffer_height));
|
||||||
|
|
||||||
|
// Work with the accumulation_buffer_ potentially starts from here onwards; set its flag.
|
||||||
|
while(is_drawing_to_accumulation_buffer_.test_and_set());
|
||||||
if(did_create_accumulation_texture) {
|
if(did_create_accumulation_texture) {
|
||||||
LOG("Changed output resolution to " << proportional_width << " by " << framebuffer_height);
|
LOG("Changed output resolution to " << proportional_width << " by " << framebuffer_height);
|
||||||
display_metrics_.announce_did_resize();
|
display_metrics_.announce_did_resize();
|
||||||
@ -701,18 +706,21 @@ void ScanTarget::update(int output_width, int output_height) {
|
|||||||
test_gl(glDisable, GL_BLEND);
|
test_gl(glDisable, GL_BLEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// That's it for operations affecting the accumulation buffer.
|
||||||
|
is_drawing_to_accumulation_buffer_.clear();
|
||||||
|
|
||||||
// All data now having been spooled to the GPU, update the read pointers to
|
// All data now having been spooled to the GPU, update the read pointers to
|
||||||
// the submit pointer location.
|
// the submit pointer location.
|
||||||
read_pointers_.store(submit_pointers);
|
read_pointers_.store(submit_pointers);
|
||||||
|
|
||||||
// Grab a fence sync object to avoid busy waiting upon the next extry into this
|
// Grab a fence sync object to avoid busy waiting upon the next extry into this
|
||||||
// function, and reset the is_drawing_ flag.
|
// function, and reset the is_updating_ flag.
|
||||||
fence_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
fence_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||||
is_drawing_.clear();
|
is_updating_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScanTarget::draw(int output_width, int output_height) {
|
void ScanTarget::draw(int output_width, int output_height) {
|
||||||
while(is_drawing_.test_and_set());
|
while(is_drawing_to_accumulation_buffer_.test_and_set());
|
||||||
|
|
||||||
if(accumulation_texture_) {
|
if(accumulation_texture_) {
|
||||||
// Copy the accumulation texture to the target.
|
// Copy the accumulation texture to the target.
|
||||||
@ -725,5 +733,5 @@ void ScanTarget::draw(int output_width, int output_height) {
|
|||||||
accumulation_texture_->draw(float(output_width) / float(output_height), 4.0f / 255.0f);
|
accumulation_texture_->draw(float(output_width) / float(output_height), 4.0f / 255.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
is_drawing_.clear();
|
is_drawing_to_accumulation_buffer_.clear();
|
||||||
}
|
}
|
||||||
|
@ -209,7 +209,8 @@ class ScanTarget: public Outputs::Display::ScanTarget {
|
|||||||
std::vector<std::string> bindings(ShaderType type) const;
|
std::vector<std::string> bindings(ShaderType type) const;
|
||||||
|
|
||||||
GLsync fence_ = nullptr;
|
GLsync fence_ = nullptr;
|
||||||
std::atomic_flag is_drawing_;
|
std::atomic_flag is_updating_;
|
||||||
|
std::atomic_flag is_drawing_to_accumulation_buffer_;
|
||||||
|
|
||||||
std::unique_ptr<Shader> input_shader_;
|
std::unique_ptr<Shader> input_shader_;
|
||||||
std::unique_ptr<Shader> output_shader_;
|
std::unique_ptr<Shader> output_shader_;
|
||||||
|
Loading…
Reference in New Issue
Block a user