mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-07-05 22:41:18 +12:00
implement sampler cache
This commit is contained in:
parent
9982ac7acb
commit
d79d7fea63
7 changed files with 181 additions and 122 deletions
128
src/Cafe/HW/Latte/Renderer/Metal/MetalSamplerCache.cpp
Normal file
128
src/Cafe/HW/Latte/Renderer/Metal/MetalSamplerCache.cpp
Normal file
|
@ -0,0 +1,128 @@
|
|||
#include "Cafe/HW/Latte/Renderer/Metal/MetalSamplerCache.h"
|
||||
#include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h"
|
||||
#include "HW/Latte/Renderer/Metal/LatteToMtl.h"
|
||||
|
||||
MetalSamplerCache::~MetalSamplerCache()
|
||||
{
|
||||
for (auto& pair : m_samplerCache)
|
||||
{
|
||||
pair.second->release();
|
||||
}
|
||||
m_samplerCache.clear();
|
||||
}
|
||||
|
||||
MTL::SamplerState* MetalSamplerCache::GetSamplerState(const LatteContextRegister& lcr, uint32 samplerIndex)
|
||||
{
|
||||
uint64 stateHash = CalculateSamplerHash(lcr, samplerIndex);
|
||||
auto& samplerState = m_samplerCache[stateHash];
|
||||
if (samplerState)
|
||||
return samplerState;
|
||||
|
||||
// Sampler state
|
||||
const _LatteRegisterSetSampler* samplerWords = lcr.SQ_TEX_SAMPLER + samplerIndex;
|
||||
|
||||
MTL::SamplerDescriptor* samplerDescriptor = MTL::SamplerDescriptor::alloc()->init();
|
||||
|
||||
// lod
|
||||
uint32 iMinLOD = samplerWords->WORD1.get_MIN_LOD();
|
||||
uint32 iMaxLOD = samplerWords->WORD1.get_MAX_LOD();
|
||||
sint32 iLodBias = samplerWords->WORD1.get_LOD_BIAS();
|
||||
|
||||
// TODO: uncomment
|
||||
// apply relative lod bias from graphic pack
|
||||
//if (baseTexture->overwriteInfo.hasRelativeLodBias)
|
||||
// iLodBias += baseTexture->overwriteInfo.relativeLodBias;
|
||||
// apply absolute lod bias from graphic pack
|
||||
//if (baseTexture->overwriteInfo.hasLodBias)
|
||||
// iLodBias = baseTexture->overwriteInfo.lodBias;
|
||||
|
||||
auto filterMip = samplerWords->WORD0.get_MIP_FILTER();
|
||||
if (filterMip == Latte::LATTE_SQ_TEX_SAMPLER_WORD0_0::E_Z_FILTER::NONE)
|
||||
{
|
||||
samplerDescriptor->setMipFilter(MTL::SamplerMipFilterNearest);
|
||||
samplerDescriptor->setLodMinClamp(0.0f);
|
||||
samplerDescriptor->setLodMaxClamp(0.25f);
|
||||
}
|
||||
else if (filterMip == Latte::LATTE_SQ_TEX_SAMPLER_WORD0_0::E_Z_FILTER::POINT)
|
||||
{
|
||||
samplerDescriptor->setMipFilter(MTL::SamplerMipFilterNearest);
|
||||
samplerDescriptor->setLodMinClamp((float)iMinLOD / 64.0f);
|
||||
samplerDescriptor->setLodMaxClamp((float)iMaxLOD / 64.0f);
|
||||
}
|
||||
else if (filterMip == Latte::LATTE_SQ_TEX_SAMPLER_WORD0_0::E_Z_FILTER::LINEAR)
|
||||
{
|
||||
samplerDescriptor->setMipFilter(MTL::SamplerMipFilterLinear);
|
||||
samplerDescriptor->setLodMinClamp((float)iMinLOD / 64.0f);
|
||||
samplerDescriptor->setLodMaxClamp((float)iMaxLOD / 64.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
// fallback for invalid constants
|
||||
samplerDescriptor->setMipFilter(MTL::SamplerMipFilterLinear);
|
||||
samplerDescriptor->setLodMinClamp((float)iMinLOD / 64.0f);
|
||||
samplerDescriptor->setLodMaxClamp((float)iMaxLOD / 64.0f);
|
||||
}
|
||||
|
||||
auto filterMin = samplerWords->WORD0.get_XY_MIN_FILTER();
|
||||
cemu_assert_debug(filterMin != Latte::LATTE_SQ_TEX_SAMPLER_WORD0_0::E_XY_FILTER::BICUBIC); // todo
|
||||
samplerDescriptor->setMinFilter((filterMin == Latte::LATTE_SQ_TEX_SAMPLER_WORD0_0::E_XY_FILTER::POINT || filterMin == Latte::LATTE_SQ_TEX_SAMPLER_WORD0_0::E_XY_FILTER::ANISO_POINT) ? MTL::SamplerMinMagFilterNearest : MTL::SamplerMinMagFilterLinear);
|
||||
|
||||
auto filterMag = samplerWords->WORD0.get_XY_MAG_FILTER();
|
||||
samplerDescriptor->setMagFilter((filterMag == Latte::LATTE_SQ_TEX_SAMPLER_WORD0_0::E_XY_FILTER::POINT || filterMin == Latte::LATTE_SQ_TEX_SAMPLER_WORD0_0::E_XY_FILTER::ANISO_POINT) ? MTL::SamplerMinMagFilterNearest : MTL::SamplerMinMagFilterLinear);
|
||||
|
||||
auto filterZ = samplerWords->WORD0.get_Z_FILTER();
|
||||
// todo: z-filter for texture array samplers is customizable for GPU7 but OpenGL/Vulkan doesn't expose this functionality?
|
||||
|
||||
auto clampX = samplerWords->WORD0.get_CLAMP_X();
|
||||
auto clampY = samplerWords->WORD0.get_CLAMP_Y();
|
||||
auto clampZ = samplerWords->WORD0.get_CLAMP_Z();
|
||||
|
||||
samplerDescriptor->setSAddressMode(GetMtlSamplerAddressMode(clampX));
|
||||
samplerDescriptor->setTAddressMode(GetMtlSamplerAddressMode(clampY));
|
||||
samplerDescriptor->setRAddressMode(GetMtlSamplerAddressMode(clampZ));
|
||||
|
||||
auto maxAniso = samplerWords->WORD0.get_MAX_ANISO_RATIO();
|
||||
|
||||
// TODO: uncomment
|
||||
//if (baseTexture->overwriteInfo.anisotropicLevel >= 0)
|
||||
// maxAniso = baseTexture->overwriteInfo.anisotropicLevel;
|
||||
|
||||
if (maxAniso > 0)
|
||||
samplerDescriptor->setMaxAnisotropy(1 << maxAniso);
|
||||
|
||||
// TODO: set lod bias
|
||||
//samplerInfo.mipLodBias = (float)iLodBias / 64.0f;
|
||||
|
||||
// depth compare
|
||||
//uint8 depthCompareMode = shader->textureUsesDepthCompare[relative_textureUnit] ? 1 : 0;
|
||||
// TODO: is it okay to just cast?
|
||||
samplerDescriptor->setCompareFunction(GetMtlCompareFunc((Latte::E_COMPAREFUNC)samplerWords->WORD0.get_DEPTH_COMPARE_FUNCTION()));
|
||||
|
||||
// border
|
||||
auto borderType = samplerWords->WORD0.get_BORDER_COLOR_TYPE();
|
||||
|
||||
if (borderType == Latte::LATTE_SQ_TEX_SAMPLER_WORD0_0::E_BORDER_COLOR_TYPE::TRANSPARENT_BLACK)
|
||||
samplerDescriptor->setBorderColor(MTL::SamplerBorderColorTransparentBlack);
|
||||
else if (borderType == Latte::LATTE_SQ_TEX_SAMPLER_WORD0_0::E_BORDER_COLOR_TYPE::OPAQUE_BLACK)
|
||||
samplerDescriptor->setBorderColor(MTL::SamplerBorderColorOpaqueBlack);
|
||||
else if (borderType == Latte::LATTE_SQ_TEX_SAMPLER_WORD0_0::E_BORDER_COLOR_TYPE::OPAQUE_WHITE)
|
||||
samplerDescriptor->setBorderColor(MTL::SamplerBorderColorOpaqueWhite);
|
||||
else
|
||||
{
|
||||
// Metal doesn't support custom border color
|
||||
samplerDescriptor->setBorderColor(MTL::SamplerBorderColorOpaqueBlack);
|
||||
}
|
||||
|
||||
samplerState = m_mtlr->GetDevice()->newSamplerState(samplerDescriptor);
|
||||
samplerDescriptor->release();
|
||||
|
||||
return samplerState;
|
||||
}
|
||||
|
||||
uint64 MetalSamplerCache::CalculateSamplerHash(const LatteContextRegister& lcr, uint32 samplerIndex)
|
||||
{
|
||||
const _LatteRegisterSetSampler* samplerWords = lcr.SQ_TEX_SAMPLER + samplerIndex;
|
||||
|
||||
// TODO: check this
|
||||
return *((uint64*)samplerWords);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue