rewrite it in rust #1
|
@ -37,13 +37,13 @@ fn vs_main(
|
||||||
|
|
||||||
// Fragment shader
|
// Fragment shader
|
||||||
@group(0) @binding(0)
|
@group(0) @binding(0)
|
||||||
var u_textures: binding_array<texture_2d<f32>>;
|
var u_texture: texture_2d<f32>;
|
||||||
@group(0) @binding(1)
|
@group(0) @binding(1)
|
||||||
var u_sampler: sampler;
|
var u_sampler: sampler;
|
||||||
|
|
||||||
|
|
||||||
@fragment
|
@fragment
|
||||||
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
|
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
|
||||||
return textureSample(u_textures[0], u_sampler, in.tex_coords);
|
return textureSample(u_texture, u_sampler, in.tex_coords);
|
||||||
// return vec4<f32>(0.3, 0.2, 0.1, 1.0);
|
// return vec4<f32>(0.3, 0.2, 0.1, 1.0);
|
||||||
}
|
}
|
||||||
|
|
26
src/app.rs
26
src/app.rs
|
@ -2,7 +2,7 @@ use imgui::*;
|
||||||
use imgui_wgpu::{Renderer, RendererConfig};
|
use imgui_wgpu::{Renderer, RendererConfig};
|
||||||
use imgui_winit_support::WinitPlatform;
|
use imgui_winit_support::WinitPlatform;
|
||||||
use pollster::block_on;
|
use pollster::block_on;
|
||||||
use std::{num::NonZero, sync::Arc, time::Instant};
|
use std::{sync::Arc, time::Instant};
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
use winit::platform::windows::{CornerPreference, WindowAttributesExtWindows as _};
|
use winit::platform::windows::{CornerPreference, WindowAttributesExtWindows as _};
|
||||||
use winit::{
|
use winit::{
|
||||||
|
@ -69,27 +69,15 @@ impl AppWindow {
|
||||||
}))
|
}))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let (device, queue) = block_on(adapter.request_device(
|
let (device, queue) =
|
||||||
&wgpu::DeviceDescriptor {
|
block_on(adapter.request_device(&wgpu::DeviceDescriptor::default(), None)).unwrap();
|
||||||
required_features: wgpu::Features::TEXTURE_BINDING_ARRAY,
|
|
||||||
..wgpu::DeviceDescriptor::default()
|
|
||||||
},
|
|
||||||
None,
|
|
||||||
))
|
|
||||||
.unwrap();
|
|
||||||
let queue = Arc::new(queue);
|
let queue = Arc::new(queue);
|
||||||
let eyes = [
|
let eyes = Arc::new(GameRenderer::create_texture(&device, "eye"));
|
||||||
Arc::new(GameRenderer::create_texture(&device, "left eye")),
|
|
||||||
Arc::new(GameRenderer::create_texture(&device, "right eye")),
|
|
||||||
];
|
|
||||||
client.send_command(EmulatorCommand::SetRenderer(GameRenderer {
|
client.send_command(EmulatorCommand::SetRenderer(GameRenderer {
|
||||||
queue: queue.clone(),
|
queue: queue.clone(),
|
||||||
eyes: eyes.clone(),
|
eyes: eyes.clone(),
|
||||||
}));
|
}));
|
||||||
let eyes = [
|
let eyes = eyes.create_view(&wgpu::TextureViewDescriptor::default());
|
||||||
eyes[0].create_view(&wgpu::TextureViewDescriptor::default()),
|
|
||||||
eyes[1].create_view(&wgpu::TextureViewDescriptor::default()),
|
|
||||||
];
|
|
||||||
let sampler = device.create_sampler(&wgpu::SamplerDescriptor::default());
|
let sampler = device.create_sampler(&wgpu::SamplerDescriptor::default());
|
||||||
let texture_bind_group_layout =
|
let texture_bind_group_layout =
|
||||||
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||||
|
@ -103,7 +91,7 @@ impl AppWindow {
|
||||||
view_dimension: wgpu::TextureViewDimension::D2,
|
view_dimension: wgpu::TextureViewDimension::D2,
|
||||||
multisampled: false,
|
multisampled: false,
|
||||||
},
|
},
|
||||||
count: NonZero::new(2),
|
count: None,
|
||||||
},
|
},
|
||||||
wgpu::BindGroupLayoutEntry {
|
wgpu::BindGroupLayoutEntry {
|
||||||
binding: 1,
|
binding: 1,
|
||||||
|
@ -119,7 +107,7 @@ impl AppWindow {
|
||||||
entries: &[
|
entries: &[
|
||||||
wgpu::BindGroupEntry {
|
wgpu::BindGroupEntry {
|
||||||
binding: 0,
|
binding: 0,
|
||||||
resource: wgpu::BindingResource::TextureViewArray(&[&eyes[0], &eyes[1]]),
|
resource: wgpu::BindingResource::TextureView(&eyes),
|
||||||
},
|
},
|
||||||
wgpu::BindGroupEntry {
|
wgpu::BindGroupEntry {
|
||||||
binding: 1,
|
binding: 1,
|
||||||
|
|
|
@ -33,7 +33,7 @@ impl Emulator {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(&mut self) {
|
pub fn run(&mut self) {
|
||||||
let mut eye_contents = [vec![0u8; 384 * 224], vec![0u8; 384 * 224]];
|
let mut eye_contents = vec![0u8; 384 * 224 * 2];
|
||||||
loop {
|
loop {
|
||||||
self.sim.emulate_frame();
|
self.sim.emulate_frame();
|
||||||
if let Some(renderer) = &mut self.renderer {
|
if let Some(renderer) = &mut self.renderer {
|
||||||
|
|
|
@ -8,18 +8,13 @@ use wgpu::{
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct GameRenderer {
|
pub struct GameRenderer {
|
||||||
pub queue: Arc<Queue>,
|
pub queue: Arc<Queue>,
|
||||||
pub eyes: [Arc<Texture>; 2],
|
pub eyes: Arc<Texture>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GameRenderer {
|
impl GameRenderer {
|
||||||
pub fn render(&self, buffers: &[Vec<u8>; 2]) {
|
pub fn render(&self, buffer: &[u8]) {
|
||||||
for (texture, buffer) in self.eyes.iter().zip(buffers) {
|
|
||||||
self.update_texture(texture, buffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn update_texture(&self, texture: &Texture, buffer: &[u8]) {
|
|
||||||
let texture = ImageCopyTexture {
|
let texture = ImageCopyTexture {
|
||||||
texture,
|
texture: &self.eyes,
|
||||||
mip_level: 0,
|
mip_level: 0,
|
||||||
origin: Origin3d::ZERO,
|
origin: Origin3d::ZERO,
|
||||||
aspect: wgpu::TextureAspect::All,
|
aspect: wgpu::TextureAspect::All,
|
||||||
|
@ -31,7 +26,7 @@ impl GameRenderer {
|
||||||
};
|
};
|
||||||
let data_layout = ImageDataLayout {
|
let data_layout = ImageDataLayout {
|
||||||
offset: 0,
|
offset: 0,
|
||||||
bytes_per_row: Some(384),
|
bytes_per_row: Some(384 * 2),
|
||||||
rows_per_image: Some(224),
|
rows_per_image: Some(224),
|
||||||
};
|
};
|
||||||
self.queue.write_texture(texture, buffer, data_layout, size);
|
self.queue.write_texture(texture, buffer, data_layout, size);
|
||||||
|
@ -47,11 +42,11 @@ impl GameRenderer {
|
||||||
mip_level_count: 1,
|
mip_level_count: 1,
|
||||||
sample_count: 1,
|
sample_count: 1,
|
||||||
dimension: wgpu::TextureDimension::D2,
|
dimension: wgpu::TextureDimension::D2,
|
||||||
format: TextureFormat::R8Unorm,
|
format: TextureFormat::Rg8Unorm,
|
||||||
usage: TextureUsages::COPY_SRC
|
usage: TextureUsages::COPY_SRC
|
||||||
| TextureUsages::COPY_DST
|
| TextureUsages::COPY_DST
|
||||||
| TextureUsages::TEXTURE_BINDING,
|
| TextureUsages::TEXTURE_BINDING,
|
||||||
view_formats: &[TextureFormat::R8Unorm],
|
view_formats: &[TextureFormat::Rg8Unorm],
|
||||||
};
|
};
|
||||||
device.create_texture(&desc)
|
device.create_texture(&desc)
|
||||||
}
|
}
|
||||||
|
|
|
@ -113,7 +113,7 @@ impl CoreVB {
|
||||||
unsafe { vb_emulate(self.sim, &mut cycles) };
|
unsafe { vb_emulate(self.sim, &mut cycles) };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_pixels(&mut self, buffers: &mut [Vec<u8>; 2]) -> bool {
|
pub fn read_pixels(&mut self, buffers: &mut [u8]) -> bool {
|
||||||
// SAFETY: the *mut VB owns its userdata.
|
// SAFETY: the *mut VB owns its userdata.
|
||||||
// There is no way for the userdata to be null or otherwise invalid.
|
// There is no way for the userdata to be null or otherwise invalid.
|
||||||
let data: &mut VBState = unsafe { &mut *vb_get_user_data(self.sim).cast() };
|
let data: &mut VBState = unsafe { &mut *vb_get_user_data(self.sim).cast() };
|
||||||
|
@ -122,17 +122,17 @@ impl CoreVB {
|
||||||
}
|
}
|
||||||
data.frame_seen = false;
|
data.frame_seen = false;
|
||||||
|
|
||||||
assert_eq!(buffers[0].len(), 384 * 224);
|
// the buffer must be big enough for our data
|
||||||
assert_eq!(buffers[1].len(), 384 * 224);
|
assert!(buffers.len() >= 384 * 224 * 2);
|
||||||
unsafe {
|
unsafe {
|
||||||
vb_get_pixels(
|
vb_get_pixels(
|
||||||
self.sim,
|
self.sim,
|
||||||
buffers[0].as_mut_ptr().cast(),
|
buffers.as_mut_ptr().cast(),
|
||||||
1,
|
2,
|
||||||
384,
|
384 * 2,
|
||||||
buffers[1].as_mut_ptr().cast(),
|
buffers.as_mut_ptr().offset(1).cast(),
|
||||||
1,
|
2,
|
||||||
384,
|
384 * 2,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
true
|
true
|
||||||
|
|
Loading…
Reference in New Issue