diff --git a/src/Cafe/CMakeLists.txt b/src/Cafe/CMakeLists.txt index 37bef0e8..100f00d8 100644 --- a/src/Cafe/CMakeLists.txt +++ b/src/Cafe/CMakeLists.txt @@ -542,6 +542,8 @@ if(ENABLE_METAL) HW/Latte/Renderer/Metal/MetalCppImpl.cpp HW/Latte/Renderer/Metal/MetalLayer.mm HW/Latte/Renderer/Metal/MetalLayer.h + HW/Latte/Renderer/Metal/MetalLayerHandle.cpp + HW/Latte/Renderer/Metal/MetalLayerHandle.h HW/Latte/Renderer/Metal/LatteToMtl.cpp HW/Latte/Renderer/Metal/LatteToMtl.h HW/Latte/Renderer/Metal/LatteTextureMtl.cpp diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalLayerHandle.cpp b/src/Cafe/HW/Latte/Renderer/Metal/MetalLayerHandle.cpp new file mode 100644 index 00000000..f4d4490e --- /dev/null +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalLayerHandle.cpp @@ -0,0 +1,45 @@ +#include "Cafe/HW/Latte/Renderer/Metal/MetalLayerHandle.h" +#include "Cafe/HW/Latte/Renderer/Metal/MetalLayer.h" + +#include "gui/guiWrapper.h" + +MetalLayerHandle::MetalLayerHandle(MTL::Device* device, const Vector2i& size) +{ + const auto& windowInfo = gui_getWindowInfo().window_main; + + m_layer = (CA::MetalLayer*)CreateMetalLayer(windowInfo.handle, m_layerScaleX, m_layerScaleY); + m_layer->setDevice(device); + m_layer->setDrawableSize(CGSize{(float)size.x * m_layerScaleX, (float)size.y * m_layerScaleY}); +} + +MetalLayerHandle::~MetalLayerHandle() +{ + if (m_layer) + m_layer->release(); +} + +void MetalLayerHandle::Resize(const Vector2i& size) +{ + m_layer->setDrawableSize(CGSize{(float)size.x * m_layerScaleX, (float)size.y * m_layerScaleY}); +} + +bool MetalLayerHandle::AcquireDrawable() +{ + if (m_drawable) + return true; + + m_drawable = m_layer->nextDrawable(); + if (!m_drawable) + { + debug_printf("failed to acquire next drawable\n"); + return false; + } + + return true; +} + +void MetalLayerHandle::PresentDrawable(MTL::CommandBuffer* commandBuffer) +{ + commandBuffer->presentDrawable(m_drawable); + m_drawable = nullptr; +} diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalLayerHandle.h b/src/Cafe/HW/Latte/Renderer/Metal/MetalLayerHandle.h new file mode 100644 index 00000000..f95bd800 --- /dev/null +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalLayerHandle.h @@ -0,0 +1,33 @@ +#pragma once + +#include + +#include "Cafe/HW/Latte/Renderer/Metal/MetalCommon.h" +#include "QuartzCore/CAMetalDrawable.hpp" +#include "QuartzCore/CAMetalLayer.hpp" +#include "util/math/vector2.h" + +class MetalLayerHandle +{ +public: + MetalLayerHandle() = default; + MetalLayerHandle(MTL::Device* device, const Vector2i& size); + + ~MetalLayerHandle(); + + void Resize(const Vector2i& size); + + bool AcquireDrawable(); + + void PresentDrawable(MTL::CommandBuffer* commandBuffer); + + CA::MetalLayer* GetLayer() const { return m_layer; } + + CA::MetalDrawable* GetDrawable() const { return m_drawable; } + +private: + CA::MetalLayer* m_layer = nullptr; + float m_layerScaleX, m_layerScaleY; + + CA::MetalDrawable* m_drawable = nullptr; +}; diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp index 0031b4e2..42ecbacf 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp @@ -1,5 +1,4 @@ #include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h" -#include "Cafe/HW/Latte/Renderer/Metal/MetalLayer.h" #include "Cafe/HW/Latte/Renderer/Metal/MetalMemoryManager.h" #include "Cafe/HW/Latte/Renderer/Metal/LatteTextureMtl.h" #include "Cafe/HW/Latte/Renderer/Metal/LatteTextureViewMtl.h" @@ -19,6 +18,7 @@ #include "Cemu/Logging/CemuDebugLogging.h" #include "HW/Latte/Core/LatteConst.h" #include "HW/Latte/Renderer/Metal/MetalCommon.h" +#include "HW/Latte/Renderer/Metal/MetalLayerHandle.h" #include "gui/guiWrapper.h" #define COMMIT_TRESHOLD 256 @@ -174,20 +174,14 @@ MetalRenderer::~MetalRenderer() m_device->release(); } -// TODO: don't ignore "mainWindow" argument void MetalRenderer::InitializeLayer(const Vector2i& size, bool mainWindow) { - const auto& windowInfo = gui_getWindowInfo().window_main; - - m_metalLayer = (CA::MetalLayer*)CreateMetalLayer(windowInfo.handle, m_layerScaleX, m_layerScaleY); - m_metalLayer->setDevice(m_device); - m_metalLayer->setDrawableSize(CGSize{(float)size.x * m_layerScaleX, (float)size.y * m_layerScaleY}); + GetLayer(mainWindow) = MetalLayerHandle(m_device, size); } -// TODO: don't ignore "mainWindow" argument void MetalRenderer::ResizeLayer(const Vector2i& size, bool mainWindow) { - m_metalLayer->setDrawableSize(CGSize{(float)size.x * m_layerScaleX, (float)size.y * m_layerScaleY}); + GetLayer(mainWindow).Resize(size); } void MetalRenderer::Initialize() @@ -222,7 +216,7 @@ void MetalRenderer::ClearColorbuffer(bool padView) if (!AcquireNextDrawable(!padView)) return; - ClearColorTextureInternal(m_drawable->texture(), 0, 0, 0.0f, 0.0f, 0.0f, 0.0f); + ClearColorTextureInternal(GetLayer(!padView).GetDrawable()->texture(), 0, 0, 0.0f, 0.0f, 0.0f, 0.0f); } void MetalRenderer::DrawEmptyFrame(bool mainWindow) @@ -234,17 +228,10 @@ void MetalRenderer::DrawEmptyFrame(bool mainWindow) void MetalRenderer::SwapBuffers(bool swapTV, bool swapDRC) { - - if (m_drawable) - { - auto commandBuffer = GetCommandBuffer(); - commandBuffer->presentDrawable(m_drawable); - } - else - { - debug_printf("skipped present!\n"); - } - m_drawable = nullptr; + if (swapTV) + SwapBuffer(true); + if (swapDRC) + SwapBuffer(false); // Release all the command buffers CommitCommandBuffer(); @@ -269,7 +256,7 @@ void MetalRenderer::DrawBackbufferQuad(LatteTextureView* texView, RendererOutput // Create render pass MTL::RenderPassDescriptor* renderPassDescriptor = MTL::RenderPassDescriptor::alloc()->init(); auto colorAttachment = renderPassDescriptor->colorAttachments()->object(0); - colorAttachment->setTexture(m_drawable->texture()); + colorAttachment->setTexture(GetLayer(!padView).GetDrawable()->texture()); // TODO: shouldn't it be LoadActionLoad when not clearing? colorAttachment->setLoadAction(clearBackground ? MTL::LoadActionClear : MTL::LoadActionDontCare); colorAttachment->setStoreAction(MTL::StoreActionStore); @@ -1351,27 +1338,16 @@ void MetalRenderer::CommitCommandBuffer() bool MetalRenderer::AcquireNextDrawable(bool mainWindow) { + auto& layer = GetLayer(mainWindow); + const bool latteBufferUsesSRGB = mainWindow ? LatteGPUState.tvBufferUsesSRGB : LatteGPUState.drcBufferUsesSRGB; if (latteBufferUsesSRGB != m_state.m_usesSRGB) { - m_metalLayer->setPixelFormat(latteBufferUsesSRGB ? MTL::PixelFormatRGBA8Unorm_sRGB : MTL::PixelFormatRGBA8Unorm); + layer.GetLayer()->setPixelFormat(latteBufferUsesSRGB ? MTL::PixelFormatRGBA8Unorm_sRGB : MTL::PixelFormatRGBA8Unorm); m_state.m_usesSRGB = latteBufferUsesSRGB; } - if (m_drawable) - { - // TODO: should this be true? - return true; - } - - m_drawable = m_metalLayer->nextDrawable(); - if (!m_drawable) - { - debug_printf("failed to acquire next drawable\n"); - return false; - } - - return true; + return layer.AcquireDrawable(); } bool MetalRenderer::CheckIfRenderPassNeedsFlush(LatteDecompilerShader* shader) @@ -1639,3 +1615,20 @@ void MetalRenderer::ClearColorTextureInternal(MTL::Texture* mtlTexture, sint32 s renderPassDescriptor->release(); EndEncoding(); } + + + +void MetalRenderer::SwapBuffer(bool mainWindow) +{ + auto& layer = GetLayer(mainWindow); + + if (layer.GetDrawable()) + { + auto commandBuffer = GetCommandBuffer(); + layer.PresentDrawable(commandBuffer); + } + else + { + debug_printf("skipped present!\n"); + } +} diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h index 4da66653..7607de1d 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h @@ -1,14 +1,8 @@ #pragma once -#include -#include -#include - #include "Cafe/HW/Latte/Renderer/Renderer.h" -#include "Cafe/HW/Latte/Renderer/Metal/MetalCommon.h" -#include "Metal/MTLResource.hpp" -#include "Metal/MTLSampler.hpp" +#include "Cafe/HW/Latte/Renderer/Metal/MetalLayerHandle.h" struct MetalBufferAllocation { @@ -428,8 +422,8 @@ public: } private: - CA::MetalLayer* m_metalLayer; - float m_layerScaleX, m_layerScaleY; + MetalLayerHandle m_mainLayer; + MetalLayerHandle m_padLayer; // Metal objects MTL::Device* m_device; @@ -473,10 +467,16 @@ private: std::vector m_commandBuffers; MetalEncoderType m_encoderType = MetalEncoderType::None; MTL::CommandEncoder* m_commandEncoder = nullptr; - CA::MetalDrawable* m_drawable = nullptr; uint32 m_recordedDrawcalls = 0; // State MetalState m_state; + + MetalLayerHandle& GetLayer(bool mainWindow) + { + return (mainWindow ? m_mainLayer : m_padLayer); + } + + void SwapBuffer(bool mainWindow); };