This PR is an effort to improve performance of the emulator, especially when rendering with pixels scaled up by a factor of three. Weirdly when the app was in focus it ran somewhat slowly, but when either opening the Open ROM... dialog or bringing another app into focus, the emulator ran at top speed in the background. After some debugging, it turned out that the problem was the so-called focus ring, namely that it was activated, as evidenced but he blue border around the canvas. Adding the focusEffectDisabled() modifier on the top level SwiftUI component made everything render much faster when the app was in focus.
I had originally thought that the problem was due to inefficiencies somewhere in the code, namely where we take the screen buffer, write it to an image, and then write that to the canvas. But that wasn't the source of the problem. Nonetheless, I changed the screen buffer to be an array of UInt8s and updated said closure in Screens Canvas to use it directly to avoid an extra copy per frame. In doing so, I had to make sure that renderPixel() wrote out threeUInt8s instead of a single NESColor to the screen buffer.
For now, the scale factor has been changed to 3.0; in a future PR, we'll try to expose something in the UI to allow the user to specify a scale value from 1.0, 2.0, or 3.0.
This PR is an effort to improve performance of the emulator, especially when rendering with pixels scaled up by a factor of three. Weirdly when the app was in focus it ran somewhat slowly, but when either opening the Open ROM... dialog or bringing another app into focus, the emulator ran at top speed in the background. After some debugging, it turned out that the problem was the so-called focus ring, namely that it was activated, as evidenced but he blue border around the canvas. Adding the
focusEffectDisabled()
modifier on the top level SwiftUI component made everything render much faster when the app was in focus.I had originally thought that the problem was due to inefficiencies somewhere in the code, namely where we take the screen buffer, write it to an image, and then write that to the canvas. But that wasn't the source of the problem. Nonetheless, I changed the screen buffer to be an array of
UInt8
s and updated said closure inScreen
sCanvas
to use it directly to avoid an extra copy per frame. In doing so, I had to make sure thatrenderPixel()
wrote out threeUInt8
s instead of a singleNESColor
to the screen buffer.For now, the scale factor has been changed to 3.0; in a future PR, we'll try to expose something in the UI to allow the user to specify a scale value from 1.0, 2.0, or 3.0.