diff --git a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitMSL.cpp b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitMSL.cpp index 7b8755bf..1c75b737 100644 --- a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitMSL.cpp +++ b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitMSL.cpp @@ -2246,6 +2246,7 @@ static void _emitTEXSampleTextureCode(LatteDecompilerShaderContext* shaderContex } bool isCompare = shaderContext->shader->textureUsesDepthCompare[texInstruction->textureFetch.textureIndex]; + bool emulateCompare = (isCompare && !IsValidDepthTextureType(texDim)); bool isGather = (texOpcode == GPU7_TEX_INST_FETCH4); bool unnormalizationHandled = false; @@ -2265,25 +2266,40 @@ static void _emitTEXSampleTextureCode(LatteDecompilerShaderContext* shaderContex return; } - src->addFmt("tex{}.", texInstruction->textureFetch.textureIndex); - if ((texOpcode == GPU7_TEX_INST_SAMPLE && (texInstruction->textureFetch.unnormalized[0] && texInstruction->textureFetch.unnormalized[1] && texInstruction->textureFetch.unnormalized[2] && texInstruction->textureFetch.unnormalized[3])) || - texOpcode == GPU7_TEX_INST_LD) + if (emulateCompare) { - if (hasOffset) - cemu_assert_unimplemented(); - src->add("read("); - unnormalizationHandled = true; - useTexelCoordinates = true; + cemu_assert_debug(!isGather); + + src->add("sampleCompareEmulate("); + } + + src->addFmt("tex{}", texInstruction->textureFetch.textureIndex); + if (!emulateCompare) + { + src->add("."); + if ((texOpcode == GPU7_TEX_INST_SAMPLE && (texInstruction->textureFetch.unnormalized[0] && texInstruction->textureFetch.unnormalized[1] && texInstruction->textureFetch.unnormalized[2] && texInstruction->textureFetch.unnormalized[3])) || + texOpcode == GPU7_TEX_INST_LD) + { + if (hasOffset) + cemu_assert_unimplemented(); + src->add("read("); + unnormalizationHandled = true; + useTexelCoordinates = true; + } + else + { + if (isGather) + src->add("gather"); + else + src->add("sample"); + if (isCompare) + src->add("_compare"); + src->addFmt("(samplr{}, ", texInstruction->textureFetch.textureIndex); + } } else { - if (isGather) - src->add("gather"); - else - src->add("sample"); - if (isCompare) - src->add("_compare"); - src->addFmt("(samplr{}, ", texInstruction->textureFetch.textureIndex); + src->addFmt(", samplr{}, ", texInstruction->textureFetch.textureIndex); } // for textureGather() add shift (todo: depends on rounding mode set in sampler registers?) @@ -3719,6 +3735,19 @@ void LatteDecompiler_emitHelperFunctions(LatteDecompilerShaderContext* shaderCon "}\r\n"); } + // Sample compare emulate + // TODO: only add when needed + + // TODO: lod_options overload + // TODO: when the sampler has linear min mag filter, use gather and filter manually + // TODO: offset? + fCStr_shaderSource->add("" + "template\r\n" + "float sampleCompareEmulate(TextureT tex, sampler samplr, CoordT coord, float compareValue) {\r\n" + "return compareValue < tex.sample(samplr, coord).x ? 1.0 : 0.0;\r\n" + "}\r\n" + ); + // clamp fCStr_shaderSource->add("" "int clampFI32(int v)\r\n" diff --git a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitMSLHeader.hpp b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitMSLHeader.hpp index 53332f7c..615e86f9 100644 --- a/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitMSLHeader.hpp +++ b/src/Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompilerEmitMSLHeader.hpp @@ -1,7 +1,8 @@ #pragma once #include "Common/precompiled.h" -#include "HW/Latte/Core/LatteConst.h" +#include "Cafe/HW/Latte/Renderer/Metal/MetalCommon.h" + namespace LatteDecompiler { static void _emitUniformVariables(LatteDecompilerShaderContext* decompilerContext) @@ -442,7 +443,8 @@ namespace LatteDecompiler src->add(", "); - if (shaderContext->shader->textureUsesDepthCompare[i]) + // Only 2D and 2D array textures can be used with comparison samplers + if (shaderContext->shader->textureUsesDepthCompare[i] && IsValidDepthTextureType(shaderContext->shader->textureUnitDim[i])) src->add("depth"); else src->add("texture"); diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalCommon.h b/src/Cafe/HW/Latte/Renderer/Metal/MetalCommon.h index a47ecf9a..a2ecc7e9 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalCommon.h +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalCommon.h @@ -3,6 +3,8 @@ #include #include +#include "Cafe/HW/Latte/Core/LatteConst.h" + struct MetalPixelFormatSupport { bool m_supportsR8Unorm_sRGB; @@ -62,3 +64,8 @@ inline NS::String* GetLabel(const std::string& label, const void* identifier) } constexpr MTL::RenderStages ALL_MTL_RENDER_STAGES = MTL::RenderStageVertex | MTL::RenderStageObject | MTL::RenderStageMesh | MTL::RenderStageFragment; + +inline bool IsValidDepthTextureType(Latte::E_DIM dim) +{ + return (dim == Latte::E_DIM::DIM_2D || dim == Latte::E_DIM::DIM_2D_MSAA || dim == Latte::E_DIM::DIM_2D_ARRAY || dim == Latte::E_DIM::DIM_2D_ARRAY_MSAA || dim == Latte::E_DIM::DIM_CUBEMAP); +}