Implement basic indirect draw macro HLE

This still requires usagetracker to avoid redundantly performing indirect draws when the memory isn't dirty, and to allow for using it with direct memory, but it's a start.
This commit is contained in:
Billy Laws 2023-02-04 22:59:42 +00:00
parent 2444f2e81d
commit 04f3fa4b7f
3 changed files with 31 additions and 10 deletions

View File

@ -499,4 +499,10 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
interconnect.Draw(topology, *registers.streamOutputEnable, true, indexBufferCount, indexBufferFirst, instanceCount, globalBaseVertexIndex, globalBaseInstanceIndex); interconnect.Draw(topology, *registers.streamOutputEnable, true, indexBufferCount, indexBufferFirst, instanceCount, globalBaseVertexIndex, globalBaseInstanceIndex);
} }
void Maxwell3D::DrawIndexedIndirect(u32 drawTopology, span<u8> indirectBuffer, u32 count, u32 stride) {
auto topology{static_cast<type::DrawTopology>(drawTopology)};
interconnect.DrawIndirect(topology, *registers.streamOutputEnable, true, indirectBuffer, count, stride);
}
} }

View File

@ -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 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 DrawIndexedInstanced(bool setRegs, u32 drawTopology, u32 indexBufferCount, u32 instanceCount, u32 globalBaseVertexIndex, u32 indexBufferFirst, u32 globalBaseInstanceIndex) override;
void DrawIndexedIndirect(u32 drawTopology, span<u8> indirectBuffer, u32 count, u32 stride) override;
}; };
} }

View File

@ -2,10 +2,22 @@
// Copyright © 2022 yuzu Emulator Project (https://yuzu-emu.org/) // Copyright © 2022 yuzu Emulator Project (https://yuzu-emu.org/)
// Copyright © 2022 Skyline Team and Contributors (https://github.com/skyline-emu/) // Copyright © 2022 Skyline Team and Contributors (https://github.com/skyline-emu/)
#include <soc/gm20b/engines/maxwell/types.h>
#include <soc/gm20b/engines/engine.h> #include <soc/gm20b/engines/engine.h>
#include "macro_state.h" #include "macro_state.h"
namespace skyline::soc::gm20b { 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 { namespace macro_hle {
bool DrawInstanced(size_t offset, span<MacroArgument> args, engine::MacroEngineBase *targetEngine) { bool DrawInstanced(size_t offset, span<MacroArgument> args, engine::MacroEngineBase *targetEngine) {
u32 instanceCount{targetEngine->ReadMethodFromMacro(0xD1B) & *args[2]}; u32 instanceCount{targetEngine->ReadMethodFromMacro(0xD1B) & *args[2]};
@ -21,16 +33,17 @@ namespace skyline::soc::gm20b {
return true; return true;
} }
void DrawInstancedIndexedWithConstantBuffer(size_t offset, span<u32> args, engine::MacroEngineBase *targetEngine) { bool DrawInstancedIndexedIndirectWithConstantBuffer(size_t offset, span<MacroArgument> args, engine::MacroEngineBase *targetEngine) {
// Writes globalBaseVertexIndex and globalBaseInstanceIndex to the bound constant buffer before performing a standard instanced indexed draw u32 topology{*args[0]};
u32 instanceCount{targetEngine->ReadMethodFromMacro(0xD1B) & args[2]}; if (TopologyRequiresConversion(static_cast<engine::maxwell3d::type::DrawTopology>(topology)) || !args[1].argumentPtr) {
targetEngine->CallMethodFromMacro(0x8e3, 0x640); // If the passed parameters aren't dirty or the indirect topology isn't supported fallback to a non indirect draw (may wait)
targetEngine->CallMethodFromMacro(0x8e4, args[4]); u32 instanceCount{targetEngine->ReadMethodFromMacro(0xD1B) & *args[2]};
targetEngine->CallMethodFromMacro(0x8e5, args[5]); targetEngine->DrawIndexedInstanced(false, topology, *args[1], instanceCount, *args[4], *args[3], *args[5]);
targetEngine->DrawIndexedInstanced(false, args[0], args[1], instanceCount, args[4], args[3], args[5]); } else {
targetEngine->CallMethodFromMacro(0x8e3, 0x640); targetEngine->DrawIndexedIndirect(topology, span(args[1].argumentPtr, 5).cast<u8>(), 1, 0);
targetEngine->CallMethodFromMacro(0x8e4, 0x0); }
targetEngine->CallMethodFromMacro(0x8e5, 0x0);
return true;
} }
struct HleFunctionInfo { struct HleFunctionInfo {