metal: create renderer

This commit is contained in:
Samuliak 2024-08-16 11:06:23 +02:00
parent 98b5d56021
commit 58e1a53699
7 changed files with 34 additions and 8 deletions

View file

@ -129,6 +129,7 @@ class MainWindow : public QMainWindow {
// Tracks whether we are using an OpenGL-backed renderer or a Vulkan-backed renderer
bool usingGL = false;
bool usingVk = false;
bool usingMtl = false;
// Variables to keep track of whether the user is controlling the 3DS analog stick with their keyboard
// This is done so when a gamepad is connected, we won't automatically override the 3DS analog stick settings with the gamepad's state

View file

@ -17,7 +17,8 @@ enum class RendererType : s8 {
Null = 0,
OpenGL = 1,
Vulkan = 2,
Software = 3,
Metal = 3,
Software = 4,
};
struct EmulatorConfig;

View file

@ -19,8 +19,8 @@ template <typename SurfaceType, size_t capacity, bool evictOnOverflow = false>
class SurfaceCache {
// Vanilla std::optional can't hold actual references
using OptionalRef = std::optional<std::reference_wrapper<SurfaceType>>;
static_assert(std::is_same<SurfaceType, ColourBuffer>() || std::is_same<SurfaceType, DepthBuffer>() ||
std::is_same<SurfaceType, Texture>(), "Invalid surface type");
//static_assert(std::is_same<SurfaceType, ColourBuffer>() || std::is_same<SurfaceType, DepthBuffer>() ||
// std::is_same<SurfaceType, Texture>(), "Invalid surface type");
size_t size;
size_t evictionIndex;

View file

@ -15,6 +15,9 @@
#ifdef PANDA3DS_ENABLE_VULKAN
#include "renderer_vk/renderer_vk.hpp"
#endif
#ifdef PANDA3DS_ENABLE_METAL
#include "renderer_mtl/renderer_mtl.hpp"
#endif
constexpr u32 topScreenWidth = 240;
constexpr u32 topScreenHeight = 400;
@ -52,6 +55,12 @@ GPU::GPU(Memory& mem, EmulatorConfig& config) : mem(mem), config(config) {
renderer.reset(new RendererVK(*this, regs, externalRegs));
break;
}
#endif
#ifdef PANDA3DS_ENABLE_METAL
case RendererType::Metal: {
renderer.reset(new RendererMTL(*this, regs, externalRegs));
break;
}
#endif
default: {
Helpers::panic("Rendering backend not supported: %s", Renderer::typeToString(config.rendererType));
@ -365,7 +374,7 @@ PICA::Vertex GPU::getImmediateModeVertex() {
// Run VS and return vertex data. TODO: Don't hardcode offsets for each attribute
shaderUnit.vs.run();
// Map shader outputs to fixed function properties
const u32 totalShaderOutputs = regs[PICA::InternalRegs::ShaderOutputCount] & 7;
for (int i = 0; i < totalShaderOutputs; i++) {

View file

@ -103,6 +103,7 @@ MainWindow::MainWindow(QApplication* app, QWidget* parent) : QMainWindow(parent)
const RendererType rendererType = emu->getConfig().rendererType;
usingGL = (rendererType == RendererType::OpenGL || rendererType == RendererType::Software || rendererType == RendererType::Null);
usingVk = (rendererType == RendererType::Vulkan);
usingMtl = (rendererType == RendererType::Metal);
if (usingGL) {
// Make GL context current for this thread, enable VSync
@ -113,6 +114,8 @@ MainWindow::MainWindow(QApplication* app, QWidget* parent) : QMainWindow(parent)
emu->initGraphicsContext(glContext);
} else if (usingVk) {
Helpers::panic("Vulkan on Qt is currently WIP, try the SDL frontend instead!");
} else if (usingMtl) {
Helpers::panic("Metal on Qt currently doesn't work, try the SDL frontend instead!");
} else {
Helpers::panic("Unsupported graphics backend for Qt frontend!");
}
@ -628,4 +631,4 @@ void MainWindow::setupControllerSensors(SDL_GameController* controller) {
if (haveGyro) {
SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_GYRO, SDL_TRUE);
}
}
}

View file

@ -67,6 +67,16 @@ FrontendSDL::FrontendSDL() : keyboardMappings(InputMappings::defaultKeyboardMapp
}
#endif
#ifdef PANDA3DS_ENABLE_METAL
if (config.rendererType == RendererType::Metal) {
window = SDL_CreateWindow("Alber", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 400, 480, SDL_WINDOW_METAL | SDL_WINDOW_RESIZABLE);
if (window == nullptr) {
Helpers::warn("Window creation failed: %s", SDL_GetError());
}
}
#endif
emu.initGraphicsContext(window);
}
@ -286,7 +296,7 @@ void FrontendSDL::run() {
}
break;
}
case SDL_CONTROLLERSENSORUPDATE: {
if (event.csensor.sensor == SDL_SENSOR_GYRO) {
auto rotation = Gyro::SDL::convertRotation({
@ -370,4 +380,4 @@ void FrontendSDL::setupControllerSensors(SDL_GameController* controller) {
if (haveGyro) {
SDL_GameControllerSetSensorEnabled(controller, SDL_SENSOR_GYRO, SDL_TRUE);
}
}
}

View file

@ -17,6 +17,7 @@ std::optional<RendererType> Renderer::typeFromString(std::string inString) {
{"null", RendererType::Null}, {"nil", RendererType::Null}, {"none", RendererType::Null},
{"gl", RendererType::OpenGL}, {"ogl", RendererType::OpenGL}, {"opengl", RendererType::OpenGL},
{"vk", RendererType::Vulkan}, {"vulkan", RendererType::Vulkan}, {"vulcan", RendererType::Vulkan},
{"mtl", RendererType::Metal}, {"metal", RendererType::Metal},
{"sw", RendererType::Software}, {"soft", RendererType::Software}, {"software", RendererType::Software},
{"softrast", RendererType::Software},
};
@ -33,7 +34,8 @@ const char* Renderer::typeToString(RendererType rendererType) {
case RendererType::Null: return "null";
case RendererType::OpenGL: return "opengl";
case RendererType::Vulkan: return "vulkan";
case RendererType::Metal: return "metal";
case RendererType::Software: return "software";
default: return "Invalid";
}
}
}