mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-07-05 22:41:18 +12:00
choose the closest matching sampler border color
This commit is contained in:
parent
0c216e40e0
commit
24e1bba31c
3 changed files with 63 additions and 18 deletions
|
@ -2049,8 +2049,7 @@ void MetalRenderer::BindStageResources(MTL::RenderCommandEncoder* renderCommandE
|
||||||
MTL::SamplerState* sampler;
|
MTL::SamplerState* sampler;
|
||||||
if (stageSamplerIndex != LATTE_DECOMPILER_SAMPLER_NONE)
|
if (stageSamplerIndex != LATTE_DECOMPILER_SAMPLER_NONE)
|
||||||
{
|
{
|
||||||
uint32 samplerIndex = stageSamplerIndex + LatteDecompiler_getTextureSamplerBaseIndex(shader->shaderType);
|
sampler = m_samplerCache->GetSamplerState(LatteGPUState.contextNew, shader->shaderType, stageSamplerIndex);
|
||||||
sampler = m_samplerCache->GetSamplerState(LatteGPUState.contextNew, samplerIndex);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,21 @@
|
||||||
#include "Cafe/HW/Latte/Renderer/Metal/MetalSamplerCache.h"
|
#include "Cafe/HW/Latte/Renderer/Metal/MetalSamplerCache.h"
|
||||||
#include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h"
|
#include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h"
|
||||||
#include "HW/Latte/Renderer/Metal/LatteToMtl.h"
|
#include "Cafe/HW/Latte/Core/LatteShader.h"
|
||||||
|
#include "Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h"
|
||||||
|
#include "Metal/MTLSampler.hpp"
|
||||||
|
|
||||||
|
inline const char* BorderColorToStr(MTL::SamplerBorderColor borderColor)
|
||||||
|
{
|
||||||
|
switch (borderColor)
|
||||||
|
{
|
||||||
|
case MTL::SamplerBorderColorTransparentBlack:
|
||||||
|
return "transparent black";
|
||||||
|
case MTL::SamplerBorderColorOpaqueBlack:
|
||||||
|
return "opaque black";
|
||||||
|
case MTL::SamplerBorderColorOpaqueWhite:
|
||||||
|
return "opaque white";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MetalSamplerCache::~MetalSamplerCache()
|
MetalSamplerCache::~MetalSamplerCache()
|
||||||
{
|
{
|
||||||
|
@ -11,9 +26,11 @@ MetalSamplerCache::~MetalSamplerCache()
|
||||||
m_samplerCache.clear();
|
m_samplerCache.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
MTL::SamplerState* MetalSamplerCache::GetSamplerState(const LatteContextRegister& lcr, uint32 samplerIndex)
|
MTL::SamplerState* MetalSamplerCache::GetSamplerState(const LatteContextRegister& lcr, LatteConst::ShaderType shaderType, uint32 stageSamplerIndex)
|
||||||
{
|
{
|
||||||
uint64 stateHash = CalculateSamplerHash(lcr, samplerIndex);
|
uint32 samplerIndex = stageSamplerIndex + LatteDecompiler_getTextureSamplerBaseIndex(shaderType);
|
||||||
|
|
||||||
|
uint64 stateHash = CalculateSamplerHash(lcr, shaderType, stageSamplerIndex, samplerIndex);
|
||||||
auto& samplerState = m_samplerCache[stateHash];
|
auto& samplerState = m_samplerCache[stateHash];
|
||||||
if (samplerState)
|
if (samplerState)
|
||||||
return samplerState;
|
return samplerState;
|
||||||
|
@ -77,9 +94,9 @@ MTL::SamplerState* MetalSamplerCache::GetSamplerState(const LatteContextRegister
|
||||||
auto clampY = samplerWords->WORD0.get_CLAMP_Y();
|
auto clampY = samplerWords->WORD0.get_CLAMP_Y();
|
||||||
auto clampZ = samplerWords->WORD0.get_CLAMP_Z();
|
auto clampZ = samplerWords->WORD0.get_CLAMP_Z();
|
||||||
|
|
||||||
samplerDescriptor->setSAddressMode(GetMtlSamplerAddressMode(clampX));
|
samplerDescriptor->setSAddressMode(GetMtlSamplerAddressMode(clampX));
|
||||||
samplerDescriptor->setTAddressMode(GetMtlSamplerAddressMode(clampY));
|
samplerDescriptor->setTAddressMode(GetMtlSamplerAddressMode(clampY));
|
||||||
samplerDescriptor->setRAddressMode(GetMtlSamplerAddressMode(clampZ));
|
samplerDescriptor->setRAddressMode(GetMtlSamplerAddressMode(clampZ));
|
||||||
|
|
||||||
auto maxAniso = samplerWords->WORD0.get_MAX_ANISO_RATIO();
|
auto maxAniso = samplerWords->WORD0.get_MAX_ANISO_RATIO();
|
||||||
|
|
||||||
|
@ -101,25 +118,53 @@ MTL::SamplerState* MetalSamplerCache::GetSamplerState(const LatteContextRegister
|
||||||
// border
|
// border
|
||||||
auto borderType = samplerWords->WORD0.get_BORDER_COLOR_TYPE();
|
auto borderType = samplerWords->WORD0.get_BORDER_COLOR_TYPE();
|
||||||
|
|
||||||
|
MTL::SamplerBorderColor borderColor;
|
||||||
if (borderType == Latte::LATTE_SQ_TEX_SAMPLER_WORD0_0::E_BORDER_COLOR_TYPE::TRANSPARENT_BLACK)
|
if (borderType == Latte::LATTE_SQ_TEX_SAMPLER_WORD0_0::E_BORDER_COLOR_TYPE::TRANSPARENT_BLACK)
|
||||||
samplerDescriptor->setBorderColor(MTL::SamplerBorderColorTransparentBlack);
|
borderColor = MTL::SamplerBorderColorTransparentBlack;
|
||||||
else if (borderType == Latte::LATTE_SQ_TEX_SAMPLER_WORD0_0::E_BORDER_COLOR_TYPE::OPAQUE_BLACK)
|
else if (borderType == Latte::LATTE_SQ_TEX_SAMPLER_WORD0_0::E_BORDER_COLOR_TYPE::OPAQUE_BLACK)
|
||||||
samplerDescriptor->setBorderColor(MTL::SamplerBorderColorOpaqueBlack);
|
borderColor = MTL::SamplerBorderColorOpaqueBlack;
|
||||||
else if (borderType == Latte::LATTE_SQ_TEX_SAMPLER_WORD0_0::E_BORDER_COLOR_TYPE::OPAQUE_WHITE)
|
else if (borderType == Latte::LATTE_SQ_TEX_SAMPLER_WORD0_0::E_BORDER_COLOR_TYPE::OPAQUE_WHITE)
|
||||||
samplerDescriptor->setBorderColor(MTL::SamplerBorderColorOpaqueWhite);
|
borderColor = MTL::SamplerBorderColorOpaqueWhite;
|
||||||
else
|
else [[unlikely]]
|
||||||
{
|
{
|
||||||
// Metal doesn't support custom border color
|
_LatteRegisterSetSamplerBorderColor* borderColorReg;
|
||||||
cemuLog_logOnce(LogType::Force, "Custom border color is not supported in Metal, using transparent black instead");
|
if (shaderType == LatteConst::ShaderType::Vertex)
|
||||||
samplerDescriptor->setBorderColor(MTL::SamplerBorderColorTransparentBlack);
|
borderColorReg = LatteGPUState.contextNew.TD_VS_SAMPLER_BORDER_COLOR + stageSamplerIndex;
|
||||||
|
else if (shaderType == LatteConst::ShaderType::Pixel)
|
||||||
|
borderColorReg = LatteGPUState.contextNew.TD_PS_SAMPLER_BORDER_COLOR + stageSamplerIndex;
|
||||||
|
else // geometry
|
||||||
|
borderColorReg = LatteGPUState.contextNew.TD_GS_SAMPLER_BORDER_COLOR + stageSamplerIndex;
|
||||||
|
float r = borderColorReg->red.get_channelValue();
|
||||||
|
float g = borderColorReg->green.get_channelValue();
|
||||||
|
float b = borderColorReg->blue.get_channelValue();
|
||||||
|
float a = borderColorReg->alpha.get_channelValue();
|
||||||
|
|
||||||
|
// Metal doesn't support custom border color
|
||||||
|
// Let's find the best match
|
||||||
|
bool opaque = (a == 1.0f);
|
||||||
|
bool white = (r == 1.0f);
|
||||||
|
if (opaque)
|
||||||
|
{
|
||||||
|
if (white)
|
||||||
|
borderColor = MTL::SamplerBorderColorOpaqueWhite;
|
||||||
|
else
|
||||||
|
borderColor = MTL::SamplerBorderColorOpaqueBlack;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
borderColor = MTL::SamplerBorderColorTransparentBlack;
|
||||||
|
}
|
||||||
|
|
||||||
|
cemuLog_log(LogType::Force, "Custom border color ({}, {}, {}, {}) is not supported on Metal, using {} instead", r, g, b, a, BorderColorToStr(borderColor));
|
||||||
}
|
}
|
||||||
|
samplerDescriptor->setBorderColor(borderColor);
|
||||||
|
|
||||||
samplerState = m_mtlr->GetDevice()->newSamplerState(samplerDescriptor);
|
samplerState = m_mtlr->GetDevice()->newSamplerState(samplerDescriptor);
|
||||||
|
|
||||||
return samplerState;
|
return samplerState;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64 MetalSamplerCache::CalculateSamplerHash(const LatteContextRegister& lcr, uint32 samplerIndex)
|
uint64 MetalSamplerCache::CalculateSamplerHash(const LatteContextRegister& lcr, LatteConst::ShaderType shaderType, uint32 stageSamplerIndex, uint32 samplerIndex)
|
||||||
{
|
{
|
||||||
const _LatteRegisterSetSampler* samplerWords = lcr.SQ_TEX_SAMPLER + samplerIndex;
|
const _LatteRegisterSetSampler* samplerWords = lcr.SQ_TEX_SAMPLER + samplerIndex;
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <Metal/Metal.hpp>
|
#include <Metal/Metal.hpp>
|
||||||
|
|
||||||
|
#include "HW/Latte/Core/LatteConst.h"
|
||||||
#include "HW/Latte/ISA/LatteReg.h"
|
#include "HW/Latte/ISA/LatteReg.h"
|
||||||
|
|
||||||
class MetalSamplerCache
|
class MetalSamplerCache
|
||||||
|
@ -10,12 +11,12 @@ public:
|
||||||
MetalSamplerCache(class MetalRenderer* metalRenderer) : m_mtlr{metalRenderer} {}
|
MetalSamplerCache(class MetalRenderer* metalRenderer) : m_mtlr{metalRenderer} {}
|
||||||
~MetalSamplerCache();
|
~MetalSamplerCache();
|
||||||
|
|
||||||
MTL::SamplerState* GetSamplerState(const LatteContextRegister& lcr, uint32 samplerIndex);
|
MTL::SamplerState* GetSamplerState(const LatteContextRegister& lcr, LatteConst::ShaderType shaderType, uint32 stageSamplerIndex);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class MetalRenderer* m_mtlr;
|
class MetalRenderer* m_mtlr;
|
||||||
|
|
||||||
std::map<uint64, MTL::SamplerState*> m_samplerCache;
|
std::map<uint64, MTL::SamplerState*> m_samplerCache;
|
||||||
|
|
||||||
uint64 CalculateSamplerHash(const LatteContextRegister& lcr, uint32 samplerIndex);
|
uint64 CalculateSamplerHash(const LatteContextRegister& lcr, LatteConst::ShaderType shaderType, uint32 stageSamplerIndex, uint32 samplerIndex);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue