Skip to content

Commit

Permalink
Implement MEM_SEMAPHORE as a global pipeline barrier
Browse files Browse the repository at this point in the history
  • Loading branch information
mikusp committed Dec 17, 2024
1 parent 8350927 commit 2c1aa0f
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 4 deletions.
38 changes: 38 additions & 0 deletions src/video_core/amdgpu/liverpool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,25 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span<const u32> dcb, std::span<c
case PM4ItOpcode::ContextControl: {
break;
}
case PM4ItOpcode::MemSemaphore: {
const auto* mem_semaphore = reinterpret_cast<const PM4CmdMemSemaphore*>(header);
const auto addr = mem_semaphore->Address<VAddr>();
const auto select = mem_semaphore->semSel;
const auto client = mem_semaphore->clientCode;
const auto signal_type = mem_semaphore->signalType;
LOG_WARNING(Lib_GnmDriver, "MemSemaphore ignored: addr {:#X}, select {}, client {}, signal {}, wait {}, mailbox {}",
addr,
select.Value() == PM4CmdMemSemaphore::MemSemaphoreSelect::SignalSemaphore ? "signal" : "wait",
client.Value() == PM4CmdMemSemaphore::MemSemaphoreClientCode::CP ? "CP" : std::to_string(std::to_underlying(client.Value())),
std::to_underlying(signal_type.Value()) == 1 ? "increment/decrement" : "set 1/do nothing",
mem_semaphore->waitOnSignal.Value(),
std::to_underlying(mem_semaphore->useMailbox.Value())
);
if (rasterizer) {
rasterizer->GlobalBarrier();
}
break;
}
case PM4ItOpcode::ClearState: {
regs.SetDefaults();
break;
Expand Down Expand Up @@ -845,6 +864,25 @@ Liverpool::Task Liverpool::ProcessCompute(std::span<const u32> acb, u32 vqid) {
release_mem->SignalFence(static_cast<Platform::InterruptId>(queue.pipe_id));
break;
}
case PM4ItOpcode::MemSemaphore: {
const auto* mem_semaphore = reinterpret_cast<const PM4CmdMemSemaphore*>(header);
const auto addr = mem_semaphore->Address<VAddr>();
const auto select = mem_semaphore->semSel;
const auto client = mem_semaphore->clientCode;
const auto signal_type = mem_semaphore->signalType;
LOG_WARNING(Lib_GnmDriver, "MemSemaphore ignored: addr {:#X}, select {}, client {}, signal {}, wait {}, mailbox {}",
addr,
select.Value() == PM4CmdMemSemaphore::MemSemaphoreSelect::SignalSemaphore ? "signal" : "wait",
client.Value() == PM4CmdMemSemaphore::MemSemaphoreClientCode::CP ? "CP" : std::to_string(std::to_underlying(client.Value())),
std::to_underlying(signal_type.Value()) == 1 ? "increment/decrement" : "set 1/do nothing",
mem_semaphore->waitOnSignal.Value(),
std::to_underlying(mem_semaphore->useMailbox.Value())
);
if (rasterizer) {
rasterizer->GlobalBarrier();
}
break;
}
default:
UNREACHABLE_MSG("Unknown PM4 type 3 opcode {:#x} with count {}",
static_cast<u32>(opcode), count);
Expand Down
8 changes: 4 additions & 4 deletions src/video_core/amdgpu/pm4_cmds.h
Original file line number Diff line number Diff line change
Expand Up @@ -876,15 +876,15 @@ struct PM4CmdMemSemaphore {
};
enum class MemSemaphoreSelect : u32 {
SignalSemaphore = 0b110u,
WaitSemaphore = 0b1111u
WaitSemaphore = 0b111u
};
enum class MemSemaphoreUseMailbox : u32 {
DoNotWaitForMailboxToBeWritten = 0u,
WaitForMailboxToBeWritten = 1u
};
enum class MemSemaphoreSignalType : u32 {
SignalIncrementOrWait = 0u,
SignalSetOne = 1u
SignalIncrementOrDecrement = 0u,
SignalSetOneOrDoNothing = 1u
};

PM4Type3Header header; ///< header
Expand All @@ -906,7 +906,7 @@ struct PM4CmdMemSemaphore {

template <typename T>
T Address() const {
return reinterpret_cast<T>(addr_lo | u64(addr_hi) << 32);
return reinterpret_cast<T>(u64(addr_lo) << 3 | (u64(addr_hi) << 32));
}
};

Expand Down
13 changes: 13 additions & 0 deletions src/video_core/renderer_vulkan/vk_rasterizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,19 @@ void Rasterizer::CpSync() {
vk::DependencyFlagBits::eByRegion, ib_barrier, {}, {});
}

void Rasterizer::GlobalBarrier() {
scheduler.EndRendering();
auto cmdbuf = scheduler.CommandBuffer();

const vk::MemoryBarrier mem_barrier{
.srcAccessMask = vk::AccessFlagBits::eMemoryWrite,
.dstAccessMask = vk::AccessFlagBits::eMemoryRead,
};
cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands,
vk::PipelineStageFlagBits::eAllCommands,
vk::DependencyFlagBits::eByRegion, {mem_barrier}, {}, {});
}

bool Rasterizer::FilterDraw() {
const auto& regs = liverpool->regs;
// There are several cases (e.g. FCE, FMask/HTile decompression) where we don't need to do an
Expand Down
1 change: 1 addition & 0 deletions src/video_core/renderer_vulkan/vk_rasterizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ class Rasterizer {
void UnmapMemory(VAddr addr, u64 size);

void CpSync();
void GlobalBarrier();
u64 Flush();
void Finish();

Expand Down

0 comments on commit 2c1aa0f

Please sign in to comment.