Merge pull request #40 from Pacuka/feat/agc-draw-index-indirect
feat(agc): emit indexed indirect draws This implements `sceAgcDcbDrawIndexIndirect` and `sceAgcDcbDrawIndexIndirectMulti`. They were stubs that aborted with "not implemented". They follow the existing non-indexed `sceAgcDcbDrawIndirect` / `DrawIndirectMulti`: - `DrawIndexIndirect` emits `DRAW_INDEX_INDIRECT` (0x25): data offset, base vertex / start instance SGPR locations, draw initiator (5 dwords, matching `GetSize` = 20). - `DrawIndexIndirectMulti` emits `DRAW_INDEX_INDIRECT_MULTI` (0x38): the same fields, plus the draw-index location / count-indirect control word, count, count address and stride (10 dwords, matching `GetSize` = 40). The stride must be at least 20, the size of an indexed record.
This commit is contained in:
commit
f38e97658f
|
|
@ -37,11 +37,9 @@ uint32_t APS5_VABI sceAgcDcbDrawIndexOffsetGetSize(void) {
|
|||
}
|
||||
|
||||
uint32_t* APS5_VABI sceAgcDcbDrawIndexIndirect(CommandBuffer* buf, uint32_t data_offset_in_bytes, uint64_t modifier) {
|
||||
(void)buf;
|
||||
(void)data_offset_in_bytes;
|
||||
(void)modifier;
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return nullptr;
|
||||
Agc::Command::Require((data_offset_in_bytes & 3u) == 0, __func__, "misaligned indirect argument offset");
|
||||
const auto offsets = Agc::Command::DrawPatchOffsets(modifier, __func__);
|
||||
return Agc::Command::Emit(buf, 0x25u, {data_offset_in_bytes, static_cast<std::uint32_t>(offsets), static_cast<std::uint32_t>(offsets >> 32u), Agc::Command::DrawInitiator(modifier, true, __func__)}, __func__);
|
||||
}
|
||||
|
||||
std::uint32_t APS5_VABI sceAgcDcbDrawIndexIndirectGetSize() {
|
||||
|
|
@ -49,15 +47,18 @@ std::uint32_t APS5_VABI sceAgcDcbDrawIndexIndirectGetSize() {
|
|||
}
|
||||
|
||||
uint32_t* APS5_VABI sceAgcDcbDrawIndexIndirectMulti(CommandBuffer* buf, uint32_t data_offset_in_bytes, uint32_t count_indirect, uint32_t max_count_or_count, const volatile void* count_addr, uint32_t stride_in_bytes, uint64_t modifier) {
|
||||
(void)buf;
|
||||
(void)data_offset_in_bytes;
|
||||
(void)count_indirect;
|
||||
(void)max_count_or_count;
|
||||
(void)count_addr;
|
||||
(void)stride_in_bytes;
|
||||
(void)modifier;
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return nullptr;
|
||||
Agc::Command::CheckBits(count_indirect, 1, __func__);
|
||||
Agc::Command::Require((data_offset_in_bytes & 3u) == 0 && (stride_in_bytes & 3u) == 0 && stride_in_bytes >= 20, __func__, "invalid indirect draw offset or stride");
|
||||
const auto address = reinterpret_cast<std::uintptr_t>(count_addr);
|
||||
if (count_indirect != 0) {
|
||||
Agc::Command::CheckAddress(address, 4, __func__);
|
||||
} else {
|
||||
Agc::Command::Require(address == 0, __func__, "count address supplied for a direct draw count");
|
||||
}
|
||||
const auto offsets = Agc::Command::DrawPatchOffsets(modifier, __func__);
|
||||
const auto low = static_cast<std::uint32_t>(modifier);
|
||||
const auto control = Agc::Command::DrawIndexLocation(modifier) | ((low & 0x10u) << 23u) | (count_indirect << 30u) | ((low & 8u) << 28u);
|
||||
return Agc::Command::Emit(buf, 0x38u, {data_offset_in_bytes, static_cast<std::uint32_t>(offsets), static_cast<std::uint32_t>(offsets >> 32u), control, max_count_or_count, static_cast<std::uint32_t>(address), static_cast<std::uint32_t>(address >> 32u), stride_in_bytes, Agc::Command::DrawInitiator(modifier, true, __func__)}, __func__);
|
||||
}
|
||||
|
||||
std::uint32_t APS5_VABI sceAgcDcbDrawIndexIndirectMultiGetSize() {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ extern "C" std::uint32_t* APS5_VABI sceAgcDcbSetFlip(CommandBuffer* buf, std::ui
|
|||
extern "C" int APS5_VABI sceAgcSuspendPoint();
|
||||
extern "C" int APS5_VABI sceAgcInit(std::uint32_t* state, std::uint32_t version);
|
||||
extern "C" std::uint32_t* APS5_VABI sceAgcDcbDrawIndexAuto(CommandBuffer* buf, std::uint32_t indexCount, std::uint64_t modifier);
|
||||
extern "C" std::uint32_t* APS5_VABI sceAgcDcbDrawIndexIndirect(CommandBuffer* buf, std::uint32_t dataOffsetInBytes, std::uint64_t modifier);
|
||||
extern "C" std::uint32_t* APS5_VABI sceAgcDcbDrawIndexIndirectMulti(CommandBuffer* buf, std::uint32_t dataOffsetInBytes, std::uint32_t countIndirect, std::uint32_t maxCountOrCount, const volatile void* countAddress, std::uint32_t strideInBytes, std::uint64_t modifier);
|
||||
extern "C" int APS5_VABI sceAgcWaitRegMemPatchReference(std::uint32_t* cmd, std::uint64_t reference);
|
||||
extern "C" int APS5_VABI sceAgcGetDataPacketPayloadAddressUnk(std::uint32_t** addr, std::uint32_t* cmd, int type);
|
||||
extern "C" std::uint32_t* APS5_VABI sceAgcCbSetShRegisterRangeDirect(CommandBuffer* buf, std::uint32_t offset, const std::uint32_t* values, std::uint32_t numValues);
|
||||
|
|
@ -96,6 +98,24 @@ bool APS5_VABI growContext(CommandBuffer* buffer, std::uint32_t count, void* use
|
|||
return true;
|
||||
}
|
||||
|
||||
void testIndexedIndirectDraws() {
|
||||
Storage storage;
|
||||
const auto* single = sceAgcDcbDrawIndexIndirect(&storage.buffer, 0x40, 0);
|
||||
const std::array<std::uint32_t, 5> expectedSingle{0xc0032500u, 0x40, 0x280, 0x280, 0};
|
||||
check(single == storage.words.data() && std::equal(expectedSingle.begin(), expectedSingle.end(), single), "indexed indirect draw packet mismatch");
|
||||
alignas(4) std::uint32_t count = 0;
|
||||
const auto* multi = sceAgcDcbDrawIndexIndirectMulti(&storage.buffer, 0x80, 1, 8, &count, 20, 0);
|
||||
const auto address = reinterpret_cast<std::uintptr_t>(&count);
|
||||
const std::array<std::uint32_t, 10> expectedMulti{0xc0083800u, 0x80, 0x280, 0x280, 0x40000280u, 8, static_cast<std::uint32_t>(address), static_cast<std::uint32_t>(address >> 32u), 20, 0};
|
||||
check(multi == storage.words.data() + expectedSingle.size() && std::equal(expectedMulti.begin(), expectedMulti.end(), multi), "indexed indirect multi draw packet mismatch");
|
||||
check(storage.buffer.cursor_up == storage.words.data() + expectedSingle.size() + expectedMulti.size(), "incorrect indexed indirect cursor advance");
|
||||
const auto before = storage.words;
|
||||
expectFailure([&] { sceAgcDcbDrawIndexIndirect(&storage.buffer, 2, 0); });
|
||||
expectFailure([&] { sceAgcDcbDrawIndexIndirectMulti(&storage.buffer, 0, 1, 8, &count, 16, 0); });
|
||||
expectFailure([&] { sceAgcDcbDrawIndexIndirectMulti(&storage.buffer, 0, 0, 8, &count, 20, 0); });
|
||||
check(storage.words == before, "invalid indexed indirect draw 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}}};
|
||||
|
|
@ -272,6 +292,7 @@ void testDefaults() {
|
|||
int main() {
|
||||
try {
|
||||
testPackets();
|
||||
testIndexedIndirectDraws();
|
||||
testContextState();
|
||||
testFlip();
|
||||
testRegisters();
|
||||
|
|
|
|||
Loading…
Reference in New Issue