Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 0 additions & 59 deletions drivers/gpu/drm/asahi/g17/fw/queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,6 @@ pub(crate) enum CommandTag {
QueueConfig = 0x0f,
/// [`KickPredecessor`].
KickPredecessor = 0x10,
/// [`FragmentBarrier`] (25G83 firmware).
FragmentBarrier = 4,
/// [`InitBufferManager`] (25G83 firmware).
InitBufferManager = 5,
}
Expand Down Expand Up @@ -569,63 +567,6 @@ impl QueueConfig {
}
}

/// The 25G83 firmware's barrier before every fragment descriptor (tag 4): the fragment work
/// waits for the paired tiling stamp, in addition to the kick-entry dependency.
#[repr(C, packed)]
#[derive(Copy, Clone, Debug)]
pub(crate) struct FragmentBarrier {
/// [`CommandTag::FragmentBarrier`].
pub(crate) tag: u32,
/// GPU address of the tiling queue's completion stamp word.
pub(crate) stamp_va: u64,
/// Timestamp of the tiling kick.
pub(crate) tiling_kick: u64,
/// QID of the tiling queue.
pub(crate) tiling_qid: u32,
/// Tiling stamp value waited for.
pub(crate) wait: u32,
pub(crate) unk_1c: [u8; 8],
/// Event of the wait: the tiling QID.
pub(crate) event: u32,
/// Fragment stamp value.
pub(crate) stamp_self: u32,
/// Current object ID of the fragment stage.
pub(crate) fragment_id: u64,
pub(crate) unk_34: u32,
pub(crate) unk_38: [u8; 0x10],
}

static_assert!(size_of::<FragmentBarrier>() == 0x48);
static_assert!(core::mem::offset_of!(FragmentBarrier, wait) == 0x18);
static_assert!(core::mem::offset_of!(FragmentBarrier, event) == 0x24);
static_assert!(core::mem::offset_of!(FragmentBarrier, fragment_id) == 0x2c);

impl FragmentBarrier {
/// The barrier of a pass whose tiling stage, kicked at `tiling_kick` on `tiling_qid`,
/// signals `stamp_value` at `stamp_va`.
pub(crate) fn new(
stamp_va: u64,
tiling_kick: KickTimestamp,
tiling_qid: u32,
stamp_value: u32,
fragment_id: u64,
) -> Self {
Self {
tag: CommandTag::FragmentBarrier as u32,
stamp_va,
tiling_kick: tiling_kick.get(),
tiling_qid,
wait: stamp_value,
unk_1c: [0; 8],
event: tiling_qid,
stamp_self: stamp_value,
fragment_id,
unk_34: 1,
unk_38: [0; 0x10],
}
}
}

/// The 25G83 firmware's buffer-manager initialization (tag 5), before the first tiling
/// descriptor that uses a parameter buffer. The block count is read from the manager.
#[repr(C, packed)]
Expand Down
9 changes: 8 additions & 1 deletion drivers/gpu/drm/asahi/g17/fw/variant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,11 @@ pub(crate) struct Variant {
pub(crate) few_primitives: bool,
/// The firmware runs ray-traversal work (ray queries and intersection programs).
pub(crate) ray_traversal: bool,
/// Tiling descriptors report whether the fragment queue still had earlier kicks
/// outstanding (`fragment_busy`).
pub(crate) fragment_busy: bool,
/// Render item rings carry lead commands: InitBufferManager before the first tiling pass
/// of a buffer manager, and FragmentBarrier before every fragment descriptor.
/// of a buffer manager.
pub(crate) lead_commands: bool,
/// Register programs of the render descriptors.
pub(crate) programs: super::render::RegisterPrograms,
Expand Down Expand Up @@ -101,6 +104,7 @@ pub(crate) const V26A428: Variant = Variant {
mcache: true,
few_primitives: true,
ray_traversal: true,
fragment_busy: true,
lead_commands: false,
programs: super::render::RegisterPrograms::G17P,
};
Expand All @@ -126,6 +130,9 @@ pub(crate) const V25G83: Variant = Variant {
few_primitives: false,
// A stalled ray traversal wedges the GPU without a firmware recovery.
ray_traversal: false,
// When a tiling pass runs out of memory with this set, the firmware resumes it without
// adding memory and the tiler stops silently; macOS always writes 0.
fragment_busy: false,
lead_commands: true,
programs: super::render::RegisterPrograms::V25G83,
};
Expand Down
10 changes: 7 additions & 3 deletions drivers/gpu/drm/asahi/g17/queue/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -587,12 +587,16 @@ impl Pair {
let stamps = host.stamps(qids)?;
fence(Ordering::Acquire);
let covered = stamps.map(|stamp| retirement::stamp_covers(stamp, ordinal));
self.memory
.completion_links(ordinal, kicks, payload, !covered[1])?;
self.memory.completion_links(
ordinal,
kicks,
payload,
self.variant.fragment_busy && !covered[1],
)?;
let leads = match self.variant.lead_commands {
true => {
let init_manager = !self.memory.manager.initialized();
self.memory.write_leads(ordinal, kicks[0], init_manager)?
self.memory.write_leads(ordinal, init_manager)?
}
false => [false; 2],
};
Expand Down
36 changes: 8 additions & 28 deletions drivers/gpu/drm/asahi/g17/queue/render/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ pub(super) const ANNOUNCE: [usize; 2] = [0x17000, 0x1b000];
pub(super) const JOB_LIST: usize = 0xa000;
pub(super) const CONFIG: [usize; 2] = [0, 0x4000];
pub(super) const CONFIG_STRIDE: usize = 0x180;
/// The lead command of a stage (InitBM before tiling, the barrier before fragment), after the
/// stage's configuration record in its slot ([`crate::g17::fw::Variant::lead_commands`]).
/// The lead command of a stage (InitBM before tiling), after the stage's configuration record
/// in its slot ([`crate::g17::fw::Variant::lead_commands`]).
pub(super) const LEAD: usize = 0xc0;
const DEPTH: usize = queues::RENDER_DEPTH as usize;
/// Offsets of the priority pair and the policy word in a queue record.
Expand Down Expand Up @@ -534,7 +534,6 @@ const _: () = {
assert!(abi::FRAGMENT_SLOT_SIZE * RECORDS <= FRAGMENT_BYTES);
assert!(RECORDS * CONFIG_STRIDE <= 0x4000);
assert!(size_of::<queue::QueueConfig>() <= LEAD);
assert!(LEAD + size_of::<queue::FragmentBarrier>() <= CONFIG_STRIDE);
assert!(LEAD + size_of::<queue::InitBufferManager>() <= CONFIG_STRIDE);
};

Expand Down Expand Up @@ -648,14 +647,8 @@ impl Memory {
}

/// Writes the lead commands of `ordinal` from its linked descriptors: InitBM before the
/// tiling descriptor when `init_manager`, and the fragment barrier. Returns which stages
/// have one.
pub(super) fn write_leads(
&mut self,
ordinal: u64,
tiling_kick: fw::kick::KickTimestamp,
init_manager: bool,
) -> Result<[bool; 2]> {
/// tiling descriptor when `init_manager`. Returns which stages have one.
pub(super) fn write_leads(&mut self, ordinal: u64, init_manager: bool) -> Result<[bool; 2]> {
if !self.owns(ordinal) {
return Err(EIO);
}
Expand All @@ -664,23 +657,10 @@ impl Memory {
.descriptors
.pointer(Graph::offset(0, ordinal), size_of::<abi::TaDescriptor>())?
.cast::<abi::TaDescriptor>();
let fragment = self
.graph
.descriptors
.pointer(Graph::offset(1, ordinal), size_of::<abi::FragmentSlot>())?
.cast::<abi::FragmentSlot>();
// SAFETY: Both views were checked during preparation and the ordinal still owns them;
// only integer fields are read.
let (ta, fragment_id) = unsafe { (&*ta, (*fragment).descriptor.current_id) };
// SAFETY: The view was checked during preparation and the ordinal still owns it; only
// integer fields are read.
let ta = unsafe { &*ta };
let slot = ordinal as usize % RECORDS * CONFIG_STRIDE + LEAD;
let barrier = queue::FragmentBarrier::new(
ta.stamp_va,
tiling_kick,
ta.qid,
ta.stamp_value,
fragment_id,
);
self.graph.config.write(CONFIG[1] + slot, barrier)?;
if init_manager {
let init = queue::InitBufferManager::new(
ta.context_id,
Expand All @@ -690,7 +670,7 @@ impl Memory {
);
self.graph.config.write(CONFIG[0] + slot, init)?;
}
Ok([init_manager, true])
Ok([init_manager, false])
}
}

Expand Down