diff --git a/desmume/src/frontend/cocoa/DeSmuME (Latest).xcodeproj/project.pbxproj b/desmume/src/frontend/cocoa/DeSmuME (Latest).xcodeproj/project.pbxproj index 42df488a0..b40938d82 100644 --- a/desmume/src/frontend/cocoa/DeSmuME (Latest).xcodeproj/project.pbxproj +++ b/desmume/src/frontend/cocoa/DeSmuME (Latest).xcodeproj/project.pbxproj @@ -296,6 +296,11 @@ AB564915186E6F67002740F4 /* Image_Piano.png in Resources */ = {isa = PBXBuildFile; fileRef = AB56490B186E6F67002740F4 /* Image_Piano.png */; }; AB5785FD17176AFC002C5FC7 /* OpenEmuBase.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB5785FC17176AFC002C5FC7 /* OpenEmuBase.framework */; }; AB58F32D1364F44B0074C376 /* cocoa_file.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB58F32C1364F44B0074C376 /* cocoa_file.mm */; }; + AB5B1D4A21D1F31E00BF0E0F /* MetalRendererCommonShaders.metal in Sources */ = {isa = PBXBuildFile; fileRef = AB5B1D4921D1F31E00BF0E0F /* MetalRendererCommonShaders.metal */; }; + AB5B1D4B21D1F31E00BF0E0F /* MetalRendererCommonShaders.metal in Sources */ = {isa = PBXBuildFile; fileRef = AB5B1D4921D1F31E00BF0E0F /* MetalRendererCommonShaders.metal */; }; + AB5B1D4C21D1F31E00BF0E0F /* MetalRendererCommonShaders.metal in Sources */ = {isa = PBXBuildFile; fileRef = AB5B1D4921D1F31E00BF0E0F /* MetalRendererCommonShaders.metal */; }; + AB5B1D4D21D1F31E00BF0E0F /* MetalRendererCommonShaders.metal in Sources */ = {isa = PBXBuildFile; fileRef = AB5B1D4921D1F31E00BF0E0F /* MetalRendererCommonShaders.metal */; }; + AB5B1D4E21D1F31E00BF0E0F /* MetalRendererCommonShaders.metal in Sources */ = {isa = PBXBuildFile; fileRef = AB5B1D4921D1F31E00BF0E0F /* MetalRendererCommonShaders.metal */; }; AB5FDDAC1D62C89E0094617C /* colorspacehandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABBFFF6F1D5F9C52003CD598 /* colorspacehandler.cpp */; }; AB64987C13ECC73800EE7DD2 /* FileTypeInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = AB64987B13ECC73800EE7DD2 /* FileTypeInfo.plist */; }; AB68101B187D4AEF0049F2C2 /* Icon_GuitarGrip_Button_Blue_512x512.png in Resources */ = {isa = PBXBuildFile; fileRef = AB681013187D4AEF0049F2C2 /* Icon_GuitarGrip_Button_Blue_512x512.png */; }; @@ -2486,6 +2491,8 @@ AB5785FC17176AFC002C5FC7 /* OpenEmuBase.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenEmuBase.framework; path = openemu/OpenEmuBase.framework; sourceTree = ""; }; AB58F32B1364F44B0074C376 /* cocoa_file.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cocoa_file.h; sourceTree = ""; }; AB58F32C1364F44B0074C376 /* cocoa_file.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = cocoa_file.mm; sourceTree = ""; }; + AB5B1D4821D1F31D00BF0E0F /* MetalRendererCommonShaders.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MetalRendererCommonShaders.h; sourceTree = ""; }; + AB5B1D4921D1F31E00BF0E0F /* MetalRendererCommonShaders.metal */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.metal; path = MetalRendererCommonShaders.metal; sourceTree = ""; }; AB64987B13ECC73800EE7DD2 /* FileTypeInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = FileTypeInfo.plist; sourceTree = ""; }; AB681013187D4AEF0049F2C2 /* Icon_GuitarGrip_Button_Blue_512x512.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_GuitarGrip_Button_Blue_512x512.png; path = images/Icon_GuitarGrip_Button_Blue_512x512.png; sourceTree = ""; }; AB681014187D4AEF0049F2C2 /* Icon_GuitarGrip_Button_Green_512x512.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon_GuitarGrip_Button_Green_512x512.png; path = images/Icon_GuitarGrip_Button_Green_512x512.png; sourceTree = ""; }; @@ -3183,12 +3190,14 @@ ABE5DFE3143FB1DA00835AD8 /* cocoa_videofilter.h */, AB1B9E611501A78000464647 /* coreaudiosound.h */, AB28625520AE3E9E00EAED43 /* macOS_driver.h */, + AB5B1D4821D1F31D00BF0E0F /* MetalRendererCommonShaders.h */, ABD10AE41715FCDD00B5729D /* mic_ext.h */, ABB24F6C1A81EE92006C1108 /* OGLDisplayOutput_3_2.h */, ABE6840E189E33D5007FD69C /* OGLDisplayOutput.h */, AB1B9E621501A78000464647 /* ringbuffer.h */, ABD104011346652500AF11D1 /* sndOSX.h */, AB82445E1704AEC400B8EE20 /* utilities.h */, + AB5B1D4921D1F31E00BF0E0F /* MetalRendererCommonShaders.metal */, ABA6574A14511EC90077E5E9 /* cocoa_cheat.mm */, ABD104121346652500AF11D1 /* cocoa_core.mm */, AB58F32C1364F44B0074C376 /* cocoa_file.mm */, @@ -5539,6 +5548,7 @@ ABD104281346653B00AF11D1 /* main.m in Sources */, AB2ABA411C9F9CFA00173B15 /* rsemaphore.c in Sources */, ABA6574B14511EC90077E5E9 /* cocoa_cheat.mm in Sources */, + AB5B1D4E21D1F31E00BF0E0F /* MetalRendererCommonShaders.metal in Sources */, ABD1041D1346652500AF11D1 /* cocoa_core.mm in Sources */, AB58F32D1364F44B0074C376 /* cocoa_file.mm in Sources */, AB3BF43E1E26289E003E2B24 /* MacMetalDisplayView.mm in Sources */, @@ -5766,6 +5776,7 @@ AB7900C8215B84E50082AE82 /* ftinit.c in Sources */, AB7900C9215B84E50082AE82 /* vfat.cpp in Sources */, AB7900CA215B84E50082AE82 /* colorspacehandler.cpp in Sources */, + AB5B1D4C21D1F31E00BF0E0F /* MetalRendererCommonShaders.metal in Sources */, AB7900CB215B84E50082AE82 /* videofilter.cpp in Sources */, AB7900CC215B84E50082AE82 /* WavFile.cpp in Sources */, AB7900CD215B84E50082AE82 /* wifi.cpp in Sources */, @@ -5878,6 +5889,7 @@ AB7901B3215B84F20082AE82 /* ClientExecutionControl.cpp in Sources */, AB7901B4215B84F20082AE82 /* deposterize.cpp in Sources */, AB7901B5215B84F20082AE82 /* ftgasp.c in Sources */, + AB5B1D4D21D1F31E00BF0E0F /* MetalRendererCommonShaders.metal in Sources */, AB7901B6215B84F20082AE82 /* ftotval.c in Sources */, AB7901B7215B84F20082AE82 /* ftdebug.c in Sources */, AB7901B8215B84F20082AE82 /* ftstroke.c in Sources */, @@ -6221,6 +6233,7 @@ ABFEA82B1BB4EC1100B08C25 /* ftinit.c in Sources */, AB796D4415CDCBA200C59155 /* vfat.cpp in Sources */, AB5FDDAC1D62C89E0094617C /* colorspacehandler.cpp in Sources */, + AB5B1D4A21D1F31E00BF0E0F /* MetalRendererCommonShaders.metal in Sources */, AB796D4515CDCBA200C59155 /* videofilter.cpp in Sources */, AB796D4615CDCBA200C59155 /* WavFile.cpp in Sources */, AB796D4715CDCBA200C59155 /* wifi.cpp in Sources */, @@ -6333,6 +6346,7 @@ ABB1C9491F5281AE0004844F /* ClientExecutionControl.cpp in Sources */, AB301BE01D9C8BCD00246A93 /* deposterize.cpp in Sources */, ABFEA8211BB4EC1000B08C25 /* ftgasp.c in Sources */, + AB5B1D4B21D1F31E00BF0E0F /* MetalRendererCommonShaders.metal in Sources */, ABFEA83C1BB4EC1100B08C25 /* ftotval.c in Sources */, ABFEA8181BB4EC1000B08C25 /* ftdebug.c in Sources */, ABFEA8541BB4EC1100B08C25 /* ftstroke.c in Sources */, diff --git a/desmume/src/frontend/cocoa/MetalRendererCommonShaders.h b/desmume/src/frontend/cocoa/MetalRendererCommonShaders.h new file mode 100644 index 000000000..c1cd9ff57 --- /dev/null +++ b/desmume/src/frontend/cocoa/MetalRendererCommonShaders.h @@ -0,0 +1,26 @@ +/* + Copyright (C) 2018 DeSmuME team + + This file is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This file is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the this software. If not, see . + */ + +#ifndef _METAL_RENDERER_COMMON_H_ +#define _METAL_RENDERER_COMMON_H_ + +float4 unpack_unorm1555_to_unorm8888(const ushort color16); + +ushort pack_color_to_unorm5551(const float4 inColor); +float4 pack_color_to_unorm6665(const float4 inColor); + +#endif // _METAL_RENDERER_COMMON_H_ diff --git a/desmume/src/frontend/cocoa/MetalRendererCommonShaders.metal b/desmume/src/frontend/cocoa/MetalRendererCommonShaders.metal new file mode 100644 index 000000000..622639308 --- /dev/null +++ b/desmume/src/frontend/cocoa/MetalRendererCommonShaders.metal @@ -0,0 +1,46 @@ +/* + Copyright (C) 2018 DeSmuME team + + This file is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This file is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the this software. If not, see . + */ + +#include +using namespace metal; + +#include "MetalRendererCommonShaders.h" + + +float4 unpack_unorm1555_to_unorm8888(const ushort color16) +{ + return float4((float)((color16 >> 0) & 0x1F) / 31.0f, + (float)((color16 >> 5) & 0x1F) / 31.0f, + (float)((color16 >> 10) & 0x1F) / 31.0f, + (float)(color16 >> 15)); +} + +ushort pack_color_to_unorm5551(const float4 inColor) +{ + ushort4 color16 = (ushort4)((inColor * 31.0f) + 0.35f); + + color16.g <<= 5; + color16.b <<= 10; + color16.a = (color16.a < 0.0001) ? 0 : 0x8000; + + return (color16.r | color16.g | color16.b | color16.a); +} + +float4 pack_color_to_unorm6665(const float4 inColor) +{ + return inColor * float4(63.0f/255.0f, 63.0f/255.0f, 63.0f/255.0f, 31.0f/255.0f); +} diff --git a/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayView.mm b/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayView.mm index 6053993a4..5ecdf777f 100644 --- a/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayView.mm +++ b/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayView.mm @@ -67,12 +67,37 @@ commandQueue = [device newCommandQueue]; _fetchCommandQueue = [device newCommandQueue]; defaultLibrary = [device newDefaultLibrary]; - _fetch555Pipeline = [[device newComputePipelineStateWithFunction:[defaultLibrary newFunctionWithName:@"nds_fetch555"] error:nil] retain]; - _fetch666Pipeline = [[device newComputePipelineStateWithFunction:[defaultLibrary newFunctionWithName:@"nds_fetch666"] error:nil] retain]; - _fetch888Pipeline = [[device newComputePipelineStateWithFunction:[defaultLibrary newFunctionWithName:@"nds_fetch888"] error:nil] retain]; - _fetch555ConvertOnlyPipeline = [[device newComputePipelineStateWithFunction:[defaultLibrary newFunctionWithName:@"nds_fetch555ConvertOnly"] error:nil] retain]; - _fetch666ConvertOnlyPipeline = [[device newComputePipelineStateWithFunction:[defaultLibrary newFunctionWithName:@"nds_fetch666ConvertOnly"] error:nil] retain]; - deposterizePipeline = [[device newComputePipelineStateWithFunction:[defaultLibrary newFunctionWithName:@"src_filter_deposterize"] error:nil] retain]; + + MTLComputePipelineDescriptor *computePipelineDesc = [[MTLComputePipelineDescriptor alloc] init]; + [computePipelineDesc setThreadGroupSizeIsMultipleOfThreadExecutionWidth:YES]; + + [computePipelineDesc setComputeFunction:[defaultLibrary newFunctionWithName:@"nds_fetch555ConvertOnly"]]; + _fetch555ConvertOnlyPipeline = [[device newComputePipelineStateWithDescriptor:computePipelineDesc options:MTLPipelineOptionNone reflection:nil error:nil] retain]; + + [computePipelineDesc setComputeFunction:[defaultLibrary newFunctionWithName:@"nds_fetch666ConvertOnly"]]; + _fetch666ConvertOnlyPipeline = [[device newComputePipelineStateWithDescriptor:computePipelineDesc options:MTLPipelineOptionNone reflection:nil error:nil] retain]; + + [computePipelineDesc setComputeFunction:[defaultLibrary newFunctionWithName:@"src_filter_deposterize"]]; + deposterizePipeline = [[device newComputePipelineStateWithDescriptor:computePipelineDesc options:MTLPipelineOptionNone reflection:nil error:nil] retain]; + +#if defined(MAC_OS_X_VERSION_10_13) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_13) + if (@available(macOS 10.13, *)) + { + [[[computePipelineDesc buffers] objectAtIndexedSubscript:0] setMutability:MTLMutabilityImmutable]; + [[[computePipelineDesc buffers] objectAtIndexedSubscript:1] setMutability:MTLMutabilityImmutable]; + } +#endif + + [computePipelineDesc setComputeFunction:[defaultLibrary newFunctionWithName:@"nds_fetch555"]]; + _fetch555Pipeline = [[device newComputePipelineStateWithDescriptor:computePipelineDesc options:MTLPipelineOptionNone reflection:nil error:nil] retain]; + + [computePipelineDesc setComputeFunction:[defaultLibrary newFunctionWithName:@"nds_fetch666"]]; + _fetch666Pipeline = [[device newComputePipelineStateWithDescriptor:computePipelineDesc options:MTLPipelineOptionNone reflection:nil error:nil] retain]; + + [computePipelineDesc setComputeFunction:[defaultLibrary newFunctionWithName:@"nds_fetch888"]]; + _fetch888Pipeline = [[device newComputePipelineStateWithDescriptor:computePipelineDesc options:MTLPipelineOptionNone reflection:nil error:nil] retain]; + + [computePipelineDesc release]; size_t tw = GetNearestPositivePOT((uint32_t)[_fetch555Pipeline threadExecutionWidth]); while ( (tw > [_fetch555Pipeline threadExecutionWidth]) || (tw > GPU_FRAMEBUFFER_NATIVE_WIDTH) ) @@ -105,6 +130,18 @@ [hudPipelineDesc setVertexFunction:[defaultLibrary newFunctionWithName:@"hud_vertex"]]; [hudPipelineDesc setFragmentFunction:hudFragmentFunction]; +#if defined(MAC_OS_X_VERSION_10_13) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_13) + if (@available(macOS 10.13, *)) + { + [[[hudPipelineDesc vertexBuffers] objectAtIndexedSubscript:0] setMutability:MTLMutabilityImmutable]; + [[[hudPipelineDesc vertexBuffers] objectAtIndexedSubscript:1] setMutability:MTLMutabilityImmutable]; + [[[hudPipelineDesc vertexBuffers] objectAtIndexedSubscript:2] setMutability:MTLMutabilityImmutable]; + [[[hudPipelineDesc vertexBuffers] objectAtIndexedSubscript:3] setMutability:MTLMutabilityImmutable]; + [[[hudPipelineDesc vertexBuffers] objectAtIndexedSubscript:4] setMutability:MTLMutabilityImmutable]; + [[[hudPipelineDesc vertexBuffers] objectAtIndexedSubscript:5] setMutability:MTLMutabilityImmutable]; + } +#endif + [[[hudPipelineDesc colorAttachments] objectAtIndexedSubscript:0] setPixelFormat:MTLPixelFormatBGRA8Unorm]; hudPipeline = [[device newRenderPipelineStateWithDescriptor:hudPipelineDesc error:nil] retain]; @@ -854,104 +891,119 @@ { id currentHQnxLUT = nil; + MTLComputePipelineDescriptor *computePipelineDesc = [[MTLComputePipelineDescriptor alloc] init]; + [computePipelineDesc setThreadGroupSizeIsMultipleOfThreadExecutionWidth:YES]; + switch (filterID) { case VideoFilterTypeID_Nearest2X: - [self setPixelScalePipeline:[[sharedData device] newComputePipelineStateWithFunction:[[sharedData defaultLibrary] newFunctionWithName:@"pixel_scaler_nearest2x"] error:nil]]; + [computePipelineDesc setComputeFunction:[[sharedData defaultLibrary] newFunctionWithName:@"pixel_scaler_nearest2x"]]; break; case VideoFilterTypeID_Scanline: - [self setPixelScalePipeline:[[sharedData device] newComputePipelineStateWithFunction:[[sharedData defaultLibrary] newFunctionWithName:@"pixel_scaler_scanline"] error:nil]]; + [computePipelineDesc setComputeFunction:[[sharedData defaultLibrary] newFunctionWithName:@"pixel_scaler_scanline"]]; break; case VideoFilterTypeID_EPX: - [self setPixelScalePipeline:[[sharedData device] newComputePipelineStateWithFunction:[[sharedData defaultLibrary] newFunctionWithName:@"pixel_scaler_2xEPX"] error:nil]]; + [computePipelineDesc setComputeFunction:[[sharedData defaultLibrary] newFunctionWithName:@"pixel_scaler_2xEPX"]]; break; case VideoFilterTypeID_EPXPlus: - [self setPixelScalePipeline:[[sharedData device] newComputePipelineStateWithFunction:[[sharedData defaultLibrary] newFunctionWithName:@"pixel_scaler_2xEPXPlus"] error:nil]]; + [computePipelineDesc setComputeFunction:[[sharedData defaultLibrary] newFunctionWithName:@"pixel_scaler_2xEPXPlus"]]; break; case VideoFilterTypeID_2xSaI: - [self setPixelScalePipeline:[[sharedData device] newComputePipelineStateWithFunction:[[sharedData defaultLibrary] newFunctionWithName:@"pixel_scaler_2xSaI"] error:nil]]; + [computePipelineDesc setComputeFunction:[[sharedData defaultLibrary] newFunctionWithName:@"pixel_scaler_2xSaI"]]; break; case VideoFilterTypeID_Super2xSaI: - [self setPixelScalePipeline:[[sharedData device] newComputePipelineStateWithFunction:[[sharedData defaultLibrary] newFunctionWithName:@"pixel_scaler_Super2xSaI"] error:nil]]; + [computePipelineDesc setComputeFunction:[[sharedData defaultLibrary] newFunctionWithName:@"pixel_scaler_Super2xSaI"]]; break; case VideoFilterTypeID_SuperEagle: - [self setPixelScalePipeline:[[sharedData device] newComputePipelineStateWithFunction:[[sharedData defaultLibrary] newFunctionWithName:@"pixel_scaler_2xSuperEagle"] error:nil]]; + [computePipelineDesc setComputeFunction:[[sharedData defaultLibrary] newFunctionWithName:@"pixel_scaler_2xSuperEagle"]]; break; case VideoFilterTypeID_LQ2X: - [self setPixelScalePipeline:[[sharedData device] newComputePipelineStateWithFunction:[[sharedData defaultLibrary] newFunctionWithName:@"pixel_scaler_LQ2x"] error:nil]]; + [computePipelineDesc setComputeFunction:[[sharedData defaultLibrary] newFunctionWithName:@"pixel_scaler_LQ2x"]]; currentHQnxLUT = [sharedData texLQ2xLUT]; break; case VideoFilterTypeID_LQ2XS: - [self setPixelScalePipeline:[[sharedData device] newComputePipelineStateWithFunction:[[sharedData defaultLibrary] newFunctionWithName:@"pixel_scaler_LQ2xS"] error:nil]]; + [computePipelineDesc setComputeFunction:[[sharedData defaultLibrary] newFunctionWithName:@"pixel_scaler_LQ2xS"]]; currentHQnxLUT = [sharedData texLQ2xLUT]; break; case VideoFilterTypeID_HQ2X: - [self setPixelScalePipeline:[[sharedData device] newComputePipelineStateWithFunction:[[sharedData defaultLibrary] newFunctionWithName:@"pixel_scaler_HQ2x"] error:nil]]; + [computePipelineDesc setComputeFunction:[[sharedData defaultLibrary] newFunctionWithName:@"pixel_scaler_HQ2x"]]; currentHQnxLUT = [sharedData texHQ2xLUT]; break; case VideoFilterTypeID_HQ2XS: - [self setPixelScalePipeline:[[sharedData device] newComputePipelineStateWithFunction:[[sharedData defaultLibrary] newFunctionWithName:@"pixel_scaler_HQ2xS"] error:nil]]; + [computePipelineDesc setComputeFunction:[[sharedData defaultLibrary] newFunctionWithName:@"pixel_scaler_HQ2xS"]]; currentHQnxLUT = [sharedData texHQ2xLUT]; break; case VideoFilterTypeID_HQ3X: - [self setPixelScalePipeline:[[sharedData device] newComputePipelineStateWithFunction:[[sharedData defaultLibrary] newFunctionWithName:@"pixel_scaler_HQ3x"] error:nil]]; + [computePipelineDesc setComputeFunction:[[sharedData defaultLibrary] newFunctionWithName:@"pixel_scaler_HQ3x"]]; currentHQnxLUT = [sharedData texHQ3xLUT]; break; case VideoFilterTypeID_HQ3XS: - [self setPixelScalePipeline:[[sharedData device] newComputePipelineStateWithFunction:[[sharedData defaultLibrary] newFunctionWithName:@"pixel_scaler_HQ3xS"] error:nil]]; + [computePipelineDesc setComputeFunction:[[sharedData defaultLibrary] newFunctionWithName:@"pixel_scaler_HQ3xS"]]; currentHQnxLUT = [sharedData texHQ3xLUT]; break; case VideoFilterTypeID_HQ4X: - [self setPixelScalePipeline:[[sharedData device] newComputePipelineStateWithFunction:[[sharedData defaultLibrary] newFunctionWithName:@"pixel_scaler_HQ4x"] error:nil]]; + [computePipelineDesc setComputeFunction:[[sharedData defaultLibrary] newFunctionWithName:@"pixel_scaler_HQ4x"]]; currentHQnxLUT = [sharedData texHQ4xLUT]; break; case VideoFilterTypeID_HQ4XS: - [self setPixelScalePipeline:[[sharedData device] newComputePipelineStateWithFunction:[[sharedData defaultLibrary] newFunctionWithName:@"pixel_scaler_HQ4xS"] error:nil]]; + [computePipelineDesc setComputeFunction:[[sharedData defaultLibrary] newFunctionWithName:@"pixel_scaler_HQ4xS"]]; currentHQnxLUT = [sharedData texHQ4xLUT]; break; case VideoFilterTypeID_2xBRZ: - [self setPixelScalePipeline:[[sharedData device] newComputePipelineStateWithFunction:[[sharedData defaultLibrary] newFunctionWithName:@"pixel_scaler_2xBRZ"] error:nil]]; + [computePipelineDesc setComputeFunction:[[sharedData defaultLibrary] newFunctionWithName:@"pixel_scaler_2xBRZ"]]; break; case VideoFilterTypeID_3xBRZ: - [self setPixelScalePipeline:[[sharedData device] newComputePipelineStateWithFunction:[[sharedData defaultLibrary] newFunctionWithName:@"pixel_scaler_3xBRZ"] error:nil]]; + [computePipelineDesc setComputeFunction:[[sharedData defaultLibrary] newFunctionWithName:@"pixel_scaler_3xBRZ"]]; break; case VideoFilterTypeID_4xBRZ: - [self setPixelScalePipeline:[[sharedData device] newComputePipelineStateWithFunction:[[sharedData defaultLibrary] newFunctionWithName:@"pixel_scaler_4xBRZ"] error:nil]]; + [computePipelineDesc setComputeFunction:[[sharedData defaultLibrary] newFunctionWithName:@"pixel_scaler_4xBRZ"]]; break; case VideoFilterTypeID_5xBRZ: - [self setPixelScalePipeline:[[sharedData device] newComputePipelineStateWithFunction:[[sharedData defaultLibrary] newFunctionWithName:@"pixel_scaler_5xBRZ"] error:nil]]; + [computePipelineDesc setComputeFunction:[[sharedData defaultLibrary] newFunctionWithName:@"pixel_scaler_5xBRZ"]]; break; case VideoFilterTypeID_6xBRZ: - [self setPixelScalePipeline:[[sharedData device] newComputePipelineStateWithFunction:[[sharedData defaultLibrary] newFunctionWithName:@"pixel_scaler_6xBRZ"] error:nil]]; + [computePipelineDesc setComputeFunction:[[sharedData defaultLibrary] newFunctionWithName:@"pixel_scaler_6xBRZ"]]; break; case VideoFilterTypeID_None: default: - [self setPixelScalePipeline:nil]; + [computePipelineDesc release]; + computePipelineDesc = nil; break; } [sharedData setTexCurrentHQnxLUT:currentHQnxLUT]; + if (computePipelineDesc != nil) + { + [self setPixelScalePipeline:[[sharedData device] newComputePipelineStateWithDescriptor:computePipelineDesc options:MTLPipelineOptionNone reflection:nil error:nil]]; + [computePipelineDesc release]; + computePipelineDesc = nil; + } + else + { + [self setPixelScalePipeline:nil]; + } + if ([self pixelScalePipeline] != nil) { const VideoFilterAttributes vfAttr = VideoFilter::GetAttributesByID(filterID); @@ -1049,6 +1101,17 @@ [self setOutputDrawablePipeline:[[sharedData device] newRenderPipelineStateWithDescriptor:outputPipelineDesc error:nil]]; } +#if defined(MAC_OS_X_VERSION_10_13) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_13) + if (@available(macOS 10.13, *)) + { + [[[outputPipelineDesc vertexBuffers] objectAtIndexedSubscript:0] setMutability:MTLMutabilityImmutable]; + [[[outputPipelineDesc vertexBuffers] objectAtIndexedSubscript:1] setMutability:MTLMutabilityImmutable]; + [[[outputPipelineDesc vertexBuffers] objectAtIndexedSubscript:2] setMutability:MTLMutabilityImmutable]; + [[[outputPipelineDesc vertexBuffers] objectAtIndexedSubscript:3] setMutability:MTLMutabilityImmutable]; + [[[outputPipelineDesc fragmentBuffers] objectAtIndexedSubscript:0] setMutability:MTLMutabilityImmutable]; + } +#endif + [outputPipelineDesc release]; } @@ -1064,6 +1127,17 @@ [outputPipelineDesc setVertexFunction:[[sharedData defaultLibrary] newFunctionWithName:@"display_output_vertex"]]; [outputPipelineDesc setFragmentFunction:[[sharedData defaultLibrary] newFunctionWithName:@"output_filter_bilinear"]]; +#if defined(MAC_OS_X_VERSION_10_13) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_13) + if (@available(macOS 10.13, *)) + { + [[[outputPipelineDesc vertexBuffers] objectAtIndexedSubscript:0] setMutability:MTLMutabilityImmutable]; + [[[outputPipelineDesc vertexBuffers] objectAtIndexedSubscript:1] setMutability:MTLMutabilityImmutable]; + [[[outputPipelineDesc vertexBuffers] objectAtIndexedSubscript:2] setMutability:MTLMutabilityImmutable]; + [[[outputPipelineDesc vertexBuffers] objectAtIndexedSubscript:3] setMutability:MTLMutabilityImmutable]; + [[[outputPipelineDesc fragmentBuffers] objectAtIndexedSubscript:0] setMutability:MTLMutabilityImmutable]; + } +#endif + [[[outputPipelineDesc colorAttachments] objectAtIndexedSubscript:0] setPixelFormat:MTLPixelFormatRGBA8Unorm]; outputRGBAPipeline = [[[sharedData device] newRenderPipelineStateWithDescriptor:outputPipelineDesc error:nil] retain]; diff --git a/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayViewShaders.metal b/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayViewShaders.metal index 4c58129a1..783554cac 100644 --- a/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayViewShaders.metal +++ b/desmume/src/frontend/cocoa/userinterface/MacMetalDisplayViewShaders.metal @@ -18,8 +18,11 @@ #include using namespace metal; +#include "../MetalRendererCommonShaders.h" + #define LANCZOS_FIX(c) max(abs(c), 1e-5) + struct HUDVtx { float4 position [[position]]; @@ -44,7 +47,6 @@ struct DisplayViewShaderProperties }; float reduce(const float3 color); -float4 unpack_unorm1555_to_unorm8888(const ushort color16); float3 color_interpolate_LTE(const float3 pixA, const float3 pixB, const float3 threshold); float4 bicubic_weight_bspline(const float x); float4 bicubic_weight_mitchell_netravali(const float x); @@ -89,14 +91,6 @@ bool InterpDiff(const float3 p1, const float3 p2) return any( yuv > float3(192.0f/255.0f, 28.0f/255.0f, 48.0f/255.0f) ); } -float4 unpack_unorm1555_to_unorm8888(const ushort color16) -{ - return float4((float)((color16 >> 0) & 0x1F) / 31.0f, - (float)((color16 >> 5) & 0x1F) / 31.0f, - (float)((color16 >> 10) & 0x1F) / 31.0f, - (float)(color16 >> 16)); -} - float3 color_interpolate_LTE(const float3 pixA, const float3 pixB, const float3 threshold) { const float3 interpPix = mix(pixA, pixB, 0.5f);