From e4abb305ac831d253b203c846a2f388c059aef92 Mon Sep 17 00:00:00 2001 From: Samuliak Date: Thu, 1 Aug 2024 20:45:24 +0200 Subject: [PATCH] implement blending --- .../HW/Latte/Renderer/Metal/LatteToMtl.cpp | 56 ++++++++++++++++++- src/Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h | 5 ++ .../HW/Latte/Renderer/Metal/MetalRenderer.cpp | 39 ++++++++++++- src/gui/CemuApp.cpp | 5 +- 4 files changed, 97 insertions(+), 8 deletions(-) diff --git a/src/Cafe/HW/Latte/Renderer/Metal/LatteToMtl.cpp b/src/Cafe/HW/Latte/Renderer/Metal/LatteToMtl.cpp index 1d0ad0a8..a7d5598c 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/LatteToMtl.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/LatteToMtl.cpp @@ -1,6 +1,7 @@ #include "Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h" #include "Common/precompiled.h" #include "Metal/MTLPixelFormat.hpp" +#include "Metal/MTLRenderPipeline.hpp" #include "Metal/MTLVertexDescriptor.hpp" std::map MTL_COLOR_FORMAT_TABLE = { @@ -134,7 +135,6 @@ MTL::PrimitiveType GetMtlPrimitiveType(LattePrimitiveMode mode) return MTL::PrimitiveTypeTriangleStrip; default: printf("unimplemented primitive type %u\n", (uint32)mode); - cemu_assert_debug(false); return MTL::PrimitiveTypeTriangle; } } @@ -201,8 +201,58 @@ MTL::IndexType GetMtlIndexType(Renderer::INDEX_TYPE indexType) case Renderer::INDEX_TYPE::U32: return MTL::IndexTypeUInt32; default: - printf("unsupported index type %u\n", (uint32)indexType); - assert_dbg(); + cemu_assert_suspicious(); return MTL::IndexTypeUInt32; } } + +MTL::BlendOperation GetMtlBlendOp(Latte::LATTE_CB_BLENDN_CONTROL::E_COMBINEFUNC combineFunc) +{ + switch (combineFunc) + { + case Latte::LATTE_CB_BLENDN_CONTROL::E_COMBINEFUNC::DST_PLUS_SRC: + return MTL::BlendOperationAdd; + case Latte::LATTE_CB_BLENDN_CONTROL::E_COMBINEFUNC::SRC_MINUS_DST: + return MTL::BlendOperationSubtract; + case Latte::LATTE_CB_BLENDN_CONTROL::E_COMBINEFUNC::MIN_DST_SRC: + return MTL::BlendOperationMin; + case Latte::LATTE_CB_BLENDN_CONTROL::E_COMBINEFUNC::MAX_DST_SRC: + return MTL::BlendOperationMax; + case Latte::LATTE_CB_BLENDN_CONTROL::E_COMBINEFUNC::DST_MINUS_SRC: + return MTL::BlendOperationReverseSubtract; + default: + cemu_assert_suspicious(); + return MTL::BlendOperationAdd; + } +} + +const MTL::BlendFactor MTL_BLEND_FACTORS[] = +{ + /* 0x00 */ MTL::BlendFactorZero, + /* 0x01 */ MTL::BlendFactorOne, + /* 0x02 */ MTL::BlendFactorSourceColor, + /* 0x03 */ MTL::BlendFactorOneMinusSourceColor, + /* 0x04 */ MTL::BlendFactorSourceAlpha, + /* 0x05 */ MTL::BlendFactorOneMinusSourceAlpha, + /* 0x06 */ MTL::BlendFactorDestinationAlpha, + /* 0x07 */ MTL::BlendFactorOneMinusDestinationAlpha, + /* 0x08 */ MTL::BlendFactorDestinationColor, + /* 0x09 */ MTL::BlendFactorOneMinusDestinationColor, + /* 0x0A */ MTL::BlendFactorSourceAlphaSaturated, + /* 0x0B */ MTL::BlendFactorZero, // TODO + /* 0x0C */ MTL::BlendFactorZero, // TODO + /* 0x0D */ MTL::BlendFactorBlendColor, + /* 0x0E */ MTL::BlendFactorOneMinusBlendColor, + /* 0x0F */ MTL::BlendFactorSource1Color, + /* 0x10 */ MTL::BlendFactorOneMinusSource1Color, + /* 0x11 */ MTL::BlendFactorSource1Alpha, + /* 0x12 */ MTL::BlendFactorOneMinusSource1Alpha, + /* 0x13 */ MTL::BlendFactorBlendAlpha, + /* 0x14 */ MTL::BlendFactorOneMinusBlendAlpha +}; + +MTL::BlendFactor GetMtlBlendFactor(Latte::LATTE_CB_BLENDN_CONTROL::E_BLENDFACTOR factor) +{ + cemu_assert_debug((uint32)factor < std::size(MTL_BLEND_FACTORS)); + return MTL_BLEND_FACTORS[(uint32)factor]; +} diff --git a/src/Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h b/src/Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h index e9eb0b91..922d536c 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h +++ b/src/Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h @@ -6,6 +6,7 @@ #include "Cafe/HW/Latte/Core/LatteConst.h" //#include "Cafe/HW/Latte/Core/FetchShader.h" #include "Cafe/HW/Latte/Renderer/Renderer.h" +#include "Metal/MTLRenderPipeline.hpp" struct Uvec2 { uint32 x; @@ -29,3 +30,7 @@ MTL::PrimitiveType GetMtlPrimitiveType(LattePrimitiveMode mode); MTL::VertexFormat GetMtlVertexFormat(uint8 format); MTL::IndexType GetMtlIndexType(Renderer::INDEX_TYPE indexType); + +MTL::BlendOperation GetMtlBlendOp(Latte::LATTE_CB_BLENDN_CONTROL::E_COMBINEFUNC combineFunc); + +MTL::BlendFactor GetMtlBlendFactor(Latte::LATTE_CB_BLENDN_CONTROL::E_BLENDFACTOR factor); diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp index 055b9aa0..00207d65 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp @@ -560,7 +560,7 @@ void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32 LatteSHRC_UpdateActiveShaders(); LatteDecompilerShader* vertexShader = LatteSHRC_GetActiveVertexShader(); LatteDecompilerShader* pixelShader = LatteSHRC_GetActivePixelShader(); - if (!vertexShader) + if (!vertexShader || !static_cast(vertexShader->shader)->GetFunction()) { printf("no vertex function, skipping draw\n"); return; @@ -631,7 +631,42 @@ void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32 { continue; } - renderPipelineDescriptor->colorAttachments()->object(i)->setPixelFormat(texture->GetTexture()->pixelFormat()); + auto colorAttachment = renderPipelineDescriptor->colorAttachments()->object(i); + colorAttachment->setPixelFormat(texture->GetTexture()->pixelFormat()); + + // Blending + const Latte::LATTE_CB_COLOR_CONTROL& colorControlReg = LatteGPUState.contextNew.CB_COLOR_CONTROL; + uint32 blendEnableMask = colorControlReg.get_BLEND_MASK(); + uint32 renderTargetMask = LatteGPUState.contextNew.CB_TARGET_MASK.get_MASK(); + + bool blendEnabled = ((blendEnableMask & (1 << i))) != 0; + if (blendEnabled) + { + colorAttachment->setBlendingEnabled(true); + + const auto& blendControlReg = LatteGPUState.contextNew.CB_BLENDN_CONTROL[i]; + + auto rgbBlendOp = GetMtlBlendOp(blendControlReg.get_COLOR_COMB_FCN()); + auto srcRgbBlendFactor = GetMtlBlendFactor(blendControlReg.get_COLOR_SRCBLEND()); + auto dstRgbBlendFactor = GetMtlBlendFactor(blendControlReg.get_COLOR_DSTBLEND()); + + colorAttachment->setWriteMask((renderTargetMask >> (i * 4)) & 0xF); + colorAttachment->setRgbBlendOperation(rgbBlendOp); + colorAttachment->setSourceRGBBlendFactor(srcRgbBlendFactor); + colorAttachment->setDestinationRGBBlendFactor(dstRgbBlendFactor); + if (blendControlReg.get_SEPARATE_ALPHA_BLEND()) + { + colorAttachment->setAlphaBlendOperation(GetMtlBlendOp(blendControlReg.get_ALPHA_COMB_FCN())); + colorAttachment->setSourceAlphaBlendFactor(GetMtlBlendFactor(blendControlReg.get_ALPHA_SRCBLEND())); + colorAttachment->setDestinationAlphaBlendFactor(GetMtlBlendFactor(blendControlReg.get_ALPHA_DSTBLEND())); + } + else + { + colorAttachment->setAlphaBlendOperation(rgbBlendOp); + colorAttachment->setSourceAlphaBlendFactor(srcRgbBlendFactor); + colorAttachment->setDestinationAlphaBlendFactor(dstRgbBlendFactor); + } + } } if (m_state.activeFBO->depthBuffer.texture) { diff --git a/src/gui/CemuApp.cpp b/src/gui/CemuApp.cpp index f91c1e3a..322980e9 100644 --- a/src/gui/CemuApp.cpp +++ b/src/gui/CemuApp.cpp @@ -368,7 +368,8 @@ void CemuApp::OnAssertFailure(const wxChar* file, int line, const wxChar* func, #if BOOST_OS_WINDOWS DumpThreadStackTrace(); #endif - cemu_assert_debug(false); + // HACK + //cemu_assert_debug(false); } int CemuApp::FilterEvent(wxEvent& event) @@ -545,5 +546,3 @@ void CemuApp::ActivateApp(wxActivateEvent& event) g_window_info.app_active = event.GetActive(); event.Skip(); } - -