From 2c1aa0fb56da061f8425a6892604290019985aaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Mon, 16 Dec 2024 16:22:23 +0000 Subject: [PATCH] Implement MEM_SEMAPHORE as a global pipeline barrier --- src/video_core/amdgpu/liverpool.cpp | 38 +++++++++++++++++++ src/video_core/amdgpu/pm4_cmds.h | 8 ++-- .../renderer_vulkan/vk_rasterizer.cpp | 13 +++++++ .../renderer_vulkan/vk_rasterizer.h | 1 + 4 files changed, 56 insertions(+), 4 deletions(-) diff --git a/src/video_core/amdgpu/liverpool.cpp b/src/video_core/amdgpu/liverpool.cpp index 5dd3edd6d..e63513f16 100644 --- a/src/video_core/amdgpu/liverpool.cpp +++ b/src/video_core/amdgpu/liverpool.cpp @@ -289,6 +289,25 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span dcb, std::span(header); + const auto addr = mem_semaphore->Address(); + 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; @@ -845,6 +864,25 @@ Liverpool::Task Liverpool::ProcessCompute(std::span acb, u32 vqid) { release_mem->SignalFence(static_cast(queue.pipe_id)); break; } + case PM4ItOpcode::MemSemaphore: { + const auto* mem_semaphore = reinterpret_cast(header); + const auto addr = mem_semaphore->Address(); + 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(opcode), count); diff --git a/src/video_core/amdgpu/pm4_cmds.h b/src/video_core/amdgpu/pm4_cmds.h index 02e0c1126..63b0c26c7 100644 --- a/src/video_core/amdgpu/pm4_cmds.h +++ b/src/video_core/amdgpu/pm4_cmds.h @@ -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 @@ -906,7 +906,7 @@ struct PM4CmdMemSemaphore { template T Address() const { - return reinterpret_cast(addr_lo | u64(addr_hi) << 32); + return reinterpret_cast(u64(addr_lo) << 3 | (u64(addr_hi) << 32)); } }; diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index bd8906f86..cbf1bf03f 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -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 diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index ec1b5e134..c02c3912a 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h @@ -60,6 +60,7 @@ public: void UnmapMemory(VAddr addr, u64 size); void CpSync(); + void GlobalBarrier(); u64 Flush(); void Finish();