From 49b2eedd1ceebec43a25012a5e2c0f928627ee8b Mon Sep 17 00:00:00 2001 From: nmzik Date: Thu, 17 Sep 2026 08:16:59 +0400 Subject: [PATCH] Fix command buffer capacity calculation Credits: YuhiAida (@YuhiAida): https://github.com/KytyPS5/KytyPS5/pull/588 https://github.com/KytyPS5/KytyPS5/pull/589 https://github.com/KytyPS5/KytyPS5/pull/652 Crimson (@Crimson3076): https://github.com/KytyPS5/KytyPS5/pull/598 --- src/libs/agc.cpp | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/src/libs/agc.cpp b/src/libs/agc.cpp index ed052e0ae..531523d36 100644 --- a/src/libs/agc.cpp +++ b/src/libs/agc.cpp @@ -262,35 +262,25 @@ struct CommandBuffer { reserved_dw); } - [[nodiscard]] KYTY_SYSV_ABI uint32_t GetAvailableSizeDW() const { - if (cursor_up == nullptr || cursor_down == nullptr || cursor_down <= cursor_up) { - return 0; - } - - auto available = static_cast(cursor_down - cursor_up); + [[nodiscard]] KYTY_SYSV_ABI uint64_t GetAvailableSizeDW() const { + // Interpret the signed cursor distance as an unsigned 64-bit DWORD count. + const auto distance = static_cast(reinterpret_cast(cursor_down) - + reinterpret_cast(cursor_up)); + const auto available = static_cast(distance >> 2); if (available <= reserved_dw) { return 0; } - if (available - reserved_dw > UINT32_MAX) { - LOGF_COLOR( - Log::Color::Red, - "\t command buffer has suspiciously large free space: cursor_up = 0x%016" PRIx64 - ", cursor_down = 0x%016" PRIx64 ", reserved_dw = %" PRIu32 "\n", - reinterpret_cast(cursor_up), reinterpret_cast(cursor_down), - reserved_dw); - return UINT32_MAX; - } - return static_cast(available - reserved_dw); + return available - reserved_dw; } KYTY_SYSV_ABI bool ReserveDW(uint32_t num_dw) { - uint32_t remaining = GetAvailableSizeDW(); + const uint64_t remaining = GetAvailableSizeDW(); if (num_dw > remaining) { if (callback == nullptr) { LOGF_COLOR( Log::Color::Red, "\t command buffer exhausted and has no grow callback: requested = %" PRIu32 - ", remaining = %" PRIu32 ", reserved_dw = %" PRIu32 "\n", + ", remaining = %" PRIu64 ", reserved_dw = %" PRIu32 "\n", num_dw, remaining, reserved_dw); DbgDump(); return false; @@ -300,7 +290,7 @@ struct CommandBuffer { if (!result) { LOGF_COLOR(Log::Color::Red, "\t command buffer grow callback failed: requested = %" PRIu32 - ", remaining = %" PRIu32 ", reserved_dw = %" PRIu32 "\n", + ", remaining = %" PRIu64 ", reserved_dw = %" PRIu32 "\n", num_dw, remaining, reserved_dw); DbgDump(); return false; @@ -308,7 +298,7 @@ struct CommandBuffer { if (GetAvailableSizeDW() < num_dw) { LOGF_COLOR(Log::Color::Red, "\t command buffer grow callback did not provide enough space: " - "requested = %" PRIu32 ", remaining = %" PRIu32 + "requested = %" PRIu32 ", remaining = %" PRIu64 ", reserved_dw = %" PRIu32 "\n", num_dw, GetAvailableSizeDW(), reserved_dw); DbgDump();