1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-01 22:41:32 +00:00

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> </Testables>
</TestAction> </TestAction>
<LaunchAction <LaunchAction
buildConfiguration = "Debug" buildConfiguration = "Release"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
enableASanStackUseAfterReturn = "YES" enableASanStackUseAfterReturn = "YES"

View File

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

View File

@ -50,7 +50,7 @@ void Metrics::announce_did_resize() {
frames_missed_ = frames_hit_ = 0; 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) { if(!complete) {
++frames_missed_; ++frames_missed_;
} else { } 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 { bool Metrics::should_lower_resolution() const {
// If less than 100 frames are on record, return no opinion; otherwise // 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 // 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. /// 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); 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. /// @returns @c true if Metrics thinks a lower output buffer resolution is desirable in the abstract; @c false otherwise.
bool should_lower_resolution() const; bool should_lower_resolution() const;