use shdrlib::{AssetManager, RuntimeManager, Language};
use std::fs;
fn main() {
println!("🔥 shdrlib Triangle Demo 🔥\n");
let mut assets = AssetManager::new();
let gpu_info = assets.gpu_info();
println!("GPU: {} ({:?})", gpu_info.name, gpu_info.backend);
println!("Driver: {}\n", gpu_info.driver_info);
let triangle_shader = r#"
@vertex
fn vs_main(@builtin(vertex_index) in_vertex_index: u32) -> @builtin(position) vec4<f32> {
var positions = array<vec2<f32>, 3>(
vec2<f32>(0.0, 0.5),
vec2<f32>(-0.5, -0.5),
vec2<f32>(0.5, -0.5)
);
let pos = positions[in_vertex_index];
return vec4<f32>(pos, 0.0, 1.0);
}
@fragment
fn fs_main() -> @location(0) vec4<f32> {
return vec4<f32>(1.0, 0.0, 0.5, 1.0); // Hot pink
}
"#;
println!("📝 Compiling shaders...");
assets.add_shader(
"triangle_vert",
triangle_shader,
naga::ShaderStage::Vertex,
Language::WGSL,
).expect("Failed to compile vertex shader");
assets.add_shader(
"triangle_frag",
triangle_shader,
naga::ShaderStage::Fragment,
Language::WGSL,
).expect("Failed to compile fragment shader");
println!("✅ Shaders compiled successfully\n");
println!("🔧 Building render pipeline...");
assets.create_pipeline(
"triangle_pipeline",
"triangle_vert",
Some("triangle_frag"),
vec![], wgpu::TextureFormat::Rgba8UnormSrgb,
).expect("Failed to create pipeline");
println!("✅ Pipeline created\n");
let runtime = RuntimeManager::new(&assets);
println!("🎨 Rendering triangle (800x600)...");
let texture = runtime.render_to_texture(
"triangle_pipeline",
800,
600,
wgpu::TextureFormat::Rgba8UnormSrgb,
wgpu::Color {
r: 0.1,
g: 0.1,
b: 0.15,
a: 1.0,
},
3, ).expect("Render failed");
println!("✅ Render complete\n");
println!("📸 Reading back pixel data...");
let bytes_per_pixel = 4; let padded_width = {
let align = wgpu::COPY_BYTES_PER_ROW_ALIGNMENT as u32;
let unpadded_bytes = 800 * bytes_per_pixel;
((unpadded_bytes + align - 1) / align) * align
};
let buffer_size = (padded_width * 600) as u64;
let staging_buffer = assets.device().create_buffer(&wgpu::BufferDescriptor {
label: Some("Readback Buffer"),
size: buffer_size,
usage: wgpu::BufferUsages::COPY_DST | wgpu::BufferUsages::MAP_READ,
mapped_at_creation: false,
});
let mut encoder = assets.device().create_command_encoder(&wgpu::CommandEncoderDescriptor {
label: Some("Readback Encoder"),
});
encoder.copy_texture_to_buffer(
wgpu::ImageCopyTexture {
texture: &texture,
mip_level: 0,
origin: wgpu::Origin3d::ZERO,
aspect: wgpu::TextureAspect::All,
},
wgpu::ImageCopyBuffer {
buffer: &staging_buffer,
layout: wgpu::ImageDataLayout {
offset: 0,
bytes_per_row: Some(padded_width),
rows_per_image: Some(600),
},
},
wgpu::Extent3d {
width: 800,
height: 600,
depth_or_array_layers: 1,
},
);
assets.queue().submit(Some(encoder.finish()));
let buffer_slice = staging_buffer.slice(..);
let (tx, rx) = std::sync::mpsc::channel();
buffer_slice.map_async(wgpu::MapMode::Read, move |result| {
tx.send(result).unwrap();
});
assets.device().poll(wgpu::Maintain::Wait);
rx.recv().unwrap().expect("Failed to map buffer");
{
let data = buffer_slice.get_mapped_range();
let sample_pixel = |x: usize, y: usize| -> (u8, u8, u8, u8) {
let offset = y * padded_width as usize + x * 4;
(data[offset], data[offset + 1], data[offset + 2], data[offset + 3])
};
let center = sample_pixel(400, 300);
println!("Center pixel (400, 300): RGBA({}, {}, {}, {})", center.0, center.1, center.2, center.3);
let corner = sample_pixel(10, 10);
println!("Corner pixel (10, 10): RGBA({}, {}, {}, {})", corner.0, corner.1, corner.2, corner.3);
if center.0 > 200 && center.2 > 100 && center.1 < 50 {
println!("\n✅ SUCCESS: Triangle rendered correctly! Pink detected at center.");
} else {
println!("\n⚠️ WARNING: Unexpected color at center. Triangle might not be visible.");
}
println!("\n💾 Saving render as 'output.ppm'...");
let mut ppm = String::from("P3\n800 600\n255\n");
for y in 0..600 {
for x in 0..800 {
let offset = y * padded_width as usize + x * 4;
let r = data[offset];
let g = data[offset + 1];
let b = data[offset + 2];
ppm.push_str(&format!("{} {} {} ", r, g, b));
}
ppm.push('\n');
}
fs::write("output.ppm", ppm).expect("Failed to write image");
}
staging_buffer.unmap();
println!("✅ Image saved! Open output.ppm to see your triangle\n");
println!("🎉 Demo complete! Your shader pipeline works!");
}