Add Metal support to Qt frontend and clean up renderer creation code (#795)
* Qt: Initial support for Metal renderer * Clean up graphics context code * Nits * More nits * Qt: Move screen-related stuff to own folder * Qt: Make screen widget polymorphic * Qt: Re-add Metal * Add factory for screen widget * Qt: Support compilation without Metal * Qt: Fix build without Metal * Oops * oops
This commit is contained in:
@@ -191,7 +191,7 @@ void RendererGL::initGraphicsContextInternal() {
|
||||
|
||||
// The OpenGL renderer doesn't need to do anything with the GL context (For Qt frontend) or the SDL window (For SDL frontend)
|
||||
// So we just call initGraphicsContextInternal for both
|
||||
void RendererGL::initGraphicsContext([[maybe_unused]] SDL_Window* window) { initGraphicsContextInternal(); }
|
||||
void RendererGL::initGraphicsContext([[maybe_unused]] void* context) { initGraphicsContextInternal(); }
|
||||
|
||||
// Set up the OpenGL blending context to match the emulated PICA
|
||||
void RendererGL::setupBlending() {
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
|
||||
#include "PICA/gpu.hpp"
|
||||
#include "PICA/pica_hash.hpp"
|
||||
#include "screen_layout.hpp"
|
||||
#include "SDL_metal.h"
|
||||
#include "screen_layout.hpp"
|
||||
|
||||
using namespace PICA;
|
||||
|
||||
@@ -57,9 +57,7 @@ void RendererMTL::reset() {
|
||||
colorRenderTargetCache.reset();
|
||||
}
|
||||
|
||||
void RendererMTL::setMTKLayer(void* layer) {
|
||||
metalLayer = (CA::MetalLayer*)layer;
|
||||
}
|
||||
void RendererMTL::setMTKLayer(void* layer) { metalLayer = (CA::MetalLayer*)layer; }
|
||||
|
||||
void RendererMTL::display() {
|
||||
CA::MetalDrawable* drawable = metalLayer->nextDrawable();
|
||||
@@ -151,13 +149,13 @@ void RendererMTL::display() {
|
||||
drawable->release();
|
||||
}
|
||||
|
||||
void RendererMTL::initGraphicsContext(SDL_Window* window) {
|
||||
// On iOS, the SwiftUI side handles the MetalLayer
|
||||
#ifdef PANDA3DS_IOS
|
||||
void RendererMTL::initGraphicsContext(void* window) {
|
||||
// On Qt and IOS, the frontend handles the MetalLayer
|
||||
#if defined(PANDA3DS_FRONTEND_QT) || defined(PANDA3DS_IOS)
|
||||
device = MTL::CreateSystemDefaultDevice();
|
||||
#else
|
||||
// TODO: what should be the type of the view?
|
||||
void* view = SDL_Metal_CreateView(window);
|
||||
void* view = SDL_Metal_CreateView((SDL_Window*)window);
|
||||
metalLayer = (CA::MetalLayer*)SDL_Metal_GetLayer(view);
|
||||
device = MTL::CreateSystemDefaultDevice();
|
||||
metalLayer->setDevice(device);
|
||||
|
||||
@@ -6,7 +6,7 @@ RendererNull::~RendererNull() {}
|
||||
|
||||
void RendererNull::reset() {}
|
||||
void RendererNull::display() {}
|
||||
void RendererNull::initGraphicsContext(SDL_Window* window) {}
|
||||
void RendererNull::initGraphicsContext(void* context) {}
|
||||
void RendererNull::clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 control) {}
|
||||
void RendererNull::displayTransfer(u32 inputAddr, u32 outputAddr, u32 inputSize, u32 outputSize, u32 flags) {}
|
||||
void RendererNull::textureCopy(u32 inputAddr, u32 outputAddr, u32 totalBytes, u32 inputSize, u32 outputSize, u32 flags) {}
|
||||
|
||||
@@ -7,7 +7,7 @@ RendererSw::~RendererSw() {}
|
||||
void RendererSw::reset() { printf("RendererSW: Unimplemented reset call\n"); }
|
||||
void RendererSw::display() { printf("RendererSW: Unimplemented display call\n"); }
|
||||
|
||||
void RendererSw::initGraphicsContext(SDL_Window* window) { printf("RendererSW: Unimplemented initGraphicsContext call\n"); }
|
||||
void RendererSw::initGraphicsContext(void* context) { printf("RendererSW: Unimplemented initGraphicsContext call\n"); }
|
||||
void RendererSw::clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 control) { printf("RendererSW: Unimplemented clearBuffer call\n"); }
|
||||
|
||||
void RendererSw::displayTransfer(u32 inputAddr, u32 outputAddr, u32 inputSize, u32 outputSize, u32 flags) {
|
||||
|
||||
@@ -173,7 +173,8 @@ std::tuple<vk::UniquePipeline, vk::UniquePipelineLayout> createGraphicsPipeline(
|
||||
vk::PipelineDynamicStateCreateInfo dynamicState = {};
|
||||
static vk::DynamicState dynamicStates[] = {// The viewport and scissor of the framebuffer will be dynamic at
|
||||
// run-time
|
||||
vk::DynamicState::eViewport, vk::DynamicState::eScissor};
|
||||
vk::DynamicState::eViewport, vk::DynamicState::eScissor
|
||||
};
|
||||
dynamicState.dynamicStateCount = std::size(dynamicStates);
|
||||
dynamicState.pDynamicStates = dynamicStates;
|
||||
|
||||
@@ -469,7 +470,8 @@ vk::RenderPass RendererVK::getRenderPass(vk::Format colorFormat, std::optional<v
|
||||
vk::SubpassDependency(
|
||||
0, VK_SUBPASS_EXTERNAL, vk::PipelineStageFlagBits::eAllGraphics, vk::PipelineStageFlagBits::eAllGraphics,
|
||||
vk::AccessFlagBits::eColorAttachmentWrite, vk::AccessFlagBits::eColorAttachmentWrite, vk::DependencyFlagBits::eByRegion
|
||||
)};
|
||||
)
|
||||
};
|
||||
|
||||
renderPassInfo.setDependencies(subpassDependencies);
|
||||
|
||||
@@ -892,8 +894,8 @@ using VulkanDynamicLoader = vk::detail::DynamicLoader;
|
||||
using VulkanDynamicLoader = vk::DynamicLoader;
|
||||
#endif
|
||||
|
||||
void RendererVK::initGraphicsContext(SDL_Window* window) {
|
||||
targetWindow = window;
|
||||
void RendererVK::initGraphicsContext(void* windowPointer) {
|
||||
targetWindow = (SDL_Window*)windowPointer;
|
||||
// Resolve all instance function pointers
|
||||
static VulkanDynamicLoader dl;
|
||||
VULKAN_HPP_DEFAULT_DISPATCHER.init(dl.getProcAddress<PFN_vkGetInstanceProcAddr>("vkGetInstanceProcAddr"));
|
||||
@@ -978,8 +980,8 @@ void RendererVK::initGraphicsContext(SDL_Window* window) {
|
||||
}
|
||||
|
||||
// Create surface
|
||||
if (window) {
|
||||
if (VkSurfaceKHR newSurface; SDL_Vulkan_CreateSurface(window, instance.get(), &newSurface)) {
|
||||
if (targetWindow) {
|
||||
if (VkSurfaceKHR newSurface; SDL_Vulkan_CreateSurface(targetWindow, instance.get(), &newSurface)) {
|
||||
swapchainSurface = newSurface;
|
||||
} else {
|
||||
Helpers::warn("Error creating Vulkan surface");
|
||||
@@ -1127,7 +1129,7 @@ void RendererVK::initGraphicsContext(SDL_Window* window) {
|
||||
vk::Extent2D swapchainExtent;
|
||||
{
|
||||
int windowWidth, windowHeight;
|
||||
SDL_Vulkan_GetDrawableSize(window, &windowWidth, &windowHeight);
|
||||
SDL_Vulkan_GetDrawableSize(targetWindow, &windowWidth, &windowHeight);
|
||||
swapchainExtent.width = windowWidth;
|
||||
swapchainExtent.height = windowHeight;
|
||||
}
|
||||
@@ -1275,7 +1277,8 @@ void RendererVK::initGraphicsContext(SDL_Window* window) {
|
||||
|
||||
static vk::DescriptorSetLayoutBinding displayShaderLayout[] = {
|
||||
{// Just a singular texture slot
|
||||
0, vk::DescriptorType::eCombinedImageSampler, 1, vk::ShaderStageFlagBits::eFragment},
|
||||
0, vk::DescriptorType::eCombinedImageSampler, 1, vk::ShaderStageFlagBits::eFragment
|
||||
},
|
||||
};
|
||||
|
||||
if (auto createResult = Vulkan::DescriptorUpdateBatch::create(device.get()); createResult.has_value()) {
|
||||
@@ -1407,7 +1410,8 @@ void RendererVK::clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 co
|
||||
|
||||
static vk::ImageSubresourceRange depthStencilRanges[2] = {
|
||||
vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1),
|
||||
vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eStencil, 0, 1, 0, 1)};
|
||||
vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eStencil, 0, 1, 0, 1)
|
||||
};
|
||||
|
||||
// Clear RenderTarget
|
||||
getCurrentCommandBuffer().clearDepthStencilImage(
|
||||
|
||||
Reference in New Issue
Block a user