diff --git a/app/src/main/cpp/skyline/soc/gm20b/gpfifo.cpp b/app/src/main/cpp/skyline/soc/gm20b/gpfifo.cpp index b8156b10..93fc87eb 100644 --- a/app/src/main/cpp/skyline/soc/gm20b/gpfifo.cpp +++ b/app/src/main/cpp/skyline/soc/gm20b/gpfifo.cpp @@ -6,8 +6,7 @@ #include #include #include -#include "engines/maxwell_3d.h" -#include "engines/fermi_2d.h" +#include "channel.h" namespace skyline::soc::gm20b { /** @@ -95,7 +94,7 @@ namespace skyline::soc::gm20b { } else { switch (subChannel) { case SubchannelId::ThreeD: - channelCtx.maxwell3D->HandleMacroCall(method - engine::EngineMethodsEnd, argument, lastCall); + channelCtx.maxwell3D.HandleMacroCall(method - engine::EngineMethodsEnd, argument, lastCall); break; case SubchannelId::TwoD: channelCtx.fermi2D.HandleMacroCall(method - engine::EngineMethodsEnd, argument, lastCall); @@ -108,9 +107,14 @@ namespace skyline::soc::gm20b { } void ChannelGpfifo::SendPure(u32 method, u32 argument, SubchannelId subChannel) { + if (subChannel == SubchannelId::ThreeD) [[likely]] { + channelCtx.maxwell3D.CallMethod(method, argument); + return; + } + switch (subChannel) { case SubchannelId::ThreeD: - channelCtx.maxwell3D->CallMethod(method, argument); + channelCtx.maxwell3D.CallMethod(method, argument); break; case SubchannelId::Compute: channelCtx.keplerCompute.CallMethod(method, argument); @@ -132,7 +136,7 @@ namespace skyline::soc::gm20b { void ChannelGpfifo::SendPureBatchNonInc(u32 method, span arguments, SubchannelId subChannel) { switch (subChannel) { case SubchannelId::ThreeD: - channelCtx.maxwell3D->CallMethodBatchNonInc(method, arguments); + channelCtx.maxwell3D.CallMethodBatchNonInc(method, arguments); break; case SubchannelId::Compute: channelCtx.keplerCompute.CallMethodBatchNonInc(method, arguments); @@ -237,62 +241,46 @@ namespace skyline::soc::gm20b { /** * @brief Handles execution of a specific method type as specified by the State template parameter - * @tparam ThreeDOnly Whether to skip subchannel method handling and send all method calls to the 3D engine */ - auto dispatchCalls{[&] () { + auto dispatchCalls{[&] () { /** * @brief Gets the offset to apply to the method address for a given dispatch loop index */ auto methodOffset{[] (u32 i) -> u32 { - switch (State) { - case MethodResumeState::State::Inc: - return i; - case MethodResumeState::State::OneInc: - return i ? 1 : 0; - case MethodResumeState::State::NonInc: - return 0; - } + if constexpr(State == MethodResumeState::State::Inc) + return i; + else if constexpr (State == MethodResumeState::State::OneInc) + return i ? 1 : 0; + else + return 0; }}; constexpr u32 BatchCutoff{4}; //!< Cutoff needed to send method calls in a batch which is espcially important for UBO updates. This helps to avoid the extra overhead batching for small packets. // TODO: Only batch for specific target methods like UBO updates, since normal dispatch is generally cheaper - if (remainingEntries >= methodHeader.methodCount) { + if (remainingEntries >= methodHeader.methodCount) { [[likely]] if (methodHeader.Pure()) [[likely]] { if constexpr (State == MethodResumeState::State::NonInc) { // For pure noninc methods we can send all method calls as a span in one go - if (methodHeader.methodCount > BatchCutoff) { - if constexpr (ThreeDOnly) - channelCtx.maxwell3D->CallMethodBatchNonInc(methodHeader.methodAddress, span(&(*++entry), methodHeader.methodCount)); - else - SendPureBatchNonInc(methodHeader.methodAddress, span(&(*++entry), methodHeader.methodCount), methodHeader.methodSubChannel); + if (methodHeader.methodCount > BatchCutoff) [[unlikely]] { + SendPureBatchNonInc(methodHeader.methodAddress, span(&(*++entry), methodHeader.methodCount), methodHeader.methodSubChannel); entry += methodHeader.methodCount - 1; return false; } } else if constexpr (State == MethodResumeState::State::OneInc) { // For pure oneinc methods we can send the initial method then send the rest as a span in one go - if (methodHeader.methodCount > (BatchCutoff + 1)) { - if constexpr (ThreeDOnly) { - channelCtx.maxwell3D->CallMethod(methodHeader.methodAddress, *++entry); - channelCtx.maxwell3D->CallMethodBatchNonInc(methodHeader.methodAddress + 1, span(&(*++entry), methodHeader.methodCount - 1)); - } else { - SendPure(methodHeader.methodAddress, *++entry, methodHeader.methodSubChannel); - SendPureBatchNonInc(methodHeader.methodAddress + 1, span(&(*++entry) ,methodHeader.methodCount - 1), methodHeader.methodSubChannel); - } + if (methodHeader.methodCount > (BatchCutoff + 1)) [[unlikely]] { + SendPure(methodHeader.methodAddress, *++entry, methodHeader.methodSubChannel); + SendPureBatchNonInc(methodHeader.methodAddress + 1, span(&(*++entry) ,methodHeader.methodCount - 1), methodHeader.methodSubChannel); entry += methodHeader.methodCount - 2; return false; } } - for (u32 i{}; i < methodHeader.methodCount; i++) { - if constexpr (ThreeDOnly) { - channelCtx.maxwell3D->CallMethod(methodHeader.methodAddress + methodOffset(i), *++entry); - } else { - SendPure(methodHeader.methodAddress + methodOffset(i), *++entry, methodHeader.methodSubChannel); - } - } + for (u32 i{}; i < methodHeader.methodCount; i++) + SendPure(methodHeader.methodAddress + methodOffset(i), *++entry, methodHeader.methodSubChannel); } else { // Slow path for methods that touch GPFIFO or macros for (u32 i{}; i < methodHeader.methodCount; i++) @@ -308,26 +296,22 @@ namespace skyline::soc::gm20b { /** * @brief Handles execution of a single method - * @tparam ThreeDOnly Whether to skip subchannel method handling and send all method calls to the 3D engine * @return If the this was the final method in the current GpEntry */ - auto processMethod{[&] () -> bool { + auto processMethod{[&] () -> bool { switch (methodHeader.secOp) { case PushBufferMethodHeader::SecOp::IncMethod: - return dispatchCalls.operator()(); + return dispatchCalls.operator()(); case PushBufferMethodHeader::SecOp::NonIncMethod: - return dispatchCalls.operator()(); + return dispatchCalls.operator()(); case PushBufferMethodHeader::SecOp::OneInc: - return dispatchCalls.operator()(); + return dispatchCalls.operator()(); case PushBufferMethodHeader::SecOp::ImmdDataMethod: - if (methodHeader.Pure()) { - if constexpr (ThreeDOnly) - channelCtx.maxwell3D->CallMethod(methodHeader.methodAddress, methodHeader.immdData); - else - SendPure(methodHeader.methodAddress, methodHeader.immdData, methodHeader.methodSubChannel); - } else { + if (methodHeader.Pure()) + SendPure(methodHeader.methodAddress, methodHeader.immdData, methodHeader.methodSubChannel); + else SendFull(methodHeader.methodAddress, methodHeader.immdData, methodHeader.methodSubChannel, true); - } + return false; case PushBufferMethodHeader::SecOp::EndPbSegment: return true; @@ -337,12 +321,9 @@ namespace skyline::soc::gm20b { }}; bool hitEnd{[&]() { - if (methodHeader.methodSubChannel == SubchannelId::ThreeD) { [[likely]] - return processMethod.operator()(); - } else { - channelCtx.maxwell3D->FlushEngineState(); // Flush the 3D engine state when doing any calls to other engines - return processMethod.operator()(); - } + if (methodHeader.methodSubChannel != SubchannelId::ThreeD) [[unlikely]] + channelCtx.maxwell3D.FlushEngineState(); // Flush the 3D engine state when doing any calls to other engines + return processMethod(); }()}; if (hitEnd)