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 947eb0a3..1c4342e7 100644 --- a/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h +++ b/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h @@ -26,6 +26,8 @@ namespace skyline::gpu::interconnect { public: GraphicsContext(GPU &gpu, soc::gm20b::ChannelContext &channelCtx, gpu::interconnect::CommandExecutor &executor) : gpu(gpu), channelCtx(channelCtx), executor(executor) { scissors.fill(DefaultScissor); + if (!gpu.quirks.supportsLastProvokingVertex) + rasterizerState.unlink(); } /* Render Targets + Render Target Control */ @@ -368,5 +370,110 @@ namespace skyline::gpu::interconnect { shader.offset = offset; shader.data = span{}; } + + /* Rasterizer State */ + private: + vk::StructureChain rasterizerState; + bool cullFaceEnabled{}; + vk::CullModeFlags cullMode{}; //!< The current cull mode regardless of it being enabled or disabled + vk::PipelineRasterizationProvokingVertexStateCreateInfoEXT provokingVertexState{}; + bool depthBiasPoint{}, depthBiasLine{}, depthBiasFill{}; + + public: + void SetDepthClampEnabled(bool enabled) { + rasterizerState.get().depthClampEnable = enabled; + } + + vk::PolygonMode ConvertPolygonMode(maxwell3d::PolygonMode mode) { + switch (mode) { + case maxwell3d::PolygonMode::Point: + return vk::PolygonMode::ePoint; + case maxwell3d::PolygonMode::Line: + return vk::PolygonMode::eLine; + case maxwell3d::PolygonMode::Fill: + return vk::PolygonMode::eFill; + } + } + + void SetPolygonModeFront(maxwell3d::PolygonMode mode) { + rasterizerState.get().polygonMode = ConvertPolygonMode(mode); + } + + void SetPolygonModeBack(maxwell3d::PolygonMode mode) { + auto frontPolygonMode{rasterizerState.get().polygonMode}; + auto backPolygonMode{ConvertPolygonMode(mode)}; + if (frontPolygonMode != backPolygonMode) + Logger::Warn("Cannot set back-facing polygon mode ({}) different from front-facing polygon mode ({}) due to Vulkan constraints", vk::to_string(backPolygonMode), vk::to_string(frontPolygonMode)); + } + + void SetCullFaceEnabled(bool enabled) { + cullFaceEnabled = enabled; + if (!enabled) + rasterizerState.get().cullMode = {}; + } + + void SetFrontFace(maxwell3d::FrontFace face) { + rasterizerState.get().frontFace = [face]() { + switch (face) { + case maxwell3d::FrontFace::Clockwise: + return vk::FrontFace::eClockwise; + case maxwell3d::FrontFace::CounterClockwise: + return vk::FrontFace::eCounterClockwise; + } + }(); + } + + void SetCullFace(maxwell3d::CullFace face) { + cullMode = [face]() -> vk::CullModeFlags { + switch (face) { + case maxwell3d::CullFace::Front: + return vk::CullModeFlagBits::eFront; + case maxwell3d::CullFace::Back: + return vk::CullModeFlagBits::eBack; + case maxwell3d::CullFace::FrontAndBack: + return vk::CullModeFlagBits::eFrontAndBack; + } + }(); + if (cullFaceEnabled) + rasterizerState.get().cullMode = cullMode; + } + + void SetProvokingVertex(bool isLast) { + if (isLast) { + if (!gpu.quirks.supportsLastProvokingVertex) + Logger::Warn("Cannot set provoking vertex to last without host GPU support"); + rasterizerState.get().provokingVertexMode = vk::ProvokingVertexModeEXT::eLastVertex; + } else { + rasterizerState.get().provokingVertexMode = vk::ProvokingVertexModeEXT::eFirstVertex; + } + } + + void SetLineWidth(float width) { + rasterizerState.get().lineWidth = width; + } + + void SetDepthBiasPointEnabled(bool enabled) { + depthBiasPoint = enabled; + } + + void SetDepthBiasLineEnabled(bool enabled) { + depthBiasLine = enabled; + } + + void SetDepthBiasFillEnabled(bool enabled) { + depthBiasFill = enabled; + } + + void SetDepthBiasConstantFactor(float factor) { + rasterizerState.get().depthBiasConstantFactor = factor; + } + + void SetDepthBiasClamp(float clamp) { + rasterizerState.get().depthBiasClamp = clamp; + } + + void SetDepthBiasSlopeFactor(float factor) { + rasterizerState.get().depthBiasSlopeFactor = factor; + } }; } 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 060c0dd5..f05119ff 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 @@ -412,6 +412,19 @@ namespace skyline::soc::gm20b::engine::maxwell3d::type { FrontAndBack = 0x408, }; + union ViewVolumeClipControl { + u32 raw; + struct { + bool forceDepthRangeZeroToOne : 1; + u8 _unk0_ : 2; + bool depthClampNear : 1; + bool depthClampFar : 1; + u8 _unk1_ : 7; + bool depthClampDisable : 1; + }; + }; + static_assert(sizeof(ViewVolumeClipControl) == sizeof(u32)); + union ColorWriteMask { u32 raw; 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 e6e51266..019cb595 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 @@ -208,6 +208,22 @@ namespace skyline::soc::gm20b::engine::maxwell3d { static_assert(4 < BOOST_PP_LIMIT_REPEAT); #undef COLOR_CLEAR_CALLBACKS + MAXWELL3D_STRUCT_CASE(polygonMode, front, { + context.SetPolygonModeFront(front); + }) + + MAXWELL3D_STRUCT_CASE(depthBiasEnable, point, { + context.SetDepthBiasPointEnabled(point); + }) + + MAXWELL3D_STRUCT_CASE(depthBiasEnable, line, { + context.SetDepthBiasLineEnabled(line); + }) + + MAXWELL3D_STRUCT_CASE(depthBiasEnable, fill, { + context.SetDepthBiasFillEnabled(fill); + }) + #define SCISSOR_CALLBACKS(z, index, data) \ MAXWELL3D_ARRAY_STRUCT_CASE(scissors, index, enable, { \ context.SetScissor(index, enable ? registers.scissors[index] : std::optional{}); \ @@ -226,6 +242,61 @@ namespace skyline::soc::gm20b::engine::maxwell3d { MAXWELL3D_CASE(renderTargetControl, { context.UpdateRenderTargetControl(renderTargetControl); }) + + MAXWELL3D_CASE(lineWidthSmooth, { + if (*registers.lineSmoothEnable) + context.SetLineWidth(lineWidthSmooth); + }) + + MAXWELL3D_CASE(lineWidthAliased, { + if (!*registers.lineSmoothEnable) + context.SetLineWidth(lineWidthAliased); + }) + + MAXWELL3D_CASE(depthBiasFactor, { + context.SetDepthBiasSlopeFactor(depthBiasFactor); + }) + + MAXWELL3D_CASE(lineSmoothEnable, { + context.SetLineWidth(lineSmoothEnable ? *registers.lineWidthSmooth : *registers.lineWidthAliased); + }) + + MAXWELL3D_CASE(depthBiasUnits, { + context.SetDepthBiasConstantFactor(depthBiasUnits / 2.0f); + }) + + MAXWELL3D_STRUCT_CASE(setProgramRegion, high, { + context.SetShaderBaseIovaHigh(high); + }) + + MAXWELL3D_STRUCT_CASE(setProgramRegion, low, { + context.SetShaderBaseIovaLow(low); + }) + + MAXWELL3D_CASE(provokingVertexIsLast, { + context.SetProvokingVertex(provokingVertexIsLast); + }) + + MAXWELL3D_CASE(depthBiasClamp, { + context.SetDepthBiasClamp(depthBiasClamp); + }) + + MAXWELL3D_CASE(cullFaceEnable, { + context.SetCullFaceEnabled(cullFaceEnable); + }) + + MAXWELL3D_CASE(frontFace, { + context.SetFrontFace(frontFace); + }) + + MAXWELL3D_CASE(cullFace, { + context.SetCullFace(cullFace); + }) + + MAXWELL3D_CASE(viewVolumeClipControl, { + context.SetDepthClampEnabled(!viewVolumeClipControl.depthClampDisable); + }) + #define SET_SHADER_ENABLE_CALLBACK(z, index, data) \ MAXWELL3D_ARRAY_STRUCT_CASE(setProgram, index, info, { \ context.SetShaderEnabled(info.stage, info.enable); \ 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 3872a23f..3ddee3e5 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 @@ -79,6 +79,13 @@ namespace skyline::soc::gm20b::engine::maxwell3d { Register<0x380, std::array> scissors; + struct DepthBiasEnable { + u32 point; // 0x370 + u32 line; // 0x371 + u32 fill; // 0x372 + }; + Register<0x370, DepthBiasEnable> depthBiasEnable; + struct StencilBackExtra { u32 compareRef; // 0x3D5 u32 writeMask; // 0x3D6 @@ -162,7 +169,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d { }; Register<0x557, SamplerPool> samplerPool; - Register<0x55B, u32> polygonOffsetFactor; + Register<0x55B, float> depthBiasFactor; Register<0x55C, u32> lineSmoothEnable; struct TexturePool { @@ -171,7 +178,6 @@ namespace skyline::soc::gm20b::engine::maxwell3d { }; Register<0x55D, TexturePool> texturePool; - Register<0x565, u32> stencilTwoSideEnable; struct StencilBack { @@ -182,16 +188,25 @@ namespace skyline::soc::gm20b::engine::maxwell3d { }; Register<0x566, StencilBack> stencilBack; + Register<0x56F, float> depthBiasUnits; + Register<0x581, type::PointCoordReplace> pointCoordReplace; + Register<0x582, type::Address> setProgramRegion; + + Register<0x5A1, u32> provokingVertexIsLast; Register<0x646, u32> cullFaceEnable; Register<0x647, type::FrontFace> frontFace; Register<0x648, type::CullFace> cullFace; + Register<0x649, u32> pixelCentreImage; Register<0x64B, u32> viewportTransformEnable; Register<0x674, type::ClearBuffers> clearBuffers; Register<0x680, std::array> colorMask; + Register<0x61F, float> depthBiasClamp; + Register<0x64F, type::ViewVolumeClipControl> viewVolumeClipControl; + struct Semaphore { type::Address address; // 0x6C0 u32 payload; // 0x6C2