mirror of
https://github.com/cemu-project/Cemu.git
synced 2024-12-02 05:54:18 +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 "Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h"
|
||||||
#include "Common/precompiled.h"
|
#include "Common/precompiled.h"
|
||||||
#include "Metal/MTLDepthStencil.hpp"
|
#include "Metal/MTLDepthStencil.hpp"
|
||||||
|
#include "Metal/MTLSampler.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?
|
||||||
@ -272,3 +273,21 @@ MTL::CompareFunction GetMtlCompareFunc(Latte::E_COMPAREFUNC func)
|
|||||||
cemu_assert_debug((uint32)func < std::size(MTL_COMPARE_FUNCTIONS));
|
cemu_assert_debug((uint32)func < std::size(MTL_COMPARE_FUNCTIONS));
|
||||||
return MTL_COMPARE_FUNCTIONS[(uint32)func];
|
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/Core/FetchShader.h"
|
||||||
#include "Cafe/HW/Latte/Renderer/Renderer.h"
|
#include "Cafe/HW/Latte/Renderer/Renderer.h"
|
||||||
#include "Metal/MTLDepthStencil.hpp"
|
#include "Metal/MTLDepthStencil.hpp"
|
||||||
|
#include "Metal/MTLSampler.hpp"
|
||||||
|
|
||||||
struct Uvec2 {
|
struct Uvec2 {
|
||||||
uint32 x;
|
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::BlendFactor GetMtlBlendFactor(Latte::LATTE_CB_BLENDN_CONTROL::E_BLENDFACTOR factor);
|
||||||
|
|
||||||
MTL::CompareFunction GetMtlCompareFunc(Latte::E_COMPAREFUNC func);
|
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 "Cafe/HW/Latte/Core/LatteIndices.h"
|
||||||
#include "Cemu/Logging/CemuDebugLogging.h"
|
#include "Cemu/Logging/CemuDebugLogging.h"
|
||||||
#include "HW/Latte/Core/Latte.h"
|
#include "HW/Latte/Core/Latte.h"
|
||||||
|
#include "HW/Latte/ISA/LatteReg.h"
|
||||||
#include "gui/guiWrapper.h"
|
#include "gui/guiWrapper.h"
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
extern bool hasValidFramebufferAttached;
|
extern bool hasValidFramebufferAttached;
|
||||||
|
|
||||||
@ -863,7 +863,7 @@ void MetalRenderer::BindStageResources(MTL::RenderCommandEncoder* renderCommandE
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//LatteTexture* baseTexture = textureView->baseTexture;
|
LatteTexture* baseTexture = textureView->baseTexture;
|
||||||
// get texture register word 0
|
// get texture register word 0
|
||||||
uint32 word4 = LatteGPUState.contextRegister[texUnitRegIndex + 4];
|
uint32 word4 = LatteGPUState.contextRegister[texUnitRegIndex + 4];
|
||||||
|
|
||||||
@ -878,8 +878,108 @@ void MetalRenderer::BindStageResources(MTL::RenderCommandEncoder* renderCommandE
|
|||||||
uint32 stageSamplerIndex = shader->textureUnitSamplerAssignment[relative_textureUnit];
|
uint32 stageSamplerIndex = shader->textureUnitSamplerAssignment[relative_textureUnit];
|
||||||
if (stageSamplerIndex != LATTE_DECOMPILER_SAMPLER_NONE)
|
if (stageSamplerIndex != LATTE_DECOMPILER_SAMPLER_NONE)
|
||||||
{
|
{
|
||||||
// TODO: bind the actual sampler
|
uint32 samplerIndex = stageSamplerIndex + LatteDecompiler_getTextureSamplerBaseIndex(shader->shaderType);
|
||||||
MTL::SamplerState* sampler = m_nearestSampler;
|
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)
|
switch (shader->shaderType)
|
||||||
{
|
{
|
||||||
case LatteConst::ShaderType::Vertex:
|
case LatteConst::ShaderType::Vertex:
|
||||||
@ -895,6 +995,7 @@ void MetalRenderer::BindStageResources(MTL::RenderCommandEncoder* renderCommandE
|
|||||||
default:
|
default:
|
||||||
UNREACHABLE;
|
UNREACHABLE;
|
||||||
}
|
}
|
||||||
|
sampler->release();
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (shader->shaderType)
|
switch (shader->shaderType)
|
||||||
|
Loading…
Reference in New Issue
Block a user