mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-23 17:22:00 +01:00
Implement GPFIFO semaphore acquire operations
This commit is contained in:
parent
2ce146e28f
commit
270ef3e0d2
@ -41,49 +41,72 @@ namespace skyline::soc::gm20b::engine {
|
|||||||
channelCtx.asCtx->gmmu.Write(address + 8, GetGpuTimeTicks());
|
channelCtx.asCtx->gmmu.Write(address + 8, GetGpuTimeTicks());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action.operation == Registers::Semaphore::Operation::Release) {
|
switch (action.operation) {
|
||||||
channelCtx.asCtx->gmmu.Write(address, registers.semaphore->payload);
|
case Registers::Semaphore::Operation::Acquire:
|
||||||
Logger::Debug("SemaphoreRelease: address: 0x{:X} payload: {}", address, registers.semaphore->payload);
|
Logger::Debug("Acquire semaphore: 0x{:X} payload: {}", address, registers.semaphore->payload);
|
||||||
} else if (action.operation == Registers::Semaphore::Operation::Reduction) {
|
channelCtx.Unlock();
|
||||||
u32 origVal{channelCtx.asCtx->gmmu.Read<u32>(address)};
|
|
||||||
bool isSigned{action.format == Registers::Semaphore::Format::Signed};
|
|
||||||
|
|
||||||
// https://github.com/NVIDIA/open-gpu-doc/blob/b7d1bd16fe62135ebaec306b39dfdbd9e5657827/manuals/turing/tu104/dev_pbdma.ref.txt#L3549
|
while (channelCtx.asCtx->gmmu.Read<u32>(address) != registers.semaphore->payload)
|
||||||
u32 val{[](Registers::Semaphore::Reduction reduction, u32 origVal, u32 payload, bool isSigned) {
|
std::this_thread::yield();
|
||||||
switch (reduction) {
|
|
||||||
case Registers::Semaphore::Reduction::Min:
|
|
||||||
if (isSigned)
|
|
||||||
return static_cast<u32>(std::min(static_cast<i32>(origVal), static_cast<i32>(payload)));
|
|
||||||
else
|
|
||||||
return std::min(origVal, payload);
|
|
||||||
case Registers::Semaphore::Reduction::Max:
|
|
||||||
if (isSigned)
|
|
||||||
return static_cast<u32>(std::max(static_cast<i32>(origVal), static_cast<i32>(payload)));
|
|
||||||
else
|
|
||||||
return std::max(origVal, payload);
|
|
||||||
case Registers::Semaphore::Reduction::Xor:
|
|
||||||
return origVal ^ payload;
|
|
||||||
case Registers::Semaphore::Reduction::And:
|
|
||||||
return origVal & payload;
|
|
||||||
case Registers::Semaphore::Reduction::Or:
|
|
||||||
return origVal | payload;
|
|
||||||
case Registers::Semaphore::Reduction::Add:
|
|
||||||
if (isSigned)
|
|
||||||
return static_cast<u32>(static_cast<i32>(origVal) + static_cast<i32>(payload));
|
|
||||||
else
|
|
||||||
return origVal + payload;
|
|
||||||
case Registers::Semaphore::Reduction::Inc:
|
|
||||||
return (origVal >= payload) ? 0 : origVal + 1;
|
|
||||||
case Registers::Semaphore::Reduction::Dec:
|
|
||||||
return (origVal == 0 || origVal > payload) ? payload : origVal - 1;
|
|
||||||
}
|
|
||||||
}(registers.semaphore->action.reduction, origVal, registers.semaphore->payload, isSigned)};
|
|
||||||
Logger::Debug("SemaphoreReduction: address: 0x{:X} op: {} payload: {} original value: {} reduced value: {}",
|
|
||||||
address, static_cast<u8>(registers.semaphore->action.reduction), registers.semaphore->payload, origVal, val);
|
|
||||||
|
|
||||||
channelCtx.asCtx->gmmu.Write(address, val);
|
channelCtx.Lock();
|
||||||
} else {
|
break;
|
||||||
Logger::Warn("Unimplemented semaphore operation: 0x{:X}", static_cast<u8>(registers.semaphore->action.operation));
|
case Registers::Semaphore::Operation::Release:
|
||||||
|
channelCtx.asCtx->gmmu.Write(address, registers.semaphore->payload);
|
||||||
|
Logger::Debug("SemaphoreRelease: address: 0x{:X} payload: {}", address, registers.semaphore->payload);
|
||||||
|
break;
|
||||||
|
case Registers::Semaphore::Operation::AcqGeq :
|
||||||
|
Logger::Debug("Acquire semaphore: 0x{:X} payload: {}", address, registers.semaphore->payload);
|
||||||
|
channelCtx.Unlock();
|
||||||
|
|
||||||
|
while (channelCtx.asCtx->gmmu.Read<u32>(address) < registers.semaphore->payload)
|
||||||
|
std::this_thread::yield();
|
||||||
|
|
||||||
|
channelCtx.Lock();
|
||||||
|
break;
|
||||||
|
case Registers::Semaphore::Operation::Reduction: {
|
||||||
|
u32 origVal{channelCtx.asCtx->gmmu.Read<u32>(address)};
|
||||||
|
bool isSigned{action.format == Registers::Semaphore::Format::Signed};
|
||||||
|
|
||||||
|
// https://github.com/NVIDIA/open-gpu-doc/blob/b7d1bd16fe62135ebaec306b39dfdbd9e5657827/manuals/turing/tu104/dev_pbdma.ref.txt#L3549
|
||||||
|
u32 val{[](Registers::Semaphore::Reduction reduction, u32 origVal, u32 payload, bool isSigned) {
|
||||||
|
switch (reduction) {
|
||||||
|
case Registers::Semaphore::Reduction::Min:
|
||||||
|
if (isSigned)
|
||||||
|
return static_cast<u32>(std::min(static_cast<i32>(origVal), static_cast<i32>(payload)));
|
||||||
|
else
|
||||||
|
return std::min(origVal, payload);
|
||||||
|
case Registers::Semaphore::Reduction::Max:
|
||||||
|
if (isSigned)
|
||||||
|
return static_cast<u32>(std::max(static_cast<i32>(origVal), static_cast<i32>(payload)));
|
||||||
|
else
|
||||||
|
return std::max(origVal, payload);
|
||||||
|
case Registers::Semaphore::Reduction::Xor:
|
||||||
|
return origVal ^ payload;
|
||||||
|
case Registers::Semaphore::Reduction::And:
|
||||||
|
return origVal & payload;
|
||||||
|
case Registers::Semaphore::Reduction::Or:
|
||||||
|
return origVal | payload;
|
||||||
|
case Registers::Semaphore::Reduction::Add:
|
||||||
|
if (isSigned)
|
||||||
|
return static_cast<u32>(static_cast<i32>(origVal) + static_cast<i32>(payload));
|
||||||
|
else
|
||||||
|
return origVal + payload;
|
||||||
|
case Registers::Semaphore::Reduction::Inc:
|
||||||
|
return (origVal >= payload) ? 0 : origVal + 1;
|
||||||
|
case Registers::Semaphore::Reduction::Dec:
|
||||||
|
return (origVal == 0 || origVal > payload) ? payload : origVal - 1;
|
||||||
|
}
|
||||||
|
}(registers.semaphore->action.reduction, origVal, registers.semaphore->payload, isSigned)};
|
||||||
|
Logger::Debug("SemaphoreReduction: address: 0x{:X} op: {} payload: {} original value: {} reduced value: {}",
|
||||||
|
address, static_cast<u8>(registers.semaphore->action.reduction), registers.semaphore->payload, origVal, val);
|
||||||
|
|
||||||
|
channelCtx.asCtx->gmmu.Write(address, val);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
Logger::Warn("Unimplemented semaphore operation: 0x{:X}", static_cast<u8>(registers.semaphore->action.operation));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user