mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-21 11:26:56 +02:00
fix (agc): implement DCB context state operations
Co-authored-by: DeathWhispers <56944463+Death-Whispers-U@users.noreply.github.com>
This commit is contained in:
@@ -15,6 +15,13 @@ bool TestWaitRegMemValue(uint64_t value, uint64_t ref, uint64_t mask, uint32_t f
|
||||
|
||||
enum class Pm4ProcessResult { Complete, Blocked };
|
||||
|
||||
enum class ContextStateOperation : uint32_t {
|
||||
Clear = 0,
|
||||
Push = 1,
|
||||
Pop = 2,
|
||||
PushClear = 3,
|
||||
};
|
||||
|
||||
class Pm4Execution {
|
||||
public:
|
||||
[[nodiscard]] bool MadeProgress() const noexcept { return m_made_progress; }
|
||||
@@ -49,6 +56,7 @@ public:
|
||||
KYTY_CLASS_NO_COPY(CommandProcessor);
|
||||
|
||||
void Reset();
|
||||
void ApplyContextStateOperation(ContextStateOperation operation);
|
||||
|
||||
void BufferInit();
|
||||
void BufferFlush();
|
||||
@@ -149,6 +157,8 @@ private:
|
||||
|
||||
RenderContext& m_renderer;
|
||||
HW::Context m_ctx;
|
||||
HW::Context m_saved_ctx;
|
||||
bool m_context_state_pushed = false;
|
||||
HW::UserConfig m_ucfg;
|
||||
HW::Shader m_sh_ctx;
|
||||
HW::UserSgprType m_user_data_marker = HW::UserSgprType::Unknown;
|
||||
|
||||
@@ -254,6 +254,7 @@ constexpr auto MakeCustomOpcodeDispatchTable() {
|
||||
g_cp_op_custom_func[Pm4::R_WAIT_MEM_64] = CpOpWaitRegMem64;
|
||||
g_cp_op_custom_func[Pm4::R_FLIP] = CpOpFlip;
|
||||
g_cp_op_custom_func[Pm4::R_RELEASE_MEM] = CpOpReleaseMem;
|
||||
g_cp_op_custom_func[Pm4::R_CONTEXT_STATE] = CpOpContextState;
|
||||
|
||||
return g_cp_op_custom_func;
|
||||
}
|
||||
|
||||
@@ -121,6 +121,7 @@ uint32_t HwUcSetGeIndexOffset(CommandProcessor&, uint32_t, uint32_t, const uint3
|
||||
uint32_t HwUcSetGdsOaRegisters(CommandProcessor&, uint32_t, uint32_t, const uint32_t*, uint32_t);
|
||||
|
||||
uint32_t CpOpNop(CommandProcessor&, uint32_t, const uint32_t*, uint32_t, uint32_t);
|
||||
uint32_t CpOpContextState(CommandProcessor&, uint32_t, const uint32_t*, uint32_t, uint32_t);
|
||||
uint32_t CpOpSetBase(CommandProcessor&, uint32_t, const uint32_t*, uint32_t, uint32_t);
|
||||
uint32_t CpOpClearState(CommandProcessor&, uint32_t, const uint32_t*, uint32_t, uint32_t);
|
||||
uint32_t CpOpIndexBase(CommandProcessor&, uint32_t, const uint32_t*, uint32_t, uint32_t);
|
||||
|
||||
@@ -2107,6 +2107,19 @@ KYTY_CP_OP_PARSER(CpOpClearState) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
KYTY_CP_OP_PARSER(CpOpContextState) {
|
||||
KYTY_PROFILER_FUNCTION();
|
||||
|
||||
const auto packet_size_dw = KYTY_PM4_LEN(cmd_id);
|
||||
EXIT_NOT_IMPLEMENTED(KYTY_PM4_R(cmd_id) != Pm4::R_CONTEXT_STATE);
|
||||
EXIT_NOT_IMPLEMENTED(packet_size_dw != 3u && packet_size_dw != 5u);
|
||||
EXIT_NOT_IMPLEMENTED(buffer[0] > static_cast<uint32_t>(ContextStateOperation::PushClear));
|
||||
|
||||
cp.ApplyContextStateOperation(static_cast<ContextStateOperation>(buffer[0]));
|
||||
|
||||
return packet_size_dw - 1u;
|
||||
}
|
||||
|
||||
KYTY_CP_OP_PARSER(CpOpDumpConstRam) {
|
||||
KYTY_PROFILER_FUNCTION();
|
||||
|
||||
|
||||
@@ -312,6 +312,8 @@ void CommandProcessor::Reset() {
|
||||
m_sh_ctx.Reset();
|
||||
m_ucfg.Reset();
|
||||
m_ctx.Reset();
|
||||
m_saved_ctx.Reset();
|
||||
m_context_state_pushed = false;
|
||||
m_index_type_and_size = 0;
|
||||
m_index_buffer_size = 0;
|
||||
m_user_data_marker = HW::UserSgprType::Unknown;
|
||||
@@ -321,6 +323,30 @@ void CommandProcessor::Reset() {
|
||||
std::memset(m_const_ram, 0, sizeof(m_const_ram));
|
||||
}
|
||||
|
||||
void CommandProcessor::ApplyContextStateOperation(ContextStateOperation operation) {
|
||||
switch (operation) {
|
||||
case ContextStateOperation::Clear: m_ctx.Reset(); break;
|
||||
case ContextStateOperation::Push:
|
||||
EXIT_IF(m_context_state_pushed);
|
||||
m_saved_ctx = m_ctx;
|
||||
m_context_state_pushed = true;
|
||||
break;
|
||||
case ContextStateOperation::Pop:
|
||||
EXIT_IF(!m_context_state_pushed);
|
||||
m_ctx = m_saved_ctx;
|
||||
m_saved_ctx = {};
|
||||
m_context_state_pushed = false;
|
||||
break;
|
||||
case ContextStateOperation::PushClear:
|
||||
EXIT_IF(m_context_state_pushed);
|
||||
m_saved_ctx = m_ctx;
|
||||
m_context_state_pushed = true;
|
||||
m_ctx.Reset();
|
||||
break;
|
||||
default: EXIT("unknown context state operation: %u\n", static_cast<uint32_t>(operation));
|
||||
}
|
||||
}
|
||||
|
||||
void CommandProcessor::BufferInit() {
|
||||
GetScheduler().Begin(m_ctx, m_ucfg, m_sh_ctx);
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ constexpr auto MakeRegisterNames() {
|
||||
names[R_FLIP] = "R_FLIP";
|
||||
names[R_RELEASE_MEM] = "R_RELEASE_MEM";
|
||||
names[R_DMA_DATA] = "R_DMA_DATA";
|
||||
names[R_CONTEXT_STATE] = "R_CONTEXT_STATE";
|
||||
return names;
|
||||
}
|
||||
|
||||
|
||||
@@ -87,6 +87,7 @@ constexpr uint32_t R_WAIT_MEM_64 = 0x16;
|
||||
constexpr uint32_t R_FLIP = 0x17;
|
||||
constexpr uint32_t R_RELEASE_MEM = 0x18;
|
||||
constexpr uint32_t R_DMA_DATA = 0x19;
|
||||
constexpr uint32_t R_CONTEXT_STATE = 0x1A;
|
||||
|
||||
constexpr uint32_t R_NUM = 0x3F + 1;
|
||||
|
||||
|
||||
+57
-13
@@ -6,6 +6,7 @@
|
||||
#include "common/logging/log.h"
|
||||
#include "common/stringUtils.h"
|
||||
#include "common/virtualMemory.h"
|
||||
#include "graphics/guest_gpu/command_processor/commandProcessor.h"
|
||||
#include "graphics/guest_gpu/gpu_defs.h"
|
||||
#include "graphics/guest_gpu/graphicsRun.h"
|
||||
#include "graphics/guest_gpu/hardwareContext.h"
|
||||
@@ -1444,29 +1445,72 @@ int KYTY_SYSV_ABI GraphicsSuspendPoint() {
|
||||
return OK;
|
||||
}
|
||||
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsUnknownQj7QZpgr9Uw(CommandBuffer* buf, uint32_t mode,
|
||||
uint32_t value) {
|
||||
PRINT_NAME();
|
||||
// ResetContextState?
|
||||
LOGF("\t mode = 0x%08" PRIx32 "\n"
|
||||
"\t value = 0x%08" PRIx32 "\n",
|
||||
mode, value);
|
||||
[[nodiscard]] static constexpr uint32_t context_state_op_size_dw(uint32_t operation) {
|
||||
switch (static_cast<ContextStateOperation>(operation)) {
|
||||
case ContextStateOperation::Clear: return 5;
|
||||
case ContextStateOperation::Push:
|
||||
case ContextStateOperation::Pop: return 27;
|
||||
case ContextStateOperation::PushClear: return 32;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (buf == nullptr) {
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsDcbContextStateOp(CommandBuffer* buf, uint32_t operation) {
|
||||
PRINT_NAME();
|
||||
LOGF("\t operation = 0x%08" PRIx32 "\n", operation);
|
||||
|
||||
const auto size_dw = context_state_op_size_dw(operation);
|
||||
if (buf == nullptr || size_dw == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
buf->DbgDump();
|
||||
|
||||
auto* cmd = buf->AllocateDW(1);
|
||||
uint32_t* first = nullptr;
|
||||
const auto append = [&](uint32_t segment_size_dw) {
|
||||
auto* segment = buf->AllocateDW(segment_size_dw);
|
||||
if (segment == nullptr) {
|
||||
return false;
|
||||
}
|
||||
std::fill_n(segment, segment_size_dw, 0u);
|
||||
if (first == nullptr) {
|
||||
first = segment;
|
||||
segment[0] = KYTY_PM4(segment_size_dw, Pm4::IT_NOP, Pm4::R_CONTEXT_STATE);
|
||||
segment[1] = operation;
|
||||
} else {
|
||||
segment[0] = KYTY_PM4(segment_size_dw, Pm4::IT_NOP, Pm4::R_ZERO);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
const auto append_save_restore = [&] {
|
||||
// The native helper reserves 22 dwords, then emits 5-, 8-, and 9-dword packets.
|
||||
return buf->ReserveDW(22) && append(5) && append(8) && append(9);
|
||||
};
|
||||
|
||||
if (cmd == nullptr) {
|
||||
return nullptr;
|
||||
// Preserve native packet sizes, allocation boundaries, Push/Pop ordering, and
|
||||
// returned first-packet address. The native packets reference process-private state buffers,
|
||||
// so their net Cx operation is represented by the first HLE packet and type-3 NOPs.
|
||||
bool complete = false;
|
||||
switch (static_cast<ContextStateOperation>(operation)) {
|
||||
case ContextStateOperation::Clear: complete = append(5); break;
|
||||
case ContextStateOperation::Push:
|
||||
complete = append_save_restore() && append(3) && append(2);
|
||||
break;
|
||||
case ContextStateOperation::Pop:
|
||||
complete = append(3) && append_save_restore() && append(2);
|
||||
break;
|
||||
case ContextStateOperation::PushClear:
|
||||
complete = append_save_restore() && append(3) && append(2) && append(5);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
cmd[0] = 0x80000000u;
|
||||
return complete ? first : nullptr;
|
||||
}
|
||||
|
||||
return cmd;
|
||||
uint64_t KYTY_SYSV_ABI GraphicsDcbContextStateOpGetSize(uint32_t operation) {
|
||||
PRINT_NAME();
|
||||
return static_cast<uint64_t>(context_state_op_size_dw(operation)) * sizeof(uint32_t);
|
||||
}
|
||||
|
||||
uint64_t KYTY_SYSV_ABI GraphicsGetIsTrinityMode() {
|
||||
|
||||
+2
-2
@@ -67,8 +67,8 @@ int KYTY_SYSV_ABI GraphicsUnknownJumpPatchSetTarget(uint32_t* cmd, const volatil
|
||||
int KYTY_SYSV_ABI GraphicsJumpPatchSetTarget(uint32_t* cmd, const volatile uint32_t* target,
|
||||
uint32_t size_in_dwords);
|
||||
int KYTY_SYSV_ABI GraphicsSuspendPoint();
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsUnknownQj7QZpgr9Uw(CommandBuffer* buf, uint32_t mode,
|
||||
uint32_t value);
|
||||
uint32_t* KYTY_SYSV_ABI GraphicsDcbContextStateOp(CommandBuffer* buf, uint32_t operation);
|
||||
uint64_t KYTY_SYSV_ABI GraphicsDcbContextStateOpGetSize(uint32_t operation);
|
||||
uint64_t KYTY_SYSV_ABI GraphicsGetIsTrinityMode();
|
||||
|
||||
uint32_t KYTY_SYSV_ABI GraphicsDriverGetDefaultOwner();
|
||||
|
||||
@@ -178,7 +178,8 @@ LIB_DEFINE(InitGraphicsDriver_1) {
|
||||
LIB_FUNC("bxca0BK4FNg", Gen5::GraphicsUnknownJumpPatchSetTarget);
|
||||
LIB_FUNC("2BS4EtAaF28", Gen5::GraphicsJumpPatchSetTarget);
|
||||
LIB_FUNC("h9z6+0hEydk", Gen5::GraphicsSuspendPoint);
|
||||
LIB_FUNC("qj7QZpgr9Uw", Gen5::GraphicsUnknownQj7QZpgr9Uw);
|
||||
LIB_FUNC("qj7QZpgr9Uw", Gen5::GraphicsDcbContextStateOp);
|
||||
LIB_FUNC("H6vHS5cidSA", Gen5::GraphicsDcbContextStateOpGetSize);
|
||||
LIB_FUNC("BfBDZGbti7A", Gen5::GraphicsGetIsTrinityMode);
|
||||
LIB_FUNC("dbOlWdppb4o", LibGen5::Graphics5UnknownDb);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user