disable writes for color attachments which are not in the active FBO

This commit is contained in:
Samuliak 2024-08-30 16:44:26 +02:00
parent 9c29acc635
commit cda4799b54
4 changed files with 34 additions and 25 deletions

View File

@ -167,7 +167,7 @@ void LatteDecompiler_emitAttributeDecodeMSL(LatteDecompilerShader* shaderContext
else if( attrib->format == FMT_8_8_8_8 && attrib->nfa == 0 && attrib->isSigned == 0 ) else if( attrib->format == FMT_8_8_8_8 && attrib->nfa == 0 && attrib->isSigned == 0 )
{ {
// seen in Minecraft Wii U Edition // seen in Minecraft Wii U Edition
src->addFmt("attrDecoder.xyzw = as_type<uint>(float4(in.attrDataSem{}.wzyx)/255.0);" _CRLF, attributeInputIndex); src->addFmt("attrDecoder.xyzw = as_type<uint4>(float4(in.attrDataSem{}.wzyx)/255.0);" _CRLF, attributeInputIndex);
} }
else if( attrib->format == FMT_8_8_8_8 && attrib->nfa == 0 && attrib->isSigned != 0 ) else if( attrib->format == FMT_8_8_8_8 && attrib->nfa == 0 && attrib->isSigned != 0 )
{ {
@ -190,7 +190,7 @@ void LatteDecompiler_emitAttributeDecodeMSL(LatteDecompilerShader* shaderContext
else if (attrib->format == FMT_8_8_8_8 && attrib->nfa == 2 && attrib->isSigned == 0) else if (attrib->format == FMT_8_8_8_8 && attrib->nfa == 2 && attrib->isSigned == 0)
{ {
// seen in Ben 10 Omniverse // seen in Ben 10 Omniverse
src->addFmt("attrDecoder.xyzw = as_type<uint>(float4(in.attrDataSem{}.wzyx));" _CRLF, attributeInputIndex); src->addFmt("attrDecoder.xyzw = as_type<uint4>(float4(in.attrDataSem{}.wzyx));" _CRLF, attributeInputIndex);
} }
else else
{ {

View File

@ -10,6 +10,7 @@
#include "HW/Latte/Core/FetchShader.h" #include "HW/Latte/Core/FetchShader.h"
#include "HW/Latte/ISA/RegDefines.h" #include "HW/Latte/ISA/RegDefines.h"
#include "Metal/MTLRenderPipeline.hpp"
#include "config/ActiveSettings.h" #include "config/ActiveSettings.h"
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 +190,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, class CachedFBOMtl* activeFBO, const LatteContextRegister& lcr) void SetFragmentState(T* desc, CachedFBOMtl* lastUsedFBO, CachedFBOMtl* activeFBO, const LatteContextRegister& lcr)
{ {
// Color attachments // Color attachments
const Latte::LATTE_CB_COLOR_CONTROL& colorControlReg = lcr.CB_COLOR_CONTROL; const Latte::LATTE_CB_COLOR_CONTROL& colorControlReg = lcr.CB_COLOR_CONTROL;
@ -197,7 +198,7 @@ void SetFragmentState(T* desc, class CachedFBOMtl* activeFBO, const LatteContext
uint32 renderTargetMask = lcr.CB_TARGET_MASK.get_MASK(); uint32 renderTargetMask = lcr.CB_TARGET_MASK.get_MASK();
for (uint8 i = 0; i < 8; i++) for (uint8 i = 0; i < 8; i++)
{ {
const auto& colorBuffer = activeFBO->colorBuffer[i]; const auto& colorBuffer = lastUsedFBO->colorBuffer[i];
auto texture = static_cast<LatteTextureViewMtl*>(colorBuffer.texture); auto texture = static_cast<LatteTextureViewMtl*>(colorBuffer.texture);
if (!texture) if (!texture)
{ {
@ -205,6 +206,14 @@ void SetFragmentState(T* desc, class CachedFBOMtl* activeFBO, const LatteContext
} }
auto colorAttachment = desc->colorAttachments()->object(i); auto colorAttachment = desc->colorAttachments()->object(i);
colorAttachment->setPixelFormat(texture->GetRGBAView()->pixelFormat()); colorAttachment->setPixelFormat(texture->GetRGBAView()->pixelFormat());
// Disable writes if not in the active FBO
if (!activeFBO->colorBuffer[i].texture)
{
colorAttachment->setWriteMask(MTL::ColorWriteMaskNone);
continue;
}
colorAttachment->setWriteMask(GetMtlColorWriteMask((renderTargetMask >> (i * 4)) & 0xF)); colorAttachment->setWriteMask(GetMtlColorWriteMask((renderTargetMask >> (i * 4)) & 0xF));
// Blending // Blending
@ -239,11 +248,11 @@ void SetFragmentState(T* desc, class CachedFBOMtl* activeFBO, const LatteContext
} }
// Depth stencil attachment // Depth stencil attachment
if (activeFBO->depthBuffer.texture) if (lastUsedFBO->depthBuffer.texture)
{ {
auto texture = static_cast<LatteTextureViewMtl*>(activeFBO->depthBuffer.texture); auto texture = static_cast<LatteTextureViewMtl*>(lastUsedFBO->depthBuffer.texture);
desc->setDepthAttachmentPixelFormat(texture->GetRGBAView()->pixelFormat()); desc->setDepthAttachmentPixelFormat(texture->GetRGBAView()->pixelFormat());
if (activeFBO->depthBuffer.hasStencil) if (lastUsedFBO->depthBuffer.hasStencil)
{ {
desc->setStencilAttachmentPixelFormat(texture->GetRGBAView()->pixelFormat()); desc->setStencilAttachmentPixelFormat(texture->GetRGBAView()->pixelFormat());
} }
@ -285,9 +294,9 @@ MetalPipelineCache::~MetalPipelineCache()
m_binaryArchiveURL->release(); m_binaryArchiveURL->release();
} }
MTL::RenderPipelineState* MetalPipelineCache::GetRenderPipelineState(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* pixelShader, CachedFBOMtl* activeFBO, const LatteContextRegister& lcr) MTL::RenderPipelineState* MetalPipelineCache::GetRenderPipelineState(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* pixelShader, CachedFBOMtl* lastUsedFBO, CachedFBOMtl* activeFBO, const LatteContextRegister& lcr)
{ {
uint64 stateHash = CalculateRenderPipelineHash(fetchShader, vertexShader, pixelShader, activeFBO, lcr); uint64 stateHash = CalculateRenderPipelineHash(fetchShader, vertexShader, pixelShader, lastUsedFBO, lcr);
auto& pipeline = m_pipelineCache[stateHash]; auto& pipeline = m_pipelineCache[stateHash];
if (pipeline) if (pipeline)
return pipeline; return pipeline;
@ -364,7 +373,7 @@ MTL::RenderPipelineState* MetalPipelineCache::GetRenderPipelineState(const Latte
debug_printf("no vertex function, skipping draw\n"); debug_printf("no vertex function, skipping draw\n");
return nullptr; return nullptr;
} }
mtlPixelShader->CompileFragmentFunction(activeFBO); mtlPixelShader->CompileFragmentFunction(lastUsedFBO);
// Render pipeline state // Render pipeline state
MTL::RenderPipelineDescriptor* desc = MTL::RenderPipelineDescriptor::alloc()->init(); MTL::RenderPipelineDescriptor* desc = MTL::RenderPipelineDescriptor::alloc()->init();
@ -373,7 +382,7 @@ MTL::RenderPipelineState* MetalPipelineCache::GetRenderPipelineState(const Latte
// TODO: don't always set the vertex descriptor? // TODO: don't always set the vertex descriptor?
desc->setVertexDescriptor(vertexDescriptor); desc->setVertexDescriptor(vertexDescriptor);
SetFragmentState(desc, activeFBO, lcr); SetFragmentState(desc, lastUsedFBO, activeFBO, lcr);
TryLoadBinaryArchive(); TryLoadBinaryArchive();
@ -440,15 +449,15 @@ MTL::RenderPipelineState* MetalPipelineCache::GetRenderPipelineState(const Latte
return pipeline; return pipeline;
} }
MTL::RenderPipelineState* MetalPipelineCache::GetMeshPipelineState(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* geometryShader, const LatteDecompilerShader* pixelShader, CachedFBOMtl* activeFBO, const LatteContextRegister& lcr, Renderer::INDEX_TYPE hostIndexType) MTL::RenderPipelineState* MetalPipelineCache::GetMeshPipelineState(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* geometryShader, const LatteDecompilerShader* pixelShader, CachedFBOMtl* lastUsedFBO, CachedFBOMtl* activeFBO, const LatteContextRegister& lcr, Renderer::INDEX_TYPE hostIndexType)
{ {
uint64 stateHash = CalculateRenderPipelineHash(fetchShader, vertexShader, pixelShader, activeFBO, lcr); uint64 stateHash = CalculateRenderPipelineHash(fetchShader, vertexShader, pixelShader, lastUsedFBO, lcr);
stateHash += lcr.GetRawView()[mmVGT_PRIMITIVE_TYPE]; stateHash += lcr.GetRawView()[mmVGT_PRIMITIVE_TYPE];
stateHash = std::rotl<uint64>(stateHash, 7); stateHash = std::rotl<uint64>(stateHash, 7);
stateHash += (uint8)hostIndexType; stateHash += (uint8)hostIndexType;
stateHash = std::rotl<uint64>(stateHash, 7); // TODO: 7?s stateHash = std::rotl<uint64>(stateHash, 7);
auto& pipeline = m_pipelineCache[stateHash]; auto& pipeline = m_pipelineCache[stateHash];
if (pipeline) if (pipeline)
@ -467,7 +476,7 @@ MTL::RenderPipelineState* MetalPipelineCache::GetMeshPipelineState(const LatteFe
} }
auto mtlPixelShader = static_cast<RendererShaderMtl*>(pixelShader->shader); auto mtlPixelShader = static_cast<RendererShaderMtl*>(pixelShader->shader);
mtlObjectShader->CompileObjectFunction(lcr, fetchShader, vertexShader, hostIndexType); mtlObjectShader->CompileObjectFunction(lcr, fetchShader, vertexShader, hostIndexType);
mtlPixelShader->CompileFragmentFunction(activeFBO); mtlPixelShader->CompileFragmentFunction(lastUsedFBO);
// Render pipeline state // Render pipeline state
MTL::MeshRenderPipelineDescriptor* desc = MTL::MeshRenderPipelineDescriptor::alloc()->init(); MTL::MeshRenderPipelineDescriptor* desc = MTL::MeshRenderPipelineDescriptor::alloc()->init();
@ -475,7 +484,7 @@ MTL::RenderPipelineState* MetalPipelineCache::GetMeshPipelineState(const LatteFe
desc->setMeshFunction(mtlMeshShader->GetFunction()); desc->setMeshFunction(mtlMeshShader->GetFunction());
desc->setFragmentFunction(mtlPixelShader->GetFunction()); desc->setFragmentFunction(mtlPixelShader->GetFunction());
SetFragmentState(desc, activeFBO, lcr); SetFragmentState(desc, lastUsedFBO, activeFBO, lcr);
TryLoadBinaryArchive(); TryLoadBinaryArchive();
@ -498,13 +507,13 @@ MTL::RenderPipelineState* MetalPipelineCache::GetMeshPipelineState(const LatteFe
return pipeline; return pipeline;
} }
uint64 MetalPipelineCache::CalculateRenderPipelineHash(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* pixelShader, class CachedFBOMtl* activeFBO, const LatteContextRegister& lcr) uint64 MetalPipelineCache::CalculateRenderPipelineHash(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* pixelShader, class CachedFBOMtl* lastUsedFBO, 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*>(activeFBO->colorBuffer[i].texture); auto textureView = static_cast<LatteTextureViewMtl*>(lastUsedFBO->colorBuffer[i].texture);
if (!textureView) if (!textureView)
continue; continue;
@ -512,9 +521,9 @@ uint64 MetalPipelineCache::CalculateRenderPipelineHash(const LatteFetchShader* f
stateHash = std::rotl<uint64>(stateHash, 7); stateHash = std::rotl<uint64>(stateHash, 7);
} }
if (activeFBO->depthBuffer.texture) if (lastUsedFBO->depthBuffer.texture)
{ {
auto textureView = static_cast<LatteTextureViewMtl*>(activeFBO->depthBuffer.texture); auto textureView = static_cast<LatteTextureViewMtl*>(lastUsedFBO->depthBuffer.texture);
stateHash += textureView->GetRGBAView()->pixelFormat(); stateHash += textureView->GetRGBAView()->pixelFormat();
stateHash = std::rotl<uint64>(stateHash, 7); stateHash = std::rotl<uint64>(stateHash, 7);
} }

View File

@ -16,9 +16,9 @@ public:
MetalPipelineCache(class MetalRenderer* metalRenderer) : m_mtlr{metalRenderer} {} MetalPipelineCache(class MetalRenderer* metalRenderer) : m_mtlr{metalRenderer} {}
~MetalPipelineCache(); ~MetalPipelineCache();
MTL::RenderPipelineState* GetRenderPipelineState(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* pixelShader, class CachedFBOMtl* activeFBO, const LatteContextRegister& lcr); MTL::RenderPipelineState* GetRenderPipelineState(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* pixelShader, class CachedFBOMtl* lastUsedFBO, class CachedFBOMtl* activeFBO, const LatteContextRegister& lcr);
MTL::RenderPipelineState* GetMeshPipelineState(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* geometryShader, const LatteDecompilerShader* pixelShader, class CachedFBOMtl* activeFBO, const LatteContextRegister& lcr, Renderer::INDEX_TYPE hostIndexType); MTL::RenderPipelineState* GetMeshPipelineState(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* geometryShader, const LatteDecompilerShader* pixelShader, class CachedFBOMtl* lastUsedFBO, class CachedFBOMtl* activeFBO, const LatteContextRegister& lcr, Renderer::INDEX_TYPE hostIndexType);
// Debug // Debug
size_t GetPipelineCacheSize() const { return m_pipelineCache.size(); } size_t GetPipelineCacheSize() const { return m_pipelineCache.size(); }
@ -31,7 +31,7 @@ private:
NS::URL* m_binaryArchiveURL; NS::URL* m_binaryArchiveURL;
MTL::BinaryArchive* m_binaryArchive; MTL::BinaryArchive* m_binaryArchive;
uint64 CalculateRenderPipelineHash(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* pixelShader, class CachedFBOMtl* activeFBO, const LatteContextRegister& lcr); uint64 CalculateRenderPipelineHash(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* pixelShader, class CachedFBOMtl* lastUsedFBO, const LatteContextRegister& lcr);
void TryLoadBinaryArchive(); void TryLoadBinaryArchive();
}; };

View File

@ -1145,9 +1145,9 @@ void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32
// Render pipeline state // Render pipeline state
MTL::RenderPipelineState* renderPipelineState; MTL::RenderPipelineState* renderPipelineState;
if (usesGeometryShader) if (usesGeometryShader)
renderPipelineState = m_pipelineCache->GetMeshPipelineState(fetchShader, vertexShader, geometryShader, pixelShader, m_state.m_lastUsedFBO, LatteGPUState.contextNew, hostIndexType); renderPipelineState = m_pipelineCache->GetMeshPipelineState(fetchShader, vertexShader, geometryShader, pixelShader, m_state.m_lastUsedFBO, m_state.m_activeFBO, LatteGPUState.contextNew, hostIndexType);
else else
renderPipelineState = m_pipelineCache->GetRenderPipelineState(fetchShader, vertexShader, pixelShader, m_state.m_lastUsedFBO, LatteGPUState.contextNew); renderPipelineState = m_pipelineCache->GetRenderPipelineState(fetchShader, vertexShader, pixelShader, m_state.m_lastUsedFBO, m_state.m_activeFBO, LatteGPUState.contextNew);
// HACK // HACK
if (!renderPipelineState) if (!renderPipelineState)