mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-27 16:02:37 +00:00
graphics: write the subdraw index of multi-draw indirect packets
Co-authored-by: Ali Almohaya <AliAlmohaya@gmail.com>
This commit is contained in:
1 parent
72d7da7266
commit
b4209dde1b
4 files changed
+19
-7
No files matched your search
@@ -27,6 +27,7 @@ struct IndirectDrawRegisters {
|
|||||||
uint32_t vertex_offset;
|
uint32_t vertex_offset;
|
||||||
uint32_t instance_offset;
|
uint32_t instance_offset;
|
||||||
uint32_t index_offset;
|
uint32_t index_offset;
|
||||||
|
uint32_t draw_index;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Pm4Execution {
|
class Pm4Execution {
|
||||||
|
|||||||
@@ -1582,7 +1582,7 @@ KYTY_CP_OP_PARSER(CpOpDrawIndirect) {
|
|||||||
// The native indexed packet enables the high-half first-index destination in word 3.
|
// The native indexed packet enables the high-half first-index destination in word 3.
|
||||||
const IndirectDrawRegisters registers {
|
const IndirectDrawRegisters registers {
|
||||||
buffer[1] & 0xffffu, buffer[2] & 0xffffu,
|
buffer[1] & 0xffffu, buffer[2] & 0xffffu,
|
||||||
indexed && (buffer[2] & (1u << 28u)) != 0 ? buffer[1] >> 16u : Pm4::SH_NOP};
|
indexed && (buffer[2] & (1u << 28u)) != 0 ? buffer[1] >> 16u : Pm4::SH_NOP, Pm4::SH_NOP};
|
||||||
|
|
||||||
cp.DrawIndirect(data_offset, registers, draw_initiator, indexed);
|
cp.DrawIndirect(data_offset, registers, draw_initiator, indexed);
|
||||||
|
|
||||||
@@ -1602,10 +1602,12 @@ KYTY_CP_OP_PARSER(CpOpDrawIndirectMulti) {
|
|||||||
const auto stride_in_bytes = buffer[7];
|
const auto stride_in_bytes = buffer[7];
|
||||||
const auto draw_initiator = buffer[8];
|
const auto draw_initiator = buffer[8];
|
||||||
const bool indexed = (cmd_id == 0xc0083800);
|
const bool indexed = (cmd_id == 0xc0083800);
|
||||||
// Multi-draw moves the first-index enable to word 4; the destinations stay in 2/3.
|
// Multi-draw moves the first-index enable to word 4; the destinations stay in 2/3. Word 4
|
||||||
|
// bit 31 enables the subdraw index, written to the register in its low half.
|
||||||
const IndirectDrawRegisters registers {
|
const IndirectDrawRegisters registers {
|
||||||
buffer[1] & 0xffffu, buffer[2] & 0xffffu,
|
buffer[1] & 0xffffu, buffer[2] & 0xffffu,
|
||||||
indexed && (buffer[3] & (1u << 28u)) != 0 ? buffer[1] >> 16u : Pm4::SH_NOP};
|
indexed && (buffer[3] & (1u << 28u)) != 0 ? buffer[1] >> 16u : Pm4::SH_NOP,
|
||||||
|
(buffer[3] >> 31u) != 0 ? buffer[3] & 0xffffu : Pm4::SH_NOP};
|
||||||
|
|
||||||
if (count_indirect == 0) {
|
if (count_indirect == 0) {
|
||||||
count_addr = nullptr;
|
count_addr = nullptr;
|
||||||
|
|||||||
@@ -789,7 +789,7 @@ void CommandProcessor::DrawIndexOffset(uint32_t index_offset, uint32_t index_cou
|
|||||||
|
|
||||||
static void PatchIndirectDrawOffsets(CommandProcessor& cp, IndirectDrawRegisters registers,
|
static void PatchIndirectDrawOffsets(CommandProcessor& cp, IndirectDrawRegisters registers,
|
||||||
uint32_t vertex_offset, uint32_t instance_offset,
|
uint32_t vertex_offset, uint32_t instance_offset,
|
||||||
uint32_t first_index) {
|
uint32_t first_index, uint32_t draw_index) {
|
||||||
const auto write = [&](uint32_t location, uint32_t value) {
|
const auto write = [&](uint32_t location, uint32_t value) {
|
||||||
if (location == Pm4::SH_NOP) {
|
if (location == Pm4::SH_NOP) {
|
||||||
return;
|
return;
|
||||||
@@ -801,6 +801,7 @@ static void PatchIndirectDrawOffsets(CommandProcessor& cp, IndirectDrawRegisters
|
|||||||
write(registers.vertex_offset, vertex_offset);
|
write(registers.vertex_offset, vertex_offset);
|
||||||
write(registers.instance_offset, instance_offset);
|
write(registers.instance_offset, instance_offset);
|
||||||
write(registers.index_offset, first_index);
|
write(registers.index_offset, first_index);
|
||||||
|
write(registers.draw_index, draw_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandProcessor::DrawIndirect(uint32_t data_offset, IndirectDrawRegisters registers,
|
void CommandProcessor::DrawIndirect(uint32_t data_offset, IndirectDrawRegisters registers,
|
||||||
@@ -839,7 +840,8 @@ void CommandProcessor::DrawIndirectMulti(uint32_t data_offset, uint32_t max_coun
|
|||||||
// while they are zero.
|
// while they are zero.
|
||||||
const DrawIndirectArgs records {args_addr, draw_count, stride_in_bytes};
|
const DrawIndirectArgs records {args_addr, draw_count, stride_in_bytes};
|
||||||
if (registers.vertex_offset == Pm4::SH_NOP && registers.instance_offset == Pm4::SH_NOP &&
|
if (registers.vertex_offset == Pm4::SH_NOP && registers.instance_offset == Pm4::SH_NOP &&
|
||||||
registers.index_offset == Pm4::SH_NOP && (!indexed || m_index_buffer_size != 0) &&
|
registers.index_offset == Pm4::SH_NOP && registers.draw_index == Pm4::SH_NOP &&
|
||||||
|
(!indexed || m_index_buffer_size != 0) &&
|
||||||
(indexed ? executor.DrawIndex(m_submit_id, CurrentBuffer(),
|
(indexed ? executor.DrawIndex(m_submit_id, CurrentBuffer(),
|
||||||
{.index_count = m_index_buffer_size,
|
{.index_count = m_index_buffer_size,
|
||||||
.index_addr = IndexAddress(0),
|
.index_addr = IndexAddress(0),
|
||||||
@@ -854,7 +856,7 @@ void CommandProcessor::DrawIndirectMulti(uint32_t data_offset, uint32_t max_coun
|
|||||||
const auto addr = args_addr + static_cast<uint64_t>(i) * stride_in_bytes;
|
const auto addr = args_addr + static_cast<uint64_t>(i) * stride_in_bytes;
|
||||||
if (!indexed) {
|
if (!indexed) {
|
||||||
const auto& args = *reinterpret_cast<const vk::DrawIndirectCommand*>(addr);
|
const auto& args = *reinterpret_cast<const vk::DrawIndirectCommand*>(addr);
|
||||||
PatchIndirectDrawOffsets(*this, registers, args.firstVertex, args.firstInstance, 0);
|
PatchIndirectDrawOffsets(*this, registers, args.firstVertex, args.firstInstance, 0, i);
|
||||||
executor.DrawAuto(m_submit_id, CurrentBuffer(),
|
executor.DrawAuto(m_submit_id, CurrentBuffer(),
|
||||||
{.vertex_count = args.vertexCount,
|
{.vertex_count = args.vertexCount,
|
||||||
.instance_count = args.instanceCount,
|
.instance_count = args.instanceCount,
|
||||||
@@ -866,7 +868,7 @@ void CommandProcessor::DrawIndirectMulti(uint32_t data_offset, uint32_t max_coun
|
|||||||
|
|
||||||
const auto& args = *reinterpret_cast<const vk::DrawIndexedIndirectCommand*>(addr);
|
const auto& args = *reinterpret_cast<const vk::DrawIndexedIndirectCommand*>(addr);
|
||||||
PatchIndirectDrawOffsets(*this, registers, static_cast<uint32_t>(args.vertexOffset),
|
PatchIndirectDrawOffsets(*this, registers, static_cast<uint32_t>(args.vertexOffset),
|
||||||
args.firstInstance, args.firstIndex);
|
args.firstInstance, args.firstIndex, i);
|
||||||
executor.DrawIndex(m_submit_id, CurrentBuffer(),
|
executor.DrawIndex(m_submit_id, CurrentBuffer(),
|
||||||
{.index_count = std::min(args.indexCount, max_indices),
|
{.index_count = std::min(args.indexCount, max_indices),
|
||||||
.index_addr = IndexAddress(args.firstIndex),
|
.index_addr = IndexAddress(args.firstIndex),
|
||||||
|
|||||||
@@ -49964,6 +49964,13 @@ void CheckPm4DrawIndirectMultiPacket(RenderContext &renderer) {
|
|||||||
KYTY_PM4(10, Pm4::IT_DRAW_INDIRECT_MULTI, 0), 0,
|
KYTY_PM4(10, Pm4::IT_DRAW_INDIRECT_MULTI, 0), 0,
|
||||||
auto_packet[2], auto_packet[3], Pm4::SH_NOP, 2, 0, 0, 16, 2};
|
auto_packet[2], auto_packet[3], Pm4::SH_NOP, 2, 0, 0, 16, 2};
|
||||||
check_offsets(auto_multi_packet, hs, {53, 15}, "non-indexed multi-draw offsets");
|
check_offsets(auto_multi_packet, hs, {53, 15}, "non-indexed multi-draw offsets");
|
||||||
|
// Word 4 bit 31 has the CP write each subdraw's index, even with no offsets to patch.
|
||||||
|
shaders.SetHsUserSgpr(11, 77);
|
||||||
|
auto_multi_packet[2] = auto_multi_packet[3] = Pm4::SH_NOP;
|
||||||
|
auto_multi_packet[4] = (1u << 31u) | (Pm4::SPI_SHADER_USER_DATA_HS_0 + 11);
|
||||||
|
Require("Pm4DrawIndirectMulti", "multi-draw index",
|
||||||
|
execute(auto_multi_packet.data(), auto_multi_packet.size()) && hs[11] == 1,
|
||||||
|
"multi-draw did not write the last subdraw index");
|
||||||
arguments = {0, 1, 99, 101};
|
arguments = {0, 1, 99, 101};
|
||||||
auto_packet[2] = Pm4::SH_NOP;
|
auto_packet[2] = Pm4::SH_NOP;
|
||||||
check_offsets(auto_packet, hs, {53, 101}, "independent destinations");
|
check_offsets(auto_packet, hs, {53, 101}, "independent destinations");
|
||||||
|
|||||||
Reference in new issue
Block a user