Merge branch 'perfMode' into Integration

This commit is contained in:
TrueZhuanjia
2025-08-30 18:57:59 +08:00
7 changed files with 71 additions and 31 deletions
+32 -3
View File
@@ -3537,6 +3537,35 @@
}
}
},
"PerfModeTip" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "- Changing the rendering mode requires restarting the application to ensure a clean start.\n\n- Performance mode is an experimental feature and cannot guarantee a positive impact on the streaming experience.\n\n- HDR under performance mode for devices of limited dynamic range like iPad mini(LCD display) could be broken.\n\n- Tapping “Quit Now” means I acknowledge the above information."
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "- 更改渲染模式需要重启应用以确保干净启动。\n\n- 性能模式为实验性功能,无法保证开启后对串流体验产生正向优化。 \n\n- 有限动态范围设备,如采用LCD的iPad mini,开启性能模式后可能无法正常显示HDR画面。\n\n- 点击“立即退出”代表我已知悉以上内容。"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "- 更改渲染模式需要重新啟動應用程式以確保乾淨啟動。\n\n- 效能模式為實驗性功能,無法保證開啟後對串流體驗產生正向優化。\n\n- 有限動態範圍裝置,如採用 LCD 的 iPad mini,開啟效能模式後可能無法正常顯示 HDR 畫面。\n\n- 點擊「立即退出」代表我已知悉以上內容。"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "- 更改渲染模式需要重新啟動應用程式以確保乾淨啟動。\n\n- 效能模式為實驗性功能,無法保證開啟後對串流體驗產生正向優化。\n\n- 有限動態範圍裝置,如採用 LCD 的 iPad mini,開啟效能模式後可能無法正常顯示 HDR 畫面。\n\n- 點擊「立即退出」代表我已知悉以上內容。"
}
}
}
},
"Performance" : {
"extractionState" : "manual",
"localizations" : {
@@ -4275,19 +4304,19 @@
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "需要重启"
"value" : "需要重启App"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "需要重新啟動"
"value" : "需要重新啟動App"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "需要重新啟動"
"value" : "需要重新啟動App"
}
}
}
+4 -1
View File
@@ -12,6 +12,7 @@
#import "ConnectionCallbacks.h"
#import "Frame.h"
#import "Plot.h"
#import "TemporarySettings.h"
@interface MetalVideoRenderer : NSObject
@@ -23,7 +24,9 @@
@property (atomic) BOOL isStopping;
@property (nonatomic) BOOL hdrEnabled;
- (nonnull instancetype)initWithMetalDevice:(nonnull id<MTLDevice>)device drawablePixelFormat:(MTLPixelFormat)drawablePixelFormat framerate:(float)framerate hdrEnabled:(BOOL)hdrEnabled;
- (instancetype _Nonnull )initWithMetalDevice:(id<MTLDevice>_Nonnull)device drawablePixelFormat:(MTLPixelFormat)drawablePixelFormat settings:(TemporarySettings* _Nonnull )currentSettings;
- (void)renderFrame:(nonnull Frame *)frame toLayer:(nonnull CAMetalLayer *)layer;
- (void)waitToRenderTo:(nonnull CAMetalLayer *)layer API_AVAILABLE(ios(13.0));
- (void)drawableResize:(CGSize)drawableSize;
+19 -12
View File
@@ -130,21 +130,24 @@ CFStringRef __currentColorSpace;
size_t _lastDrawableHeight;
id<MTLBuffer> _CscParamsBuffer;
id<MTLBuffer> _VideoVertexBuffer;
CFStringRef _nonFullHdrColorSpace;
MTLPixelFormat _nonFullHdrPixelFormat;
// https://developer.apple.com/documentation/metal/synchronizing-cpu-and-gpu-work?language=objc
dispatch_semaphore_t _inFlightSemaphore;
}
- (instancetype)initWithMetalDevice:(id<MTLDevice>)device drawablePixelFormat:(MTLPixelFormat)drawablePixelFormat framerate:(float)framerate hdrEnabled:(BOOL)hdrEnabled {
- (instancetype)initWithMetalDevice:(id<MTLDevice>)device drawablePixelFormat:(MTLPixelFormat)drawablePixelFormat settings:(TemporarySettings* )currentSettings {
self = [super init];
if (self) {
_sq = dispatch_queue_create("com.moonlight.MetalVideoRenderer",
dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_USER_INTERACTIVE, 0));
_averageGPUTime = (1.0f / framerate) / 2;
_averageGPUTime = (1.0f / currentSettings.framerate.floatValue) / 2;
_device = device;
_colorPixelFormat = drawablePixelFormat;
_framerate = framerate;
_hdrEnabled = hdrEnabled;
_framerate = currentSettings.framerate.floatValue;
_hdrEnabled = currentSettings.enableHdr;
_commandQueue = [_device newCommandQueue];
_currentEDRHeadroom = 1.0f;
_lastColorSpace = -1;
@@ -170,6 +173,10 @@ CFStringRef __currentColorSpace;
_renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(0, 0, 0, 0);
_renderPassDescriptor.colorAttachments[0].storeAction = MTLStoreActionStore;
if (@available(iOS 14.0, *)) _nonFullHdrColorSpace = kCGColorSpaceITUR_2100_PQ;
else _nonFullHdrColorSpace = kCGColorSpaceITUR_2020;
_nonFullHdrPixelFormat = MTLPixelFormatRGBA16Float;
// Initialize texture array to NULL
for (int i = 0; i < MAX_VIDEO_PLANES; i++) {
_cvMetalTextures[i] = NULL;
@@ -399,16 +406,12 @@ CFStringRef __currentColorSpace;
CFStringRef frame_trc = CFDictionaryGetValue(ext, kCVImageBufferTransferFunctionKey);
if (CFEqual(frame_trc, kCVImageBufferTransferFunction_SMPTE_ST_2084_PQ)) {
isHDR = YES;
if (@available(iOS 14.0, *)) {
newColorSpace = CGColorSpaceCreateWithName(kCGColorSpaceITUR_2100_PQ);
} else {
newColorSpace = CGColorSpaceCreateWithName(kCGColorSpaceITUR_2020);
}
newPixelFormat = MTLPixelFormatBGRA10_XR;
newColorSpace = CGColorSpaceCreateWithName(_nonFullHdrColorSpace);
newPixelFormat = _nonFullHdrPixelFormat;
} else {
// SDR 2020, I'm not sure it's possible to stream this though
newColorSpace = CGColorSpaceCreateWithName(kCGColorSpaceITUR_2020);
newPixelFormat = MTLPixelFormatBGRA10_XR;
newColorSpace = CGColorSpaceCreateWithName(_nonFullHdrColorSpace);
newPixelFormat = _nonFullHdrPixelFormat;
}
if (isHDR) {
paramBuffer.cscParams = (fullRange ? k_CscParams_Bt2020Full_10bit : k_CscParams_Bt2020Lim_10bit);
@@ -494,6 +497,10 @@ CFStringRef __currentColorSpace;
_lastColorSpace = colorspace;
_lastFullRange = fullRange;
}
// NSLog(@"layer.pixelFormat %lu", (unsigned long)layer.pixelFormat);
return YES;
}
+3 -4
View File
@@ -12,15 +12,14 @@
#import "ImGuiRenderer.h"
#import "MetalVideoRenderer.h"
#import "MetalView.h"
#import "TemporarySettings.h"
@interface MetalViewController : UIViewController <MetalViewDelegate>
@property (nonatomic) CGRect bounds;
- (nonnull instancetype)initWithFrame:(CGRect)bounds
framerate:(float)framerate
enableHdr:(BOOL)enableHdr
metricsHandler:(MetricsHandler _Nonnull)metricsHandler;
- (nonnull instancetype)initWithFrame:(CGRect)bounds framerate:(float)framerate settings:(TemporarySettings* _Nonnull )settings metricsHandler:(MetricsHandler _Nonnull)metricsHandler;
- (void)pauseRendering;
- (void)resumeRendering;
+5 -6
View File
@@ -14,20 +14,20 @@
@implementation MetalViewController {
FrameQueue *_frameQueue;
float _framerate;
BOOL _enableHdr;
TemporarySettings* _currentSettings;
MetalView *_metalView;
MetalVideoRenderer *_renderer;
MetricsHandler _metricsHandler;
CADisplayLink *_displayLink;
}
- (nonnull instancetype)initWithFrame:(CGRect)bounds framerate:(float)framerate enableHdr:(BOOL)enableHdr metricsHandler:(MetricsHandler)metricsHandler {
- (nonnull instancetype)initWithFrame:(CGRect)bounds framerate:(float)framerate settings:(TemporarySettings* )settings metricsHandler:(MetricsHandler)metricsHandler {
self = [super init];
if (self) {
_bounds = bounds;
_frameQueue = [FrameQueue sharedInstance];
_framerate = framerate;
_enableHdr = enableHdr;
_currentSettings = settings;
_metricsHandler = metricsHandler;
}
return self;
@@ -68,7 +68,7 @@
Log(LOG_W, @"Running on iOS Simulator, using BGRA8Unorm pixel format");
#else
// On real devices, check if we should enable HDR
if (_enableHdr) {
if (_currentSettings.enableHdr) {
pixelFormat = MTLPixelFormatBGRA10_XR;
Log(LOG_I, @"HDR enabled, using BGRA10_XR pixel format");
} else {
@@ -80,8 +80,7 @@
// Initialize the renderer.
MetalVideoRenderer *renderer = [[MetalVideoRenderer alloc] initWithMetalDevice:device
drawablePixelFormat:pixelFormat
framerate:self->_framerate
hdrEnabled:self->_enableHdr];
settings:_currentSettings];
if (!renderer) {
Log(LOG_E, @"The renderer couldn't be initialized.");
return;
@@ -42,6 +42,7 @@
MenuSectionView *touchAndControlSection;
MenuSectionView *videoSection;
MenuSectionView *otherSection;
MenuSectionView *experimentalSection;
NSMutableSet* hiddenStacks;
}
@@ -570,7 +571,6 @@ BOOL isCustomResolution(int resolutionSelected) {
[self addSetting:self.pipStack ofId:@"pipStack" withInfoTag:YES withDynamicLabel:NO to:videoSection];
[self addSetting:self.framePacingStack ofId:@"framePacingStack" withInfoTag:YES withDynamicLabel:NO to:videoSection];
[self addSetting:self.frameQueueSizeStack ofId:@"frameQueueSizeStack" withInfoTag:NO withDynamicLabel:YES to:videoSection];
[self addSetting:self.renderingBackendStack ofId:@"renderingBackendStack" withInfoTag:YES withDynamicLabel:NO to:videoSection];
[videoSection addToParentStack:_parentStack];
[videoSection setExpanded:YES];
@@ -657,13 +657,16 @@ BOOL isCustomResolution(int resolutionSelected) {
[otherSection setExpanded:YES];
MenuSectionView *experimentalSection = [[MenuSectionView alloc] init];
experimentalSection = [[MenuSectionView alloc] init];
experimentalSection.delegate = self;
experimentalSection.sectionTitle = [LocalizationHelper localizedStringForKey:@"Experimental"];
if (@available(iOS 13.0, *)) {
[experimentalSection setSectionWithIcon:[UIImage imageNamed:@"flask"] andSize:20];
}
[self addSetting:self.touchMoveEventIntervalStack ofId:@"touchMoveEventIntervalStack" withInfoTag:NO withDynamicLabel:YES to:experimentalSection];
[self addSetting:self.renderingBackendStack ofId:@"renderingBackendStack" withInfoTag:YES withDynamicLabel:NO to:experimentalSection];
[experimentalSection addToParentStack:_parentStack];
[experimentalSection setExpanded:YES];
}
@@ -1300,6 +1303,7 @@ BOOL isCustomResolution(int resolutionSelected) {
- (void)viewDidLoad {
//[self updateTheme];
settingStackWillBeRelocatedToLowestPosition = false;
hiddenStacks = [[NSMutableSet alloc] init];
@@ -1710,12 +1714,11 @@ BOOL isCustomResolution(int resolutionSelected) {
DataManager* dataMan = [[DataManager alloc] init];
TemporarySettings* currentSettings = [dataMan getSettings];
NSInteger previousBackend = [currentSettings.renderingBackend integerValue];
// Check if the rendering backend has actually changed
if (previousBackend != sender.selectedSegmentIndex) {
// Show alert to prompt user to restart the app
NSString *message = [LocalizationHelper localizedStringForKey:@"Rendering mode change requires app restart"];
NSString *message = [LocalizationHelper localizedStringForKey: sender.selectedSegmentIndex == 1 ? @"PerfModeTip" : @"Rendering mode change requires app restart"];
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:[LocalizationHelper localizedStringForKey:@"Restart Required"]
message:message
@@ -714,7 +714,7 @@
Log(LOG_I, @"StreamFrameViewController creating MetalViewController");
self.metalViewController = [[MetalViewController alloc] initWithFrame:self.view.bounds
framerate:[self->_settings.framerate floatValue]
enableHdr:self->_settings.enableHdr
settings:self->_settings
metricsHandler:self.imguiView.metricsHandler];
self.metalViewController.view.userInteractionEnabled = NO;
[self addChildViewController:self.metalViewController];