From cb11662ea552362d18c371b20312b0a21c441827 Mon Sep 17 00:00:00 2001 From: Billy Laws Date: Sat, 3 Sep 2022 12:36:56 +0100 Subject: [PATCH] Implement depth stencil pipeline state --- .../maxwell_3d/pipeline_state.cpp | 98 ++++++++++++++++++- .../interconnect/maxwell_3d/pipeline_state.h | 29 ++++++ .../skyline/soc/gm20b/engines/maxwell/types.h | 6 +- .../skyline/soc/gm20b/engines/maxwell_3d.cpp | 1 + .../skyline/soc/gm20b/engines/maxwell_3d.h | 6 +- 5 files changed, 130 insertions(+), 10 deletions(-) diff --git a/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/pipeline_state.cpp b/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/pipeline_state.cpp index 181bdfbb..a648e3e9 100644 --- a/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/pipeline_state.cpp +++ b/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/pipeline_state.cpp @@ -542,6 +542,92 @@ namespace skyline::gpu::interconnect::maxwell3d { rasterizationState.get().provokingVertexMode = ConvertProvokingVertex(engine->provokingVertex.value); } + /* Depth Stencil State */ + void DepthStencilState::EngineRegisters::DirtyBind(DirtyManager &manager, dirty::Handle handle) const { + manager.Bind(handle, depthTestEnable, depthWriteEnable, depthFunc, depthBoundsTestEnable, stencilTestEnable, twoSidedStencilTestEnable, stencilOps, stencilBack); + } + + DepthStencilState::DepthStencilState(dirty::Handle dirtyHandle, DirtyManager &manager, const EngineRegisters &engine) : engine{manager, dirtyHandle, engine} {} + + static vk::CompareOp ConvertCompareFunc(engine::CompareFunc func) { + switch (func) { + case engine::CompareFunc::D3DNever: + case engine::CompareFunc::OglNever: + return vk::CompareOp::eNever; + case engine::CompareFunc::D3DLess: + case engine::CompareFunc::OglLess: + return vk::CompareOp::eLess; + case engine::CompareFunc::D3DEqual: + case engine::CompareFunc::OglEqual: + return vk::CompareOp::eEqual; + case engine::CompareFunc::D3DLessEqual: + case engine::CompareFunc::OglLEqual: + return vk::CompareOp::eLessOrEqual; + case engine::CompareFunc::D3DGreater: + case engine::CompareFunc::OglGreater: + return vk::CompareOp::eGreater; + case engine::CompareFunc::D3DNotEqual: + case engine::CompareFunc::OglNotEqual: + return vk::CompareOp::eNotEqual; + case engine::CompareFunc::D3DGreaterEqual: + case engine::CompareFunc::OglGEqual: + return vk::CompareOp::eGreaterOrEqual; + case engine::CompareFunc::D3DAlways: + case engine::CompareFunc::OglAlways: + return vk::CompareOp::eAlways; + } + } + + static vk::StencilOp ConvertStencilOp(engine::StencilOps::Op op) { + switch (op) { + case engine::StencilOps::Op::OglZero: + case engine::StencilOps::Op::D3DZero: + return vk::StencilOp::eZero; + case engine::StencilOps::Op::D3DKeep: + case engine::StencilOps::Op::OglKeep: + return vk::StencilOp::eKeep; + case engine::StencilOps::Op::D3DReplace: + case engine::StencilOps::Op::OglReplace: + return vk::StencilOp::eReplace; + case engine::StencilOps::Op::D3DIncrSat: + case engine::StencilOps::Op::OglIncrSat: + return vk::StencilOp::eIncrementAndClamp; + case engine::StencilOps::Op::D3DDecrSat: + case engine::StencilOps::Op::OglDecrSat: + return vk::StencilOp::eDecrementAndClamp; + case engine::StencilOps::Op::D3DInvert: + case engine::StencilOps::Op::OglInvert: + return vk::StencilOp::eInvert; + case engine::StencilOps::Op::D3DIncr: + case engine::StencilOps::Op::OglIncr: + return vk::StencilOp::eIncrementAndWrap; + case engine::StencilOps::Op::D3DDecr: + case engine::StencilOps::Op::OglDecr: + return vk::StencilOp::eDecrementAndWrap; + } + } + + static vk::StencilOpState ConvertStencilOpsState(engine::StencilOps ops) { + return { + .passOp = ConvertStencilOp(ops.zPass), + .depthFailOp = ConvertStencilOp(ops.zFail), + .failOp = ConvertStencilOp(ops.fail), + .compareOp = ConvertCompareFunc(ops.func), + }; + } + + void DepthStencilState::Flush() { + depthStencilState.depthTestEnable = engine->depthTestEnable; + depthStencilState.depthWriteEnable = engine->depthWriteEnable; + depthStencilState.depthCompareOp = ConvertCompareFunc(engine->depthFunc); + depthStencilState.depthBoundsTestEnable = engine->depthBoundsTestEnable; + depthStencilState.stencilTestEnable = engine->stencilTestEnable; + + auto stencilBack{engine->twoSidedStencilTestEnable ? engine->stencilBack : engine->stencilOps}; + depthStencilState.front = ConvertStencilOpsState(engine->stencilOps); + depthStencilState.back = ConvertStencilOpsState(stencilBack); + }; + /* Pipeline State */ void PipelineState::EngineRegisters::DirtyBind(DirtyManager &manager, dirty::Handle handle) const { auto bindFunc{[&](auto ®s) { regs.DirtyBind(manager, handle); }}; @@ -555,7 +641,8 @@ namespace skyline::gpu::interconnect::maxwell3d { : engine{manager, dirtyHandle, engine}, colorRenderTargets{util::MergeInto, engine::ColorTargetCount>(manager, engine.colorRenderTargetsRegisters)}, depthRenderTarget{manager, engine.depthRenderTargetRegisters}, - rasterization{manager, engine.rasterizationRegisters} {} + rasterization{manager, engine.rasterizationRegisters}, + depthStencil{manager, engine.depthStencilRegisters} {} void PipelineState::Flush(InterconnectContext &ctx, StateUpdateBuilder &builder) { auto updateFunc{[&](auto &stateElem, auto &&... args) { stateElem.Update(ctx, args...); }}; @@ -563,9 +650,14 @@ namespace skyline::gpu::interconnect::maxwell3d { updateFunc(depthRenderTarget); auto vertexState{directState.vertexInput.Build(ctx, engine->vertexInputRegisters)}; - auto inputAssemblyState{directState.inputAssembly.Build()}; - auto tessellationState{directState.tessellation.Build()}; + const auto &inputAssemblyState{directState.inputAssembly.Build()}; + const auto &tessellationState{directState.tessellation.Build()}; const auto &rasterizationState{rasterization.UpdateGet().rasterizationState}; + vk::PipelineMultisampleStateCreateInfo multisampleState{ + .rasterizationSamples = vk::SampleCountFlagBits::e1 + }; + const auto &depthStencilState{depthStencil.UpdateGet().depthStencilState}; + } diff --git a/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/pipeline_state.h b/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/pipeline_state.h index 06fc0ca7..aef92d00 100644 --- a/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/pipeline_state.h +++ b/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/pipeline_state.h @@ -170,6 +170,32 @@ namespace skyline::gpu::interconnect::maxwell3d { void Flush(); }; + class DepthStencilState : dirty::ManualDirty { + public: + struct EngineRegisters { + const u32 &depthTestEnable; + const u32 &depthWriteEnable; + const engine::CompareFunc &depthFunc; + const u32 &depthBoundsTestEnable; + const u32 &stencilTestEnable; + const u32 &twoSidedStencilTestEnable; + const engine::StencilOps &stencilOps; + const engine::StencilOps &stencilBack; + + void DirtyBind(DirtyManager &manager, dirty::Handle handle) const; + }; + + private: + dirty::BoundSubresource engine; + + public: + vk::PipelineDepthStencilStateCreateInfo depthStencilState; + + DepthStencilState(dirty::Handle dirtyHandle, DirtyManager &manager, const EngineRegisters &engine); + + void Flush(); + }; + /** * @brief Holds all GPU state for a pipeline, any changes to this will result in a pipeline cache lookup */ @@ -182,6 +208,7 @@ namespace skyline::gpu::interconnect::maxwell3d { InputAssemblyState::EngineRegisters inputAssemblyRegisters; TessellationState::EngineRegisters tessellationRegisters; RasterizationState::EngineRegisters rasterizationRegisters; + DepthStencilState::EngineRegisters depthStencilRegisters; void DirtyBind(DirtyManager &manager, dirty::Handle handle) const; }; @@ -192,6 +219,8 @@ namespace skyline::gpu::interconnect::maxwell3d { std::array, engine::ColorTargetCount> colorRenderTargets; dirty::ManualDirtyState depthRenderTarget; dirty::ManualDirtyState rasterization; + dirty::ManualDirtyState depthStencil; + public: DirectPipelineState directState; diff --git a/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell/types.h b/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell/types.h index 727e61ae..854784c8 100644 --- a/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell/types.h +++ b/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell/types.h @@ -549,8 +549,6 @@ namespace skyline::soc::gm20b::engine::maxwell3d::type { }; static_assert(sizeof(MultisampleControl) == sizeof(u32)); - - enum class CompareFunc : u32 { D3DNever = 1, D3DLess = 2, @@ -564,10 +562,10 @@ namespace skyline::soc::gm20b::engine::maxwell3d::type { OglNever = 0x200, OglLess = 0x201, OglEqual = 0x202, - OglLeEqual = 0x203, + OglLEqual = 0x203, OglGreater = 0x204, OglNotEqual = 0x205, - OglGequal = 0x206, + OglGEqual = 0x206, OglAlways = 0x207, }; diff --git a/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.cpp b/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.cpp index 98d8ac3c..5921480e 100644 --- a/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.cpp +++ b/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.cpp @@ -20,6 +20,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d { .inputAssemblyRegisters = {*registers.primitiveRestartEnable}, .tessellationRegisters = {*registers.patchSize, *registers.tessellationParameters}, .rasterizationRegisters = {*registers.rasterEnable, *registers.frontPolygonMode, *registers.backPolygonMode, *registers.oglCullEnable, *registers.oglCullFace, *registers.windowOrigin, *registers.oglFrontFace, *registers.viewportClipControl, *registers.polyOffset, *registers.provokingVertex}, + .depthStencilRegisters = {*registers.depthTestEnable, *registers.depthWriteEnable, *registers.depthFunc, *registers.depthBoundsTestEnable, *registers.stencilTestEnable, *registers.twoSidedStencilTestEnable, *registers.stencilOps, *registers.stencilBack}, }; } diff --git a/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.h b/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.h index 493d2f69..3967094f 100644 --- a/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.h +++ b/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.h @@ -193,7 +193,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d { Register<0x4B9, u32> independentBlendEnable; Register<0x4BA, u32> depthWriteEnable; Register<0x4BB, u32> alphaTestEnable; - Register<0x4C3, type::CompareFunc> depthTestFunc; + Register<0x4C3, type::CompareFunc> depthFunc; Register<0x4C4, float> alphaTestRef; Register<0x4C5, type::CompareFunc> alphaTestFunc; Register<0x4C6, u32> drawTFBStride; @@ -222,7 +222,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d { Register<0x4D8, std::array> rtBlendEnable; - Register<0x4E0, u32> stencilEnable; + Register<0x4E0, u32> stencilTestEnable; Register<0x4E1, type::StencilOps> stencilOps; Register<0x4E5, type::StencilValues> stencilValues; @@ -334,7 +334,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d { Register<0x652, type::PrimitiveTopologyControl> primitiveTopologyControl; Register<0x65C, type::PrimitiveTopology> primitiveTopology; - Register<0x66F, u32> depthBoundsEnable; + Register<0x66F, u32> depthBoundsTestEnable; struct ColorLogicOp { u32 enable;