From 6a6f51ea84c67172329b6c4eeccb750d7b44919f Mon Sep 17 00:00:00 2001 From: PixelyIon Date: Thu, 13 Jan 2022 02:27:43 +0530 Subject: [PATCH] Implement Maxwell3D Depth/Stencil State Implements the entirety of Maxwell3D Depth/Stencil state for both faces including compare/write masks and reference value. Maxwell3D register `stencilTwoSideEnable` is ignored as its behavior is unknown and could mean the same behavior for both stencils or the back facing stencil being disabled as a result of this it is unimplemented. --- .../gpu/interconnect/graphics_context.h | 145 ++++++++++++++++++ .../skyline/soc/gm20b/engines/maxwell_3d.cpp | 84 ++++++++++ .../skyline/soc/gm20b/engines/maxwell_3d.h | 23 ++- 3 files changed, 244 insertions(+), 8 deletions(-) diff --git a/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h b/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h index a1bd9780..5e253c8f 100644 --- a/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h +++ b/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h @@ -2052,6 +2052,151 @@ namespace skyline::gpu::interconnect { /* Depth */ vk::PipelineDepthStencilStateCreateInfo depthState{}; + void SetDepthTestEnabled(bool enabled) { + depthState.depthTestEnable = enabled; + } + + vk::CompareOp ConvertCompareOp(maxwell3d::CompareOp op) { + using MaxwellOp = maxwell3d::CompareOp; + using VkOp = vk::CompareOp; + switch (op) { + case MaxwellOp::Never: + case MaxwellOp::NeverGL: + return VkOp::eNever; + + case MaxwellOp::Less: + case MaxwellOp::LessGL: + return VkOp::eLess; + + case MaxwellOp::Equal: + case MaxwellOp::EqualGL: + return VkOp::eEqual; + + case MaxwellOp::LessOrEqual: + case MaxwellOp::LessOrEqualGL: + return VkOp::eLessOrEqual; + + case MaxwellOp::Greater: + case MaxwellOp::GreaterGL: + return VkOp::eGreater; + + case MaxwellOp::NotEqual: + case MaxwellOp::NotEqualGL: + return VkOp::eNotEqual; + + case MaxwellOp::GreaterOrEqual: + case MaxwellOp::GreaterOrEqualGL: + return VkOp::eGreaterOrEqual; + + case MaxwellOp::Always: + case MaxwellOp::AlwaysGL: + return VkOp::eAlways; + } + } + + void SetDepthTestFunction(maxwell3d::CompareOp function) { + depthState.depthCompareOp = ConvertCompareOp(function); + } + + void SetDepthWriteEnabled(bool enabled) { + depthState.depthWriteEnable = enabled; + } + + void SetDepthBoundsTestEnabled(bool enabled) { + depthState.depthBoundsTestEnable = enabled; + } + + void SetMinDepthBounds(float min) { + depthState.minDepthBounds = min; + } + + void SetMaxDepthBounds(float max) { + depthState.maxDepthBounds = max; + } + + void SetStencilTestEnabled(bool enabled) { + depthState.stencilTestEnable = enabled; + } + + vk::StencilOp ConvertStencilOp(maxwell3d::StencilOp op) { + using MaxwellOp = maxwell3d::StencilOp; + using VkOp = vk::StencilOp; + switch (op) { + case MaxwellOp::Keep: + return VkOp::eKeep; + case MaxwellOp::Zero: + return VkOp::eZero; + case MaxwellOp::Replace: + return VkOp::eReplace; + case MaxwellOp::IncrementAndClamp: + return VkOp::eIncrementAndClamp; + case MaxwellOp::DecrementAndClamp: + return VkOp::eDecrementAndClamp; + case MaxwellOp::Invert: + return VkOp::eInvert; + case MaxwellOp::IncrementAndWrap: + return VkOp::eIncrementAndWrap; + case MaxwellOp::DecrementAndWrap: + return VkOp::eDecrementAndWrap; + } + } + + void SetStencilFrontFailOp(maxwell3d::StencilOp op) { + depthState.front.failOp = ConvertStencilOp(op); + } + + void SetStencilBackFailOp(maxwell3d::StencilOp op) { + depthState.back.failOp = ConvertStencilOp(op); + } + + void SetStencilFrontPassOp(maxwell3d::StencilOp op) { + depthState.front.passOp = ConvertStencilOp(op); + } + + void SetStencilBackPassOp(maxwell3d::StencilOp op) { + depthState.back.passOp = ConvertStencilOp(op); + } + + void SetStencilFrontDepthFailOp(maxwell3d::StencilOp op) { + depthState.front.depthFailOp = ConvertStencilOp(op); + } + + void SetStencilBackDepthFailOp(maxwell3d::StencilOp op) { + depthState.back.depthFailOp = ConvertStencilOp(op); + } + + void SetStencilFrontCompareOp(maxwell3d::CompareOp op) { + depthState.front.compareOp = ConvertCompareOp(op); + } + + void SetStencilBackCompareOp(maxwell3d::CompareOp op) { + depthState.back.compareOp = ConvertCompareOp(op); + } + + void SetStencilFrontCompareMask(u32 mask) { + depthState.front.compareMask = mask; + } + + void SetStencilBackCompareMask(u32 mask) { + depthState.back.compareMask = mask; + } + + void SetStencilFrontWriteMask(u32 mask) { + depthState.front.writeMask = mask; + } + + void SetStencilBackWriteMask(u32 mask) { + depthState.back.writeMask = mask; + } + + void SetStencilFrontReference(u32 reference) { + depthState.front.reference = reference; + } + + void SetStencilBackReference(u32 reference) { + depthState.back.reference = reference; + } + /* Multisampling */ vk::PipelineMultisampleStateCreateInfo multisampleState{ .rasterizationSamples = vk::SampleCountFlagBits::e1, 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 8b1c69e7..dadba97e 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 @@ -234,6 +234,90 @@ namespace skyline::soc::gm20b::engine::maxwell3d { context.UpdateRenderTargetControl(renderTargetControl); }) + MAXWELL3D_CASE(depthTestEnable, { + context.SetDepthTestEnabled(depthTestEnable); + }) + + MAXWELL3D_CASE(depthTestFunc, { + context.SetDepthTestFunction(depthTestFunc); + }) + + MAXWELL3D_CASE(depthWriteEnable, { + context.SetDepthWriteEnabled(depthWriteEnable); + }) + + MAXWELL3D_CASE(depthBoundsEnable, { + context.SetDepthBoundsTestEnabled(depthBoundsEnable); + }) + + MAXWELL3D_CASE(depthBoundsNear, { + context.SetMinDepthBounds(depthBoundsNear); + }) + + MAXWELL3D_CASE(depthBoundsFar, { + context.SetMaxDepthBounds(depthBoundsFar); + }) + + MAXWELL3D_CASE(stencilEnable, { + context.SetStencilTestEnabled(stencilEnable); + }) + + MAXWELL3D_STRUCT_CASE(stencilFront, failOp, { + context.SetStencilFrontFailOp(failOp); + }) + + MAXWELL3D_STRUCT_CASE(stencilFront, zFailOp, { + context.SetStencilFrontDepthFailOp(zFailOp); + }) + + MAXWELL3D_STRUCT_CASE(stencilFront, passOp, { + context.SetStencilFrontPassOp(passOp); + }) + + MAXWELL3D_STRUCT_CASE(stencilFront, compareOp, { + context.SetStencilFrontCompareOp(compareOp); + }) + + MAXWELL3D_STRUCT_CASE(stencilFront, compareReference, { + context.SetStencilFrontReference(compareReference); + }) + + MAXWELL3D_STRUCT_CASE(stencilFront, compareMask, { + context.SetStencilFrontCompareMask(compareMask); + }) + + MAXWELL3D_STRUCT_CASE(stencilFront, writeMask, { + context.SetStencilFrontWriteMask(writeMask); + }) + + MAXWELL3D_STRUCT_CASE(stencilBack, failOp, { + context.SetStencilBackFailOp(failOp); + }) + + MAXWELL3D_STRUCT_CASE(stencilBack, zFailOp, { + context.SetStencilBackDepthFailOp(zFailOp); + }) + + MAXWELL3D_STRUCT_CASE(stencilBack, passOp, { + context.SetStencilBackPassOp(passOp); + }) + + MAXWELL3D_STRUCT_CASE(stencilBack, compareOp, { + context.SetStencilBackCompareOp(compareOp); + }) + + MAXWELL3D_STRUCT_CASE(stencilBackExtra, compareReference, { + context.SetStencilBackReference(compareReference); + }) + + MAXWELL3D_STRUCT_CASE(stencilBackExtra, compareMask, { + context.SetStencilBackCompareMask(compareMask); + }) + + MAXWELL3D_STRUCT_CASE(stencilBackExtra, writeMask, { + context.SetStencilBackWriteMask(writeMask); + }) + MAXWELL3D_CASE(independentBlendEnable, { context.SetIndependentBlendingEnabled(independentBlendEnable); }) 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 11f81e69..a37dce87 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 @@ -95,7 +95,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d { Register<0x370, DepthBiasEnable> depthBiasEnable; struct StencilBackExtra { - u32 compareRef; // 0x3D5 + u32 compareReference; // 0x3D5 u32 writeMask; // 0x3D6 u32 compareMask; // 0x3D7 }; @@ -109,6 +109,10 @@ namespace skyline::soc::gm20b::engine::maxwell3d { Register<0x3D9, TiledCacheSize> tiledCacheSize; Register<0x3E4, u32> commonColorWriteMask; //!< If enabled, the color write masks for all RTs must be set to that of the first RT + + Register<0x3E7, float> depthBoundsNear; + Register<0x3E8, float> depthBoundsFar; + Register<0x3EB, u32> rtSeparateFragData; Register<0x3F8, type::Address> depthTargetAddress; @@ -117,13 +121,16 @@ namespace skyline::soc::gm20b::engine::maxwell3d { Register<0x3FC, u32> depthTargetLayerStride; Register<0x458, std::array> vertexAttributeState; + Register<0x487, type::RenderTargetControl> renderTargetControl; Register<0x48A, u32> depthTargetWidth; Register<0x48B, u32> depthTargetHeight; Register<0x48C, type::RenderTargetArrayMode> depthTargetArrayMode; + Register<0x4B3, u32> depthTestEnable; Register<0x4B9, u32> independentBlendEnable; + Register<0x4BA, u32> depthWriteEnable; Register<0x4BB, u32> alphaTestEnable; Register<0x4C3, type::CompareOp> depthTestFunc; Register<0x4C4, float> alphaTestRef; @@ -158,13 +165,11 @@ namespace skyline::soc::gm20b::engine::maxwell3d { struct StencilFront { type::StencilOp failOp; // 0x4E1 type::StencilOp zFailOp; // 0x4E2 - type::StencilOp zPassOp; // 0x4E3 + type::StencilOp passOp; // 0x4E3 - struct { - type::CompareOp op; // 0x4E4 - i32 ref; // 0x4E5 - u32 mask; // 0x4E6 - } compare; + type::CompareOp compareOp; // 0x4E4 + u32 compareReference; // 0x4E5 + u32 compareMask; // 0x4E6 u32 writeMask; // 0x4E7 }; @@ -207,7 +212,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d { struct StencilBack { type::StencilOp failOp; // 0x566 type::StencilOp zFailOp; // 0x567 - type::StencilOp zPassOp; // 0x568 + type::StencilOp passOp; // 0x568 type::CompareOp compareOp; // 0x569 }; Register<0x566, StencilBack> stencilBack; @@ -239,6 +244,8 @@ namespace skyline::soc::gm20b::engine::maxwell3d { Register<0x64B, u32> viewportTransformEnable; Register<0x64F, type::ViewVolumeClipControl> viewVolumeClipControl; + Register<0x66F, u32> depthBoundsEnable; + struct ColorLogicOp { u32 enable; type::ColorLogicOp type;