mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-10-11 21:49:59 +00:00
Implement sceGnmRequestFlipAndSubmitDone and sceGnmDrawIndirectCountMulti (#5341)
* sceGnmRequestFlipAndSubmitDone Used by H1Z1: Battle Royal. This, paired with a hack to get around some weird stack overflows this thing is doing, gets the game running. * sceGnmDrawIndirectCountMulti Still need to implement the PM4 opcode though * Oops * some other fixups * Implement IT_DRAW_INDIRECT_COUNT_MULTI * Remove indirect buffer wrapping We don't need it
This commit is contained in:
@@ -524,9 +524,7 @@ s32 PS4_SYSV_ABI sceGnmDrawIndexIndirectCountMulti(u32* cmdbuf, u32 size, u32 da
|
||||
(shader_stage == ShaderStages::Vs || shader_stage == ShaderStages::Es ||
|
||||
shader_stage == ShaderStages::Ls)) {
|
||||
|
||||
cmdbuf = WriteHeader<PM4ItOpcode::Nop>(cmdbuf, 2);
|
||||
cmdbuf = WriteBody(cmdbuf, 0u);
|
||||
cmdbuf += 1;
|
||||
cmdbuf = WriteTrailingNop<2>(cmdbuf);
|
||||
|
||||
const auto predicate = flags & 1 ? PM4Predicate::PredEnable : PM4Predicate::PredDisable;
|
||||
cmdbuf = WriteHeader<PM4ItOpcode::DrawIndexIndirectCountMulti>(
|
||||
@@ -627,10 +625,37 @@ s32 PS4_SYSV_ABI sceGnmDrawIndirect(u32* cmdbuf, u32 size, u32 data_offset, u32
|
||||
return -1;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceGnmDrawIndirectCountMulti() {
|
||||
LOG_ERROR(Lib_GnmDriver, "(STUBBED) called");
|
||||
UNREACHABLE();
|
||||
return ORBIS_OK;
|
||||
s32 PS4_SYSV_ABI sceGnmDrawIndirectCountMulti(u32* cmdbuf, u32 size, u32 data_offset, u32 max_count,
|
||||
u64 count_addr, u32 shader_stage,
|
||||
u32 vertex_sgpr_offset, u32 instance_sgpr_offset,
|
||||
u32 flags) {
|
||||
LOG_TRACE(Lib_GnmDriver, "called");
|
||||
|
||||
if (cmdbuf && (size == 0x10) && (shader_stage < ShaderStages::Max) &&
|
||||
(vertex_sgpr_offset < 0x10u) && (instance_sgpr_offset < 0x10u)) {
|
||||
|
||||
cmdbuf = WriteTrailingNop<2>(cmdbuf);
|
||||
|
||||
const auto predicate = flags & 1 ? PM4Predicate::PredEnable : PM4Predicate::PredDisable;
|
||||
cmdbuf = WriteHeader<PM4ItOpcode::DrawIndirectCountMulti>(
|
||||
cmdbuf, 9, PM4ShaderType::ShaderGraphics, predicate);
|
||||
|
||||
const auto sgpr_offset = indirect_sgpr_offsets[shader_stage];
|
||||
|
||||
cmdbuf[0] = data_offset;
|
||||
cmdbuf[1] = vertex_sgpr_offset == 0 ? 0 : (vertex_sgpr_offset & 0xffffu) + sgpr_offset;
|
||||
cmdbuf[2] = instance_sgpr_offset == 0 ? 0 : (instance_sgpr_offset & 0xffffu) + sgpr_offset;
|
||||
cmdbuf[3] = (count_addr != 0 ? 1u : 0u) << 0x1e;
|
||||
cmdbuf[4] = max_count;
|
||||
*(u64*)(&cmdbuf[5]) = count_addr;
|
||||
cmdbuf[7] = sizeof(DrawIndirectArgs);
|
||||
cmdbuf[8] = sceKernelIsNeoMode() ? flags & 0xe0000000u | 2u : 2u; // auto index
|
||||
|
||||
cmdbuf += 9;
|
||||
WriteTrailingNop<2>(cmdbuf);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceGnmDrawIndirectMulti(u32* cmdbuf, u32 size, u32 data_offset, u32 max_count,
|
||||
@@ -642,7 +667,7 @@ s32 PS4_SYSV_ABI sceGnmDrawIndirectMulti(u32* cmdbuf, u32 size, u32 data_offset,
|
||||
instance_sgpr_offset < 0x10) {
|
||||
const auto predicate = flags & 1 ? PM4Predicate::PredEnable : PM4Predicate::PredDisable;
|
||||
cmdbuf = WriteHeader<PM4ItOpcode::DrawIndirectMulti>(
|
||||
cmdbuf, 4, PM4ShaderType::ShaderGraphics, predicate);
|
||||
cmdbuf, 6, PM4ShaderType::ShaderGraphics, predicate);
|
||||
|
||||
const auto sgpr_offset = indirect_sgpr_offsets[shader_stage];
|
||||
cmdbuf[0] = data_offset;
|
||||
@@ -1299,13 +1324,150 @@ s32 PS4_SYSV_ABI sceGnmRegisterResource(void* res_handle, void* owner_handle, co
|
||||
return ORBIS_GNM_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceGnmRequestFlipAndSubmitDone() {
|
||||
LOG_ERROR(Lib_GnmDriver, "(STUBBED) called");
|
||||
static inline s32 PatchFlipRequest(u32* cmdbuf, u32 size, u32 vo_handle, u32 buf_idx, u32 flip_mode,
|
||||
s64 flip_arg, void* unk) {
|
||||
// check for `prepareFlip` packet
|
||||
cmdbuf += size - 64;
|
||||
ASSERT_MSG(cmdbuf[0] == 0xc03e1000, "Can't find `prepareFlip` packet");
|
||||
|
||||
std::array<u32, 7> backup{};
|
||||
std::memcpy(backup.data(), cmdbuf, backup.size() * sizeof(decltype(backup)::value_type));
|
||||
|
||||
ASSERT_MSG(((backup[2] & 3) == 0u) || (backup[1] != PM4CmdNop::PayloadType::PrepareFlipLabel),
|
||||
"Invalid flip packet");
|
||||
ASSERT_MSG(buf_idx != 0xffff'ffffu, "Invalid VO buffer index");
|
||||
|
||||
const s32 flip_result = VideoOut::sceVideoOutSubmitEopFlip(vo_handle, buf_idx, flip_mode,
|
||||
flip_arg, nullptr /*unk*/);
|
||||
if (flip_result != 0) {
|
||||
if (flip_result == 0x80290012) {
|
||||
LOG_ERROR(Lib_GnmDriver, "Flip queue is full");
|
||||
return 0x80d11081;
|
||||
} else {
|
||||
LOG_ERROR(Lib_GnmDriver, "Flip request failed");
|
||||
return flip_result;
|
||||
}
|
||||
}
|
||||
|
||||
uintptr_t label_addr{};
|
||||
ASSERT_MSG(VideoOut::sceVideoOutGetBufferLabelAddress(vo_handle, &label_addr) == 16,
|
||||
"sceVideoOutGetBufferLabelAddress call failed");
|
||||
|
||||
// Write event to lock the VO surface
|
||||
auto* write_lock = reinterpret_cast<PM4CmdWriteData*>(cmdbuf);
|
||||
write_lock->header = PM4Type3Header{PM4ItOpcode::WriteData, 3};
|
||||
write_lock->raw = 0x500u;
|
||||
const auto addr = (label_addr + buf_idx * sizeof(label_addr)) & ~0x3ull;
|
||||
write_lock->Address<uintptr_t>(addr);
|
||||
write_lock->data[0] = 1;
|
||||
|
||||
auto* nop = reinterpret_cast<PM4CmdNop*>(cmdbuf + 5);
|
||||
|
||||
if (backup[1] == PM4CmdNop::PayloadType::PrepareFlip) {
|
||||
nop->header = PM4Type3Header{PM4ItOpcode::Nop, 0x39};
|
||||
nop->data_block[0] = PM4CmdNop::PayloadType::PatchedFlip;
|
||||
} else {
|
||||
if (backup[1] == PM4CmdNop::PayloadType::PrepareFlipLabel) {
|
||||
nop->header = PM4Type3Header{PM4ItOpcode::Nop, 0x34};
|
||||
nop->data_block[0] = PM4CmdNop::PayloadType::PatchedFlip;
|
||||
|
||||
// Write event to update label
|
||||
auto* write_label = reinterpret_cast<PM4CmdWriteData*>(cmdbuf + 0x3b);
|
||||
write_label->header = PM4Type3Header{PM4ItOpcode::WriteData, 3};
|
||||
write_label->raw = 0x500u;
|
||||
write_label->dst_addr_lo = backup[2] & 0xffff'fffcu;
|
||||
write_label->dst_addr_hi = backup[3];
|
||||
write_label->data[0] = backup[4];
|
||||
}
|
||||
if (backup[1] == PM4CmdNop::PayloadType::PrepareFlipInterruptLabel) {
|
||||
nop->header = PM4Type3Header{PM4ItOpcode::Nop, 0x33};
|
||||
nop->data_block[0] = PM4CmdNop::PayloadType::PatchedFlip;
|
||||
|
||||
auto* write_eop = reinterpret_cast<PM4CmdEventWriteEop*>(cmdbuf + 0x3a);
|
||||
write_eop->header = PM4Type3Header{PM4ItOpcode::EventWriteEop, 4};
|
||||
write_eop->event_control = (backup[5] & 0x3f) + 0x500u + (backup[6] & 0x3f) * 0x1000;
|
||||
write_eop->address_lo = backup[2] & 0xffff'fffcu;
|
||||
write_eop->data_control = (backup[3] & 0xffffu) | 0x2200'0000u;
|
||||
write_eop->data_lo = backup[4];
|
||||
write_eop->data_hi = 0u;
|
||||
}
|
||||
if (backup[1] == PM4CmdNop::PayloadType::PrepareFlipInterrupt) {
|
||||
nop->header = PM4Type3Header{PM4ItOpcode::Nop, 0x33};
|
||||
nop->data_block[0] = PM4CmdNop::PayloadType::PatchedFlip;
|
||||
|
||||
auto* write_eop = reinterpret_cast<PM4CmdEventWriteEop*>(cmdbuf + 0x3a);
|
||||
write_eop->header = PM4Type3Header{PM4ItOpcode::EventWriteEop, 4};
|
||||
write_eop->event_control = (backup[5] & 0x3f) + 0x500u + (backup[6] & 0x3f) * 0x1000;
|
||||
write_eop->address_lo = 0u;
|
||||
write_eop->data_control = 0x100'0000u;
|
||||
write_eop->data_lo = 0u;
|
||||
write_eop->data_hi = 0u;
|
||||
}
|
||||
}
|
||||
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceGnmRequestFlipAndSubmitDoneForWorkload() {
|
||||
LOG_ERROR(Lib_GnmDriver, "(STUBBED) called");
|
||||
s32 PS4_SYSV_ABI sceGnmRequestFlipAndSubmitDone(u32* gpu_addr, u32 gpu_addr_size_in_bytes,
|
||||
u32 video_out_handle, u32 display_buffer_index,
|
||||
u32 flip_mode, s64 flip_arg) {
|
||||
return sceGnmRequestFlipAndSubmitDoneForWorkload(reinterpret_cast<u64>(gpu_addr), gpu_addr,
|
||||
gpu_addr_size_in_bytes, video_out_handle,
|
||||
display_buffer_index, flip_mode, flip_arg);
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceGnmRequestFlipAndSubmitDoneForWorkload(u64 workload, u32* gpu_addr,
|
||||
u32 gpu_addr_size_in_bytes,
|
||||
u32 vo_handle, u32 buf_idx,
|
||||
u32 flip_mode, s64 flip_arg) {
|
||||
LOG_DEBUG(Lib_GnmDriver, "called [buf = {}]", buf_idx);
|
||||
if (gpu_addr_size_in_bytes < 0x100) {
|
||||
return ORBIS_GNM_ERROR_SUBMISSION_NOT_ENOUGH_RESOURCES;
|
||||
}
|
||||
|
||||
std::scoped_lock lk{m_submit_lock};
|
||||
WaitGpuIdle();
|
||||
|
||||
// Write a PrepareFlip, then patch the flip request
|
||||
auto* nop = reinterpret_cast<PM4CmdNop*>(gpu_addr);
|
||||
nop->header = PM4Type3Header{PM4ItOpcode::Nop, 0x3e};
|
||||
nop->data_block[0] = PM4CmdNop::PayloadType::PrepareFlip;
|
||||
const s32 patch_result =
|
||||
PatchFlipRequest(gpu_addr, 0x40, vo_handle, buf_idx, flip_mode, flip_arg, nullptr /*unk*/);
|
||||
if (patch_result != ORBIS_OK) {
|
||||
return patch_result;
|
||||
}
|
||||
|
||||
// Submit
|
||||
const auto& dcb_span = std::span{gpu_addr, 0x40};
|
||||
if (DebugState.DumpingCurrentFrame()) {
|
||||
static auto last_frame_num = -1LL;
|
||||
static u32 seq_num{};
|
||||
if (last_frame_num == frames_submitted) {
|
||||
++seq_num;
|
||||
} else {
|
||||
last_frame_num = frames_submitted;
|
||||
seq_num = 0u;
|
||||
}
|
||||
|
||||
using DebugStateType::QueueType;
|
||||
|
||||
DebugState.PushQueueDump({
|
||||
.type = QueueType::dcb,
|
||||
.submit_num = seq_num,
|
||||
.num2 = 0,
|
||||
.data = {dcb_span.begin(), dcb_span.end()},
|
||||
.base_addr = reinterpret_cast<uintptr_t>(gpu_addr),
|
||||
});
|
||||
}
|
||||
liverpool->SubmitGfx(dcb_span, {});
|
||||
|
||||
if (!liverpool->IsGpuIdle()) {
|
||||
submission_lock = true;
|
||||
}
|
||||
liverpool->SubmitDone();
|
||||
send_init_packet = true;
|
||||
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
@@ -2117,90 +2279,6 @@ int PS4_SYSV_ABI sceGnmSqttWaitForEvent() {
|
||||
return ORBIS_GNM_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
static inline s32 PatchFlipRequest(u32* cmdbuf, u32 size, u32 vo_handle, u32 buf_idx, u32 flip_mode,
|
||||
s64 flip_arg, void* unk) {
|
||||
// check for `prepareFlip` packet
|
||||
cmdbuf += size - 64;
|
||||
ASSERT_MSG(cmdbuf[0] == 0xc03e1000, "Can't find `prepareFlip` packet");
|
||||
|
||||
std::array<u32, 7> backup{};
|
||||
std::memcpy(backup.data(), cmdbuf, backup.size() * sizeof(decltype(backup)::value_type));
|
||||
|
||||
ASSERT_MSG(((backup[2] & 3) == 0u) || (backup[1] != PM4CmdNop::PayloadType::PrepareFlipLabel),
|
||||
"Invalid flip packet");
|
||||
ASSERT_MSG(buf_idx != 0xffff'ffffu, "Invalid VO buffer index");
|
||||
|
||||
const s32 flip_result = VideoOut::sceVideoOutSubmitEopFlip(vo_handle, buf_idx, flip_mode,
|
||||
flip_arg, nullptr /*unk*/);
|
||||
if (flip_result != 0) {
|
||||
if (flip_result == 0x80290012) {
|
||||
LOG_ERROR(Lib_GnmDriver, "Flip queue is full");
|
||||
return 0x80d11081;
|
||||
} else {
|
||||
LOG_ERROR(Lib_GnmDriver, "Flip request failed");
|
||||
return flip_result;
|
||||
}
|
||||
}
|
||||
|
||||
uintptr_t label_addr{};
|
||||
ASSERT_MSG(VideoOut::sceVideoOutGetBufferLabelAddress(vo_handle, &label_addr) == 16,
|
||||
"sceVideoOutGetBufferLabelAddress call failed");
|
||||
|
||||
// Write event to lock the VO surface
|
||||
auto* write_lock = reinterpret_cast<PM4CmdWriteData*>(cmdbuf);
|
||||
write_lock->header = PM4Type3Header{PM4ItOpcode::WriteData, 3};
|
||||
write_lock->raw = 0x500u;
|
||||
const auto addr = (label_addr + buf_idx * sizeof(label_addr)) & ~0x3ull;
|
||||
write_lock->Address<uintptr_t>(addr);
|
||||
write_lock->data[0] = 1;
|
||||
|
||||
auto* nop = reinterpret_cast<PM4CmdNop*>(cmdbuf + 5);
|
||||
|
||||
if (backup[1] == PM4CmdNop::PayloadType::PrepareFlip) {
|
||||
nop->header = PM4Type3Header{PM4ItOpcode::Nop, 0x39};
|
||||
nop->data_block[0] = PM4CmdNop::PayloadType::PatchedFlip;
|
||||
} else {
|
||||
if (backup[1] == PM4CmdNop::PayloadType::PrepareFlipLabel) {
|
||||
nop->header = PM4Type3Header{PM4ItOpcode::Nop, 0x34};
|
||||
nop->data_block[0] = PM4CmdNop::PayloadType::PatchedFlip;
|
||||
|
||||
// Write event to update label
|
||||
auto* write_label = reinterpret_cast<PM4CmdWriteData*>(cmdbuf + 0x3b);
|
||||
write_label->header = PM4Type3Header{PM4ItOpcode::WriteData, 3};
|
||||
write_label->raw = 0x500u;
|
||||
write_label->dst_addr_lo = backup[2] & 0xffff'fffcu;
|
||||
write_label->dst_addr_hi = backup[3];
|
||||
write_label->data[0] = backup[4];
|
||||
}
|
||||
if (backup[1] == PM4CmdNop::PayloadType::PrepareFlipInterruptLabel) {
|
||||
nop->header = PM4Type3Header{PM4ItOpcode::Nop, 0x33};
|
||||
nop->data_block[0] = PM4CmdNop::PayloadType::PatchedFlip;
|
||||
|
||||
auto* write_eop = reinterpret_cast<PM4CmdEventWriteEop*>(cmdbuf + 0x3a);
|
||||
write_eop->header = PM4Type3Header{PM4ItOpcode::EventWriteEop, 4};
|
||||
write_eop->event_control = (backup[5] & 0x3f) + 0x500u + (backup[6] & 0x3f) * 0x1000;
|
||||
write_eop->address_lo = backup[2] & 0xffff'fffcu;
|
||||
write_eop->data_control = (backup[3] & 0xffffu) | 0x2200'0000u;
|
||||
write_eop->data_lo = backup[4];
|
||||
write_eop->data_hi = 0u;
|
||||
}
|
||||
if (backup[1] == PM4CmdNop::PayloadType::PrepareFlipInterrupt) {
|
||||
nop->header = PM4Type3Header{PM4ItOpcode::Nop, 0x33};
|
||||
nop->data_block[0] = PM4CmdNop::PayloadType::PatchedFlip;
|
||||
|
||||
auto* write_eop = reinterpret_cast<PM4CmdEventWriteEop*>(cmdbuf + 0x3a);
|
||||
write_eop->header = PM4Type3Header{PM4ItOpcode::EventWriteEop, 4};
|
||||
write_eop->event_control = (backup[5] & 0x3f) + 0x500u + (backup[6] & 0x3f) * 0x1000;
|
||||
write_eop->address_lo = 0u;
|
||||
write_eop->data_control = 0x100'0000u;
|
||||
write_eop->data_lo = 0u;
|
||||
write_eop->data_hi = 0u;
|
||||
}
|
||||
}
|
||||
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
static inline s32 PerformSubmit(u32 count, const u32* dcb_gpu_addrs[], u32* dcb_sizes_in_bytes,
|
||||
const u32* ccb_gpu_addrs[], u32* ccb_sizes_in_bytes) {
|
||||
if (DebugState.ShouldPauseInSubmit()) {
|
||||
|
||||
@@ -59,7 +59,10 @@ s32 PS4_SYSV_ABI sceGnmDrawIndexOffset(u32* cmdbuf, u32 size, u32 index_offset,
|
||||
u32 flags);
|
||||
s32 PS4_SYSV_ABI sceGnmDrawIndirect(u32* cmdbuf, u32 size, u32 data_offset, u32 shader_stage,
|
||||
u32 vertex_sgpr_offset, u32 instance_sgpr_offset, u32 flags);
|
||||
int PS4_SYSV_ABI sceGnmDrawIndirectCountMulti();
|
||||
s32 PS4_SYSV_ABI sceGnmDrawIndirectCountMulti(u32* cmdbuf, u32 size, u32 data_offset, u32 max_count,
|
||||
u64 count_addr, u32 shader_stage,
|
||||
u32 vertex_sgpr_offset, u32 instance_sgpr_offset,
|
||||
u32 flags);
|
||||
s32 PS4_SYSV_ABI sceGnmDrawIndirectMulti(u32* cmdbuf, u32 size, u32 data_offset, u32 max_count,
|
||||
u32 shader_stage, u32 vertex_sgpr_offset,
|
||||
u32 instance_sgpr_offset, u32 flags);
|
||||
@@ -138,8 +141,13 @@ void PS4_SYSV_ABI sceGnmRegisterGnmLiveCallbackConfig();
|
||||
s32 PS4_SYSV_ABI sceGnmRegisterOwner(void* handle, const char* name);
|
||||
s32 PS4_SYSV_ABI sceGnmRegisterResource(void* res_handle, void* owner_handle, const void* addr,
|
||||
size_t size, const char* name, int res_type, u64 user_data);
|
||||
int PS4_SYSV_ABI sceGnmRequestFlipAndSubmitDone();
|
||||
int PS4_SYSV_ABI sceGnmRequestFlipAndSubmitDoneForWorkload();
|
||||
s32 PS4_SYSV_ABI sceGnmRequestFlipAndSubmitDone(u32* gpu_addr, u32 gpu_addr_size_in_bytes,
|
||||
u32 video_out_handle, u32 display_buffer_index,
|
||||
u32 flip_mode, s64 flip_arg);
|
||||
s32 PS4_SYSV_ABI sceGnmRequestFlipAndSubmitDoneForWorkload(u64 workload, u32* gpu_addr,
|
||||
u32 gpu_addr_size_in_bytes,
|
||||
u32 vo_handle, u32 buf_idx,
|
||||
u32 flip_mode, s64 flip_arg);
|
||||
int PS4_SYSV_ABI sceGnmRequestMipStatsReportAndReset();
|
||||
s32 PS4_SYSV_ABI sceGnmResetVgtControl(u32* cmdbuf, u32 size);
|
||||
int PS4_SYSV_ABI sceGnmSdmaClose();
|
||||
|
||||
@@ -489,6 +489,27 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span<const u32> dcb, std::span<c
|
||||
});
|
||||
break;
|
||||
}
|
||||
case PM4ItOpcode::DrawIndirectCountMulti: {
|
||||
const auto* draw_indirect =
|
||||
reinterpret_cast<const PM4CmdDrawIndirectCountMulti*>(header);
|
||||
const auto offset = draw_indirect->data_offset;
|
||||
const auto stride = sizeof(DrawIndirectArgs);
|
||||
if (DebugState.DumpingCurrentReg()) {
|
||||
DebugState.PushRegsDump(base_addr, reinterpret_cast<uintptr_t>(header), regs);
|
||||
}
|
||||
if (!rasterizer) {
|
||||
break;
|
||||
}
|
||||
const auto cmd_address = reinterpret_cast<const void*>(header);
|
||||
rasterizer->ScopeMarker(
|
||||
"gfx:{}:DrawIndirectCountMulti", fmt::make_format_args(cmd_address), [&] {
|
||||
rasterizer->DrawIndirect(
|
||||
false, indirect_args_addr, offset, draw_indirect->stride,
|
||||
draw_indirect->count, draw_indirect->count_addr,
|
||||
draw_indirect->base_vtx_loc, draw_indirect->start_inst_loc);
|
||||
});
|
||||
break;
|
||||
}
|
||||
case PM4ItOpcode::DrawIndirectMulti: {
|
||||
const auto* draw_indirect =
|
||||
reinterpret_cast<const PM4CmdDrawIndirectMulti*>(header);
|
||||
|
||||
@@ -1066,6 +1066,33 @@ struct PM4CmdDrawIndirect {
|
||||
u32 draw_initiator; ///< Draw Initiator Register
|
||||
};
|
||||
|
||||
struct PM4CmdDrawIndirectCountMulti {
|
||||
PM4Type3Header header; ///< header
|
||||
u32 data_offset; ///< Byte aligned offset where the required data structure starts
|
||||
union {
|
||||
u32 dw2;
|
||||
BitField<0, 16, u32> base_vtx_loc; ///< Offset where the CP will write the
|
||||
///< BaseVertexLocation it fetched from memory
|
||||
};
|
||||
union {
|
||||
u32 dw3;
|
||||
BitField<0, 16, u32> start_inst_loc; ///< Offset where the CP will write the
|
||||
///< StartInstanceLocation it fetched from memory
|
||||
};
|
||||
union {
|
||||
u32 dw4;
|
||||
BitField<0, 16, u32> draw_index_loc; ///< register offset to write the Draw Index count
|
||||
BitField<30, 1, u32>
|
||||
count_indirect_enable; ///< Indicates the data structure count is in memory
|
||||
BitField<31, 1, u32>
|
||||
draw_index_enable; ///< Enables writing of Draw Index count to DRAW_INDEX_LOC
|
||||
};
|
||||
u32 count; ///< Count of data structures to loop through before going to next packet
|
||||
u64 count_addr; ///< DWord aligned Address[31:2]; Valid if countIndirectEnable is set
|
||||
u32 stride; ///< Stride in memory from one data structure to the next
|
||||
u32 draw_initiator; ///< Draw Initiator Register
|
||||
};
|
||||
|
||||
struct PM4CmdDrawIndirectMulti {
|
||||
PM4Type3Header header; ///< header
|
||||
u32 data_offset; ///< Byte aligned offset where the required data structure starts
|
||||
|
||||
@@ -37,7 +37,7 @@ enum class PM4ItOpcode : u32 {
|
||||
WriteData = 0x37,
|
||||
DrawIndexIndirectMulti = 0x38,
|
||||
MemSemaphore = 0x39,
|
||||
WaitRegMem = 0x3c,
|
||||
WaitRegMem = 0x3C,
|
||||
IndirectBuffer = 0x3F,
|
||||
CondIndirectBuffer = 0x3F,
|
||||
CopyData = 0x40,
|
||||
@@ -72,7 +72,8 @@ enum class PM4ItOpcode : u32 {
|
||||
WaitOnCeCounter = 0x86,
|
||||
WaitOnDeCounterDiff = 0x88,
|
||||
GetLodStats = 0x8E,
|
||||
DrawIndexIndirectCountMulti = 0x9d,
|
||||
DrawIndirectCountMulti = 0x9C,
|
||||
DrawIndexIndirectCountMulti = 0x9D,
|
||||
};
|
||||
|
||||
} // namespace AmdGpu
|
||||
|
||||
Reference in New Issue
Block a user