renderer_vulkan: Commize and adjust buffer bindings (#1412)

* shader_recompiler: Implement finite cmp class

* shader_recompiler: Implement more opcodes

* renderer_vulkan: Commonize buffer binding

* liverpool: More dma data impl

* fix

* copy_shader: Handle additional instructions from Knack

* translator: Add V_CMPX_GE_I32
This commit is contained in:
TheTurtle 2024-10-19 15:30:58 +03:00 committed by GitHub
parent 47ba6c6344
commit 87f8fea4de
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
23 changed files with 438 additions and 342 deletions

View file

@ -8,6 +8,7 @@
#include "common/thread.h"
#include "core/debug_state.h"
#include "core/libraries/videoout/driver.h"
#include "core/memory.h"
#include "video_core/amdgpu/liverpool.h"
#include "video_core/amdgpu/pm4_cmds.h"
#include "video_core/renderdoc.h"
@ -504,7 +505,12 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span<const u32> dcb, std::span<c
}
case PM4ItOpcode::EventWriteEos: {
const auto* event_eos = reinterpret_cast<const PM4CmdEventWriteEos*>(header);
event_eos->SignalFence();
event_eos->SignalFence([](void* address, u64 data, u32 num_bytes) {
auto* memory = Core::Memory::Instance();
if (!memory->TryWriteBacking(address, &data, num_bytes)) {
memcpy(address, &data, num_bytes);
}
});
if (event_eos->command == PM4CmdEventWriteEos::Command::GdsStore) {
ASSERT(event_eos->size == 1);
if (rasterizer) {
@ -517,13 +523,42 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span<const u32> dcb, std::span<c
}
case PM4ItOpcode::EventWriteEop: {
const auto* event_eop = reinterpret_cast<const PM4CmdEventWriteEop*>(header);
event_eop->SignalFence();
event_eop->SignalFence([](void* address, u64 data, u32 num_bytes) {
auto* memory = Core::Memory::Instance();
if (!memory->TryWriteBacking(address, &data, num_bytes)) {
memcpy(address, &data, num_bytes);
}
});
break;
}
case PM4ItOpcode::DmaData: {
const auto* dma_data = reinterpret_cast<const PM4DmaData*>(header);
if (dma_data->dst_addr_lo == 0x3022C) {
break;
}
if (dma_data->src_sel == DmaDataSrc::Data && dma_data->dst_sel == DmaDataDst::Gds) {
rasterizer->InlineDataToGds(dma_data->dst_addr_lo, dma_data->data);
rasterizer->InlineData(dma_data->dst_addr_lo, &dma_data->data, sizeof(u32),
true);
} else if (dma_data->src_sel == DmaDataSrc::Memory &&
dma_data->dst_sel == DmaDataDst::Gds) {
rasterizer->InlineData(dma_data->dst_addr_lo,
dma_data->SrcAddress<const void*>(),
dma_data->NumBytes(), true);
} else if (dma_data->src_sel == DmaDataSrc::Data &&
dma_data->dst_sel == DmaDataDst::Memory) {
rasterizer->InlineData(dma_data->DstAddress<VAddr>(), &dma_data->data,
sizeof(u32), false);
} else if (dma_data->src_sel == DmaDataSrc::Gds &&
dma_data->dst_sel == DmaDataDst::Memory) {
LOG_WARNING(Render_Vulkan, "GDS memory read");
} else if (dma_data->src_sel == DmaDataSrc::Memory &&
dma_data->dst_sel == DmaDataDst::Memory) {
rasterizer->InlineData(dma_data->DstAddress<VAddr>(),
dma_data->SrcAddress<const void*>(),
dma_data->NumBytes(), false);
} else {
UNREACHABLE_MSG("WriteData src_sel = {}, dst_sel = {}",
u32(dma_data->src_sel.Value()), u32(dma_data->dst_sel.Value()));
}
break;
}
@ -631,6 +666,35 @@ Liverpool::Task Liverpool::ProcessCompute(std::span<const u32> acb, int vqid) {
};
break;
}
case PM4ItOpcode::DmaData: {
const auto* dma_data = reinterpret_cast<const PM4DmaData*>(header);
if (dma_data->dst_addr_lo == 0x3022C) {
break;
}
if (dma_data->src_sel == DmaDataSrc::Data && dma_data->dst_sel == DmaDataDst::Gds) {
rasterizer->InlineData(dma_data->dst_addr_lo, &dma_data->data, sizeof(u32), true);
} else if (dma_data->src_sel == DmaDataSrc::Memory &&
dma_data->dst_sel == DmaDataDst::Gds) {
rasterizer->InlineData(dma_data->dst_addr_lo, dma_data->SrcAddress<const void*>(),
dma_data->NumBytes(), true);
} else if (dma_data->src_sel == DmaDataSrc::Data &&
dma_data->dst_sel == DmaDataDst::Memory) {
rasterizer->InlineData(dma_data->DstAddress<VAddr>(), &dma_data->data, sizeof(u32),
false);
} else if (dma_data->src_sel == DmaDataSrc::Gds &&
dma_data->dst_sel == DmaDataDst::Memory) {
LOG_WARNING(Render_Vulkan, "GDS memory read");
} else if (dma_data->src_sel == DmaDataSrc::Memory &&
dma_data->dst_sel == DmaDataDst::Memory) {
rasterizer->InlineData(dma_data->DstAddress<VAddr>(),
dma_data->SrcAddress<const void*>(), dma_data->NumBytes(),
false);
} else {
UNREACHABLE_MSG("WriteData src_sel = {}, dst_sel = {}",
u32(dma_data->src_sel.Value()), u32(dma_data->dst_sel.Value()));
}
break;
}
case PM4ItOpcode::AcquireMem: {
break;
}

View file

@ -313,25 +313,26 @@ struct PM4CmdEventWriteEop {
return data_lo | u64(data_hi) << 32;
}
void SignalFence() const {
void SignalFence(auto&& write_mem) const {
u32* address = Address<u32>();
switch (data_sel.Value()) {
case DataSelect::None: {
break;
}
case DataSelect::Data32Low: {
*Address<u32>() = DataDWord();
write_mem(address, DataDWord(), sizeof(u32));
break;
}
case DataSelect::Data64: {
*Address<u64>() = DataQWord();
write_mem(address, DataQWord(), sizeof(u64));
break;
}
case DataSelect::GpuClock64: {
*Address<u64>() = GetGpuClock64();
write_mem(address, GetGpuClock64(), sizeof(u64));
break;
}
case DataSelect::PerfCounter: {
*Address<u64>() = Common::FencedRDTSC();
write_mem(address, Common::FencedRDTSC(), sizeof(u64));
break;
}
default: {
@ -401,6 +402,20 @@ struct PM4DmaData {
u32 dst_addr_lo;
u32 dst_addr_hi;
u32 command;
template <typename T>
T SrcAddress() const {
return std::bit_cast<T>(src_addr_lo | u64(src_addr_hi) << 32);
}
template <typename T>
T DstAddress() const {
return std::bit_cast<T>(dst_addr_lo | u64(dst_addr_hi) << 32);
}
u32 NumBytes() const noexcept {
return command & 0x1fffff;
}
};
struct PM4CmdWaitRegMem {
@ -432,7 +447,7 @@ struct PM4CmdWaitRegMem {
template <typename T = u32*>
T Address() const {
return reinterpret_cast<T>((uintptr_t(poll_addr_hi) << 32) | poll_addr_lo);
return std::bit_cast<T>((uintptr_t(poll_addr_hi) << 32) | poll_addr_lo);
}
bool Test() const {
@ -534,11 +549,11 @@ struct PM4CmdEventWriteEos {
return this->data;
}
void SignalFence() const {
void SignalFence(auto&& write_mem) const {
const auto cmd = command.Value();
switch (cmd) {
case Command::SignalFence: {
*Address() = DataDWord();
write_mem(Address(), DataDWord(), sizeof(u32));
break;
}
case Command::GdsStore: {