mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-21 02:09:05 +02:00
Metal: Hook up the backend on Mac, with the null GPU for now
Selectable with --graphics=metal, the backend choice in settings and the Mac menu bar. SDL creates a Metal view for it, and headless renders offscreen. Games run on the null GPU until there's a GPU/Metal. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
16ed2ad55a
commit
8d7ce57fa8
10 files changed
+59
-5
No files matched your search
@@ -57,6 +57,7 @@ bool MetalGraphicsContext::InitSurface(WindowSystem winsys, void *data1, void *d
|
||||
renderManager_ = new MetalRenderManager(device, layer, offscreenWidth_, offscreenHeight_);
|
||||
renderManager_->SetInflightFrames(g_Config.iInflightFrames);
|
||||
draw_ = Draw::T3DCreateMetalContext(renderManager_);
|
||||
INFO_LOG(Log::G3D, "Metal: Using %s, backbuffer %dx%d%s", [[device name] UTF8String], renderManager_->BackbufferWidth(), renderManager_->BackbufferHeight(), layer ? "" : " (offscreen)");
|
||||
SetGPUBackend(GPUBackend::METAL, [[device name] UTF8String]);
|
||||
if (!draw_->CreatePresets()) {
|
||||
*errorMessage = "Failed to compile preset shaders";
|
||||
|
||||
@@ -468,6 +468,9 @@ CommandLineParseResult CommandLineOptions::Parse(int argc, const char *argv[], C
|
||||
} else if (restOfOption == "vulkan") {
|
||||
gpuBackend = GPUBackend::VULKAN;
|
||||
softwareRendering = false;
|
||||
} else if (restOfOption == "metal") {
|
||||
gpuBackend = GPUBackend::METAL;
|
||||
softwareRendering = false;
|
||||
} else if (restOfOption == "software") {
|
||||
gpuBackend = GPUBackend::OPENGL;
|
||||
softwareRendering = true;
|
||||
|
||||
@@ -29,6 +29,7 @@ enum GPUCore : int {
|
||||
GPUCORE_DIRECTX11 = 3,
|
||||
GPUCORE_VULKAN = 4,
|
||||
GPUCORE_NULL = 5, // Draws nothing, see GPU_Null.h.
|
||||
GPUCORE_METAL = 6,
|
||||
};
|
||||
|
||||
enum class FPSLimit {
|
||||
|
||||
@@ -70,6 +70,9 @@ static GPUCommon *CreateGPUCore(GPUCore gpuCore, GraphicsContext *ctx, Draw::Dra
|
||||
}
|
||||
return new GPU_Vulkan(ctx, draw);
|
||||
#endif
|
||||
case GPUCORE_METAL:
|
||||
// TODO: The Metal GPU backend. Until then, nothing is drawn.
|
||||
return CreateNullGPU(ctx);
|
||||
case GPUCORE_NULL:
|
||||
return CreateNullGPU(ctx);
|
||||
default:
|
||||
|
||||
@@ -467,7 +467,7 @@ static bool CanUseSaveStates(bool isSaveAction) {
|
||||
[self addSeparatorTo:menu];
|
||||
|
||||
NSMenu *backends = [self addSubmenu:DesktopUI("Backend") to:menu];
|
||||
for (GPUBackend backend : { GPUBackend::OPENGL, GPUBackend::VULKAN }) {
|
||||
for (GPUBackend backend : { GPUBackend::OPENGL, GPUBackend::VULKAN, GPUBackend::METAL }) {
|
||||
if (!g_Config.IsBackendEnabled(backend)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
+28
-1
@@ -75,6 +75,8 @@ SDLJoystick *joystick = NULL;
|
||||
#if PPSSPP_PLATFORM(MAC) || PPSSPP_PLATFORM(IOS)
|
||||
#include "Core/Util/DarwinFileSystemServices.h"
|
||||
#include "SDL/SDLCocoaMetalLayer.h"
|
||||
#include "Common/GPU/Metal/MetalGraphicsContext.h"
|
||||
#include <SDL3/SDL_metal.h>
|
||||
#endif
|
||||
|
||||
#if PPSSPP_PLATFORM(MAC)
|
||||
@@ -2158,6 +2160,11 @@ int main(int argc, char *argv[]) {
|
||||
case GPUBackend::OPENGL:
|
||||
fallbackGPUBackend = (int)GPUBackend::VULKAN;
|
||||
break;
|
||||
#if PPSSPP_PLATFORM(MAC)
|
||||
case GPUBackend::METAL:
|
||||
fallbackGPUBackend = vulkanMayBeAvailable ? (int)GPUBackend::VULKAN : (int)GPUBackend::OPENGL;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
fprintf(stderr, "Unknown GPU backend %d, switching to Vulkan.\n", g_Config.iGPUBackend);
|
||||
g_Config.iGPUBackend = (int)GPUBackend::VULKAN;
|
||||
@@ -2178,6 +2185,26 @@ int main(int argc, char *argv[]) {
|
||||
windowDesc.data2 = (void *)glContext;
|
||||
|
||||
ctx = new SDLGLGraphicsContext();
|
||||
#if PPSSPP_PLATFORM(MAC)
|
||||
} else if (backend == GPUBackend::METAL) {
|
||||
window = SDL_CreateWindow("Initializing graphics...", w, h, (SDL_WindowFlags)(mode | SDL_WINDOW_METAL | SDL_WINDOW_HIDDEN));
|
||||
if (!window) {
|
||||
*errorMessage = StringFromFormat("Error creating SDL window: %s", SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
if (x != SDL_WINDOWPOS_UNDEFINED && y != SDL_WINDOWPOS_UNDEFINED) {
|
||||
SDL_SetWindowPosition(window, x, y);
|
||||
}
|
||||
SDL_MetalView metalView = SDL_Metal_CreateView(window);
|
||||
if (!metalView) {
|
||||
*errorMessage = StringFromFormat("Error creating Metal view: %s", SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
windowDesc.winsys = WINDOWSYSTEM_METAL_EXT;
|
||||
windowDesc.data1 = SDL_Metal_GetLayer(metalView);
|
||||
windowDesc.data2 = (void *)window;
|
||||
ctx = new MetalGraphicsContext();
|
||||
#endif
|
||||
} else {
|
||||
// Use a local copy of mode: this flag combination is Vulkan-specific, and if we fall back to
|
||||
// OpenGL below, we don't want SDL_WINDOW_VULKAN to stick around and get OR'd in there too.
|
||||
@@ -2231,7 +2258,7 @@ int main(int argc, char *argv[]) {
|
||||
if (!initializeBackend((GPUBackend)g_Config.iGPUBackend, &graphicsContext, &error_message)) {
|
||||
fprintf(stderr, "Failed to initialize graphics backend: %s\n", error_message.c_str());
|
||||
if (fallbackGPUBackend != -1) {
|
||||
fprintf(stderr, "Attempting to fall back to %s...\n", fallbackGPUBackend == (int)GPUBackend::OPENGL ? "OpenGL" : "Vulkan");
|
||||
fprintf(stderr, "Attempting to fall back to %s...\n", GPUBackendToString((GPUBackend)fallbackGPUBackend).c_str());
|
||||
g_Config.iGPUBackend = fallbackGPUBackend;
|
||||
error_message.clear();
|
||||
if (!initializeBackend((GPUBackend)g_Config.iGPUBackend, &graphicsContext, &error_message)) {
|
||||
|
||||
+3
-1
@@ -763,7 +763,7 @@ void TouchTestScreen::CreateViews() {
|
||||
root_->Add(theTwo);
|
||||
|
||||
#if !PPSSPP_PLATFORM(UWP)
|
||||
static const char *renderingBackend[] = { "OpenGL", "(n/a)", "Direct3D 11", "Vulkan" };
|
||||
static const char *renderingBackend[] = { "OpenGL", "(n/a)", "Direct3D 11", "Vulkan", "Metal" };
|
||||
PopupMultiChoice *renderingBackendChoice = root_->Add(new PopupMultiChoice(&g_Config.iGPUBackend, gr->T("Backend"), renderingBackend, (int)GPUBackend::OPENGL, ARRAY_SIZE(renderingBackend), I18NCat::GRAPHICS, screenManager()));
|
||||
renderingBackendChoice->OnChoice.Handle(this, &TouchTestScreen::OnRenderingBackend);
|
||||
|
||||
@@ -774,6 +774,8 @@ void TouchTestScreen::CreateViews() {
|
||||
renderingBackendChoice->HideChoice((int)GPUBackend::DIRECT3D11);
|
||||
if (!g_Config.IsBackendEnabled(GPUBackend::VULKAN))
|
||||
renderingBackendChoice->HideChoice((int)GPUBackend::VULKAN);
|
||||
if (!g_Config.IsBackendEnabled(GPUBackend::METAL))
|
||||
renderingBackendChoice->HideChoice((int)GPUBackend::METAL);
|
||||
#endif
|
||||
|
||||
#if PPSSPP_PLATFORM(ANDROID)
|
||||
|
||||
@@ -312,6 +312,9 @@ void EmuScreen::ProcessGameBoot(const Path &filename) {
|
||||
coreParam.gpuCore = GPUCORE_VULKAN;
|
||||
break;
|
||||
#endif
|
||||
case GPUBackend::METAL:
|
||||
coreParam.gpuCore = GPUCORE_METAL;
|
||||
break;
|
||||
}
|
||||
|
||||
// Preserve the existing graphics context.
|
||||
|
||||
@@ -279,7 +279,7 @@ void GameSettingsScreen::CreateGraphicsSettings(UI::ViewGroup *graphicsSettings)
|
||||
Draw::DrawContext *draw = screenManager()->getDrawContext();
|
||||
|
||||
#if !PPSSPP_PLATFORM(UWP)
|
||||
static const char *renderingBackend[] = { "OpenGL", "Direct3D 9", "Direct3D 11", "Vulkan" };
|
||||
static const char *renderingBackend[] = { "OpenGL", "Direct3D 9", "Direct3D 11", "Vulkan", "Metal" };
|
||||
PopupMultiChoice *renderingBackendChoice = graphicsSettings->Add(new PopupMultiChoice(&g_Config.iGPUBackend, gr->T("Backend"), renderingBackend, (int)GPUBackend::OPENGL, ARRAY_SIZE(renderingBackend), I18NCat::GRAPHICS, screenManager()));
|
||||
renderingBackendChoice->SetPreOpenCallback([this](UI::PopupMultiChoice *choice) {
|
||||
// Don't filter until the last possible moment, since it involves trying to initialize Vulkan, if we were
|
||||
@@ -293,6 +293,8 @@ void GameSettingsScreen::CreateGraphicsSettings(UI::ViewGroup *graphicsSettings)
|
||||
choice->HideChoice((int)GPUBackend::DIRECT3D11);
|
||||
if (!g_Config.IsBackendEnabled(GPUBackend::VULKAN))
|
||||
choice->HideChoice((int)GPUBackend::VULKAN);
|
||||
if (!g_Config.IsBackendEnabled(GPUBackend::METAL))
|
||||
choice->HideChoice((int)GPUBackend::METAL);
|
||||
});
|
||||
|
||||
if (!IsFirstInstance()) {
|
||||
|
||||
+13
-1
@@ -49,6 +49,9 @@
|
||||
#include "Common/StringUtils.h"
|
||||
#include "Common/Thread/ThreadManager.h"
|
||||
#include "Common/GPU/Vulkan/VulkanGraphicsContext.h"
|
||||
#if PPSSPP_PLATFORM(MAC) || PPSSPP_PLATFORM(IOS)
|
||||
#include "Common/GPU/Metal/MetalGraphicsContext.h"
|
||||
#endif
|
||||
#include "Core/CmdLine.h"
|
||||
#include "Common/Net/HTTPRequest.h"
|
||||
#include "Core/Config.h"
|
||||
@@ -422,7 +425,7 @@ struct AutoTestOptions {
|
||||
// swaps with interval 0). D3D11 presents to a hidden window, which could.
|
||||
static void EndDrawFrame(Draw::DrawContext *draw) {
|
||||
draw->EndFrame();
|
||||
if (GetGPUBackend() == GPUBackend::VULKAN || GetGPUBackend() == GPUBackend::OPENGL) {
|
||||
if (GetGPUBackend() == GPUBackend::VULKAN || GetGPUBackend() == GPUBackend::OPENGL || GetGPUBackend() == GPUBackend::METAL) {
|
||||
draw->Present(Draw::PresentMode::FIFO);
|
||||
}
|
||||
}
|
||||
@@ -1080,6 +1083,9 @@ int main(int argc, const char* argv[]) {
|
||||
case GPUBackend::VULKAN:
|
||||
gpuCore = GPUCORE_VULKAN;
|
||||
break;
|
||||
case GPUBackend::METAL:
|
||||
gpuCore = GPUCORE_METAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cmdLineOptions.nullGraphics.value_or(false)) {
|
||||
@@ -1106,6 +1112,12 @@ int main(int argc, const char* argv[]) {
|
||||
vulkanContext->SetOffscreen(480, 272);
|
||||
graphicsContext = vulkanContext;
|
||||
deviceSetting = &g_Config.sVulkanDevice;
|
||||
#if PPSSPP_PLATFORM(MAC) || PPSSPP_PLATFORM(IOS)
|
||||
} else if (gpuCore == GPUCORE_METAL) {
|
||||
MetalGraphicsContext *metalContext = new MetalGraphicsContext();
|
||||
metalContext->SetOffscreen(480, 272);
|
||||
graphicsContext = metalContext;
|
||||
#endif
|
||||
#if PPSSPP_PLATFORM(MAC) && defined(SDL)
|
||||
} else if (gpuCore == GPUCORE_GLES) {
|
||||
// So does OpenGL, into a framebuffer object of its own.
|
||||
|
||||
Reference in new issue
Block a user