Handle PM4 type-2 packets (#556)

* video_core: handle PM4 type-2 packets

* video_core: rewrite pm4 comand type handling into a switch statement
This commit is contained in:
Random 2024-08-28 09:53:27 +02:00 committed by GitHub
parent e4254ebdaa
commit c37679154e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 287 additions and 276 deletions

View File

@ -175,11 +175,17 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span<const u32> dcb, std::span<c
while (!dcb.empty()) { while (!dcb.empty()) {
const auto* header = reinterpret_cast<const PM4Header*>(dcb.data()); const auto* header = reinterpret_cast<const PM4Header*>(dcb.data());
const u32 type = header->type; const u32 type = header->type;
if (type != 3) {
// No other types of packets were spotted so far
UNREACHABLE_MSG("Invalid PM4 type {}", type);
}
switch (type) {
case 0:
case 1:
UNREACHABLE_MSG("Unsupported PM4 type {}", type);
break;
case 2:
// Type-2 packet are used for padding purposes
dcb = dcb.subspan(1);
continue;
case 3:
const u32 count = header->type3.NumWords(); const u32 count = header->type3.NumWords();
const PM4ItOpcode opcode = header->type3.opcode; const PM4ItOpcode opcode = header->type3.opcode;
switch (opcode) { switch (opcode) {
@ -235,10 +241,10 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span<const u32> dcb, std::span<c
// In the case of HW, render target memory has alignment as color block operates on // In the case of HW, render target memory has alignment as color block operates on
// tiles. There is no information of actual resource extents stored in CB context // tiles. There is no information of actual resource extents stored in CB context
// regs, so any deduction of it from slices/pitch will lead to a larger surface created. // regs, so any deduction of it from slices/pitch will lead to a larger surface
// The same applies to the depth targets. Fortunately, the guest always sends // created. The same applies to the depth targets. Fortunately, the guest always
// a trailing NOP packet right after the context regs setup, so we can use the heuristic // sends a trailing NOP packet right after the context regs setup, so we can use the
// below and extract the hint to determine actual resource dims. // heuristic below and extract the hint to determine actual resource dims.
switch (reg_addr) { switch (reg_addr) {
case ContextRegs::CbColor0Base: case ContextRegs::CbColor0Base:
@ -271,7 +277,8 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span<const u32> dcb, std::span<c
case ContextRegs::CbColor5Cmask: case ContextRegs::CbColor5Cmask:
case ContextRegs::CbColor6Cmask: case ContextRegs::CbColor6Cmask:
case ContextRegs::CbColor7Cmask: { case ContextRegs::CbColor7Cmask: {
const auto col_buf_id = (reg_addr - ContextRegs::CbColor0Cmask) / const auto col_buf_id =
(reg_addr - ContextRegs::CbColor0Cmask) /
(ContextRegs::CbColor1Cmask - ContextRegs::CbColor0Cmask); (ContextRegs::CbColor1Cmask - ContextRegs::CbColor0Cmask);
ASSERT(col_buf_id < NumColorBuffers); ASSERT(col_buf_id < NumColorBuffers);
@ -306,8 +313,8 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span<const u32> dcb, std::span<c
} }
case PM4ItOpcode::SetUconfigReg: { case PM4ItOpcode::SetUconfigReg: {
const auto* set_data = reinterpret_cast<const PM4CmdSetData*>(header); const auto* set_data = reinterpret_cast<const PM4CmdSetData*>(header);
std::memcpy(&regs.reg_array[UconfigRegWordOffset + set_data->reg_offset], header + 2, std::memcpy(&regs.reg_array[UconfigRegWordOffset + set_data->reg_offset],
(count - 1) * sizeof(u32)); header + 2, (count - 1) * sizeof(u32));
break; break;
} }
case PM4ItOpcode::IndexType: { case PM4ItOpcode::IndexType: {
@ -332,13 +339,15 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span<const u32> dcb, std::span<c
break; break;
} }
case PM4ItOpcode::DrawIndexOffset2: { case PM4ItOpcode::DrawIndexOffset2: {
const auto* draw_index_off = reinterpret_cast<const PM4CmdDrawIndexOffset2*>(header); const auto* draw_index_off =
reinterpret_cast<const PM4CmdDrawIndexOffset2*>(header);
regs.max_index_size = draw_index_off->max_size; regs.max_index_size = draw_index_off->max_size;
regs.num_indices = draw_index_off->index_count; regs.num_indices = draw_index_off->index_count;
regs.draw_initiator = draw_index_off->draw_initiator; regs.draw_initiator = draw_index_off->draw_initiator;
if (rasterizer) { if (rasterizer) {
const auto cmd_address = reinterpret_cast<const void*>(header); const auto cmd_address = reinterpret_cast<const void*>(header);
rasterizer->ScopeMarkerBegin(fmt::format("dcb:{}:DrawIndexOffset2", cmd_address)); rasterizer->ScopeMarkerBegin(
fmt::format("dcb:{}:DrawIndexOffset2", cmd_address));
rasterizer->Breadcrumb(u64(cmd_address)); rasterizer->Breadcrumb(u64(cmd_address));
rasterizer->Draw(true, draw_index_off->index_offset); rasterizer->Draw(true, draw_index_off->index_offset);
rasterizer->ScopeMarkerEnd(); rasterizer->ScopeMarkerEnd();
@ -463,6 +472,8 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span<const u32> dcb, std::span<c
static_cast<u32>(opcode), count); static_cast<u32>(opcode), count);
} }
dcb = dcb.subspan(header->type3.NumWords() + 1); dcb = dcb.subspan(header->type3.NumWords() + 1);
break;
}
} }
if (ce_task.handle) { if (ce_task.handle) {