Use one texture with two channels for video
This commit is contained in:
		
							parent
							
								
									8fdff927eb
								
							
						
					
					
						commit
						b025f72604
					
				| 
						 | 
					@ -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