fix(libSceAgc): accept a null base in sceAgcDcbSetBaseIndirectArgs
The builder threw on a null indirect base, while the PM4 executor accepts SET_BASE with address 0 (it only requires the alignment and address bits) and an indirect draw that later reads the base is checked there. Titles clear the base with 0, as with sceAgcDcbSetIndexBuffer, which already accepts 0 to unbind. A non-null base is still checked for 8-byte alignment. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
961b25fe24
commit
8d96b44917
|
|
@ -20,7 +20,7 @@ uint32_t* APS5_VABI sceAgcDcbSetBaseIndirectArgs(CommandBuffer* buf, uint32_t sh
|
|||
// SET_BASE with base index 1; header bit 1 selects the dispatch (compute) base over the draw base.
|
||||
Agc::Command::CheckBits(shader_type, 1, __func__);
|
||||
const auto address = reinterpret_cast<std::uintptr_t>(indirect_base_addr);
|
||||
Agc::Command::CheckAddress(address, 8, __func__);
|
||||
if (address != 0) Agc::Command::CheckAddress(address, 8, __func__);
|
||||
Agc::Command::CheckBits(address, 0xffffffffffffull, __func__);
|
||||
auto* packet = Agc::Command::Allocate(buf, 4, __func__);
|
||||
packet[0] = Agc::Command::Header(0x11u, 4, shader_type != 0 ? 2u : 0u);
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ extern "C" std::uint32_t* APS5_VABI sceAgcAcbPushMarker(CommandBuffer* buf, cons
|
|||
extern "C" std::uint32_t* APS5_VABI sceAgcAcbPopMarker(CommandBuffer* buf);
|
||||
extern "C" std::uint32_t* APS5_VABI sceAgcAcbSetMarker(CommandBuffer* buf, const char* str, std::uint32_t color);
|
||||
extern "C" std::uint32_t* APS5_VABI sceAgcDcbSetIndexBuffer(CommandBuffer* buf, std::uint64_t indexAddress);
|
||||
extern "C" std::uint32_t* APS5_VABI sceAgcDcbSetBaseIndirectArgs(CommandBuffer* buf, std::uint32_t shaderType, const volatile void* indirectBaseAddr);
|
||||
extern "C" std::uint32_t* APS5_VABI sceAgcSetNop(CommandBuffer* buf, std::uint32_t sizeDw);
|
||||
|
||||
namespace {
|
||||
|
|
@ -221,6 +222,19 @@ void testIndexBuffer() {
|
|||
throw std::runtime_error("misaligned index buffer was accepted");
|
||||
}
|
||||
|
||||
void testIndirectBase() {
|
||||
Storage storage;
|
||||
alignas(8) std::uint32_t arguments[4]{};
|
||||
const auto address = reinterpret_cast<std::uintptr_t>(arguments);
|
||||
const auto* bound = sceAgcDcbSetBaseIndirectArgs(&storage.buffer, 0, arguments);
|
||||
check(bound[1] == 1 && bound[2] == static_cast<std::uint32_t>(address) && bound[3] == static_cast<std::uint32_t>(address >> 32u), "indirect base address mismatch");
|
||||
const auto* cleared = sceAgcDcbSetBaseIndirectArgs(&storage.buffer, 1, nullptr);
|
||||
check(cleared == bound + 4 && (cleared[0] & 2u) != 0 && cleared[1] == 1 && cleared[2] == 0 && cleared[3] == 0, "indirect base was not cleared");
|
||||
const auto before = storage.words;
|
||||
expectFailure([&] { sceAgcDcbSetBaseIndirectArgs(&storage.buffer, 0, reinterpret_cast<const volatile void*>(address + 4)); });
|
||||
check(storage.words == before, "misaligned indirect base modified packet memory");
|
||||
}
|
||||
|
||||
void testContextState() {
|
||||
const std::array<std::array<std::uint32_t, 6>, 4> sizes{{{5}, {5, 8, 9, 3, 2}, {3, 5, 8, 9, 2}, {5, 8, 9, 3, 2, 5}}};
|
||||
const std::array<std::array<std::uint32_t, 4>, 4> reservations{{{5}, {22, 3, 2}, {3, 22, 2}, {22, 3, 2, 5}}};
|
||||
|
|
@ -425,6 +439,7 @@ int main(int argc, char** argv) {
|
|||
testIndexedIndirectDraws();
|
||||
testMarkers();
|
||||
testIndexBuffer();
|
||||
testIndirectBase();
|
||||
testContextState();
|
||||
testFlip();
|
||||
testRegisters();
|
||||
|
|
|
|||
Loading…
Reference in New Issue