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/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

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/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");
}
}

View File

@ -1,14 +1,8 @@
#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/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<MetalCommandBuffer> 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);
};