Skip to content

Commit 69afc32

Browse files
committed
Slightly optimize 3D rendering
1 parent d63c2e3 commit 69afc32

File tree

5 files changed

+99
-71
lines changed

5 files changed

+99
-71
lines changed

core/src/cpu/psr.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
use crate::utils::Savestate;
22

33
mod bounded {
4-
use crate::utils::bounded_int_lit;
4+
use crate::utils::{bounded_int_from_into, bounded_int_lit};
55
bounded_int_lit!(pub struct Mode(u8), max 0xF);
6+
bounded_int_from_into!(Mode(u8));
67
}
78
pub use bounded::Mode;
89

core/src/gpu/engine_3d.rs

+53-38
Original file line numberDiff line numberDiff line change
@@ -130,37 +130,48 @@ enum PrimitiveType {
130130
}
131131

132132
mod bounded {
133-
use crate::utils::{bounded_int_lit, bounded_int_savestate};
133+
use crate::utils::{bounded_int_lit, bounded_int_savestate, bounded_int_unsafe_from_into};
134134
bounded_int_lit!(pub struct PrimVertIndex(u8), max 3);
135135
bounded_int_savestate!(PrimVertIndex(u8));
136136
bounded_int_lit!(pub struct PrimMaxVerts(u8), max 4);
137137
bounded_int_savestate!(PrimMaxVerts(u8));
138138
bounded_int_lit!(pub struct PolyVertIndex(u8), max 9);
139-
bounded_int_savestate!(PolyVertIndex(u8));
140139
bounded_int_lit!(pub struct PolyVertsLen(u8), max 10);
141-
bounded_int_savestate!(PolyVertsLen(u8));
140+
bounded_int_unsafe_from_into!(PolyVertsLen(u8));
142141
bounded_int_lit!(pub struct PolyAddr(u16), max 2047);
143-
bounded_int_savestate!(PolyAddr(u16));
144142
bounded_int_lit!(pub struct VertexAddr(u16), max 6143);
145143
bounded_int_savestate!(VertexAddr(u16));
146144
}
147145
pub use bounded::{PolyAddr, PolyVertIndex, PolyVertsLen, VertexAddr};
148146
use bounded::{PrimMaxVerts, PrimVertIndex};
149147

148+
proc_bitfield::bitfield! {
149+
#[derive(Clone, Copy, PartialEq, Eq, Savestate)]
150+
pub struct RenderingPolygonAttrs(u32): Debug {
151+
pub raw: u32 [read_only] @ ..,
152+
pub verts_len: u8 [unsafe PolyVertsLen] @ 0..=3,
153+
pub mode: u8 @ 4..=5,
154+
pub update_depth_for_translucent: bool @ 11,
155+
pub depth_test_equal: bool @ 14,
156+
pub fog_enabled: bool @ 15,
157+
pub alpha: u8 @ 16..=20,
158+
pub id: u8 @ 24..=29,
159+
pub is_front_facing: bool @ 30,
160+
pub is_translucent: bool @ 30,
161+
}
162+
}
163+
150164
#[derive(Clone, Copy, Debug, PartialEq, Eq, Savestate)]
151165
#[repr(C)]
152166
pub struct Polygon {
153-
pub vertices: [VertexAddr; 10],
167+
pub verts: [VertexAddr; 10],
154168
pub depth_values: [u32; 10],
155169
pub w_values: [u16; 10],
156170
pub top_y: u8,
157171
pub bot_y: u8,
158-
pub vertices_len: PolyVertsLen,
159-
pub attrs: PolygonAttrs,
160-
pub is_front_facing: bool,
161-
pub is_translucent: bool,
162-
pub tex_params: TextureParams,
163172
pub tex_palette_base: u16,
173+
pub tex_params: TextureParams,
174+
pub attrs: RenderingPolygonAttrs,
164175
}
165176

166177
proc_bitfield::bitfield! {
@@ -936,7 +947,7 @@ impl Engine3d {
936947
};
937948
}
938949

939-
macro_rules! run_pass {
950+
macro_rules! run_clip_pass {
940951
($axis_i: expr, $clip_far: expr, $input: expr$(, $assume_init: ident)? => $output: expr) => {
941952
let input_len = replace(&mut clipped_verts_len, shared_verts);
942953
for (i, vert) in $input[..input_len].iter().enumerate().skip(shared_verts) {
@@ -1004,6 +1015,7 @@ impl Engine3d {
10041015
}
10051016
}
10061017
if clipped_verts_len == 0 {
1018+
self.connect_to_last_strip_prim = false;
10071019
return;
10081020
}
10091021
};
@@ -1022,43 +1034,48 @@ impl Engine3d {
10221034
buffer_0[i] = MaybeUninit::new(self.cur_prim_verts[i]);
10231035
buffer_1[i] = MaybeUninit::new(self.cur_prim_verts[i]);
10241036
}
1025-
run_pass!(2, self.cur_poly_attrs.clip_far_plane(), self.cur_prim_verts => buffer_0);
1037+
run_clip_pass!(2, self.cur_poly_attrs.clip_far_plane(), self.cur_prim_verts => buffer_0);
10261038
unsafe {
1027-
run_pass!(1, true, buffer_0, assume_init_ref => buffer_1);
1028-
run_pass!(0, true, buffer_1, assume_init_ref => buffer_0);
1039+
run_clip_pass!(1, true, buffer_0, assume_init_ref => buffer_1);
1040+
run_clip_pass!(0, true, buffer_1, assume_init_ref => buffer_0);
10291041
}
1042+
let clipped_verts =
1043+
unsafe { MaybeUninit::slice_assume_init_mut(&mut buffer_0[..clipped_verts_len]) };
10301044

10311045
if self.vert_ram_level as usize > self.vert_ram.len() - (clipped_verts_len - shared_verts) {
10321046
self.rendering_state
10331047
.control
10341048
.set_poly_vert_ram_overflow(true);
1049+
self.connect_to_last_strip_prim = false;
10351050
return;
10361051
}
10371052

1053+
let is_translucent = matches!(self.cur_poly_attrs.alpha(), 1..=30)
1054+
|| (matches!(self.cur_poly_attrs.mode(), 0 | 2)
1055+
&& matches!(self.tex_params.format(), 1 | 6));
1056+
10381057
let poly = &mut self.poly_ram[self.poly_ram_level as usize];
10391058
self.poly_ram_level += 1;
1040-
poly.vertices_len = PolyVertsLen::new(clipped_verts_len as u8);
10411059
poly.tex_palette_base = self.tex_palette_base;
10421060
poly.tex_params = self.tex_params;
1043-
poly.attrs = self.cur_poly_attrs;
1044-
poly.is_front_facing = is_front_facing;
1045-
poly.is_translucent = matches!(poly.attrs.alpha(), 1..=30)
1046-
|| (matches!(poly.attrs.mode(), 0 | 2) && matches!(poly.tex_params.format(), 1 | 6));
1061+
poly.attrs = RenderingPolygonAttrs(self.cur_poly_attrs.0)
1062+
.with_verts_len(PolyVertsLen::new(clipped_verts_len as u8))
1063+
.with_is_front_facing(is_front_facing)
1064+
.with_is_translucent(is_translucent);
10471065

10481066
if connect_to_last_strip_prim {
1049-
poly.vertices[..2].copy_from_slice(&self.last_strip_prim_vert_indices);
1067+
poly.verts[..2].copy_from_slice(&self.last_strip_prim_vert_indices);
10501068
}
10511069

10521070
let mut top_y = 0xFF;
10531071
let mut bot_y = 0;
10541072

10551073
let viewport_origin = self.viewport_origin;
10561074
let viewport_size = self.viewport_size;
1057-
for (vert, vert_addr) in buffer_0[shared_verts..clipped_verts_len]
1075+
for (vert, vert_addr) in clipped_verts[shared_verts..]
10581076
.iter_mut()
1059-
.zip(&mut poly.vertices[shared_verts..clipped_verts_len])
1077+
.zip(&mut poly.verts[shared_verts..clipped_verts_len])
10601078
{
1061-
let vert = unsafe { vert.assume_init_mut() };
10621079
vert.coords[3] &= 0x00FF_FFFF;
10631080
let w = vert.coords[3] as u32;
10641081
let coords = if w == 0 {
@@ -1114,7 +1131,7 @@ impl Engine3d {
11141131
self.vert_ram_level += 1;
11151132
}
11161133

1117-
for &vert_addr in &poly.vertices[..shared_verts] {
1134+
for &vert_addr in &poly.verts[..shared_verts] {
11181135
let y = self.vert_ram[vert_addr.get() as usize].coords[1] as u8;
11191136
top_y = top_y.min(y);
11201137
bot_y = bot_y.max(y);
@@ -1124,26 +1141,24 @@ impl Engine3d {
11241141
poly.bot_y = bot_y;
11251142

11261143
let mut w_leading_zeros = 32;
1127-
for vert in &buffer_0[..clipped_verts_len] {
1128-
w_leading_zeros =
1129-
w_leading_zeros.min(unsafe { vert.assume_init_ref() }.coords[3].leading_zeros());
1144+
for vert in clipped_verts.iter() {
1145+
w_leading_zeros = w_leading_zeros.min(vert.coords[3].leading_zeros());
11301146
}
11311147
w_leading_zeros &= !3;
11321148

11331149
if w_leading_zeros >= 16 {
11341150
let shift = w_leading_zeros - 16;
1135-
for (i, vert) in buffer_0[..clipped_verts_len].iter().enumerate() {
1136-
poly.w_values[i] = (unsafe { vert.assume_init_ref() }.coords[3] << shift) as u16;
1151+
for (i, vert) in clipped_verts.iter().enumerate() {
1152+
poly.w_values[i] = (vert.coords[3] << shift) as u16;
11371153
}
11381154
} else {
11391155
let shift = 16 - w_leading_zeros;
1140-
for (i, vert) in buffer_0[..clipped_verts_len].iter().enumerate() {
1141-
poly.w_values[i] = (unsafe { vert.assume_init_ref() }.coords[3] >> shift) as u16;
1156+
for (i, vert) in clipped_verts.iter().enumerate() {
1157+
poly.w_values[i] = (vert.coords[3] >> shift) as u16;
11421158
}
11431159
}
11441160

1145-
for (i, vert) in buffer_0[..clipped_verts_len].iter().enumerate() {
1146-
let vert = unsafe { vert.assume_init_ref() };
1161+
for (i, vert) in clipped_verts.iter().enumerate() {
11471162
let w = vert.coords[3] as u32;
11481163
poly.depth_values[i] = if self.rendering_state.w_buffering {
11491164
w & !((((1_u64 << (32 - w_leading_zeros)) - 1) as u32) >> 16)
@@ -1160,14 +1175,14 @@ impl Engine3d {
11601175
match self.cur_prim_type {
11611176
PrimitiveType::TriangleStrip => {
11621177
self.last_strip_prim_vert_indices = if self.cur_strip_prim_is_odd {
1163-
[poly.vertices[0], poly.vertices[2]]
1178+
[poly.verts[0], poly.verts[2]]
11641179
} else {
1165-
[poly.vertices[2], poly.vertices[1]]
1180+
[poly.verts[2], poly.verts[1]]
11661181
};
11671182
}
11681183

11691184
PrimitiveType::QuadStrip => {
1170-
self.last_strip_prim_vert_indices = [poly.vertices[3], poly.vertices[2]];
1185+
self.last_strip_prim_vert_indices = [poly.verts[3], poly.verts[2]];
11711186
}
11721187

11731188
_ => {}
@@ -1201,7 +1216,7 @@ impl Engine3d {
12011216
{
12021217
emu.gpu.engine_3d.poly_ram[..emu.gpu.engine_3d.poly_ram_level as usize]
12031218
.sort_by_key(|poly| {
1204-
if poly.is_translucent {
1219+
if poly.attrs.is_translucent() {
12051220
0x1_0000
12061221
} else {
12071222
(poly.bot_y as u32) << 8 | poly.top_y as u32
@@ -1210,7 +1225,7 @@ impl Engine3d {
12101225
} else {
12111226
emu.gpu.engine_3d.poly_ram[..emu.gpu.engine_3d.poly_ram_level as usize]
12121227
.sort_by_key(|poly| {
1213-
(poly.is_translucent as u32) << 16
1228+
(poly.attrs.is_translucent() as u32) << 16
12141229
| (poly.bot_y as u32) << 8
12151230
| poly.top_y as u32
12161231
});

core/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
adt_const_params,
66
doc_cfg,
77
maybe_uninit_uninit_array,
8+
maybe_uninit_slice,
89
portable_simd,
910
new_uninit
1011
)]

0 commit comments

Comments
 (0)