Skip to content

Commit a5a1253

Browse files
authored
liverpool: Implement PM4 MEM_SEMAPHORE. (shadps4-emu#2235)
1 parent 564dbc7 commit a5a1253

File tree

2 files changed

+85
-0
lines changed

2 files changed

+85
-0
lines changed

src/video_core/amdgpu/liverpool.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,18 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span<const u32> dcb, std::span<c
636636
}
637637
break;
638638
}
639+
case PM4ItOpcode::MemSemaphore: {
640+
const auto* mem_semaphore = reinterpret_cast<const PM4CmdMemSemaphore*>(header);
641+
if (mem_semaphore->IsSignaling()) {
642+
mem_semaphore->Signal();
643+
} else {
644+
while (!mem_semaphore->Signaled()) {
645+
YIELD_GFX();
646+
}
647+
mem_semaphore->Decrement();
648+
}
649+
break;
650+
}
639651
case PM4ItOpcode::AcquireMem: {
640652
// const auto* acquire_mem = reinterpret_cast<PM4CmdAcquireMem*>(header);
641653
break;
@@ -848,6 +860,18 @@ Liverpool::Task Liverpool::ProcessCompute(std::span<const u32> acb, u32 vqid) {
848860
}
849861
break;
850862
}
863+
case PM4ItOpcode::MemSemaphore: {
864+
const auto* mem_semaphore = reinterpret_cast<const PM4CmdMemSemaphore*>(header);
865+
if (mem_semaphore->IsSignaling()) {
866+
mem_semaphore->Signal();
867+
} else {
868+
while (!mem_semaphore->Signaled()) {
869+
YIELD_ASC(vqid);
870+
}
871+
mem_semaphore->Decrement();
872+
}
873+
break;
874+
}
851875
case PM4ItOpcode::WaitRegMem: {
852876
const auto* wait_reg_mem = reinterpret_cast<const PM4CmdWaitRegMem*>(header);
853877
ASSERT(wait_reg_mem->engine.Value() == PM4CmdWaitRegMem::Engine::Me);

src/video_core/amdgpu/pm4_cmds.h

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -884,4 +884,65 @@ struct PM4CmdDrawIndexIndirectMulti {
884884
u32 draw_initiator; ///< Draw Initiator Register
885885
};
886886

887+
struct PM4CmdMemSemaphore {
888+
enum class ClientCode : u32 {
889+
CommandProcessor = 0u,
890+
CommandBuffer = 1u,
891+
DataBuffer = 2u,
892+
};
893+
enum class Select : u32 {
894+
SignalSemaphore = 6u,
895+
WaitSemaphore = 7u,
896+
};
897+
enum class SignalType : u32 {
898+
Increment = 0u,
899+
Write = 1u,
900+
};
901+
902+
PM4Type3Header header; ///< header
903+
union {
904+
u32 dw1;
905+
BitField<3, 29, u32> addr_lo; ///< Semaphore address bits [31:3]
906+
};
907+
union {
908+
u32 dw2;
909+
BitField<0, 8, u32> addr_hi; ///< Semaphore address bits [39:32]
910+
BitField<16, 1, u32> use_mailbox; ///< Enables waiting until mailbox is written to
911+
BitField<20, 1, SignalType> signal_type; ///< Indicates the type of signal sent
912+
BitField<24, 2, ClientCode> client_code;
913+
BitField<29, 3, Select> sem_sel; ///< Indicates whether to do a signal or wait operation
914+
};
915+
916+
template <typename T>
917+
[[nodiscard]] T Address() const {
918+
return std::bit_cast<T>(u64(addr_lo) << 3 | (u64(addr_hi) << 32));
919+
}
920+
921+
[[nodiscard]] bool IsSignaling() const {
922+
return sem_sel == Select::SignalSemaphore;
923+
}
924+
925+
[[nodiscard]] bool Signaled() const {
926+
return *Address<u64*>() > 0;
927+
}
928+
929+
void Decrement() const {
930+
*Address<u64*>() -= 1;
931+
}
932+
933+
void Signal() const {
934+
auto* ptr = Address<u64*>();
935+
switch (signal_type) {
936+
case SignalType::Increment:
937+
*ptr += 1;
938+
break;
939+
case SignalType::Write:
940+
*ptr = 1;
941+
break;
942+
default:
943+
UNREACHABLE_MSG("Unknown signal type {}", static_cast<u32>(signal_type.Value()));
944+
}
945+
}
946+
};
947+
887948
} // namespace AmdGpu

0 commit comments

Comments
 (0)