use std::time::Instant;
const WIDTH: usize = 1280;
const HEIGHT: usize = 720;
const TEX_SIZE: usize = 1024;
fn build_texture() -> Vec<u32> {
let mut tex = vec![0u32; TEX_SIZE * TEX_SIZE];
for y in 0..TEX_SIZE {
for x in 0..TEX_SIZE {
let r = (x as u8).wrapping_mul(7).wrapping_add(y as u8).wrapping_mul(3);
let g = (x as u8).wrapping_mul(11).wrapping_add(y as u8).wrapping_mul(5);
let b = (x as u8).wrapping_mul(2).wrapping_add(y as u8).wrapping_mul(7);
tex[y * TEX_SIZE + x] = 0xFF000000
| ((r as u32) << 16)
| ((g as u32) << 8)
| (b as u32);
}
}
tex
}
#[inline(always)]
fn fragment_full_shader(
x: u32, y: u32, frame: u32,
texture: &[u32],
depth_buf: &mut [f32],
color_buf: &mut [u32],
) {
let x_f = x as f32 / WIDTH as f32;
let y_f = y as f32 / HEIGHT as f32;
let t = frame as f32 * 0.01_f32;
let uv_x = ((x_f * 4.0_f32 + t).sin() * 0.5_f32 + 0.5_f32) * TEX_SIZE as f32;
let uv_y = ((y_f * 4.0_f32 + t).cos() * 0.5_f32 + 0.5_f32) * TEX_SIZE as f32;
let tx0 = ((uv_x as i32).rem_euclid(TEX_SIZE as i32)) as usize;
let ty0 = ((uv_y as i32).rem_euclid(TEX_SIZE as i32)) as usize;
let texel = texture[ty0 * TEX_SIZE + tx0];
let tr = ((texel >> 16) & 0xFF) as f32 / 255.0_f32;
let tg = ((texel >> 8) & 0xFF) as f32 / 255.0_f32;
let tb = (texel & 0xFF) as f32 / 255.0_f32;
let nx = (x_f * 6.0_f32).sin();
let ny = (y_f * 6.0_f32).cos();
let mut total_intensity: f32 = 0.0_f32;
for l in 0..4i32 {
let angle = (t * 3.14159_f32 / 2.0_f32) + (l as f32) * 1.57079_f32;
let lx = angle.cos();
let ly = angle.sin();
let lz = 1.0_f32;
let lambert = (nx * lx + ny * ly + 1.0_f32 * lz).max(0.0_f32) * 0.6_f32;
total_intensity += lambert;
}
total_intensity = total_intensity.clamp(0.0_f32, 1.5_f32);
let r = (tr * total_intensity * 255.0_f32) as u32;
let g = (tg * total_intensity * 255.0_f32) as u32;
let b_val = (tb * total_intensity * 255.0_f32) as u32;
let _a: u32 = 255;
let depth = (y as f32 / HEIGHT as f32) + (t.sin() * 0.1_f32);
let buf_idx = y as usize * WIDTH + x as usize;
if depth < depth_buf[buf_idx] {
depth_buf[buf_idx] = depth;
let old = color_buf[buf_idx];
let old_r = (old >> 16) & 0xFF;
let old_g = (old >> 8) & 0xFF;
let old_b = old & 0xFF;
let nr = (r as u64 + (old_r as u64) * 3 / 10).min(255) as u32;
let ng = (g as u64 + (old_g as u64) * 3 / 10).min(255) as u32;
let nb = (b_val as u64 + (old_b as u64) * 3 / 10).min(255) as u32;
color_buf[buf_idx] = (255_u32 << 24) | (nr << 16) | (ng << 8) | nb;
}
}
#[inline(never)]
fn render_full_frame(
color_buf: &mut [u32],
depth_buf: &mut [f32],
frame: u32,
texture: &[u32],
) {
for y in 0..HEIGHT as u32 {
for x in 0..WIDTH as u32 {
fragment_full_shader(x, y, frame, texture, depth_buf, color_buf);
}
}
}
fn main() {
println!("Aetheric Silicon — FULL-PIPELINE Software Rasterizer");
println!("Target: 1280x720 (720p) at 30+ fps on X5680");
println!("Workload per pixel: 4-light Lambert + texture sample + depth test + alpha blend\n");
let mut color_buf = vec![0xFF101018u32; WIDTH * HEIGHT];
let mut depth_buf = vec![1.0_f32; WIDTH * HEIGHT];
let texture = build_texture();
println!("Frame color buffer: {} KiB", color_buf.len() * 4 / 1024);
println!("Frame depth buffer: {} KiB", depth_buf.len() * 4 / 1024);
println!("Texture memory: {} MiB", texture.len() * 4 / (1024 * 1024));
println!("\nRunning warm-up + 30 measured frames...\n");
for f in 0..3 {
render_full_frame(&mut color_buf, &mut depth_buf, f, &texture);
}
let n_frames = 30;
let start = Instant::now();
let mut checksum = 0u64;
for f in 3..(3 + n_frames) {
render_full_frame(&mut color_buf, &mut depth_buf, f, &texture);
checksum = checksum.wrapping_add(color_buf[((f as usize) * WIDTH + 7) % color_buf.len()] as u64);
checksum = checksum.wrapping_add(depth_buf[((f as usize) * WIDTH + 11) % depth_buf.len()].to_bits() as u64);
}
let elapsed = start.elapsed();
println!("checksum (prevents DCE): 0x{:016x}", checksum);
let ms_per_frame = elapsed.as_secs_f64() * 1000.0 / n_frames as f64;
let fps = n_frames as f64 / elapsed.as_secs_f64();
let mpix_s = (WIDTH * HEIGHT) as f64 * fps / 1e6;
println!("--- RESULTS ---");
println!("Time / frame: {:.2} ms ({:.1} fps)", ms_per_frame, fps);
println!("Pixels / sec: {:.1} Mpixels/s", mpix_s);
println!("Total bench time: {:.2} seconds", elapsed.as_secs_f64());
println!("\n--- COMPARISON ---");
let target_fps = 30.0_f64;
if fps >= target_fps {
println!("[v] HIT the 30 fps full-pipeline target on X5680");
} else {
println!("[x] below 30 fps full pipeline (got {:.1} fps)", fps);
}
println!("\nFor reference: dGPU at 1080p60 heavy games = ~120 Mpixels/s");
println!("Ratio: {:.2}x of dGPU pixel rate", mpix_s / 120.0);
}