mirror of
https://github.com/cemu-project/Cemu.git
synced 2024-12-01 21:44:17 +01:00
implement sampler states
This commit is contained in:
parent
d2edc41680
commit
ce6d4cacd1
@ -1,6 +1,7 @@
|
||||
#include "Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h"
|
||||
#include "Common/precompiled.h"
|
||||
#include "Metal/MTLDepthStencil.hpp"
|
||||
#include "Metal/MTLSampler.hpp"
|
||||
|
||||
std::map<Latte::E_GX2SURFFMT, MtlPixelFormatInfo> MTL_COLOR_FORMAT_TABLE = {
|
||||
{Latte::E_GX2SURFFMT::R4_G4_UNORM, {MTL::PixelFormatRG8Unorm, 2}}, // TODO: correct?
|
||||
@ -272,3 +273,21 @@ MTL::CompareFunction GetMtlCompareFunc(Latte::E_COMPAREFUNC func)
|
||||
cemu_assert_debug((uint32)func < std::size(MTL_COMPARE_FUNCTIONS));
|
||||
return MTL_COMPARE_FUNCTIONS[(uint32)func];
|
||||
}
|
||||
|
||||
// TODO: clamp to border color? (should be fine though)
|
||||
const MTL::SamplerAddressMode MTL_SAMPLER_ADDRESS_MODES[] = {
|
||||
MTL::SamplerAddressModeRepeat, // WRAP
|
||||
MTL::SamplerAddressModeMirrorRepeat, // MIRROR
|
||||
MTL::SamplerAddressModeClampToEdge, // CLAMP_LAST_TEXEL
|
||||
MTL::SamplerAddressModeMirrorClampToEdge, // MIRROR_ONCE_LAST_TEXEL
|
||||
MTL::SamplerAddressModeClampToEdge, // unsupported HALF_BORDER
|
||||
MTL::SamplerAddressModeClampToBorderColor, // unsupported MIRROR_ONCE_HALF_BORDER
|
||||
MTL::SamplerAddressModeClampToBorderColor, // CLAMP_BORDER
|
||||
MTL::SamplerAddressModeClampToBorderColor // MIRROR_ONCE_BORDER
|
||||
};
|
||||
|
||||
MTL::SamplerAddressMode GetMtlSamplerAddressMode(Latte::LATTE_SQ_TEX_SAMPLER_WORD0_0::E_CLAMP clamp)
|
||||
{
|
||||
cemu_assert_debug((uint32)clamp < std::size(MTL_SAMPLER_ADDRESS_MODES));
|
||||
return MTL_SAMPLER_ADDRESS_MODES[(uint32)clamp];
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
//#include "Cafe/HW/Latte/Core/FetchShader.h"
|
||||
#include "Cafe/HW/Latte/Renderer/Renderer.h"
|
||||
#include "Metal/MTLDepthStencil.hpp"
|
||||
#include "Metal/MTLSampler.hpp"
|
||||
|
||||
struct Uvec2 {
|
||||
uint32 x;
|
||||
@ -36,3 +37,5 @@ MTL::BlendOperation GetMtlBlendOp(Latte::LATTE_CB_BLENDN_CONTROL::E_COMBINEFUNC
|
||||
MTL::BlendFactor GetMtlBlendFactor(Latte::LATTE_CB_BLENDN_CONTROL::E_BLENDFACTOR factor);
|
||||
|
||||
MTL::CompareFunction GetMtlCompareFunc(Latte::E_COMPAREFUNC func);
|
||||
|
||||
MTL::SamplerAddressMode GetMtlSamplerAddressMode(Latte::LATTE_SQ_TEX_SAMPLER_WORD0_0::E_CLAMP clamp);
|
||||
|
@ -15,8 +15,8 @@
|
||||
#include "Cafe/HW/Latte/Core/LatteIndices.h"
|
||||
#include "Cemu/Logging/CemuDebugLogging.h"
|
||||
#include "HW/Latte/Core/Latte.h"
|
||||
#include "HW/Latte/ISA/LatteReg.h"
|
||||
#include "gui/guiWrapper.h"
|
||||
#include <stdexcept>
|
||||
|
||||
extern bool hasValidFramebufferAttached;
|
||||
|
||||
@ -863,7 +863,7 @@ void MetalRenderer::BindStageResources(MTL::RenderCommandEncoder* renderCommandE
|
||||
continue;
|
||||
}
|
||||
|
||||
//LatteTexture* baseTexture = textureView->baseTexture;
|
||||
LatteTexture* baseTexture = textureView->baseTexture;
|
||||
// get texture register word 0
|
||||
uint32 word4 = LatteGPUState.contextRegister[texUnitRegIndex + 4];
|
||||
|
||||
@ -878,8 +878,108 @@ void MetalRenderer::BindStageResources(MTL::RenderCommandEncoder* renderCommandE
|
||||
uint32 stageSamplerIndex = shader->textureUnitSamplerAssignment[relative_textureUnit];
|
||||
if (stageSamplerIndex != LATTE_DECOMPILER_SAMPLER_NONE)
|
||||
{
|
||||
// TODO: bind the actual sampler
|
||||
MTL::SamplerState* sampler = m_nearestSampler;
|
||||
uint32 samplerIndex = stageSamplerIndex + LatteDecompiler_getTextureSamplerBaseIndex(shader->shaderType);
|
||||
const _LatteRegisterSetSampler* samplerWords = LatteGPUState.contextNew.SQ_TEX_SAMPLER + samplerIndex;
|
||||
|
||||
// TODO: cache this instead
|
||||
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();
|
||||
|
||||
// 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->setRAddressMode(GetMtlSamplerAddressMode(clampX));
|
||||
samplerDescriptor->setSAddressMode(GetMtlSamplerAddressMode(clampY));
|
||||
samplerDescriptor->setTAddressMode(GetMtlSamplerAddressMode(clampZ));
|
||||
|
||||
auto maxAniso = samplerWords->WORD0.get_MAX_ANISO_RATIO();
|
||||
|
||||
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;
|
||||
if (depthCompareMode == 1)
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
|
||||
MTL::SamplerState* sampler = m_device->newSamplerState(samplerDescriptor);
|
||||
samplerDescriptor->release();
|
||||
|
||||
switch (shader->shaderType)
|
||||
{
|
||||
case LatteConst::ShaderType::Vertex:
|
||||
@ -895,6 +995,7 @@ void MetalRenderer::BindStageResources(MTL::RenderCommandEncoder* renderCommandE
|
||||
default:
|
||||
UNREACHABLE;
|
||||
}
|
||||
sampler->release();
|
||||
}
|
||||
|
||||
switch (shader->shaderType)
|
||||
|
Loading…
Reference in New Issue
Block a user