mirror of
https://github.com/cemu-project/Cemu.git
synced 2024-12-01 21:44:17 +01:00
refactor fbos
This commit is contained in:
parent
6b47d4f61e
commit
cd21d957b3
@ -534,6 +534,7 @@ if(APPLE)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(ENABLE_METAL)
|
if(ENABLE_METAL)
|
||||||
|
# TODO: sort alphabetically
|
||||||
target_sources(CemuCafe PRIVATE
|
target_sources(CemuCafe PRIVATE
|
||||||
HW/Latte/Renderer/Metal/MetalRenderer.cpp
|
HW/Latte/Renderer/Metal/MetalRenderer.cpp
|
||||||
HW/Latte/Renderer/Metal/MetalRenderer.h
|
HW/Latte/Renderer/Metal/MetalRenderer.h
|
||||||
@ -555,6 +556,8 @@ if(ENABLE_METAL)
|
|||||||
HW/Latte/Renderer/Metal/RendererShaderMtl.h
|
HW/Latte/Renderer/Metal/RendererShaderMtl.h
|
||||||
HW/Latte/Renderer/Metal/CachedFBOMtl.cpp
|
HW/Latte/Renderer/Metal/CachedFBOMtl.cpp
|
||||||
HW/Latte/Renderer/Metal/CachedFBOMtl.h
|
HW/Latte/Renderer/Metal/CachedFBOMtl.h
|
||||||
|
HW/Latte/Renderer/Metal/MetalAttachmentsInfo.cpp
|
||||||
|
HW/Latte/Renderer/Metal/MetalAttachmentsInfo.h
|
||||||
HW/Latte/Renderer/Metal/MetalBufferAllocator.h
|
HW/Latte/Renderer/Metal/MetalBufferAllocator.h
|
||||||
HW/Latte/Renderer/Metal/MetalMemoryManager.cpp
|
HW/Latte/Renderer/Metal/MetalMemoryManager.cpp
|
||||||
HW/Latte/Renderer/Metal/MetalMemoryManager.h
|
HW/Latte/Renderer/Metal/MetalMemoryManager.h
|
||||||
|
48
src/Cafe/HW/Latte/Renderer/Metal/MetalAttachmentsInfo.cpp
Normal file
48
src/Cafe/HW/Latte/Renderer/Metal/MetalAttachmentsInfo.cpp
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#include "Cafe/HW/Latte/Renderer/Metal/MetalAttachmentsInfo.h"
|
||||||
|
#include "Cafe/HW/Latte/Renderer/Metal/CachedFBOMtl.h"
|
||||||
|
#include "Cafe/HW/Latte/Renderer/Metal/LatteTextureViewMtl.h"
|
||||||
|
#include "Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h"
|
||||||
|
|
||||||
|
MetalAttachmentsInfo::MetalAttachmentsInfo(class CachedFBOMtl* fbo)
|
||||||
|
{
|
||||||
|
for (uint8 i = 0; i < LATTE_NUM_COLOR_TARGET; i++)
|
||||||
|
{
|
||||||
|
const auto& colorBuffer = fbo->colorBuffer[i];
|
||||||
|
auto texture = static_cast<LatteTextureViewMtl*>(colorBuffer.texture);
|
||||||
|
if (!texture)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
colorFormats[i] = texture->format;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Depth stencil attachment
|
||||||
|
if (fbo->depthBuffer.texture)
|
||||||
|
{
|
||||||
|
auto texture = static_cast<LatteTextureViewMtl*>(fbo->depthBuffer.texture);
|
||||||
|
depthFormat = texture->format;
|
||||||
|
hasStencil = fbo->depthBuffer.hasStencil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MetalAttachmentsInfo::MetalAttachmentsInfo(const LatteContextRegister& lcr, const LatteDecompilerShader* pixelShader)
|
||||||
|
{
|
||||||
|
uint8 cbMask = LatteMRT::GetActiveColorBufferMask(pixelShader, lcr);
|
||||||
|
bool dbMask = LatteMRT::GetActiveDepthBufferMask(lcr);
|
||||||
|
|
||||||
|
// Color attachments
|
||||||
|
for (int i = 0; i < 8; ++i)
|
||||||
|
{
|
||||||
|
if ((cbMask & (1 << i)) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
colorFormats[i] = LatteMRT::GetColorBufferFormat(i, lcr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Depth stencil attachment
|
||||||
|
if (dbMask)
|
||||||
|
{
|
||||||
|
Latte::E_GX2SURFFMT format = LatteMRT::GetDepthBufferFormat(lcr);
|
||||||
|
depthFormat = format;
|
||||||
|
hasStencil = GetMtlPixelFormatInfo(format, true).hasStencil;
|
||||||
|
}
|
||||||
|
}
|
15
src/Cafe/HW/Latte/Renderer/Metal/MetalAttachmentsInfo.h
Normal file
15
src/Cafe/HW/Latte/Renderer/Metal/MetalAttachmentsInfo.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Cafe/HW/Latte/Renderer/Metal/MetalCommon.h"
|
||||||
|
|
||||||
|
class MetalAttachmentsInfo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MetalAttachmentsInfo() = default;
|
||||||
|
MetalAttachmentsInfo(class CachedFBOMtl* fbo);
|
||||||
|
MetalAttachmentsInfo(const LatteContextRegister& lcr, const class LatteDecompilerShader* pixelShader);
|
||||||
|
|
||||||
|
Latte::E_GX2SURFFMT colorFormats[LATTE_NUM_COLOR_TARGET] = {Latte::E_GX2SURFFMT::INVALID_FORMAT};
|
||||||
|
Latte::E_GX2SURFFMT depthFormat = Latte::E_GX2SURFFMT::INVALID_FORMAT;
|
||||||
|
bool hasStencil = false;
|
||||||
|
};
|
@ -11,6 +11,9 @@
|
|||||||
#include "Cafe/HW/Latte/Core/LatteShaderCache.h"
|
#include "Cafe/HW/Latte/Core/LatteShaderCache.h"
|
||||||
#include "Cemu/FileCache/FileCache.h"
|
#include "Cemu/FileCache/FileCache.h"
|
||||||
#include "HW/Latte/Core/LatteShader.h"
|
#include "HW/Latte/Core/LatteShader.h"
|
||||||
|
#include "HW/Latte/ISA/LatteReg.h"
|
||||||
|
#include "HW/Latte/Renderer/Metal/LatteToMtl.h"
|
||||||
|
#include "HW/Latte/Renderer/Metal/MetalAttachmentsInfo.h"
|
||||||
#include "util/helpers/helpers.h"
|
#include "util/helpers/helpers.h"
|
||||||
#include "config/ActiveSettings.h"
|
#include "config/ActiveSettings.h"
|
||||||
#include <openssl/sha.h>
|
#include <openssl/sha.h>
|
||||||
@ -35,15 +38,15 @@ MetalPipelineCache::~MetalPipelineCache()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MTL::RenderPipelineState* MetalPipelineCache::GetRenderPipelineState(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* geometryShader, const LatteDecompilerShader* pixelShader, class CachedFBOMtl* lastUsedFBO, class CachedFBOMtl* activeFBO, const LatteContextRegister& lcr)
|
MTL::RenderPipelineState* MetalPipelineCache::GetRenderPipelineState(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* geometryShader, const LatteDecompilerShader* pixelShader, const MetalAttachmentsInfo& lastUsedAttachmentsInfo, const MetalAttachmentsInfo& activeAttachmentsInfo, const LatteContextRegister& lcr)
|
||||||
{
|
{
|
||||||
uint64 hash = CalculatePipelineHash(fetchShader, vertexShader, geometryShader, pixelShader, lastUsedFBO, activeFBO, lcr);
|
uint64 hash = CalculatePipelineHash(fetchShader, vertexShader, geometryShader, pixelShader, lastUsedAttachmentsInfo, activeAttachmentsInfo, lcr);
|
||||||
auto& pipeline = m_pipelineCache[hash];
|
auto& pipeline = m_pipelineCache[hash];
|
||||||
if (pipeline)
|
if (pipeline)
|
||||||
return pipeline;
|
return pipeline;
|
||||||
|
|
||||||
MetalPipelineCompiler compiler(m_mtlr);
|
MetalPipelineCompiler compiler(m_mtlr);
|
||||||
compiler.InitFromState(fetchShader, vertexShader, geometryShader, pixelShader, lastUsedFBO, activeFBO, lcr);
|
compiler.InitFromState(fetchShader, vertexShader, geometryShader, pixelShader, lastUsedAttachmentsInfo, activeAttachmentsInfo, lcr);
|
||||||
pipeline = compiler.Compile(false, true);
|
pipeline = compiler.Compile(false, true);
|
||||||
|
|
||||||
if (!HasPipelineCached(vertexShader->baseHash, hash))
|
if (!HasPipelineCached(vertexShader->baseHash, hash))
|
||||||
@ -52,33 +55,32 @@ MTL::RenderPipelineState* MetalPipelineCache::GetRenderPipelineState(const Latte
|
|||||||
return pipeline;
|
return pipeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64 MetalPipelineCache::CalculatePipelineHash(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* geometryShader, const LatteDecompilerShader* pixelShader, class CachedFBOMtl* lastUsedFBO, class CachedFBOMtl* activeFBO, const LatteContextRegister& lcr)
|
uint64 MetalPipelineCache::CalculatePipelineHash(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* geometryShader, const LatteDecompilerShader* pixelShader, const MetalAttachmentsInfo& lastUsedAttachmentsInfo, const MetalAttachmentsInfo& activeAttachmentsInfo, const LatteContextRegister& lcr)
|
||||||
{
|
{
|
||||||
// Hash
|
// Hash
|
||||||
uint64 stateHash = 0;
|
uint64 stateHash = 0;
|
||||||
for (int i = 0; i < Latte::GPU_LIMITS::NUM_COLOR_ATTACHMENTS; ++i)
|
for (int i = 0; i < Latte::GPU_LIMITS::NUM_COLOR_ATTACHMENTS; ++i)
|
||||||
{
|
{
|
||||||
auto textureView = static_cast<LatteTextureViewMtl*>(lastUsedFBO->colorBuffer[i].texture);
|
Latte::E_GX2SURFFMT format = lastUsedAttachmentsInfo.colorFormats[i];
|
||||||
if (!textureView)
|
if (format == Latte::E_GX2SURFFMT::INVALID_FORMAT)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
stateHash += textureView->GetRGBAView()->pixelFormat() + i * 31;
|
stateHash += GetMtlPixelFormat(format, false) + i * 31;
|
||||||
stateHash = std::rotl<uint64>(stateHash, 7);
|
stateHash = std::rotl<uint64>(stateHash, 7);
|
||||||
|
|
||||||
if (activeFBO->colorBuffer[i].texture)
|
if (activeAttachmentsInfo.colorFormats[i] == Latte::E_GX2SURFFMT::INVALID_FORMAT)
|
||||||
{
|
{
|
||||||
stateHash += 1;
|
stateHash += 1;
|
||||||
stateHash = std::rotl<uint64>(stateHash, 1);
|
stateHash = std::rotl<uint64>(stateHash, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lastUsedFBO->depthBuffer.texture)
|
if (lastUsedAttachmentsInfo.depthFormat != Latte::E_GX2SURFFMT::INVALID_FORMAT)
|
||||||
{
|
{
|
||||||
auto textureView = static_cast<LatteTextureViewMtl*>(lastUsedFBO->depthBuffer.texture);
|
stateHash += GetMtlPixelFormat(lastUsedAttachmentsInfo.depthFormat, true);
|
||||||
stateHash += textureView->GetRGBAView()->pixelFormat();
|
|
||||||
stateHash = std::rotl<uint64>(stateHash, 7);
|
stateHash = std::rotl<uint64>(stateHash, 7);
|
||||||
|
|
||||||
if (activeFBO->depthBuffer.texture)
|
if (activeAttachmentsInfo.depthFormat == Latte::E_GX2SURFFMT::INVALID_FORMAT)
|
||||||
{
|
{
|
||||||
stateHash += 1;
|
stateHash += 1;
|
||||||
stateHash = std::rotl<uint64>(stateHash, 1);
|
stateHash = std::rotl<uint64>(stateHash, 1);
|
||||||
@ -347,33 +349,28 @@ void MetalPipelineCache::LoadPipelineFromCache(std::span<uint8> fileData)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// create pipeline info
|
MetalAttachmentsInfo attachmentsInfo(*lcr, pixelShader);
|
||||||
m_pipelineIsCachedLock.lock();
|
|
||||||
m_pipelineIsCachedLock.unlock();
|
|
||||||
throw;
|
|
||||||
// TODO: uncomment
|
|
||||||
/*
|
|
||||||
// compile
|
// compile
|
||||||
{
|
{
|
||||||
MetalPipelineCompiler pp(m_mtlr);
|
MetalPipelineCompiler pp(m_mtlr);
|
||||||
if (!pp.InitFromState(fetchShader, vertexShader, geometryShader, pixelShader, activeFBO, activeFBO, *lcr))
|
pp.InitFromState(vertexShader->compatibleFetchShader, vertexShader, geometryShader, pixelShader, attachmentsInfo, attachmentsInfo, *lcr);
|
||||||
{
|
//{
|
||||||
s_spinlockSharedInternal.lock();
|
// s_spinlockSharedInternal.lock();
|
||||||
delete lcr;
|
// delete lcr;
|
||||||
delete cachedPipeline;
|
// delete cachedPipeline;
|
||||||
s_spinlockSharedInternal.unlock();
|
// s_spinlockSharedInternal.unlock();
|
||||||
return;
|
// return;
|
||||||
}
|
//}
|
||||||
pp.Compile(true, true);
|
pp.Compile(true, true);
|
||||||
// destroy pp early
|
// destroy pp early
|
||||||
}
|
}
|
||||||
// on success, calculate pipeline hash and flag as present in cache
|
// on success, calculate pipeline hash and flag as present in cache
|
||||||
uint64 pipelineBaseHash = vertexShader->baseHash;
|
uint64 pipelineBaseHash = vertexShader->baseHash;
|
||||||
uint64 pipelineStateHash = CalculatePipelineHash(fetchShader, vertexShader, geometryShader, pixelShader, activeFBO, activeFBO, *lcr);
|
uint64 pipelineStateHash = CalculatePipelineHash(vertexShader->compatibleFetchShader, vertexShader, geometryShader, pixelShader, attachmentsInfo, attachmentsInfo, *lcr);
|
||||||
m_pipelineIsCachedLock.lock();
|
m_pipelineIsCachedLock.lock();
|
||||||
m_pipelineIsCached.emplace(pipelineBaseHash, pipelineStateHash);
|
m_pipelineIsCached.emplace(pipelineBaseHash, pipelineStateHash);
|
||||||
m_pipelineIsCachedLock.unlock();
|
m_pipelineIsCachedLock.unlock();
|
||||||
*/
|
|
||||||
|
|
||||||
// clean up
|
// clean up
|
||||||
s_spinlockSharedInternal.lock();
|
s_spinlockSharedInternal.lock();
|
||||||
|
@ -36,7 +36,7 @@ public:
|
|||||||
MetalPipelineCache(class MetalRenderer* metalRenderer);
|
MetalPipelineCache(class MetalRenderer* metalRenderer);
|
||||||
~MetalPipelineCache();
|
~MetalPipelineCache();
|
||||||
|
|
||||||
MTL::RenderPipelineState* GetRenderPipelineState(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* geometryShader, const LatteDecompilerShader* pixelShader, class CachedFBOMtl* lastUsedFBO, class CachedFBOMtl* activeFBO, const LatteContextRegister& lcr);
|
MTL::RenderPipelineState* GetRenderPipelineState(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* geometryShader, const LatteDecompilerShader* pixelShader, const class MetalAttachmentsInfo& lastUsedAttachmentsInfo, const class MetalAttachmentsInfo& activeAttachmentsInfo, const LatteContextRegister& lcr);
|
||||||
|
|
||||||
// Cache loading
|
// Cache loading
|
||||||
uint32 BeginLoading(uint64 cacheTitleId); // returns count of pipelines stored in cache
|
uint32 BeginLoading(uint64 cacheTitleId); // returns count of pipelines stored in cache
|
||||||
@ -70,7 +70,7 @@ private:
|
|||||||
ConcurrentQueue<std::vector<uint8>> m_compilationQueue;
|
ConcurrentQueue<std::vector<uint8>> m_compilationQueue;
|
||||||
std::atomic_uint32_t m_compilationCount;
|
std::atomic_uint32_t m_compilationCount;
|
||||||
|
|
||||||
static uint64 CalculatePipelineHash(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* geometryShader, const LatteDecompilerShader* pixelShader, class CachedFBOMtl* lastUsedFBO, class CachedFBOMtl* activeFBO, const LatteContextRegister& lcr);
|
static uint64 CalculatePipelineHash(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* geometryShader, const LatteDecompilerShader* pixelShader, const class MetalAttachmentsInfo& lastUsedAttachmentsInfo, const class MetalAttachmentsInfo& activeAttachmentsInfo, const LatteContextRegister& lcr);
|
||||||
|
|
||||||
int CompilerThread();
|
int CompilerThread();
|
||||||
void WorkerThread();
|
void WorkerThread();
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
#include "Cafe/HW/Latte/ISA/RegDefines.h"
|
#include "Cafe/HW/Latte/ISA/RegDefines.h"
|
||||||
#include "Cafe/HW/Latte/Core/LatteConst.h"
|
#include "Cafe/HW/Latte/Core/LatteConst.h"
|
||||||
#include "Cafe/HW/Latte/Core/LatteShader.h"
|
#include "Cafe/HW/Latte/Core/LatteShader.h"
|
||||||
|
#include "HW/Latte/ISA/LatteReg.h"
|
||||||
|
#include "Metal/MTLPixelFormat.hpp"
|
||||||
|
|
||||||
static void rectsEmulationGS_outputSingleVertex(std::string& gsSrc, const LatteDecompilerShader* vertexShader, LatteShaderPSInputTable* psInputTable, sint32 vIdx, const LatteContextRegister& latteRegister)
|
static void rectsEmulationGS_outputSingleVertex(std::string& gsSrc, const LatteDecompilerShader* vertexShader, LatteShaderPSInputTable* psInputTable, sint32 vIdx, const LatteContextRegister& latteRegister)
|
||||||
{
|
{
|
||||||
@ -189,7 +191,7 @@ extern std::atomic_int g_compiled_shaders_total;
|
|||||||
extern std::atomic_int g_compiled_shaders_async;
|
extern std::atomic_int g_compiled_shaders_async;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void SetFragmentState(T* desc, CachedFBOMtl* lastUsedFBO, CachedFBOMtl* activeFBO, const LatteDecompilerShader* pixelShader, const LatteContextRegister& lcr)
|
void SetFragmentState(T* desc, const MetalAttachmentsInfo& lastUsedAttachmentsInfo, const MetalAttachmentsInfo& activeAttachmentsInfo, const LatteDecompilerShader* pixelShader, const LatteContextRegister& lcr)
|
||||||
{
|
{
|
||||||
// Rasterization
|
// Rasterization
|
||||||
bool rasterizationEnabled = !lcr.PA_CL_CLIP_CNTL.get_DX_RASTERIZATION_KILL();
|
bool rasterizationEnabled = !lcr.PA_CL_CLIP_CNTL.get_DX_RASTERIZATION_KILL();
|
||||||
@ -222,17 +224,16 @@ void SetFragmentState(T* desc, CachedFBOMtl* lastUsedFBO, CachedFBOMtl* activeFB
|
|||||||
uint32 renderTargetMask = lcr.CB_TARGET_MASK.get_MASK();
|
uint32 renderTargetMask = lcr.CB_TARGET_MASK.get_MASK();
|
||||||
for (uint8 i = 0; i < LATTE_NUM_COLOR_TARGET; i++)
|
for (uint8 i = 0; i < LATTE_NUM_COLOR_TARGET; i++)
|
||||||
{
|
{
|
||||||
const auto& colorBuffer = lastUsedFBO->colorBuffer[i];
|
Latte::E_GX2SURFFMT format = lastUsedAttachmentsInfo.colorFormats[i];
|
||||||
auto texture = static_cast<LatteTextureViewMtl*>(colorBuffer.texture);
|
if (format == Latte::E_GX2SURFFMT::INVALID_FORMAT)
|
||||||
if (!texture)
|
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
MTL::PixelFormat pixelFormat = GetMtlPixelFormat(format, false);
|
||||||
auto colorAttachment = desc->colorAttachments()->object(i);
|
auto colorAttachment = desc->colorAttachments()->object(i);
|
||||||
colorAttachment->setPixelFormat(texture->GetRGBAView()->pixelFormat());
|
colorAttachment->setPixelFormat(pixelFormat);
|
||||||
|
|
||||||
// Disable writes if not in the active FBO
|
// Disable writes if not in the active FBO
|
||||||
if (!activeFBO->colorBuffer[i].texture)
|
if (activeAttachmentsInfo.colorFormats[i] == Latte::E_GX2SURFFMT::INVALID_FORMAT)
|
||||||
{
|
{
|
||||||
colorAttachment->setWriteMask(MTL::ColorWriteMaskNone);
|
colorAttachment->setWriteMask(MTL::ColorWriteMaskNone);
|
||||||
continue;
|
continue;
|
||||||
@ -243,7 +244,7 @@ void SetFragmentState(T* desc, CachedFBOMtl* lastUsedFBO, CachedFBOMtl* activeFB
|
|||||||
// Blending
|
// Blending
|
||||||
bool blendEnabled = ((blendEnableMask & (1 << i))) != 0;
|
bool blendEnabled = ((blendEnableMask & (1 << i))) != 0;
|
||||||
// Only float data type is blendable
|
// Only float data type is blendable
|
||||||
if (blendEnabled && GetMtlPixelFormatInfo(texture->format, false).dataType == MetalDataType::FLOAT)
|
if (blendEnabled && GetMtlPixelFormatInfo(format, false).dataType == MetalDataType::FLOAT)
|
||||||
{
|
{
|
||||||
colorAttachment->setBlendingEnabled(true);
|
colorAttachment->setBlendingEnabled(true);
|
||||||
|
|
||||||
@ -272,14 +273,12 @@ void SetFragmentState(T* desc, CachedFBOMtl* lastUsedFBO, CachedFBOMtl* activeFB
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Depth stencil attachment
|
// Depth stencil attachment
|
||||||
if (lastUsedFBO->depthBuffer.texture)
|
if (lastUsedAttachmentsInfo.depthFormat != Latte::E_GX2SURFFMT::INVALID_FORMAT)
|
||||||
{
|
{
|
||||||
auto texture = static_cast<LatteTextureViewMtl*>(lastUsedFBO->depthBuffer.texture);
|
MTL::PixelFormat pixelFormat = GetMtlPixelFormat(lastUsedAttachmentsInfo.depthFormat, true);
|
||||||
desc->setDepthAttachmentPixelFormat(texture->GetRGBAView()->pixelFormat());
|
desc->setDepthAttachmentPixelFormat(pixelFormat);
|
||||||
if (lastUsedFBO->depthBuffer.hasStencil)
|
if (lastUsedAttachmentsInfo.hasStencil)
|
||||||
{
|
desc->setStencilAttachmentPixelFormat(pixelFormat);
|
||||||
desc->setStencilAttachmentPixelFormat(texture->GetRGBAView()->pixelFormat());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -306,7 +305,7 @@ MetalPipelineCompiler::~MetalPipelineCompiler()
|
|||||||
m_pipelineDescriptor->release();
|
m_pipelineDescriptor->release();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetalPipelineCompiler::InitFromState(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* geometryShader, const LatteDecompilerShader* pixelShader, class CachedFBOMtl* lastUsedFBO, class CachedFBOMtl* activeFBO, const LatteContextRegister& lcr)
|
void MetalPipelineCompiler::InitFromState(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* geometryShader, const LatteDecompilerShader* pixelShader, const MetalAttachmentsInfo& lastUsedAttachmentsInfo, const MetalAttachmentsInfo& activeAttachmentsInfo, const LatteContextRegister& lcr)
|
||||||
{
|
{
|
||||||
const LattePrimitiveMode primitiveMode = static_cast<LattePrimitiveMode>(LatteGPUState.contextRegister[mmVGT_PRIMITIVE_TYPE]);
|
const LattePrimitiveMode primitiveMode = static_cast<LattePrimitiveMode>(LatteGPUState.contextRegister[mmVGT_PRIMITIVE_TYPE]);
|
||||||
bool isPrimitiveRect = (primitiveMode == Latte::LATTE_VGT_PRIMITIVE_TYPE::E_PRIMITIVE_TYPE::RECTS);
|
bool isPrimitiveRect = (primitiveMode == Latte::LATTE_VGT_PRIMITIVE_TYPE::E_PRIMITIVE_TYPE::RECTS);
|
||||||
@ -314,9 +313,9 @@ void MetalPipelineCompiler::InitFromState(const LatteFetchShader* fetchShader, c
|
|||||||
m_usesGeometryShader = (geometryShader != nullptr || isPrimitiveRect);
|
m_usesGeometryShader = (geometryShader != nullptr || isPrimitiveRect);
|
||||||
|
|
||||||
if (m_usesGeometryShader)
|
if (m_usesGeometryShader)
|
||||||
InitFromStateMesh(fetchShader, vertexShader, geometryShader, pixelShader, lastUsedFBO, activeFBO, lcr);
|
InitFromStateMesh(fetchShader, vertexShader, geometryShader, pixelShader, lastUsedAttachmentsInfo, activeAttachmentsInfo, lcr);
|
||||||
else
|
else
|
||||||
InitFromStateRender(fetchShader, vertexShader, pixelShader, lastUsedFBO, activeFBO, lcr);
|
InitFromStateRender(fetchShader, vertexShader, pixelShader, lastUsedAttachmentsInfo, activeAttachmentsInfo, lcr);
|
||||||
}
|
}
|
||||||
|
|
||||||
MTL::RenderPipelineState* MetalPipelineCompiler::Compile(bool forceCompile, bool isRenderThread)
|
MTL::RenderPipelineState* MetalPipelineCompiler::Compile(bool forceCompile, bool isRenderThread)
|
||||||
@ -358,7 +357,7 @@ MTL::RenderPipelineState* MetalPipelineCompiler::Compile(bool forceCompile, bool
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetalPipelineCompiler::InitFromStateRender(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* pixelShader, CachedFBOMtl* lastUsedFBO, CachedFBOMtl* activeFBO, const LatteContextRegister& lcr)
|
void MetalPipelineCompiler::InitFromStateRender(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* pixelShader, const MetalAttachmentsInfo& lastUsedAttachmentsInfo, const MetalAttachmentsInfo& activeAttachmentsInfo, const LatteContextRegister& lcr)
|
||||||
{
|
{
|
||||||
// Shaders
|
// Shaders
|
||||||
auto vertexShaderMtl = static_cast<RendererShaderMtl*>(vertexShader->shader);
|
auto vertexShaderMtl = static_cast<RendererShaderMtl*>(vertexShader->shader);
|
||||||
@ -437,7 +436,7 @@ void MetalPipelineCompiler::InitFromStateRender(const LatteFetchShader* fetchSha
|
|||||||
vertexDescriptor->release();
|
vertexDescriptor->release();
|
||||||
}
|
}
|
||||||
|
|
||||||
SetFragmentState(desc, lastUsedFBO, activeFBO, pixelShader, lcr);
|
SetFragmentState(desc, lastUsedAttachmentsInfo, activeAttachmentsInfo, pixelShader, lcr);
|
||||||
|
|
||||||
m_pipelineDescriptor = desc;
|
m_pipelineDescriptor = desc;
|
||||||
|
|
||||||
@ -498,7 +497,7 @@ void MetalPipelineCompiler::InitFromStateRender(const LatteFetchShader* fetchSha
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetalPipelineCompiler::InitFromStateMesh(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* geometryShader, const LatteDecompilerShader* pixelShader, CachedFBOMtl* lastUsedFBO, CachedFBOMtl* activeFBO, const LatteContextRegister& lcr)
|
void MetalPipelineCompiler::InitFromStateMesh(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* geometryShader, const LatteDecompilerShader* pixelShader, const MetalAttachmentsInfo& lastUsedAttachmentsInfo, const MetalAttachmentsInfo& activeAttachmentsInfo, const LatteContextRegister& lcr)
|
||||||
{
|
{
|
||||||
auto objectShaderMtl = static_cast<RendererShaderMtl*>(vertexShader->shader);
|
auto objectShaderMtl = static_cast<RendererShaderMtl*>(vertexShader->shader);
|
||||||
RendererShaderMtl* meshShaderMtl;
|
RendererShaderMtl* meshShaderMtl;
|
||||||
@ -517,7 +516,7 @@ void MetalPipelineCompiler::InitFromStateMesh(const LatteFetchShader* fetchShade
|
|||||||
desc->setObjectFunction(objectShaderMtl->GetFunction());
|
desc->setObjectFunction(objectShaderMtl->GetFunction());
|
||||||
desc->setMeshFunction(meshShaderMtl->GetFunction());
|
desc->setMeshFunction(meshShaderMtl->GetFunction());
|
||||||
|
|
||||||
SetFragmentState(desc, lastUsedFBO, activeFBO, pixelShader, lcr);
|
SetFragmentState(desc, lastUsedAttachmentsInfo, activeAttachmentsInfo, pixelShader, lcr);
|
||||||
|
|
||||||
m_pipelineDescriptor = desc;
|
m_pipelineDescriptor = desc;
|
||||||
|
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Metal/Metal.hpp>
|
#include "Cafe/HW/Latte/Renderer/Metal/MetalAttachmentsInfo.h"
|
||||||
|
|
||||||
#include "Foundation/NSObject.hpp"
|
#include "Cafe/HW/Latte/ISA/LatteReg.h"
|
||||||
#include "HW/Latte/ISA/LatteReg.h"
|
#include "Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompiler.h"
|
||||||
#include "HW/Latte/LegacyShaderDecompiler/LatteDecompiler.h"
|
|
||||||
#include "Cafe/HW/Latte/Renderer/Renderer.h"
|
|
||||||
|
|
||||||
class MetalPipelineCompiler
|
class MetalPipelineCompiler
|
||||||
{
|
{
|
||||||
@ -13,7 +11,7 @@ public:
|
|||||||
MetalPipelineCompiler(class MetalRenderer* metalRenderer) : m_mtlr{metalRenderer} {}
|
MetalPipelineCompiler(class MetalRenderer* metalRenderer) : m_mtlr{metalRenderer} {}
|
||||||
~MetalPipelineCompiler();
|
~MetalPipelineCompiler();
|
||||||
|
|
||||||
void InitFromState(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* geometryShader, const LatteDecompilerShader* pixelShader, class CachedFBOMtl* lastUsedFBO, class CachedFBOMtl* activeFBO, const LatteContextRegister& lcr);
|
void InitFromState(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* geometryShader, const LatteDecompilerShader* pixelShader, const class MetalAttachmentsInfo& lastUsedAttachmentsInfo, const class MetalAttachmentsInfo& activeAttachmentsInfo, const LatteContextRegister& lcr);
|
||||||
|
|
||||||
MTL::RenderPipelineState* Compile(bool forceCompile, bool isRenderThread);
|
MTL::RenderPipelineState* Compile(bool forceCompile, bool isRenderThread);
|
||||||
|
|
||||||
@ -30,9 +28,9 @@ private:
|
|||||||
*/
|
*/
|
||||||
NS::Object* m_pipelineDescriptor;
|
NS::Object* m_pipelineDescriptor;
|
||||||
|
|
||||||
void InitFromStateRender(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* pixelShader, class CachedFBOMtl* lastUsedFBO, class CachedFBOMtl* activeFBO, const LatteContextRegister& lcr);
|
void InitFromStateRender(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* pixelShader, const class MetalAttachmentsInfo& lastUsedAttachmentsInfo, const class MetalAttachmentsInfo& activeAttachmentsInfo, const LatteContextRegister& lcr);
|
||||||
|
|
||||||
void InitFromStateMesh(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* geometryShader, const LatteDecompilerShader* pixelShader, class CachedFBOMtl* lastUsedFBO, class CachedFBOMtl* activeFBO, const LatteContextRegister& lcr);
|
void InitFromStateMesh(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* geometryShader, const LatteDecompilerShader* pixelShader, const class MetalAttachmentsInfo& lastUsedAttachmentsInfo, const class MetalAttachmentsInfo& activeAttachmentsInfo, const LatteContextRegister& lcr);
|
||||||
|
|
||||||
//void TryLoadBinaryArchive();
|
//void TryLoadBinaryArchive();
|
||||||
};
|
};
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "Cafe/HW/Latte/Renderer/Metal/MetalCommon.h"
|
#include "Cafe/HW/Latte/Renderer/Metal/MetalCommon.h"
|
||||||
#include "Cafe/HW/Latte/Renderer/Metal/MetalLayerHandle.h"
|
#include "Cafe/HW/Latte/Renderer/Metal/MetalLayerHandle.h"
|
||||||
#include "Cafe/HW/Latte/Renderer/Renderer.h"
|
#include "Cafe/HW/Latte/Renderer/Renderer.h"
|
||||||
|
#include "HW/Latte/Renderer/Metal/MetalAttachmentsInfo.h"
|
||||||
#include "config/CemuConfig.h"
|
#include "config/CemuConfig.h"
|
||||||
|
|
||||||
#define IMGUI_IMPL_METAL_CPP
|
#define IMGUI_IMPL_METAL_CPP
|
||||||
@ -511,13 +512,13 @@ LatteCachedFBO* MetalRenderer::rendertarget_createCachedFBO(uint64 key)
|
|||||||
|
|
||||||
void MetalRenderer::rendertarget_deleteCachedFBO(LatteCachedFBO* cfbo)
|
void MetalRenderer::rendertarget_deleteCachedFBO(LatteCachedFBO* cfbo)
|
||||||
{
|
{
|
||||||
if (cfbo == (LatteCachedFBO*)m_state.m_activeFBO)
|
if (cfbo == (LatteCachedFBO*)m_state.m_activeFBO.m_fbo)
|
||||||
m_state.m_activeFBO = nullptr;
|
m_state.m_activeFBO = {nullptr};
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetalRenderer::rendertarget_bindFramebufferObject(LatteCachedFBO* cfbo)
|
void MetalRenderer::rendertarget_bindFramebufferObject(LatteCachedFBO* cfbo)
|
||||||
{
|
{
|
||||||
m_state.m_activeFBO = (CachedFBOMtl*)cfbo;
|
m_state.m_activeFBO = {(CachedFBOMtl*)cfbo, MetalAttachmentsInfo((CachedFBOMtl*)cfbo)};
|
||||||
}
|
}
|
||||||
|
|
||||||
void* MetalRenderer::texture_acquireTextureUploadBuffer(uint32 size)
|
void* MetalRenderer::texture_acquireTextureUploadBuffer(uint32 size)
|
||||||
@ -1008,7 +1009,7 @@ void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32
|
|||||||
// Disable depth write when there is no depth attachment
|
// Disable depth write when there is no depth attachment
|
||||||
auto& depthControl = LatteGPUState.contextNew.DB_DEPTH_CONTROL;
|
auto& depthControl = LatteGPUState.contextNew.DB_DEPTH_CONTROL;
|
||||||
bool depthWriteEnable = depthControl.get_Z_WRITE_ENABLE();
|
bool depthWriteEnable = depthControl.get_Z_WRITE_ENABLE();
|
||||||
if (!m_state.m_activeFBO->depthBuffer.texture)
|
if (!m_state.m_activeFBO.m_fbo->depthBuffer.texture)
|
||||||
depthControl.set_Z_WRITE_ENABLE(false);
|
depthControl.set_Z_WRITE_ENABLE(false);
|
||||||
|
|
||||||
MTL::DepthStencilState* depthStencilState = m_depthStencilCache->GetDepthStencilState(LatteGPUState.contextNew);
|
MTL::DepthStencilState* depthStencilState = m_depthStencilCache->GetDepthStencilState(LatteGPUState.contextNew);
|
||||||
@ -1222,7 +1223,7 @@ void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32
|
|||||||
//}
|
//}
|
||||||
|
|
||||||
// Render pipeline state
|
// Render pipeline state
|
||||||
MTL::RenderPipelineState* renderPipelineState = m_pipelineCache->GetRenderPipelineState(fetchShader, vertexShader, geometryShader, pixelShader, m_state.m_lastUsedFBO, m_state.m_activeFBO, LatteGPUState.contextNew);
|
MTL::RenderPipelineState* renderPipelineState = m_pipelineCache->GetRenderPipelineState(fetchShader, vertexShader, geometryShader, pixelShader, m_state.m_lastUsedFBO.m_attachmentsInfo, m_state.m_activeFBO.m_attachmentsInfo, LatteGPUState.contextNew);
|
||||||
if (!renderPipelineState)
|
if (!renderPipelineState)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -1524,12 +1525,12 @@ MTL::RenderCommandEncoder* MetalRenderer::GetRenderCommandEncoder(bool forceRecr
|
|||||||
{
|
{
|
||||||
if (m_encoderType == MetalEncoderType::Render)
|
if (m_encoderType == MetalEncoderType::Render)
|
||||||
{
|
{
|
||||||
bool needsNewRenderPass = (m_state.m_lastUsedFBO == nullptr);
|
bool needsNewRenderPass = (m_state.m_lastUsedFBO.m_fbo == nullptr);
|
||||||
if (!needsNewRenderPass)
|
if (!needsNewRenderPass)
|
||||||
{
|
{
|
||||||
for (uint8 i = 0; i < 8; i++)
|
for (uint8 i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
if (m_state.m_activeFBO->colorBuffer[i].texture && m_state.m_activeFBO->colorBuffer[i].texture != m_state.m_lastUsedFBO->colorBuffer[i].texture)
|
if (m_state.m_activeFBO.m_fbo->colorBuffer[i].texture && m_state.m_activeFBO.m_fbo->colorBuffer[i].texture != m_state.m_lastUsedFBO.m_fbo->colorBuffer[i].texture)
|
||||||
{
|
{
|
||||||
needsNewRenderPass = true;
|
needsNewRenderPass = true;
|
||||||
break;
|
break;
|
||||||
@ -1539,7 +1540,7 @@ MTL::RenderCommandEncoder* MetalRenderer::GetRenderCommandEncoder(bool forceRecr
|
|||||||
|
|
||||||
if (!needsNewRenderPass)
|
if (!needsNewRenderPass)
|
||||||
{
|
{
|
||||||
if (m_state.m_activeFBO->depthBuffer.texture && (m_state.m_activeFBO->depthBuffer.texture != m_state.m_lastUsedFBO->depthBuffer.texture || ( m_state.m_activeFBO->depthBuffer.hasStencil && !m_state.m_lastUsedFBO->depthBuffer.hasStencil)))
|
if (m_state.m_activeFBO.m_fbo->depthBuffer.texture && (m_state.m_activeFBO.m_fbo->depthBuffer.texture != m_state.m_lastUsedFBO.m_fbo->depthBuffer.texture || ( m_state.m_activeFBO.m_fbo->depthBuffer.hasStencil && !m_state.m_lastUsedFBO.m_fbo->depthBuffer.hasStencil)))
|
||||||
{
|
{
|
||||||
needsNewRenderPass = true;
|
needsNewRenderPass = true;
|
||||||
}
|
}
|
||||||
@ -1557,7 +1558,7 @@ MTL::RenderCommandEncoder* MetalRenderer::GetRenderCommandEncoder(bool forceRecr
|
|||||||
|
|
||||||
auto commandBuffer = GetCommandBuffer();
|
auto commandBuffer = GetCommandBuffer();
|
||||||
|
|
||||||
auto renderCommandEncoder = commandBuffer->renderCommandEncoder(m_state.m_activeFBO->GetRenderPassDescriptor());
|
auto renderCommandEncoder = commandBuffer->renderCommandEncoder(m_state.m_activeFBO.m_fbo->GetRenderPassDescriptor());
|
||||||
#ifdef CEMU_DEBUG_ASSERT
|
#ifdef CEMU_DEBUG_ASSERT
|
||||||
renderCommandEncoder->setLabel(GetLabel("Render command encoder", renderCommandEncoder));
|
renderCommandEncoder->setLabel(GetLabel("Render command encoder", renderCommandEncoder));
|
||||||
#endif
|
#endif
|
||||||
@ -1716,7 +1717,7 @@ bool MetalRenderer::CheckIfRenderPassNeedsFlush(LatteDecompilerShader* shader)
|
|||||||
// If the texture is also used in the current render pass, we need to end the render pass to "flush" the texture
|
// If the texture is also used in the current render pass, we need to end the render pass to "flush" the texture
|
||||||
for (uint8 i = 0; i < LATTE_NUM_COLOR_TARGET; i++)
|
for (uint8 i = 0; i < LATTE_NUM_COLOR_TARGET; i++)
|
||||||
{
|
{
|
||||||
auto colorTarget = m_state.m_activeFBO->colorBuffer[i].texture;
|
auto colorTarget = m_state.m_activeFBO.m_fbo->colorBuffer[i].texture;
|
||||||
if (colorTarget && colorTarget->baseTexture == baseTexture)
|
if (colorTarget && colorTarget->baseTexture == baseTexture)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include "Cafe/HW/Latte/Renderer/Metal/MetalLayerHandle.h"
|
#include "Cafe/HW/Latte/Renderer/Metal/MetalLayerHandle.h"
|
||||||
#include "Cafe/HW/Latte/Renderer/Metal/MetalPerformanceMonitor.h"
|
#include "Cafe/HW/Latte/Renderer/Metal/MetalPerformanceMonitor.h"
|
||||||
#include "Cafe/HW/Latte/Renderer/Metal/MetalOutputShaderCache.h"
|
#include "Cafe/HW/Latte/Renderer/Metal/MetalOutputShaderCache.h"
|
||||||
|
#include "Cafe/HW/Latte/Renderer/Metal/MetalAttachmentsInfo.h"
|
||||||
|
|
||||||
struct MetalBufferAllocation
|
struct MetalBufferAllocation
|
||||||
{
|
{
|
||||||
@ -121,6 +122,12 @@ struct MetalStreamoutState
|
|||||||
sint32 verticesPerInstance;
|
sint32 verticesPerInstance;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct MetalActiveFBOState
|
||||||
|
{
|
||||||
|
class CachedFBOMtl* m_fbo = nullptr;
|
||||||
|
MetalAttachmentsInfo m_attachmentsInfo;
|
||||||
|
};
|
||||||
|
|
||||||
struct MetalState
|
struct MetalState
|
||||||
{
|
{
|
||||||
MetalEncoderState m_encoderState{};
|
MetalEncoderState m_encoderState{};
|
||||||
@ -130,9 +137,9 @@ struct MetalState
|
|||||||
bool m_skipDrawSequence = false;
|
bool m_skipDrawSequence = false;
|
||||||
bool m_isFirstDrawInRenderPass = true;
|
bool m_isFirstDrawInRenderPass = true;
|
||||||
|
|
||||||
class CachedFBOMtl* m_activeFBO = nullptr;
|
MetalActiveFBOState m_activeFBO;
|
||||||
// If the FBO changes, but it's the same FBO as the last one with some omitted attachments, this FBO doesn't change'
|
// If the FBO changes, but it's the same FBO as the last one with some omitted attachments, this FBO doesn't change
|
||||||
class CachedFBOMtl* m_lastUsedFBO = nullptr;
|
MetalActiveFBOState m_lastUsedFBO;
|
||||||
|
|
||||||
MetalBoundBuffer m_vertexBuffers[MAX_MTL_BUFFERS] = {{}};
|
MetalBoundBuffer m_vertexBuffers[MAX_MTL_BUFFERS] = {{}};
|
||||||
// TODO: find out what is the max number of bound textures on the Wii U
|
// TODO: find out what is the max number of bound textures on the Wii U
|
||||||
|
Loading…
Reference in New Issue
Block a user