amdgpu: indirect buffer, release mem and some additional irq modes

This commit is contained in:
psucien 2024-06-21 20:37:30 +02:00
parent 966ff741d1
commit b8290ea521
2 changed files with 109 additions and 0 deletions

View File

@ -265,6 +265,7 @@ enum class InterruptSelect : u32 {
None = 0, None = 0,
IrqOnly = 1, IrqOnly = 1,
IrqWhenWriteConfirm = 2, IrqWhenWriteConfirm = 2,
IrqUndocumented = 3,
}; };
struct PM4CmdEventWriteEop { struct PM4CmdEventWriteEop {
@ -299,6 +300,9 @@ struct PM4CmdEventWriteEop {
void SignalFence() const { void SignalFence() const {
switch (data_sel.Value()) { switch (data_sel.Value()) {
case DataSelect::None: {
break;
}
case DataSelect::Data32Low: { case DataSelect::Data32Low: {
*Address<u32>() = DataDWord(); *Address<u32>() = DataDWord();
break; break;
@ -321,6 +325,9 @@ struct PM4CmdEventWriteEop {
// No interrupt // No interrupt
break; break;
} }
case InterruptSelect::IrqOnly:
ASSERT(data_sel == DataSelect::None);
[[fallthrough]];
case InterruptSelect::IrqWhenWriteConfirm: { case InterruptSelect::IrqWhenWriteConfirm: {
Platform::IrqC::Instance()->Signal(Platform::InterruptId::GfxEop); Platform::IrqC::Instance()->Signal(Platform::InterruptId::GfxEop);
break; break;
@ -559,4 +566,105 @@ struct PM4CmdDrawIndexBase {
u32 addr_hi; u32 addr_hi;
}; };
struct PM4CmdIndirectBuffer {
PM4Type3Header header;
u32 ibase_lo; ///< Indirect buffer base address, must be 4 byte aligned
union {
BitField<0, 16, u32> ibase_hi; ///< Indirect buffer base address
u32 dw1;
};
union {
BitField<0, 20, u32> ib_size; ///< Indirect buffer size
BitField<20, 1, u32> chain; ///< set to chain to IB allocations
BitField<24, 8, u32> vmid; ///< Virtual memory domain ID for command buffer
u32 dw2;
};
template <typename T>
T* Address() const {
return reinterpret_cast<T*>((u64(ibase_hi) << 32u) | ibase_lo);
}
};
struct PM4CmdReleaseMem {
PM4Type3Header header;
union {
BitField<0, 6, u32> event_type; ///< Event type written to VGT_EVENT_INITIATOR
BitField<8, 4, u32> event_index; ///< Event index
BitField<12, 1, u32> tcl1_vol_action_ena;
BitField<13, 1, u32> tc_vol_action_ena;
BitField<15, 1, u32> tc_wb_action_ena;
BitField<16, 1, u32> tcl1__action_ena;
BitField<17, 1, u32> tc_action_ena;
BitField<25, 2, u32> cache_policy; ///< Cache Policy setting used for writing fences and
///< timestamps to the TCL2
u32 dw1;
};
union {
BitField<16, 2, u32> dst_sel; ///< destination select
BitField<24, 3, InterruptSelect> int_sel; ///< selects interrupt action for end-of-pipe
BitField<29, 3, DataSelect> data_sel; ///< selects source of data
u32 dw2;
};
u32 address_lo; ///< low bits of address
u32 address_hi; ///< high bits of address
union {
struct {
u16 gds_index; ///< Byte offset into GDS to copy from
u16 num_dw; ///< Number of DWORDS of GDS to copy
};
u32 data_lo; ///< value that will be written to memory when event occurs
};
u32 data_hi;
template <typename T>
T* Address() const {
return reinterpret_cast<T*>(address_lo | u64(address_hi) << 32);
}
u32 DataDWord() const {
return data_lo;
}
u64 DataQWord() const {
return data_lo | u64(data_hi) << 32;
}
void SignalFence(Platform::InterruptId irq_id) const {
switch (data_sel.Value()) {
case DataSelect::Data32Low: {
*Address<u32>() = DataDWord();
break;
}
case DataSelect::Data64: {
*Address<u64>() = DataQWord();
break;
}
case DataSelect::PerfCounter: {
*Address<u64>() = Common::FencedRDTSC();
break;
}
default: {
UNREACHABLE();
}
}
switch (int_sel.Value()) {
case InterruptSelect::None: {
// No interrupt
break;
}
case InterruptSelect::IrqUndocumented:
[[fallthrough]];
case InterruptSelect::IrqWhenWriteConfirm: {
Platform::IrqC::Instance()->Signal(irq_id);
break;
}
default: {
UNREACHABLE();
}
}
}
};
} // namespace AmdGpu } // namespace AmdGpu

View File

@ -46,6 +46,7 @@ enum class PM4ItOpcode : u32 {
EventWrite = 0x46, EventWrite = 0x46,
EventWriteEop = 0x47, EventWriteEop = 0x47,
EventWriteEos = 0x48, EventWriteEos = 0x48,
ReleaseMem = 0x49,
PremableCntl = 0x4A, PremableCntl = 0x4A,
DmaData = 0x50, DmaData = 0x50,
ContextRegRmw = 0x51, ContextRegRmw = 0x51,