implement depth state & texture clears

This commit is contained in:
Samuliak 2024-08-02 19:42:34 +02:00
parent a2d15858ad
commit 4173675f03
3 changed files with 145 additions and 5 deletions

View File

@ -1,4 +1,6 @@
#include "Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h" #include "Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h"
#include "Common/precompiled.h"
#include "Metal/MTLDepthStencil.hpp"
std::map<Latte::E_GX2SURFFMT, MtlPixelFormatInfo> MTL_COLOR_FORMAT_TABLE = { std::map<Latte::E_GX2SURFFMT, MtlPixelFormatInfo> MTL_COLOR_FORMAT_TABLE = {
{Latte::E_GX2SURFFMT::R4_G4_UNORM, {MTL::PixelFormatRG8Unorm, 2}}, // TODO: correct? {Latte::E_GX2SURFFMT::R4_G4_UNORM, {MTL::PixelFormatRG8Unorm, 2}}, // TODO: correct?
@ -252,3 +254,21 @@ MTL::BlendFactor GetMtlBlendFactor(Latte::LATTE_CB_BLENDN_CONTROL::E_BLENDFACTOR
cemu_assert_debug((uint32)factor < std::size(MTL_BLEND_FACTORS)); cemu_assert_debug((uint32)factor < std::size(MTL_BLEND_FACTORS));
return MTL_BLEND_FACTORS[(uint32)factor]; return MTL_BLEND_FACTORS[(uint32)factor];
} }
const MTL::CompareFunction MTL_COMPARE_FUNCTIONS[8] =
{
MTL::CompareFunctionNever,
MTL::CompareFunctionLess,
MTL::CompareFunctionEqual,
MTL::CompareFunctionLessEqual,
MTL::CompareFunctionGreater,
MTL::CompareFunctionNotEqual,
MTL::CompareFunctionGreaterEqual,
MTL::CompareFunctionAlways
};
MTL::CompareFunction GetMtlCompareFunc(Latte::E_COMPAREFUNC func)
{
cemu_assert_debug((uint32)func < std::size(MTL_COMPARE_FUNCTIONS));
return MTL_COMPARE_FUNCTIONS[(uint32)func];
}

View File

@ -6,6 +6,7 @@
#include "Cafe/HW/Latte/Core/LatteConst.h" #include "Cafe/HW/Latte/Core/LatteConst.h"
//#include "Cafe/HW/Latte/Core/FetchShader.h" //#include "Cafe/HW/Latte/Core/FetchShader.h"
#include "Cafe/HW/Latte/Renderer/Renderer.h" #include "Cafe/HW/Latte/Renderer/Renderer.h"
#include "Metal/MTLDepthStencil.hpp"
struct Uvec2 { struct Uvec2 {
uint32 x; uint32 x;
@ -33,3 +34,5 @@ MTL::IndexType GetMtlIndexType(Renderer::INDEX_TYPE indexType);
MTL::BlendOperation GetMtlBlendOp(Latte::LATTE_CB_BLENDN_CONTROL::E_COMBINEFUNC combineFunc); MTL::BlendOperation GetMtlBlendOp(Latte::LATTE_CB_BLENDN_CONTROL::E_COMBINEFUNC combineFunc);
MTL::BlendFactor GetMtlBlendFactor(Latte::LATTE_CB_BLENDN_CONTROL::E_BLENDFACTOR factor); MTL::BlendFactor GetMtlBlendFactor(Latte::LATTE_CB_BLENDN_CONTROL::E_BLENDFACTOR factor);
MTL::CompareFunction GetMtlCompareFunc(Latte::E_COMPAREFUNC func);

View File

@ -13,7 +13,9 @@
#include "Cafe/HW/Latte/Core/LatteIndices.h" #include "Cafe/HW/Latte/Core/LatteIndices.h"
#include "Cemu/Logging/CemuDebugLogging.h" #include "Cemu/Logging/CemuDebugLogging.h"
#include "Foundation/NSTypes.hpp" #include "Foundation/NSTypes.hpp"
#include "Metal/MTLDepthStencil.hpp"
#include "Metal/MTLRenderCommandEncoder.hpp" #include "Metal/MTLRenderCommandEncoder.hpp"
#include "Metal/MTLRenderPass.hpp"
#include "gui/guiWrapper.h" #include "gui/guiWrapper.h"
extern bool hasValidFramebufferAttached; extern bool hasValidFramebufferAttached;
@ -377,14 +379,48 @@ void MetalRenderer::texture_loadSlice(LatteTexture* hostTexture, sint32 width, s
mtlTexture->GetTexture()->replaceRegion(MTL::Region(0, 0, width, height), mipIndex, sliceIndex, pixelData, bytesPerRow, bytesPerImage); mtlTexture->GetTexture()->replaceRegion(MTL::Region(0, 0, width, height), mipIndex, sliceIndex, pixelData, bytesPerRow, bytesPerImage);
} }
// TODO: use sliceIndex and mipIndex
void MetalRenderer::texture_clearColorSlice(LatteTexture* hostTexture, sint32 sliceIndex, sint32 mipIndex, float r, float g, float b, float a) void MetalRenderer::texture_clearColorSlice(LatteTexture* hostTexture, sint32 sliceIndex, sint32 mipIndex, float r, float g, float b, float a)
{ {
debug_printf("MetalRenderer::texture_clearColorSlice not implemented\n"); auto mtlTexture = static_cast<LatteTextureMtl*>(hostTexture)->GetTexture();
MTL::RenderPassDescriptor* renderPassDescriptor = MTL::RenderPassDescriptor::alloc()->init();
auto colorAttachment = renderPassDescriptor->colorAttachments()->object(0);
colorAttachment->setTexture(mtlTexture);
colorAttachment->setClearColor(MTL::ClearColor(r, g, b, a));
colorAttachment->setLoadAction(MTL::LoadActionClear);
colorAttachment->setStoreAction(MTL::StoreActionStore);
MTL::Texture* colorRenderTargets[8] = {nullptr};
colorRenderTargets[0] = mtlTexture;
GetRenderCommandEncoder(renderPassDescriptor, colorRenderTargets, nullptr);
} }
// TODO: use sliceIndex and mipIndex
void MetalRenderer::texture_clearDepthSlice(LatteTexture* hostTexture, uint32 sliceIndex, sint32 mipIndex, bool clearDepth, bool clearStencil, float depthValue, uint32 stencilValue) void MetalRenderer::texture_clearDepthSlice(LatteTexture* hostTexture, uint32 sliceIndex, sint32 mipIndex, bool clearDepth, bool clearStencil, float depthValue, uint32 stencilValue)
{ {
debug_printf("MetalRenderer::texture_clearDepthSlice not implemented\n"); auto mtlTexture = static_cast<LatteTextureMtl*>(hostTexture)->GetTexture();
MTL::RenderPassDescriptor* renderPassDescriptor = MTL::RenderPassDescriptor::alloc()->init();
if (clearDepth)
{
auto depthAttachment = renderPassDescriptor->depthAttachment();
depthAttachment->setTexture(mtlTexture);
depthAttachment->setClearDepth(depthValue);
depthAttachment->setLoadAction(MTL::LoadActionClear);
depthAttachment->setStoreAction(MTL::StoreActionStore);
}
if (clearStencil)
{
auto stencilAttachment = renderPassDescriptor->stencilAttachment();
stencilAttachment->setTexture(mtlTexture);
stencilAttachment->setClearStencil(stencilValue);
stencilAttachment->setLoadAction(MTL::LoadActionClear);
stencilAttachment->setStoreAction(MTL::StoreActionStore);
}
MTL::Texture* colorRenderTargets[8] = {nullptr};
GetRenderCommandEncoder(renderPassDescriptor, colorRenderTargets, mtlTexture);
} }
LatteTexture* MetalRenderer::texture_createTextureEx(Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle, Latte::E_HWTILEMODE tileMode, bool isDepth) LatteTexture* MetalRenderer::texture_createTextureEx(Latte::E_DIM dim, MPTR physAddress, MPTR physMipAddress, Latte::E_GX2SURFFMT format, uint32 width, uint32 height, uint32 depth, uint32 pitch, uint32 mipLevels, uint32 swizzle, Latte::E_HWTILEMODE tileMode, bool isDepth)
@ -683,6 +719,87 @@ void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32
} }
renderCommandEncoder->setRenderPipelineState(renderPipelineState); renderCommandEncoder->setRenderPipelineState(renderPipelineState);
// Depth stencil state
bool depthEnable = LatteGPUState.contextNew.DB_DEPTH_CONTROL.get_Z_ENABLE();
auto depthFunc = LatteGPUState.contextNew.DB_DEPTH_CONTROL.get_Z_FUNC();
bool depthWriteEnable = LatteGPUState.contextNew.DB_DEPTH_CONTROL.get_Z_WRITE_ENABLE();
MTL::DepthStencilDescriptor* depthStencilDescriptor = MTL::DepthStencilDescriptor::alloc()->init();
depthStencilDescriptor->setDepthWriteEnabled(depthWriteEnable);
auto depthCompareFunc = GetMtlCompareFunc(depthFunc);
if (!depthEnable)
{
depthCompareFunc = MTL::CompareFunctionAlways;
}
depthStencilDescriptor->setDepthCompareFunction(depthCompareFunc);
// TODO: stencil state
/*
// get stencil control parameters
bool stencilEnable = LatteGPUState.contextNew.DB_DEPTH_CONTROL.get_STENCIL_ENABLE();
bool backStencilEnable = LatteGPUState.contextNew.DB_DEPTH_CONTROL.get_BACK_STENCIL_ENABLE();
auto frontStencilFunc = LatteGPUState.contextNew.DB_DEPTH_CONTROL.get_STENCIL_FUNC_F();
auto frontStencilZPass = LatteGPUState.contextNew.DB_DEPTH_CONTROL.get_STENCIL_ZPASS_F();
auto frontStencilZFail = LatteGPUState.contextNew.DB_DEPTH_CONTROL.get_STENCIL_ZFAIL_F();
auto frontStencilFail = LatteGPUState.contextNew.DB_DEPTH_CONTROL.get_STENCIL_FAIL_F();
auto backStencilFunc = LatteGPUState.contextNew.DB_DEPTH_CONTROL.get_STENCIL_FUNC_B();
auto backStencilZPass = LatteGPUState.contextNew.DB_DEPTH_CONTROL.get_STENCIL_ZPASS_B();
auto backStencilZFail = LatteGPUState.contextNew.DB_DEPTH_CONTROL.get_STENCIL_ZFAIL_B();
auto backStencilFail = LatteGPUState.contextNew.DB_DEPTH_CONTROL.get_STENCIL_FAIL_B();
// get stencil control parameters
uint32 stencilCompareMaskFront = LatteGPUState.contextNew.DB_STENCILREFMASK.get_STENCILMASK_F();
uint32 stencilWriteMaskFront = LatteGPUState.contextNew.DB_STENCILREFMASK.get_STENCILWRITEMASK_F();
uint32 stencilRefFront = LatteGPUState.contextNew.DB_STENCILREFMASK.get_STENCILREF_F();
uint32 stencilCompareMaskBack = LatteGPUState.contextNew.DB_STENCILREFMASK_BF.get_STENCILMASK_B();
uint32 stencilWriteMaskBack = LatteGPUState.contextNew.DB_STENCILREFMASK_BF.get_STENCILWRITEMASK_B();
uint32 stencilRefBack = LatteGPUState.contextNew.DB_STENCILREFMASK_BF.get_STENCILREF_B();
static const VkStencilOp stencilOpTable[8] = {
VK_STENCIL_OP_KEEP,
VK_STENCIL_OP_ZERO,
VK_STENCIL_OP_REPLACE,
VK_STENCIL_OP_INCREMENT_AND_CLAMP,
VK_STENCIL_OP_DECREMENT_AND_CLAMP,
VK_STENCIL_OP_INVERT,
VK_STENCIL_OP_INCREMENT_AND_WRAP,
VK_STENCIL_OP_DECREMENT_AND_WRAP
};
depthStencilState.stencilTestEnable = stencilEnable ? VK_TRUE : VK_FALSE;
depthStencilState.front.reference = stencilRefFront;
depthStencilState.front.compareMask = stencilCompareMaskFront;
depthStencilState.front.writeMask = stencilWriteMaskBack;
depthStencilState.front.compareOp = vkDepthCompareTable[(size_t)frontStencilFunc];
depthStencilState.front.depthFailOp = stencilOpTable[(size_t)frontStencilZFail];
depthStencilState.front.failOp = stencilOpTable[(size_t)frontStencilFail];
depthStencilState.front.passOp = stencilOpTable[(size_t)frontStencilZPass];
if (backStencilEnable)
{
depthStencilState.back.reference = stencilRefBack;
depthStencilState.back.compareMask = stencilCompareMaskBack;
depthStencilState.back.writeMask = stencilWriteMaskBack;
depthStencilState.back.compareOp = vkDepthCompareTable[(size_t)backStencilFunc];
depthStencilState.back.depthFailOp = stencilOpTable[(size_t)backStencilZFail];
depthStencilState.back.failOp = stencilOpTable[(size_t)backStencilFail];
depthStencilState.back.passOp = stencilOpTable[(size_t)backStencilZPass];
}
else
{
depthStencilState.back.reference = stencilRefFront;
depthStencilState.back.compareMask = stencilCompareMaskFront;
depthStencilState.back.writeMask = stencilWriteMaskFront;
depthStencilState.back.compareOp = vkDepthCompareTable[(size_t)frontStencilFunc];
depthStencilState.back.depthFailOp = stencilOpTable[(size_t)frontStencilZFail];
depthStencilState.back.failOp = stencilOpTable[(size_t)frontStencilFail];
depthStencilState.back.passOp = stencilOpTable[(size_t)frontStencilZPass];
}
*/
MTL::DepthStencilState* depthStencilState = m_device->newDepthStencilState(depthStencilDescriptor);
renderCommandEncoder->setDepthStencilState(depthStencilState);
// Primitive type // Primitive type
const LattePrimitiveMode primitiveMode = static_cast<LattePrimitiveMode>(LatteGPUState.contextRegister[mmVGT_PRIMITIVE_TYPE]); const LattePrimitiveMode primitiveMode = static_cast<LattePrimitiveMode>(LatteGPUState.contextRegister[mmVGT_PRIMITIVE_TYPE]);
auto mtlPrimitiveType = GetMtlPrimitiveType(primitiveMode); auto mtlPrimitiveType = GetMtlPrimitiveType(primitiveMode);
@ -840,8 +957,8 @@ void MetalRenderer::BindStageResources(MTL::RenderCommandEncoder* renderCommandE
UNREACHABLE; UNREACHABLE;
} }
//if (shader->resourceMapping.uniformVarsBufferBindingPoint >= 0) if (shader->resourceMapping.uniformVarsBufferBindingPoint >= 0)
//{ {
if (shader->uniform.list_ufTexRescale.empty() == false) if (shader->uniform.list_ufTexRescale.empty() == false)
{ {
for (auto& entry : shader->uniform.list_ufTexRescale) for (auto& entry : shader->uniform.list_ufTexRescale)
@ -915,7 +1032,7 @@ void MetalRenderer::BindStageResources(MTL::RenderCommandEncoder* renderCommandE
default: default:
UNREACHABLE; UNREACHABLE;
} }
//} }
// Uniform buffers // Uniform buffers
for (sint32 i = 0; i < LATTE_NUM_MAX_UNIFORM_BUFFERS; i++) for (sint32 i = 0; i < LATTE_NUM_MAX_UNIFORM_BUFFERS; i++)