cache output shaders

This commit is contained in:
Samuliak 2024-09-30 16:28:07 +02:00
parent b088ddcfab
commit 28e553eb1a
5 changed files with 77 additions and 14 deletions

View File

@ -558,6 +558,8 @@ if(ENABLE_METAL)
HW/Latte/Renderer/Metal/MetalBufferAllocator.h
HW/Latte/Renderer/Metal/MetalMemoryManager.cpp
HW/Latte/Renderer/Metal/MetalMemoryManager.h
HW/Latte/Renderer/Metal/MetalOutputShaderCache.cpp
HW/Latte/Renderer/Metal/MetalOutputShaderCache.h
HW/Latte/Renderer/Metal/MetalPipelineCache.cpp
HW/Latte/Renderer/Metal/MetalPipelineCache.h
HW/Latte/Renderer/Metal/MetalDepthStencilCache.cpp

View File

@ -0,0 +1,38 @@
#include "Cafe/HW/Latte/Renderer/Metal/MetalOutputShaderCache.h"
#include "Cafe/HW/Latte/Renderer/Metal/RendererShaderMtl.h"
MetalOutputShaderCache::~MetalOutputShaderCache()
{
for (uint8 i = 0; i < METAL_OUTPUT_SHADER_CACHE_SIZE; i++)
{
if (m_cache[i])
m_cache[i]->release();
}
}
MTL::RenderPipelineState* MetalOutputShaderCache::GetPipeline(RendererOutputShader* shader, uint8 shaderIndex, bool usesSRGB)
{
uint8 cacheIndex = (usesSRGB ? METAL_SHADER_TYPE_COUNT : 0) + shaderIndex;
auto& renderPipelineState = m_cache[cacheIndex];
if (renderPipelineState)
return renderPipelineState;
// Create a new render pipeline state
auto vertexShaderMtl = static_cast<RendererShaderMtl*>(shader->GetVertexShader())->GetFunction();
auto fragmentShaderMtl = static_cast<RendererShaderMtl*>(shader->GetFragmentShader())->GetFunction();
auto renderPipelineDescriptor = MTL::RenderPipelineDescriptor::alloc()->init();
renderPipelineDescriptor->setVertexFunction(vertexShaderMtl);
renderPipelineDescriptor->setFragmentFunction(fragmentShaderMtl);
renderPipelineDescriptor->colorAttachments()->object(0)->setPixelFormat(usesSRGB ? MTL::PixelFormatBGRA8Unorm_sRGB : MTL::PixelFormatBGRA8Unorm);
NS::Error* error = nullptr;
renderPipelineState = m_mtlr->GetDevice()->newRenderPipelineState(renderPipelineDescriptor, &error);
if (error)
{
cemuLog_log(LogType::Force, "error creating output render pipeline state: {}", error->localizedDescription()->utf8String());
error->release();
}
return renderPipelineState;
}

View File

@ -0,0 +1,20 @@
#pragma once
#include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h"
constexpr uint8 METAL_SHADER_TYPE_COUNT = 6;
constexpr uint8 METAL_OUTPUT_SHADER_CACHE_SIZE = 2 * METAL_SHADER_TYPE_COUNT;
class MetalOutputShaderCache
{
public:
MetalOutputShaderCache(class MetalRenderer* metalRenderer) : m_mtlr{metalRenderer} {}
~MetalOutputShaderCache();
MTL::RenderPipelineState* GetPipeline(RendererOutputShader* shader, uint8 shaderIndex, bool usesSRGB);
private:
class MetalRenderer* m_mtlr;
MTL::RenderPipelineState* m_cache[METAL_OUTPUT_SHADER_CACHE_SIZE] = {nullptr};
};

View File

@ -4,6 +4,7 @@
#include "Cafe/HW/Latte/Renderer/Metal/LatteTextureViewMtl.h"
#include "Cafe/HW/Latte/Renderer/Metal/RendererShaderMtl.h"
#include "Cafe/HW/Latte/Renderer/Metal/CachedFBOMtl.h"
#include "Cafe/HW/Latte/Renderer/Metal/MetalOutputShaderCache.h"
#include "Cafe/HW/Latte/Renderer/Metal/MetalPipelineCache.h"
#include "Cafe/HW/Latte/Renderer/Metal/MetalDepthStencilCache.h"
#include "Cafe/HW/Latte/Renderer/Metal/MetalSamplerCache.h"
@ -81,6 +82,7 @@ MetalRenderer::MetalRenderer()
textureDescriptor->release();
m_memoryManager = new MetalMemoryManager(this);
m_outputShaderCache = new MetalOutputShaderCache(this);
m_pipelineCache = new MetalPipelineCache(this);
m_depthStencilCache = new MetalDepthStencilCache(this);
m_samplerCache = new MetalSamplerCache(this);
@ -174,6 +176,7 @@ MetalRenderer::~MetalRenderer()
m_presentPipelineLinear->release();
m_presentPipelineSRGB->release();
delete m_outputShaderCache;
delete m_pipelineCache;
delete m_depthStencilCache;
delete m_samplerCache;
@ -276,7 +279,6 @@ void MetalRenderer::SwapBuffers(bool swapTV, bool swapDRC)
m_performanceMonitor.ResetPerFrameData();
}
// TODO: use `shader` for drawing
void MetalRenderer::DrawBackbufferQuad(LatteTextureView* texView, RendererOutputShader* shader, bool useLinearTexFilter,
sint32 imageX, sint32 imageY, sint32 imageWidth, sint32 imageHeight,
bool padView, bool clearBackground)
@ -299,21 +301,20 @@ void MetalRenderer::DrawBackbufferQuad(LatteTextureView* texView, RendererOutput
renderPassDescriptor->release();
// Get a render pipeline
auto vertexShaderMtl = static_cast<RendererShaderMtl*>(shader->GetVertexShader())->GetFunction();
auto fragmentShaderMtl = static_cast<RendererShaderMtl*>(shader->GetFragmentShader())->GetFunction();
auto renderPipelineDescriptor = MTL::RenderPipelineDescriptor::alloc()->init();
renderPipelineDescriptor->setVertexFunction(vertexShaderMtl);
renderPipelineDescriptor->setFragmentFunction(fragmentShaderMtl);
renderPipelineDescriptor->colorAttachments()->object(0)->setPixelFormat(m_state.m_usesSRGB ? MTL::PixelFormatBGRA8Unorm_sRGB : MTL::PixelFormatBGRA8Unorm);
// Find out which shader we are using
uint8 shaderIndex = 255;
if (shader == RendererOutputShader::s_copy_shader) shaderIndex = 0;
else if (shader == RendererOutputShader::s_bicubic_shader) shaderIndex = 1;
else if (shader == RendererOutputShader::s_hermit_shader) shaderIndex = 2;
else if (shader == RendererOutputShader::s_copy_shader_ud) shaderIndex = 3;
else if (shader == RendererOutputShader::s_bicubic_shader_ud) shaderIndex = 4;
else if (shader == RendererOutputShader::s_hermit_shader_ud) shaderIndex = 5;
NS::Error* error = nullptr;
auto renderPipelineState = m_device->newRenderPipelineState(renderPipelineDescriptor, &error);
if (error)
{
printf("AAA: %s\n", error->localizedDescription()->utf8String());
error->release();
}
uint8 shaderType = shaderIndex % 3;
// Get the render pipeline state
auto renderPipelineState = m_outputShaderCache->GetPipeline(shader, shaderIndex, m_state.m_usesSRGB);
// Draw to Metal layer
renderCommandEncoder->setRenderPipelineState(renderPipelineState);

View File

@ -4,6 +4,7 @@
#include "Cafe/HW/Latte/Renderer/Metal/MetalLayerHandle.h"
#include "Cafe/HW/Latte/Renderer/Metal/MetalPerformanceMonitor.h"
#include "Cafe/HW/Latte/Renderer/Metal/MetalOutputShaderCache.h"
struct MetalBufferAllocation
{
@ -460,6 +461,7 @@ private:
// Managers and caches
class MetalMemoryManager* m_memoryManager;
class MetalOutputShaderCache* m_outputShaderCache;
class MetalPipelineCache* m_pipelineCache;
class MetalDepthStencilCache* m_depthStencilCache;
class MetalSamplerCache* m_samplerCache;