diff --git a/AppleCommon/GBViewBase.m b/AppleCommon/GBViewBase.m index 20af0a9a2..de914ddb6 100644 --- a/AppleCommon/GBViewBase.m +++ b/AppleCommon/GBViewBase.m @@ -5,6 +5,7 @@ uint32_t *_imageBuffers[3]; unsigned _currentBuffer; GB_frame_blending_mode_t _frameBlendingMode; + bool _oddFrame; } - (void)screenSizeChanged @@ -23,6 +24,7 @@ - (void)flip { _currentBuffer = (_currentBuffer + 1) % self.numberOfBuffers; + _oddFrame = GB_is_odd_frame(_gb); } - (unsigned) numberOfBuffers @@ -62,7 +64,7 @@ if (!_gb || GB_is_sgb(_gb)) { return GB_FRAME_BLENDING_MODE_SIMPLE; } - return GB_is_odd_frame(_gb)? GB_FRAME_BLENDING_MODE_ACCURATE_ODD : GB_FRAME_BLENDING_MODE_ACCURATE_EVEN; + return _oddFrame ? GB_FRAME_BLENDING_MODE_ACCURATE_ODD : GB_FRAME_BLENDING_MODE_ACCURATE_EVEN; } return _frameBlendingMode; } diff --git a/AppleCommon/GBViewMetal.m b/AppleCommon/GBViewMetal.m index 088d4027f..9aa79d7cd 100644 --- a/AppleCommon/GBViewMetal.m +++ b/AppleCommon/GBViewMetal.m @@ -85,7 +85,7 @@ static const vector_float2 rect[] = #endif } -- (void) loadShader +- (void)loadShader { NSError *error = nil; NSString *shader_source = [NSString stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"MasterShader" @@ -160,22 +160,44 @@ static const vector_float2 rect[] = {texture.width, texture.height, 1} // MTLSize }; - [texture replaceRegion:region - mipmapLevel:0 - withBytes:[self currentBuffer] - bytesPerRow:texture.width * 4]; - if ([self frameBlendingMode]) { - [previous_texture replaceRegion:region - mipmapLevel:0 - withBytes:[self previousBuffer] - bytesPerRow:texture.width * 4]; + GB_frame_blending_mode_t mode = [self frameBlendingMode]; + + switch (mode) { + case GB_FRAME_BLENDING_MODE_SIMPLE: + case GB_FRAME_BLENDING_MODE_ACCURATE_EVEN: + [previous_texture replaceRegion:region + mipmapLevel:0 + withBytes:[self previousBuffer] + bytesPerRow:texture.width * 4]; + case GB_FRAME_BLENDING_MODE_DISABLED: + [texture replaceRegion:region + mipmapLevel:0 + withBytes:[self currentBuffer] + bytesPerRow:texture.width * 4]; + break; + case GB_FRAME_BLENDING_MODE_ACCURATE_ODD: + /* + I don't understand GPUs. When rapidly changing `mode`, the shader might sometimes incorrectly + use the old value. I couldn't figure out how to fix it, so I just work around the issue by + avoiding rapid changes in `mode`. + */ + mode = GB_FRAME_BLENDING_MODE_ACCURATE_EVEN; + [previous_texture replaceRegion:region + mipmapLevel:0 + withBytes:[self currentBuffer] + bytesPerRow:texture.width * 4]; + [texture replaceRegion:region + mipmapLevel:0 + withBytes:[self previousBuffer] + bytesPerRow:texture.width * 4]; + break; } MTLRenderPassDescriptor *render_pass_descriptor = view.currentRenderPassDescriptor; id command_buffer = [command_queue commandBuffer]; if (render_pass_descriptor) { - *(GB_frame_blending_mode_t *)[frame_blending_mode_buffer contents] = [self frameBlendingMode]; + *(GB_frame_blending_mode_t *)[frame_blending_mode_buffer contents] = mode; *(vector_float2 *)[output_resolution_buffer contents] = output_resolution; id render_encoder = diff --git a/Cocoa/Document.xib b/Cocoa/Document.xib index 855b56fb1..2e2c670ad 100644 --- a/Cocoa/Document.xib +++ b/Cocoa/Document.xib @@ -703,7 +703,7 @@ - +