mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-29 12:50:28 +00:00
Experimentally introduces adaptive quality intermediate buffers.
This commit is contained in:
parent
cfebf1dc4a
commit
5660007221
@ -8,13 +8,72 @@
|
|||||||
|
|
||||||
#include "DisplayMetrics.hpp"
|
#include "DisplayMetrics.hpp"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
using namespace Outputs::Display;
|
using namespace Outputs::Display;
|
||||||
|
|
||||||
|
// MARK: Frame size estimation.
|
||||||
|
|
||||||
void Metrics::announce_event(ScanTarget::Event event) {
|
void Metrics::announce_event(ScanTarget::Event event) {
|
||||||
|
switch(event) {
|
||||||
|
case ScanTarget::Event::EndHorizontalRetrace:
|
||||||
|
++lines_this_frame_;
|
||||||
|
break;
|
||||||
|
case ScanTarget::Event::EndVerticalRetrace:
|
||||||
|
add_line_total(lines_this_frame_);
|
||||||
|
lines_this_frame_ = 0;
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Metrics::add_line_total(int total) {
|
||||||
|
// std::cout << total << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
float Metrics::lines_per_frame_estimate() {
|
||||||
|
return 1.0f; // TODO.
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: GPU processing speed decisions.
|
||||||
|
|
||||||
void Metrics::announce_did_resize() {
|
void Metrics::announce_did_resize() {
|
||||||
|
frames_missed_ = frames_hit_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Metrics::announce_draw_status(size_t lines, std::chrono::high_resolution_clock::duration duration, bool complete) {
|
void Metrics::announce_draw_status(size_t lines, std::chrono::high_resolution_clock::duration duration, bool complete) {
|
||||||
|
if(!complete) {
|
||||||
|
++frames_missed_;
|
||||||
|
} else {
|
||||||
|
++frames_hit_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't allow the record of history to extend too far into the past.
|
||||||
|
if(frames_hit_ + frames_missed_ > 200) {
|
||||||
|
// Subtract from whichever wasn't just incremented, to ensure the
|
||||||
|
// most recent information is more important than the historic stuff.
|
||||||
|
if(!complete) {
|
||||||
|
--frames_hit_;
|
||||||
|
} else {
|
||||||
|
--frames_missed_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rebalance if either thing has gone negative.
|
||||||
|
if(frames_hit_ < 0) {
|
||||||
|
frames_missed_ += frames_hit_;
|
||||||
|
frames_hit_ = 0;
|
||||||
|
}
|
||||||
|
if(frames_missed_ < 0) {
|
||||||
|
frames_hit_ += frames_missed_;
|
||||||
|
frames_missed_ = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Metrics::should_lower_resolution() {
|
||||||
|
// If less than 100 frames are on record, return no opinion; otherwise
|
||||||
|
// suggest a lower resolution if more than 10 frames in the last 100-200
|
||||||
|
// took too long to produce.
|
||||||
|
if(frames_hit_ + frames_missed_ < 100) return false;
|
||||||
|
return frames_missed_ > 10;
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,16 @@ class Metrics {
|
|||||||
|
|
||||||
void announce_did_resize();
|
void announce_did_resize();
|
||||||
void announce_draw_status(size_t lines, std::chrono::high_resolution_clock::duration duration, bool complete);
|
void announce_draw_status(size_t lines, std::chrono::high_resolution_clock::duration duration, bool complete);
|
||||||
|
|
||||||
|
bool should_lower_resolution();
|
||||||
|
float lines_per_frame_estimate();
|
||||||
|
|
||||||
|
private:
|
||||||
|
int lines_this_frame_ = 0;
|
||||||
|
void add_line_total(int);
|
||||||
|
|
||||||
|
int frames_hit_ = 0;
|
||||||
|
int frames_missed_ = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ TextureTarget::TextureTarget(GLsizei width, GLsizei height, GLenum texture_unit,
|
|||||||
bind_texture();
|
bind_texture();
|
||||||
|
|
||||||
// Set dimensions and set the user-supplied magnification filter.
|
// Set dimensions and set the user-supplied magnification filter.
|
||||||
test_gl(glTexImage2D, GL_TEXTURE_2D, 0, GL_RGBA, GLsizei(expanded_width_), GLsizei(expanded_height_), 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
test_gl(glTexImage2D, GL_TEXTURE_2D, 0, GL_RGB, GLsizei(expanded_width_), GLsizei(expanded_height_), 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
|
||||||
test_gl(glTexParameteri, GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter);
|
test_gl(glTexParameteri, GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter);
|
||||||
test_gl(glTexParameteri, GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
test_gl(glTexParameteri, GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
using namespace Outputs::Display::OpenGL;
|
using namespace Outputs::Display::OpenGL;
|
||||||
|
|
||||||
@ -550,13 +551,26 @@ void ScanTarget::update(int output_width, int output_height) {
|
|||||||
test_gl(glDrawArraysInstanced, GL_TRIANGLE_STRIP, 0, 4, GLsizei(new_scans));
|
test_gl(glDrawArraysInstanced, GL_TRIANGLE_STRIP, 0, 4, GLsizei(new_scans));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the accumulation buffer is properly sized.
|
// Logic for reducing resolution: start doing so if the metrics object reports that
|
||||||
// TODO: based on a decision about host speed, potentially switch to the std::min fragment as shown below,
|
// it's a good idea. Go up to a quarter of the requested resolution, subject to
|
||||||
// which would limit total output buffer size to 1440x1080.
|
// clamping at each stage. If the output resolution changes, or anything else about
|
||||||
const int framebuffer_height = output_height;//std::min(output_height, 1080);
|
// the output pipeline, just start trying the highest size again.
|
||||||
|
if(display_metrics_.should_lower_resolution()) {
|
||||||
|
resolution_reduction_level_ = std::min(resolution_reduction_level_+1, 4);
|
||||||
|
}
|
||||||
|
if(output_height_ != output_height || did_setup_pipeline) {
|
||||||
|
resolution_reduction_level_ = 1;
|
||||||
|
output_height_ = output_height;
|
||||||
|
}
|
||||||
|
const int min_framebuffer_height = (resolution_reduction_level_ > 1) ? 2160 / resolution_reduction_level_ : std::numeric_limits<int>::max();
|
||||||
|
|
||||||
|
// Ensure the accumulation buffer is properly sized, allowing for the metrics object's
|
||||||
|
// feelings about whether too high a resolution is being used.
|
||||||
|
int framebuffer_height = std::min(output_height / resolution_reduction_level_, min_framebuffer_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_ || ( /* !synchronous && */ (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));
|
||||||
if(did_create_accumulation_texture) {
|
if(did_create_accumulation_texture) {
|
||||||
|
LOG("Changed output resolution to " << proportional_width << " by " << framebuffer_height);
|
||||||
display_metrics_.announce_did_resize();
|
display_metrics_.announce_did_resize();
|
||||||
std::unique_ptr<OpenGL::TextureTarget> new_framebuffer(
|
std::unique_ptr<OpenGL::TextureTarget> new_framebuffer(
|
||||||
new TextureTarget(
|
new TextureTarget(
|
||||||
|
@ -84,6 +84,8 @@ class ScanTarget: public Outputs::Display::ScanTarget {
|
|||||||
bool output_is_visible_ = false;
|
bool output_is_visible_ = false;
|
||||||
|
|
||||||
Metrics display_metrics_;
|
Metrics display_metrics_;
|
||||||
|
int resolution_reduction_level_ = 1;
|
||||||
|
int output_height_ = 0;
|
||||||
|
|
||||||
size_t lines_submitted_ = 0;
|
size_t lines_submitted_ = 0;
|
||||||
std::chrono::high_resolution_clock::time_point line_submission_begin_time_;
|
std::chrono::high_resolution_clock::time_point line_submission_begin_time_;
|
||||||
|
Loading…
Reference in New Issue
Block a user