SwiftUI 更新降低了金属窗的 FPS
Posted
技术标签:
【中文标题】SwiftUI 更新降低了金属窗的 FPS【英文标题】:SwiftUI updates reduce FPS of metal window 【发布时间】:2019-12-06 11:30:10 【问题描述】:我正在试验 SwiftUI 和 Metal。我有 2 个窗口,一个有各种列表和控件,另一个是 Metal 窗口。
我有更新金属窗口的滑块数据,但是当我移动滑块时,FPS 从 60 下降到大约 25。我删除了视图之间的所有链接,移动滑块仍然会使金属窗口中的 FPS 下降。
列表视图似乎也会降低 FPS。
我在启动时使用以下方法创建金属窗口:
metalWindow = NSWindow(contentRect: NSRect(x: 0, y: 0, width: 480, height: 300),
styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
backing: .buffered, defer: false)
metalWindow.center()
metalWindow.setFrameAutosaveName("Metal Window")
metalWindow.makeKeyAndOrderFront(nil)
mtkView = MTKView()
mtkView.translatesAutoresizingMaskIntoConstraints = false
metalWindow.contentView!.addSubview(mtkView)
metalWindow.contentView!.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "|[mtkView]|", options: [], metrics: nil, views: ["mtkView" : mtkView!]))
metalWindow.contentView!.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[mtkView]|", options: [], metrics: nil, views: ["mtkView" : mtkView!]))
device = MTLCreateSystemDefaultDevice()!
mtkView.device = device
mtkView.colorPixelFormat = .bgra8Unorm
commandQueue = device.makeCommandQueue()!
mtkView.delegate = self
mtkView.sampleCount = 4
mtkView.clearColor = MTLClearColor(red: 0.0, green: 0.5, blue: 1.0, alpha: 1.0)
mtkView.depthStencilPixelFormat = .depth32Float
控制窗口是一个 SwiftUI 视图:
struct ControlPanelView: View
@ObservedObject var controlPanel = ControlPanel()
@State private var cameraPos = Floatx3()
@State private var lightingPos = Floatx3()
var body: some View
HStack
VStack
VStack
Text("Objects")
List(self.controlPanel.objectFiles) object in
Text(object.name)
VStack
Text("Textures")
List(self.controlPanel.textureFiles) texture in
HStack
Image(nsImage: texture.image).resizable()
.frame(width: 32, height: 32)
Text(texture.name)
VStack
HStack
XYZControl(heading: "Camera Controls", xyzPos: $cameraPos)
XYZControl(heading: "Lighting Controls", xyzPos: $lightingPos)
.padding()
HStack
Text("Frames Per Second:")
//Text(String(renderer.finalFpsCount))
.border(Color.red).padding()
struct XYZControl: View
var heading : String
@Binding var xyzPos : Floatx3
var body: some View
VStack
Text(heading).padding(.bottom, 5.0)
PositionSlider(sliderValue: $xyzPos.x, label: "X", minimum: -15.0, maximum: 15.0)
PositionSlider(sliderValue: $xyzPos.y, label: "Y", minimum: -15.0, maximum: 15.0)
PositionSlider(sliderValue: $xyzPos.z, label: "Z", minimum: -15.0, maximum: 15.0)
.border(Color.yellow).padding(.leading)
struct PositionSlider: View
@Binding var sliderValue : Float
var label : String
var minimum : Float
var maximum : Float
static let posFormatter: NumberFormatter =
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.maximumFractionDigits = 3
return formatter
()
var body: some View
VStack
Text(label)
HStack
Text("\(Self.posFormatter.string(from:NSNumber(value: minimum))!)")
Slider(value: $sliderValue, in: minimum ... maximum)
Text("\(Self.posFormatter.string(from:NSNumber(value: maximum))!)")
.padding(.horizontal).frame(width: 150.0, height: 15.0, alignment: .leading)
Text("\(Self.posFormatter.string(from:NSNumber(value: sliderValue))!)")
.border(Color.white)
谁能帮忙解释为什么帧率下降?
我删除了金属窗口并使用 NSViewRepresentable 将其合并到控制窗口中,所以现在看起来像这样:
这仍然有同样的问题。
渲染代码(没做太多!)。即使不渲染茶壶,它仍然会变慢。
func draw(in view: MTKView)
if let commandBuffer = commandQueue.makeCommandBuffer()
commandBuffer.label = "Frame command buffer"
if let renderEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: view.currentRenderPassDescriptor!)
renderEncoder.label = "render encoder"
renderEncoder.endEncoding()
commandBuffer.present(view.currentDrawable!)
commandBuffer.addCompletedHandler completedCommandBuffer in
self.computeFPS()
commandBuffer.commit()
【问题讨论】:
你如何测量 FPS? 我只使用了一个从 commandBuffer.addCompletedHandler 调用的简单计时器。移动滑块时,金属视图中的旋转茶壶也会减慢速度。 可以显示渲染代码吗? 我认为你的 SwiftUI 阻塞了主线程。 正如 0xBFE1A8 所说,SwiftUI 阻塞了主线程。我使用 CVDisplayLink .global(qos: .userInteractive) 将绘图函数移动到回调设置中。当滑块移动时,这会阻止渲染速度减慢。 【参考方案1】:正如 0xBFE1A8 所说,SwiftUI 阻塞了主线程。我使用 CVDisplayLink .global(qos: .userInteractive) 将绘图函数移动到回调设置中。当滑块移动时,这会阻止渲染速度减慢。
【讨论】:
以上是关于SwiftUI 更新降低了金属窗的 FPS的主要内容,如果未能解决你的问题,请参考以下文章
如何在 SwiftUI 中以降低透明度为菜单项获取 AccentColor 背景?
react中antd每当打开不一样的弹窗时,不能更新弹窗的内容