Uses DisplayMetrics to disable supersampling when too slow.

This commit is contained in:
Thomas Harte 2020-09-13 21:07:59 -04:00
parent d7972a7b86
commit c5e9a74c88
4 changed files with 30 additions and 6 deletions

View File

@ -67,7 +67,7 @@
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
buildConfiguration = "Release"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
enableASanStackUseAfterReturn = "YES"

View File

@ -276,6 +276,7 @@ using BufferingScanTarget = Outputs::Display::BufferingScanTarget;
// Additional pipeline information.
size_t _lumaKernelSize;
size_t _chromaKernelSize;
std::atomic<bool> _isUsingSupersampling;
// The output view.
__weak MTKView *_view;
@ -359,14 +360,22 @@ using BufferingScanTarget = Outputs::Display::BufferingScanTarget;
[self setAspectRatio];
@synchronized(self) {
// Always [re]try multisampling upon a resize.
_scanTarget.display_metrics_.announce_did_resize();
_isUsingSupersampling = true;
[self updateSizeBuffersToSize:size];
}
}
- (void)updateSizeBuffers {
@synchronized(self) {
[self updateSizeBuffersToSize:_view.drawableSize];
}
}
- (void)updateSizeBuffersToSize:(CGSize)size {
// TODO: above what size threshold is supersampling no longer desired?
const NSUInteger frameBufferWidth = NSUInteger(size.width * _view.layer.contentsScale) * 2;
const NSUInteger frameBufferHeight = NSUInteger(size.height * _view.layer.contentsScale) * 2;
const NSUInteger frameBufferWidth = NSUInteger(size.width * _view.layer.contentsScale) * (_isUsingSupersampling ? 2 : 1);
const NSUInteger frameBufferHeight = NSUInteger(size.height * _view.layer.contentsScale) * (_isUsingSupersampling ? 2 : 1);
// Generate a framebuffer and a stencil.
MTLTextureDescriptor *const textureDescriptor = [MTLTextureDescriptor
@ -1075,9 +1084,16 @@ using BufferingScanTarget = Outputs::Display::BufferingScanTarget;
*/
- (void)drawInMTKView:(nonnull MTKView *)view {
if(_isDrawing.test_and_set()) {
_scanTarget.display_metrics_.announce_draw_status(false);
return;
}
// Disable supersampling if performance requires it.
if(_isUsingSupersampling && _scanTarget.display_metrics_.should_lower_resolution()) {
_isUsingSupersampling = false;
[self updateSizeBuffers];
}
// Schedule a copy from the current framebuffer to the view; blitting is unavailable as the target is a framebuffer texture.
id<MTLCommandBuffer> commandBuffer = [_commandQueue commandBuffer];
@ -1085,7 +1101,7 @@ using BufferingScanTarget = Outputs::Display::BufferingScanTarget;
view.currentRenderPassDescriptor.colorAttachments[0].loadAction = MTLLoadActionDontCare;
id<MTLRenderCommandEncoder> encoder = [commandBuffer renderCommandEncoderWithDescriptor:view.currentRenderPassDescriptor];
[encoder setRenderPipelineState:_supersamplePipeline];
[encoder setRenderPipelineState:_isUsingSupersampling ? _supersamplePipeline : _copyPipeline];
[encoder setVertexTexture:_frameBuffer atIndex:0];
[encoder setFragmentTexture:_frameBuffer atIndex:0];
@ -1095,6 +1111,7 @@ using BufferingScanTarget = Outputs::Display::BufferingScanTarget;
[commandBuffer presentDrawable:view.currentDrawable];
[commandBuffer addCompletedHandler:^(id<MTLCommandBuffer> _Nonnull) {
self->_isDrawing.clear();
self->_scanTarget.display_metrics_.announce_draw_status(true);
}];
[commandBuffer commit];
}

View File

@ -50,7 +50,7 @@ void Metrics::announce_did_resize() {
frames_missed_ = frames_hit_ = 0;
}
void Metrics::announce_draw_status(size_t, std::chrono::high_resolution_clock::duration, bool complete) {
void Metrics::announce_draw_status(bool complete) {
if(!complete) {
++frames_missed_;
} else {
@ -79,6 +79,10 @@ void Metrics::announce_draw_status(size_t, std::chrono::high_resolution_clock::d
}
}
void Metrics::announce_draw_status(size_t, std::chrono::high_resolution_clock::duration, bool complete) {
announce_draw_status(complete);
}
bool Metrics::should_lower_resolution() const {
// 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

View File

@ -33,6 +33,9 @@ class Metrics {
/// Provides Metrics with a new data point for output speed estimation.
void announce_draw_status(size_t lines, std::chrono::high_resolution_clock::duration duration, bool complete);
/// Provides Metrics with a new data point for output speed estimation, albeit without line-specific information.
void announce_draw_status(bool complete);
/// @returns @c true if Metrics thinks a lower output buffer resolution is desirable in the abstract; @c false otherwise.
bool should_lower_resolution() const;