From c440575a56611ab20156bc5ed37a1ee36a1de10b Mon Sep 17 00:00:00 2001 From: Billy Laws Date: Tue, 21 Mar 2023 22:39:02 +0000 Subject: [PATCH] Add partial conditional rendering support Disabled for cases where the results come from queries rn, however still functional for cases like AC which don't use it with queries. --- .../gpu/interconnect/command_executor.cpp | 1 + .../skyline/soc/gm20b/engines/maxwell_3d.cpp | 59 ++++++++++++++++--- .../skyline/soc/gm20b/engines/maxwell_3d.h | 28 +++++++++ 3 files changed, 80 insertions(+), 8 deletions(-) diff --git a/app/src/main/cpp/skyline/gpu/interconnect/command_executor.cpp b/app/src/main/cpp/skyline/gpu/interconnect/command_executor.cpp index f20c7a08..6c4b5db5 100644 --- a/app/src/main/cpp/skyline/gpu/interconnect/command_executor.cpp +++ b/app/src/main/cpp/skyline/gpu/interconnect/command_executor.cpp @@ -616,6 +616,7 @@ namespace skyline::gpu::interconnect { slot->nodes.splice(slot->nodes.end(), slot->pendingPostRenderPassNodes); + { slot->WaitReady(); 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 6d645cba..be2af8d6 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 @@ -62,6 +62,47 @@ namespace skyline::soc::gm20b::engine::maxwell3d { beginMethodTopology : type::ConvertPrimitiveTopologyToDrawTopology(*registers.primitiveTopology); } + bool Maxwell3D::CheckRenderEnable() { + if (registers.renderEnableOverride->mode == Registers::RenderEnableOverride::Mode::AlwaysRender) + return true; + else if (registers.renderEnableOverride->mode == Registers::RenderEnableOverride::Mode::NeverRender) + return false; + + + + switch (registers.renderEnable->mode) { + case Registers::RenderEnable::Mode::True: + return true; + case Registers::RenderEnable::Mode::False: + return false; + case Registers::RenderEnable::Mode::Conditional: + // TODO: Use indirect draws to emulate conditional rendering with queries, for now just ignore such cases as they would decrease performance anyway by forcing a CPU sync + if (interconnect.QueryPresentAtAddress(u64{registers.renderEnable->offset})) + return true; + + return channelCtx.asCtx->gmmu.Read(registers.renderEnable->offset) != 0; + case Registers::RenderEnable::Mode::RenderIfEqual: + // TODO: See above + if (interconnect.QueryPresentAtAddress(u64{registers.renderEnable->offset}) || + interconnect.QueryPresentAtAddress(u64{registers.renderEnable->offset + 16})) + return true; + + return channelCtx.asCtx->gmmu.Read(registers.renderEnable->offset) == + channelCtx.asCtx->gmmu.Read(registers.renderEnable->offset + 16); + case Registers::RenderEnable::Mode::RenderIfNotEqual: + // TODO: See above + if (interconnect.QueryPresentAtAddress(u64{registers.renderEnable->offset}) || + interconnect.QueryPresentAtAddress(u64{registers.renderEnable->offset + 16})) + return true; + + return channelCtx.asCtx->gmmu.Read(registers.renderEnable->offset) != + channelCtx.asCtx->gmmu.Read(registers.renderEnable->offset + 16); + } + + return true; + } + + Maxwell3D::Maxwell3D(const DeviceState &state, ChannelContext &channelCtx, MacroState ¯oState) : MacroEngineBase{macroState}, syncpoints{state.soc->host1x.syncpoints}, @@ -76,7 +117,8 @@ namespace skyline::soc::gm20b::engine::maxwell3d { __attribute__((always_inline)) void Maxwell3D::FlushDeferredDraw() { if (batchEnableState.drawActive) { batchEnableState.drawActive = false; - interconnect.Draw(deferredDraw.drawTopology, *registers.streamOutputEnable, deferredDraw.indexed, deferredDraw.drawCount, deferredDraw.drawFirst, deferredDraw.instanceCount, deferredDraw.drawBaseVertex, deferredDraw.drawBaseInstance); + if (CheckRenderEnable()) + interconnect.Draw(deferredDraw.drawTopology, *registers.streamOutputEnable, deferredDraw.indexed, deferredDraw.drawCount, deferredDraw.drawFirst, deferredDraw.instanceCount, deferredDraw.drawBaseVertex, deferredDraw.drawBaseInstance); deferredDraw.instanceCount = 1; } } @@ -229,7 +271,8 @@ namespace skyline::soc::gm20b::engine::maxwell3d { }) ENGINE_CASE(clearSurface, { - interconnect.Clear(clearSurface); + if (CheckRenderEnable()) + interconnect.Clear(clearSurface); }) ENGINE_CASE(begin, { @@ -489,23 +532,23 @@ namespace skyline::soc::gm20b::engine::maxwell3d { auto topology{static_cast(drawTopology)}; registers.globalBaseInstanceIndex = globalBaseInstanceIndex; registers.vertexArrayStart = vertexArrayStart; - - interconnect.Draw(topology, *registers.streamOutputEnable, false, vertexArrayCount, vertexArrayStart, instanceCount, 0, globalBaseInstanceIndex); + if (CheckRenderEnable()) + interconnect.Draw(topology, *registers.streamOutputEnable, false, vertexArrayCount, vertexArrayStart, instanceCount, 0, globalBaseInstanceIndex); registers.globalBaseInstanceIndex = 0; } void Maxwell3D::DrawIndexedInstanced(u32 drawTopology, u32 indexBufferCount, u32 instanceCount, u32 globalBaseVertexIndex, u32 indexBufferFirst, u32 globalBaseInstanceIndex) { FlushEngineState(); - auto topology{static_cast(drawTopology)}; - interconnect.Draw(topology, *registers.streamOutputEnable, true, indexBufferCount, indexBufferFirst, instanceCount, globalBaseVertexIndex, globalBaseInstanceIndex); + if (CheckRenderEnable()) + interconnect.Draw(topology, *registers.streamOutputEnable, true, indexBufferCount, indexBufferFirst, instanceCount, globalBaseVertexIndex, globalBaseInstanceIndex); } void Maxwell3D::DrawIndexedIndirect(u32 drawTopology, span indirectBuffer, u32 count, u32 stride) { FlushEngineState(); - auto topology{static_cast(drawTopology)}; - interconnect.DrawIndirect(topology, *registers.streamOutputEnable, true, indirectBuffer, count, stride); + if (CheckRenderEnable()) + interconnect.DrawIndirect(topology, *registers.streamOutputEnable, true, indirectBuffer, count, stride); } } 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 e094d0ee..b66136cb 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 @@ -69,6 +69,8 @@ namespace skyline::soc::gm20b::engine::maxwell3d { } } deferredDraw{}; + bool CheckRenderEnable(); + type::DrawTopology ApplyTopologyOverride(type::DrawTopology beginMethodTopology); void FlushDeferredDraw(); @@ -268,6 +270,19 @@ namespace skyline::soc::gm20b::engine::maxwell3d { Register<0x54F, type::MultisampleControl> multisampleControl; + struct RenderEnable { + enum class Mode : u32 { + False = 0, + True = 1, + Conditional = 2, + RenderIfEqual = 3, + RenderIfNotEqual = 4, + }; + Address offset; + Mode mode; + }; + Register<0x554, RenderEnable> renderEnable; + Register<0x557, TexSamplerPool> texSamplerPool; Register<0x55B, float> slopeScaleDepthBias; @@ -375,6 +390,19 @@ namespace skyline::soc::gm20b::engine::maxwell3d { Register<0x64B, u32> viewportScaleOffsetEnable; Register<0x64F, type::ViewportClipControl> viewportClipControl; + struct RenderEnableOverride { + enum class Mode : u8 { + UseRenderEnable = 0, + AlwaysRender = 1, + NeverRender = 2, + }; + + Mode mode : 2; + u32 _pad_ : 30; + }; + Register<0x651, RenderEnableOverride> renderEnableOverride; + + Register<0x652, type::PrimitiveTopologyControl> primitiveTopologyControl; Register<0x65C, type::PrimitiveTopology> primitiveTopology;