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 fb492b0c..fdc3eb9f 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 @@ -499,4 +499,10 @@ namespace skyline::soc::gm20b::engine::maxwell3d { interconnect.Draw(topology, *registers.streamOutputEnable, true, indexBufferCount, indexBufferFirst, instanceCount, globalBaseVertexIndex, globalBaseInstanceIndex); } + + void Maxwell3D::DrawIndexedIndirect(u32 drawTopology, span indirectBuffer, u32 count, u32 stride) { + auto topology{static_cast(drawTopology)}; + 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 0814c2fe..655eb254 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 @@ -456,5 +456,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d { void DrawInstanced(bool setRegs, u32 drawTopology, u32 vertexArrayCount, u32 instanceCount, u32 vertexArrayStart, u32 globalBaseInstanceIndex) override; void DrawIndexedInstanced(bool setRegs, u32 drawTopology, u32 indexBufferCount, u32 instanceCount, u32 globalBaseVertexIndex, u32 indexBufferFirst, u32 globalBaseInstanceIndex) override; + + void DrawIndexedIndirect(u32 drawTopology, span indirectBuffer, u32 count, u32 stride) override; }; } diff --git a/app/src/main/cpp/skyline/soc/gm20b/macro/macro_state.cpp b/app/src/main/cpp/skyline/soc/gm20b/macro/macro_state.cpp index dafaa4e6..caea1775 100644 --- a/app/src/main/cpp/skyline/soc/gm20b/macro/macro_state.cpp +++ b/app/src/main/cpp/skyline/soc/gm20b/macro/macro_state.cpp @@ -2,10 +2,22 @@ // Copyright © 2022 yuzu Emulator Project (https://yuzu-emu.org/) // Copyright © 2022 Skyline Team and Contributors (https://github.com/skyline-emu/) +#include #include #include "macro_state.h" namespace skyline::soc::gm20b { + static bool TopologyRequiresConversion(engine::maxwell3d::type::DrawTopology topology) { + switch (topology) { + case engine::maxwell3d::type::DrawTopology::Quads: + case engine::maxwell3d::type::DrawTopology::QuadStrip: + case engine::maxwell3d::type::DrawTopology::Polygon: + return true; + default: + return false; + } + } + namespace macro_hle { bool DrawInstanced(size_t offset, span args, engine::MacroEngineBase *targetEngine) { u32 instanceCount{targetEngine->ReadMethodFromMacro(0xD1B) & *args[2]}; @@ -21,16 +33,17 @@ namespace skyline::soc::gm20b { return true; } - void DrawInstancedIndexedWithConstantBuffer(size_t offset, span args, engine::MacroEngineBase *targetEngine) { - // Writes globalBaseVertexIndex and globalBaseInstanceIndex to the bound constant buffer before performing a standard instanced indexed draw - u32 instanceCount{targetEngine->ReadMethodFromMacro(0xD1B) & args[2]}; - targetEngine->CallMethodFromMacro(0x8e3, 0x640); - targetEngine->CallMethodFromMacro(0x8e4, args[4]); - targetEngine->CallMethodFromMacro(0x8e5, args[5]); - targetEngine->DrawIndexedInstanced(false, args[0], args[1], instanceCount, args[4], args[3], args[5]); - targetEngine->CallMethodFromMacro(0x8e3, 0x640); - targetEngine->CallMethodFromMacro(0x8e4, 0x0); - targetEngine->CallMethodFromMacro(0x8e5, 0x0); + bool DrawInstancedIndexedIndirectWithConstantBuffer(size_t offset, span args, engine::MacroEngineBase *targetEngine) { + u32 topology{*args[0]}; + if (TopologyRequiresConversion(static_cast(topology)) || !args[1].argumentPtr) { + // If the passed parameters aren't dirty or the indirect topology isn't supported fallback to a non indirect draw (may wait) + u32 instanceCount{targetEngine->ReadMethodFromMacro(0xD1B) & *args[2]}; + targetEngine->DrawIndexedInstanced(false, topology, *args[1], instanceCount, *args[4], *args[3], *args[5]); + } else { + targetEngine->DrawIndexedIndirect(topology, span(args[1].argumentPtr, 5).cast(), 1, 0); + } + + return true; } struct HleFunctionInfo {