mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-16 18:59:48 +12:00
enable stencil testing
This commit is contained in:
parent
dff6f5bf3f
commit
9ec116da18
3 changed files with 60 additions and 14 deletions
|
@ -7,8 +7,10 @@ using namespace PICA;
|
||||||
namespace Metal {
|
namespace Metal {
|
||||||
|
|
||||||
struct DepthStencilHash {
|
struct DepthStencilHash {
|
||||||
bool depthWrite;
|
bool depthStencilWrite;
|
||||||
u8 depthFunc;
|
u8 depthFunc;
|
||||||
|
u32 stencilConfig;
|
||||||
|
u16 stencilOpConfig;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DepthStencilCache {
|
class DepthStencilCache {
|
||||||
|
@ -24,16 +26,45 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
MTL::DepthStencilState* get(DepthStencilHash hash) {
|
MTL::DepthStencilState* get(DepthStencilHash hash) {
|
||||||
u8 intHash = hash.depthWrite | (hash.depthFunc << 1);
|
u64 intHash = ((u64)hash.depthStencilWrite << 56) | ((u64)hash.depthFunc << 48) | ((u64)hash.stencilConfig << 16) | (u64)hash.stencilOpConfig;
|
||||||
auto& depthStencilState = depthStencilCache[intHash];
|
auto& depthStencilState = depthStencilCache[intHash];
|
||||||
if (!depthStencilState) {
|
if (!depthStencilState) {
|
||||||
MTL::DepthStencilDescriptor* desc = MTL::DepthStencilDescriptor::alloc()->init();
|
MTL::DepthStencilDescriptor* desc = MTL::DepthStencilDescriptor::alloc()->init();
|
||||||
desc->setDepthWriteEnabled(hash.depthWrite);
|
desc->setDepthWriteEnabled(hash.depthStencilWrite);
|
||||||
desc->setDepthCompareFunction(toMTLCompareFunc(hash.depthFunc));
|
desc->setDepthCompareFunction(toMTLCompareFunc(hash.depthFunc));
|
||||||
|
|
||||||
|
const bool stencilEnable = Helpers::getBit<0>(hash.stencilConfig);
|
||||||
|
MTL::StencilDescriptor* stencilDesc = nullptr;
|
||||||
|
if (stencilEnable) {
|
||||||
|
const u8 stencilFunc = Helpers::getBits<4, 3>(hash.stencilConfig);
|
||||||
|
const s8 reference = s8(Helpers::getBits<16, 8>(hash.stencilConfig)); // Signed reference value
|
||||||
|
const u8 stencilRefMask = Helpers::getBits<24, 8>(hash.stencilConfig);
|
||||||
|
|
||||||
|
const u32 stencilBufferMask = hash.depthStencilWrite ? Helpers::getBits<8, 8>(hash.stencilConfig) : 0;
|
||||||
|
|
||||||
|
const u8 stencilFailOp = Helpers::getBits<0, 3>(hash.stencilOpConfig);
|
||||||
|
const u8 depthFailOp = Helpers::getBits<4, 3>(hash.stencilOpConfig);
|
||||||
|
const u8 passOp = Helpers::getBits<8, 3>(hash.stencilOpConfig);
|
||||||
|
|
||||||
|
stencilDesc = MTL::StencilDescriptor::alloc()->init();
|
||||||
|
stencilDesc->setStencilFailureOperation(toMTLStencilOperation(stencilFailOp));
|
||||||
|
stencilDesc->setDepthFailureOperation(toMTLStencilOperation(depthFailOp));
|
||||||
|
stencilDesc->setDepthStencilPassOperation(toMTLStencilOperation(passOp));
|
||||||
|
stencilDesc->setStencilCompareFunction(toMTLCompareFunc(stencilFunc));
|
||||||
|
stencilDesc->setReadMask(stencilRefMask);
|
||||||
|
stencilDesc->setWriteMask(stencilBufferMask);
|
||||||
|
// TODO: Set reference value
|
||||||
|
|
||||||
|
desc->setFrontFaceStencil(stencilDesc);
|
||||||
|
desc->setBackFaceStencil(stencilDesc);
|
||||||
|
}
|
||||||
|
|
||||||
depthStencilState = device->newDepthStencilState(desc);
|
depthStencilState = device->newDepthStencilState(desc);
|
||||||
|
|
||||||
desc->release();
|
desc->release();
|
||||||
|
if (stencilDesc) {
|
||||||
|
stencilDesc->release();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return depthStencilState;
|
return depthStencilState;
|
||||||
|
@ -47,7 +78,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_map<u8, MTL::DepthStencilState*> depthStencilCache;
|
std::unordered_map<u64, MTL::DepthStencilState*> depthStencilCache;
|
||||||
|
|
||||||
MTL::Device* device;
|
MTL::Device* device;
|
||||||
};
|
};
|
||||||
|
|
|
@ -81,4 +81,20 @@ inline MTL::BlendFactor toMTLBlendFactor(u8 factor) {
|
||||||
return MTL::BlendFactorOne;
|
return MTL::BlendFactorOne;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline MTL::StencilOperation toMTLStencilOperation(u8 op) {
|
||||||
|
switch (op) {
|
||||||
|
case 0: return MTL::StencilOperationKeep;
|
||||||
|
case 1: return MTL::StencilOperationZero;
|
||||||
|
case 2: return MTL::StencilOperationReplace;
|
||||||
|
case 3: return MTL::StencilOperationIncrementClamp;
|
||||||
|
case 4: return MTL::StencilOperationDecrementClamp;
|
||||||
|
case 5: return MTL::StencilOperationInvert;
|
||||||
|
case 6: return MTL::StencilOperationIncrementWrap;
|
||||||
|
case 7: return MTL::StencilOperationDecrementWrap;
|
||||||
|
default: panic("Unknown stencil operation %u", op);
|
||||||
|
}
|
||||||
|
|
||||||
|
return MTL::StencilOperationKeep;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace PICA
|
} // namespace PICA
|
||||||
|
|
|
@ -324,34 +324,33 @@ void RendererMTL::drawVertices(PICA::PrimType primType, std::span<const PICA::Ve
|
||||||
|
|
||||||
// Depth stencil
|
// Depth stencil
|
||||||
const u32 depthControl = regs[PICA::InternalRegs::DepthAndColorMask];
|
const u32 depthControl = regs[PICA::InternalRegs::DepthAndColorMask];
|
||||||
const bool depthWrite = regs[PICA::InternalRegs::DepthBufferWrite];
|
const bool depthStencilWrite = regs[PICA::InternalRegs::DepthBufferWrite];
|
||||||
const bool depthTestEnable = depthControl & 0x1;
|
const bool depthEnable = depthControl & 0x1;
|
||||||
const bool depthWriteEnable = Helpers::getBit<12>(depthControl);
|
const bool depthWriteEnable = Helpers::getBit<12>(depthControl);
|
||||||
const u8 depthFunc = Helpers::getBits<4, 3>(depthControl);
|
const u8 depthFunc = Helpers::getBits<4, 3>(depthControl);
|
||||||
const u8 colorMask = Helpers::getBits<8, 4>(depthControl);
|
const u8 colorMask = Helpers::getBits<8, 4>(depthControl);
|
||||||
// TODO: color mask
|
// TODO: color mask
|
||||||
// gl.setColourMask(colorMask & 0x1, colorMask & 0x2, colorMask & 0x4, colorMask & 0x8);
|
// gl.setColourMask(colorMask & 0x1, colorMask & 0x2, colorMask & 0x4, colorMask & 0x8);
|
||||||
|
|
||||||
const u32 stencilConfig = regs[PICA::InternalRegs::StencilTest];
|
Metal::DepthStencilHash depthStencilHash{false, 1};
|
||||||
const bool stencilEnable = Helpers::getBit<0>(stencilConfig);
|
depthStencilHash.stencilConfig = regs[PICA::InternalRegs::StencilTest];
|
||||||
|
depthStencilHash.stencilOpConfig = regs[PICA::InternalRegs::StencilOp];
|
||||||
|
const bool stencilEnable = Helpers::getBit<0>(depthStencilHash.stencilConfig);
|
||||||
|
|
||||||
std::optional<Metal::DepthStencilRenderTarget> depthStencilRenderTarget = std::nullopt;
|
std::optional<Metal::DepthStencilRenderTarget> depthStencilRenderTarget = std::nullopt;
|
||||||
Metal::DepthStencilHash depthStencilHash{false, 1};
|
if (depthEnable) {
|
||||||
if (depthTestEnable) {
|
depthStencilHash.depthStencilWrite = depthWriteEnable && depthStencilWrite;
|
||||||
depthStencilHash.depthWrite = depthWriteEnable && depthWrite;
|
|
||||||
depthStencilHash.depthFunc = depthFunc;
|
depthStencilHash.depthFunc = depthFunc;
|
||||||
depthStencilRenderTarget = getDepthRenderTarget();
|
depthStencilRenderTarget = getDepthRenderTarget();
|
||||||
} else {
|
} else {
|
||||||
if (depthWriteEnable) {
|
if (depthWriteEnable) {
|
||||||
depthStencilHash.depthWrite = true;
|
depthStencilHash.depthStencilWrite = true;
|
||||||
depthStencilRenderTarget = getDepthRenderTarget();
|
depthStencilRenderTarget = getDepthRenderTarget();
|
||||||
} else if (stencilEnable) {
|
} else if (stencilEnable) {
|
||||||
depthStencilRenderTarget = getDepthRenderTarget();
|
depthStencilRenderTarget = getDepthRenderTarget();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: stencil tests
|
|
||||||
|
|
||||||
// TODO: don't begin a new render pass every time
|
// TODO: don't begin a new render pass every time
|
||||||
MTL::RenderPassDescriptor* renderPassDescriptor = MTL::RenderPassDescriptor::alloc()->init();
|
MTL::RenderPassDescriptor* renderPassDescriptor = MTL::RenderPassDescriptor::alloc()->init();
|
||||||
MTL::RenderPassColorAttachmentDescriptor* colorAttachment = renderPassDescriptor->colorAttachments()->object(0);
|
MTL::RenderPassColorAttachmentDescriptor* colorAttachment = renderPassDescriptor->colorAttachments()->object(0);
|
||||||
|
|
Loading…
Add table
Reference in a new issue