rework the present system

This commit is contained in:
Samuliak 2024-08-23 10:52:20 +02:00
parent 6bb191212b
commit d4a1074425
5 changed files with 120 additions and 47 deletions

View File

@ -542,6 +542,8 @@ if(ENABLE_METAL)
HW/Latte/Renderer/Metal/MetalCppImpl.cpp HW/Latte/Renderer/Metal/MetalCppImpl.cpp
HW/Latte/Renderer/Metal/MetalLayer.mm HW/Latte/Renderer/Metal/MetalLayer.mm
HW/Latte/Renderer/Metal/MetalLayer.h 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.cpp
HW/Latte/Renderer/Metal/LatteToMtl.h HW/Latte/Renderer/Metal/LatteToMtl.h
HW/Latte/Renderer/Metal/LatteTextureMtl.cpp HW/Latte/Renderer/Metal/LatteTextureMtl.cpp

View File

@ -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;
}

View File

@ -0,0 +1,33 @@
#pragma once
#include <QuartzCore/QuartzCore.hpp>
#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;
};

View File

@ -1,5 +1,4 @@
#include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h" #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/MetalMemoryManager.h"
#include "Cafe/HW/Latte/Renderer/Metal/LatteTextureMtl.h" #include "Cafe/HW/Latte/Renderer/Metal/LatteTextureMtl.h"
#include "Cafe/HW/Latte/Renderer/Metal/LatteTextureViewMtl.h" #include "Cafe/HW/Latte/Renderer/Metal/LatteTextureViewMtl.h"
@ -19,6 +18,7 @@
#include "Cemu/Logging/CemuDebugLogging.h" #include "Cemu/Logging/CemuDebugLogging.h"
#include "HW/Latte/Core/LatteConst.h" #include "HW/Latte/Core/LatteConst.h"
#include "HW/Latte/Renderer/Metal/MetalCommon.h" #include "HW/Latte/Renderer/Metal/MetalCommon.h"
#include "HW/Latte/Renderer/Metal/MetalLayerHandle.h"
#include "gui/guiWrapper.h" #include "gui/guiWrapper.h"
#define COMMIT_TRESHOLD 256 #define COMMIT_TRESHOLD 256
@ -174,20 +174,14 @@ MetalRenderer::~MetalRenderer()
m_device->release(); m_device->release();
} }
// TODO: don't ignore "mainWindow" argument
void MetalRenderer::InitializeLayer(const Vector2i& size, bool mainWindow) void MetalRenderer::InitializeLayer(const Vector2i& size, bool mainWindow)
{ {
const auto& windowInfo = gui_getWindowInfo().window_main; GetLayer(mainWindow) = MetalLayerHandle(m_device, size);
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});
} }
// TODO: don't ignore "mainWindow" argument
void MetalRenderer::ResizeLayer(const Vector2i& size, bool mainWindow) 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() void MetalRenderer::Initialize()
@ -222,7 +216,7 @@ void MetalRenderer::ClearColorbuffer(bool padView)
if (!AcquireNextDrawable(!padView)) if (!AcquireNextDrawable(!padView))
return; 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) void MetalRenderer::DrawEmptyFrame(bool mainWindow)
@ -234,17 +228,10 @@ void MetalRenderer::DrawEmptyFrame(bool mainWindow)
void MetalRenderer::SwapBuffers(bool swapTV, bool swapDRC) void MetalRenderer::SwapBuffers(bool swapTV, bool swapDRC)
{ {
if (swapTV)
if (m_drawable) SwapBuffer(true);
{ if (swapDRC)
auto commandBuffer = GetCommandBuffer(); SwapBuffer(false);
commandBuffer->presentDrawable(m_drawable);
}
else
{
debug_printf("skipped present!\n");
}
m_drawable = nullptr;
// Release all the command buffers // Release all the command buffers
CommitCommandBuffer(); CommitCommandBuffer();
@ -269,7 +256,7 @@ void MetalRenderer::DrawBackbufferQuad(LatteTextureView* texView, RendererOutput
// Create render pass // Create render pass
MTL::RenderPassDescriptor* renderPassDescriptor = MTL::RenderPassDescriptor::alloc()->init(); MTL::RenderPassDescriptor* renderPassDescriptor = MTL::RenderPassDescriptor::alloc()->init();
auto colorAttachment = renderPassDescriptor->colorAttachments()->object(0); 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? // TODO: shouldn't it be LoadActionLoad when not clearing?
colorAttachment->setLoadAction(clearBackground ? MTL::LoadActionClear : MTL::LoadActionDontCare); colorAttachment->setLoadAction(clearBackground ? MTL::LoadActionClear : MTL::LoadActionDontCare);
colorAttachment->setStoreAction(MTL::StoreActionStore); colorAttachment->setStoreAction(MTL::StoreActionStore);
@ -1351,27 +1338,16 @@ void MetalRenderer::CommitCommandBuffer()
bool MetalRenderer::AcquireNextDrawable(bool mainWindow) bool MetalRenderer::AcquireNextDrawable(bool mainWindow)
{ {
auto& layer = GetLayer(mainWindow);
const bool latteBufferUsesSRGB = mainWindow ? LatteGPUState.tvBufferUsesSRGB : LatteGPUState.drcBufferUsesSRGB; const bool latteBufferUsesSRGB = mainWindow ? LatteGPUState.tvBufferUsesSRGB : LatteGPUState.drcBufferUsesSRGB;
if (latteBufferUsesSRGB != m_state.m_usesSRGB) 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; m_state.m_usesSRGB = latteBufferUsesSRGB;
} }
if (m_drawable) return layer.AcquireDrawable();
{
// 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;
} }
bool MetalRenderer::CheckIfRenderPassNeedsFlush(LatteDecompilerShader* shader) bool MetalRenderer::CheckIfRenderPassNeedsFlush(LatteDecompilerShader* shader)
@ -1639,3 +1615,20 @@ void MetalRenderer::ClearColorTextureInternal(MTL::Texture* mtlTexture, sint32 s
renderPassDescriptor->release(); renderPassDescriptor->release();
EndEncoding(); 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");
}
}

View File

@ -1,14 +1,8 @@
#pragma once #pragma once
#include <Foundation/Foundation.hpp>
#include <QuartzCore/QuartzCore.hpp>
#include <Metal/Metal.hpp>
#include "Cafe/HW/Latte/Renderer/Renderer.h" #include "Cafe/HW/Latte/Renderer/Renderer.h"
#include "Cafe/HW/Latte/Renderer/Metal/MetalCommon.h" #include "Cafe/HW/Latte/Renderer/Metal/MetalLayerHandle.h"
#include "Metal/MTLResource.hpp"
#include "Metal/MTLSampler.hpp"
struct MetalBufferAllocation struct MetalBufferAllocation
{ {
@ -428,8 +422,8 @@ public:
} }
private: private:
CA::MetalLayer* m_metalLayer; MetalLayerHandle m_mainLayer;
float m_layerScaleX, m_layerScaleY; MetalLayerHandle m_padLayer;
// Metal objects // Metal objects
MTL::Device* m_device; MTL::Device* m_device;
@ -473,10 +467,16 @@ private:
std::vector<MetalCommandBuffer> m_commandBuffers; std::vector<MetalCommandBuffer> m_commandBuffers;
MetalEncoderType m_encoderType = MetalEncoderType::None; MetalEncoderType m_encoderType = MetalEncoderType::None;
MTL::CommandEncoder* m_commandEncoder = nullptr; MTL::CommandEncoder* m_commandEncoder = nullptr;
CA::MetalDrawable* m_drawable = nullptr;
uint32 m_recordedDrawcalls = 0; uint32 m_recordedDrawcalls = 0;
// State // State
MetalState m_state; MetalState m_state;
MetalLayerHandle& GetLayer(bool mainWindow)
{
return (mainWindow ? m_mainLayer : m_padLayer);
}
void SwapBuffer(bool mainWindow);
}; };