mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-29 13:05:29 +03:00
Optimise GPFIFO command processing
GPFIFO code is very high throughput due to the sheer number of commands used for rendering. Adjust some types and switch to a if statement with hints to slightly increase processing speed.
This commit is contained in:
parent
2cdf6c1fe6
commit
bd7eee8e2b
@ -61,7 +61,7 @@ namespace skyline::soc::gm20b {
|
|||||||
* @brief Checks if a method is 'pure' i.e. does not touch macro or GPFIFO methods
|
* @brief Checks if a method is 'pure' i.e. does not touch macro or GPFIFO methods
|
||||||
*/
|
*/
|
||||||
bool Pure() const {
|
bool Pure() const {
|
||||||
u16 size{[&]() -> u16 {
|
u32 size{[&]() -> u32 {
|
||||||
switch (secOp) {
|
switch (secOp) {
|
||||||
case SecOp::NonIncMethod:
|
case SecOp::NonIncMethod:
|
||||||
case SecOp::ImmdDataMethod:
|
case SecOp::ImmdDataMethod:
|
||||||
@ -73,7 +73,7 @@ namespace skyline::soc::gm20b {
|
|||||||
}
|
}
|
||||||
}()};
|
}()};
|
||||||
|
|
||||||
u16 end{static_cast<u16>(methodAddress + size)};
|
u32 end{static_cast<u32>(methodAddress + size)};
|
||||||
return end < engine::EngineMethodsEnd && methodAddress >= engine::GPFIFO::RegisterCount;
|
return end < engine::EngineMethodsEnd && methodAddress >= engine::GPFIFO::RegisterCount;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -212,12 +212,13 @@ namespace skyline::soc::gm20b {
|
|||||||
|
|
||||||
// Process more methods if the entries are still not all used up after handling resuming
|
// Process more methods if the entries are still not all used up after handling resuming
|
||||||
for (; entry != pushBuffer.end(); entry++) {
|
for (; entry != pushBuffer.end(); entry++) {
|
||||||
if (entry >= pushBuffer.end())
|
if (entry >= pushBuffer.end()) [[unlikely]]
|
||||||
throw exception("GPFIFO buffer overflow!"); // This should never happen
|
throw exception("GPFIFO buffer overflow!"); // This should never happen
|
||||||
|
|
||||||
// An entry containing all zeroes is a NOP, skip over it
|
// Entries containing all zeroes is a NOP, skip over them
|
||||||
if (*entry == 0)
|
for (; *entry == 0; entry++)
|
||||||
continue;
|
if (entry == std::prev(pushBuffer.end()))
|
||||||
|
return;
|
||||||
|
|
||||||
PushBufferMethodHeader methodHeader{.raw = *entry};
|
PushBufferMethodHeader methodHeader{.raw = *entry};
|
||||||
|
|
||||||
@ -279,6 +280,7 @@ namespace skyline::soc::gm20b {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma unroll(2)
|
||||||
for (u32 i{}; i < methodHeader.methodCount; i++)
|
for (u32 i{}; i < methodHeader.methodCount; i++)
|
||||||
SendPure(methodHeader.methodAddress + methodOffset(i), *++entry, methodHeader.methodSubChannel);
|
SendPure(methodHeader.methodAddress + methodOffset(i), *++entry, methodHeader.methodSubChannel);
|
||||||
} else {
|
} else {
|
||||||
@ -299,23 +301,22 @@ namespace skyline::soc::gm20b {
|
|||||||
* @return If the this was the final method in the current GpEntry
|
* @return If the this was the final method in the current GpEntry
|
||||||
*/
|
*/
|
||||||
auto processMethod{[&] () -> bool {
|
auto processMethod{[&] () -> bool {
|
||||||
switch (methodHeader.secOp) {
|
if (methodHeader.secOp == PushBufferMethodHeader::SecOp::IncMethod) [[likely]] {
|
||||||
case PushBufferMethodHeader::SecOp::IncMethod:
|
return dispatchCalls.operator()<MethodResumeState::State::Inc>();
|
||||||
return dispatchCalls.operator()<MethodResumeState::State::Inc>();
|
} else if (methodHeader.secOp == PushBufferMethodHeader::SecOp::OneInc) [[likely]] {
|
||||||
case PushBufferMethodHeader::SecOp::NonIncMethod:
|
return dispatchCalls.operator()<MethodResumeState::State::OneInc>();
|
||||||
return dispatchCalls.operator()<MethodResumeState::State::NonInc>();
|
} else if (methodHeader.secOp == PushBufferMethodHeader::SecOp::ImmdDataMethod) {
|
||||||
case PushBufferMethodHeader::SecOp::OneInc:
|
if (methodHeader.Pure())
|
||||||
return dispatchCalls.operator()<MethodResumeState::State::OneInc>();
|
SendPure(methodHeader.methodAddress, methodHeader.immdData, methodHeader.methodSubChannel);
|
||||||
case PushBufferMethodHeader::SecOp::ImmdDataMethod:
|
else
|
||||||
if (methodHeader.Pure())
|
SendFull(methodHeader.methodAddress, methodHeader.immdData, methodHeader.methodSubChannel, true);
|
||||||
SendPure(methodHeader.methodAddress, methodHeader.immdData, methodHeader.methodSubChannel);
|
|
||||||
else
|
|
||||||
SendFull(methodHeader.methodAddress, methodHeader.immdData, methodHeader.methodSubChannel, true);
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
case PushBufferMethodHeader::SecOp::EndPbSegment:
|
} else if (methodHeader.secOp == PushBufferMethodHeader::SecOp::NonIncMethod) [[unlikely]] {
|
||||||
|
return dispatchCalls.operator()<MethodResumeState::State::NonInc>();
|
||||||
|
} else if (methodHeader.secOp == PushBufferMethodHeader::SecOp::EndPbSegment) [[unlikely]] {
|
||||||
return true;
|
return true;
|
||||||
default:
|
} else {
|
||||||
throw exception("Unsupported pushbuffer method SecOp: {}", static_cast<u8>(methodHeader.secOp));
|
throw exception("Unsupported pushbuffer method SecOp: {}", static_cast<u8>(methodHeader.secOp));
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
|
Loading…
Reference in New Issue
Block a user