Skip to main content
← PSoXide SDK guides and examples · SDK f2fec1c301f1 · All Cargo features enabled; check feature gates before use.

psx_residency/
host.rs

1//! The edge of the crate: what the engine asks of its host, and what it hands
2//! to the transport.
3
4use crate::key::{Class, ResourceKey};
5use crate::pool::{Handle, PageRun};
6
7/// Where a resource lives on the disc and how much room it needs.
8#[derive(Copy, Clone, Debug, PartialEq, Eq)]
9pub struct Extent {
10    /// First sector of the resource on the disc.
11    pub lba: u32,
12    /// Sectors to read.
13    pub sectors: u32,
14    /// Pages the resource needs in its pool (equal to `sectors` for RAM
15    /// pages, one per slot for texture pages).
16    pub pages: u32,
17    /// Payload length in bytes (at most `pages` pages).
18    pub bytes: u32,
19}
20
21/// Identifies one read request from submission until its outcome is reported.
22#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
23pub struct RequestId(pub u32);
24
25/// One read for the transport to perform: `sectors` sectors from `lba` into
26/// `run` of the pool named by `handle`, sector `n` landing at page
27/// `run.first_page + n`.
28#[derive(Copy, Clone, Debug, PartialEq, Eq)]
29pub struct ReadRequest {
30    /// Identity to report the outcome against.
31    pub id: RequestId,
32    /// The resource being read.
33    pub key: ResourceKey,
34    /// Priority class at submission (see [`Host::promote`]).
35    pub class: Class,
36    /// Allocation the sectors land in.
37    pub handle: Handle,
38    /// The pages of that allocation.
39    pub run: PageRun,
40    /// First sector on the disc.
41    pub lba: u32,
42    /// Sector count.
43    pub sectors: u32,
44    /// Ticks until the data is needed, as the engine's wanted entry said
45    /// (`u32::MAX` when unknown). Earliest deadline first inside a class.
46    pub deadline_ticks: u32,
47    /// An in-flight request that ends exactly at `lba`. A transport can chain
48    /// the two without a seek.
49    pub contiguous_with: Option<RequestId>,
50}
51
52/// A transport's answer to [`Host::submit`].
53#[derive(Copy, Clone, Debug, PartialEq, Eq)]
54pub enum Submit {
55    /// The request is queued.
56    Accepted,
57    /// The queue is full; nothing was queued.
58    Full,
59}
60
61/// How a request ended, reported with [`crate::Residency::complete_read`].
62#[derive(Copy, Clone, Debug, PartialEq, Eq)]
63pub enum ReadOutcome {
64    /// Every sector landed.
65    Done,
66    /// The read failed (drive error, checksum). The resource backs off.
67    Failed,
68    /// The transport stopped the request after [`Host::cancel`]; no sector
69    /// will land in the pages any more.
70    Cancelled,
71}
72
73/// Pages freed by an eviction, reported by [`crate::Residency::step`]. Unlink
74/// the resource (patch the parent, drop cached views) before using resident
75/// data again; the handle is already stale.
76#[derive(Copy, Clone, Debug, PartialEq, Eq)]
77pub struct Eviction {
78    /// The evicted resource.
79    pub key: ResourceKey,
80    /// Its former allocation (stale now).
81    pub handle: Handle,
82    /// The pages it held.
83    pub run: PageRun,
84}
85
86impl Eviction {
87    /// A placeholder for initialising an eviction buffer
88    /// (`[Eviction::NONE; 8]`); [`crate::Residency::step`] overwrites the
89    /// entries it reports.
90    pub const NONE: Eviction = Eviction {
91        key: match ResourceKey::from_u32(0) {
92            Some(key) => key,
93            None => panic!("key 0 is valid"),
94        },
95        handle: Handle::NONE,
96        run: PageRun {
97            first_page: 0,
98            page_count: 0,
99        },
100    };
101}
102
103/// Everything the engine needs from the game, the region graph and the
104/// transport. One value implements it; the engine borrows it for a call.
105pub trait Host {
106    /// Disc position and size of `key`, or `None` when the key is unknown.
107    fn extent(&self, key: ResourceKey) -> Option<Extent>;
108
109    /// Walk distance from the viewer to `key`, in the same units as
110    /// [`crate::Wanted::distance`]. Asked only for resident resources the
111    /// current wanted list did not mention, when eviction needs to rank them.
112    fn walk_distance(&self, key: ResourceKey) -> u32;
113
114    /// Whether the transport can take another request right now.
115    fn can_accept(&self) -> bool {
116        true
117    }
118
119    /// Queue `request`. A [`Submit::Full`] answer rolls the allocation back.
120    fn submit(&mut self, request: &ReadRequest) -> Submit;
121
122    /// Stop `request`. The transport reports [`ReadOutcome::Cancelled`] (or
123    /// [`ReadOutcome::Done`] if the sectors had already landed) through
124    /// [`crate::Residency::complete_read`]; the pages stay reserved until then.
125    fn cancel(&mut self, request: RequestId);
126
127    /// A request already in flight is now wanted at a more urgent class.
128    fn promote(&mut self, _request: RequestId, _class: Class) {}
129
130    /// Move `page_count` pages of `pool` from `from_page` to `to_page` (a
131    /// `memmove`). Called only for categories configured as movable.
132    fn move_pages(&mut self, _pool: u8, _from_page: u32, _to_page: u32, _page_count: u32) {}
133}