-
-
Save bczhc/e8d11db2280ffd20fee43fb1fed7410e to your computer and use it in GitHub Desktop.
vkd3d issue
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| use std::env; | |
| use std::sync::Arc; | |
| use wgpu::util::RenderEncoder; | |
| use winit::{ | |
| application::ApplicationHandler, | |
| event::WindowEvent, | |
| event_loop::{ActiveEventLoop, ControlFlow, EventLoop}, | |
| window::{Window, WindowId}, | |
| }; | |
| #[derive(Default)] | |
| struct App { | |
| state: Option<render::State>, | |
| window: Option<Arc<Window>>, | |
| } | |
| macro_rules! default { | |
| () => { | |
| Default::default() | |
| }; | |
| } | |
| impl ApplicationHandler for App { | |
| fn resumed(&mut self, event_loop: &ActiveEventLoop) { | |
| // Create window object | |
| let window = Arc::new( | |
| event_loop | |
| .create_window(Window::default_attributes()) | |
| .unwrap(), | |
| ); | |
| let state = pollster::block_on(render::State::new(window.clone())); | |
| self.state = Some(state); | |
| window.request_redraw(); | |
| self.window = Some(Arc::clone(&window)); | |
| } | |
| fn window_event(&mut self, event_loop: &ActiveEventLoop, _id: WindowId, event: WindowEvent) { | |
| let state = self.state.as_mut().unwrap(); | |
| match event { | |
| WindowEvent::CloseRequested => { | |
| println!("The close button was pressed; stopping"); | |
| event_loop.exit(); | |
| } | |
| WindowEvent::RedrawRequested => { | |
| if let Some(w) = self.window.as_ref() { | |
| state.render(|| w.pre_present_notify()); | |
| w.request_redraw(); | |
| } | |
| } | |
| WindowEvent::Resized(size) => { | |
| // Reconfigures the size of the surface. We do not re-render | |
| // here as this event is always followed up by redraw request. | |
| state.resize(size); | |
| } | |
| _ => {} | |
| } | |
| } | |
| } | |
| fn main() { | |
| unsafe { | |
| env::set_var("RUST_LOG", "info"); | |
| } | |
| env_logger::init(); | |
| let event_loop = EventLoop::new().unwrap(); | |
| event_loop.set_control_flow(ControlFlow::Poll); | |
| let mut app = App::default(); | |
| event_loop.run_app(&mut app).unwrap(); | |
| } | |
| mod render { | |
| use clap::Parser; | |
| use std::fs::File; | |
| use std::io::Read; | |
| use std::path::PathBuf; | |
| use std::sync::Arc; | |
| use wgpu::{ | |
| BackendOptions, Backends, Color, ColorTargetState, CurrentSurfaceTexture, Features, | |
| FragmentState, Instance, InstanceDescriptor, InstanceFlags, MemoryBudgetThresholds | |
| , PipelineLayoutDescriptor, RenderPipeline, RenderPipelineDescriptor | |
| , ShaderModuleDescriptorPassthrough, VertexState, | |
| }; | |
| use winit::window::Window; | |
| pub struct State { | |
| device: wgpu::Device, | |
| queue: wgpu::Queue, | |
| size: winit::dpi::PhysicalSize<u32>, | |
| surface: wgpu::Surface<'static>, | |
| surface_format: wgpu::TextureFormat, | |
| pipeline: RenderPipeline, | |
| } | |
| #[derive(Parser)] | |
| struct Args { | |
| hlsl_file: PathBuf, | |
| vs_entry: String, | |
| } | |
| fn parse_cli_args() -> Args { | |
| Args::parse() | |
| } | |
| impl State { | |
| pub async fn new(window: Arc<Window>) -> State { | |
| let instance = Instance::new(InstanceDescriptor { | |
| backends: Backends::from_env().unwrap_or_default(), | |
| backend_options: BackendOptions::default(), | |
| display: None, | |
| flags: InstanceFlags::default(), | |
| memory_budget_thresholds: MemoryBudgetThresholds::default(), | |
| }); | |
| let adapter = instance | |
| .request_adapter(&wgpu::RequestAdapterOptions::default()) | |
| .await | |
| .unwrap(); | |
| let (device, queue) = adapter | |
| .request_device(&wgpu::DeviceDescriptor { | |
| required_features: Features::PASSTHROUGH_SHADERS, | |
| ..default!() | |
| }) | |
| .await | |
| .unwrap(); | |
| let size = window.inner_size(); | |
| let surface = instance.create_surface(window.clone()).unwrap(); | |
| let cap = surface.get_capabilities(&adapter); | |
| let surface_format = cap.formats[0]; | |
| let args = parse_cli_args(); | |
| let mut hlsl_code = String::new(); | |
| File::open(args.hlsl_file) | |
| .unwrap() | |
| .read_to_string(&mut hlsl_code) | |
| .unwrap(); | |
| let shader_module = unsafe { | |
| device.create_shader_module_passthrough(ShaderModuleDescriptorPassthrough { | |
| label: None, | |
| num_workgroups: (1, 1, 1), | |
| spirv: None, | |
| dxil: None, | |
| hlsl: Some(hlsl_code.into()), | |
| metallib: None, | |
| msl: None, | |
| glsl: None, | |
| wgsl: None, | |
| }) | |
| }; | |
| let pipeline_layout = device.create_pipeline_layout(&PipelineLayoutDescriptor { | |
| label: None, | |
| bind_group_layouts: &[], | |
| immediate_size: 0, | |
| }); | |
| let pipeline = device.create_render_pipeline(&RenderPipelineDescriptor { | |
| vertex: VertexState { | |
| module: &shader_module, | |
| entry_point: Some(&args.vs_entry), | |
| compilation_options: Default::default(), | |
| buffers: default!(), | |
| }, | |
| fragment: Some(FragmentState { | |
| module: &shader_module, | |
| entry_point: Some("fs_main"), | |
| compilation_options: Default::default(), | |
| targets: &[Some(ColorTargetState { | |
| format: surface_format.add_srgb_suffix(), | |
| blend: None, | |
| write_mask: Default::default(), | |
| })], | |
| }), | |
| label: None, | |
| layout: Some(&pipeline_layout), | |
| primitive: default!(), | |
| depth_stencil: None, | |
| multisample: Default::default(), | |
| multiview_mask: None, | |
| cache: None, | |
| }); | |
| let state = State { | |
| device, | |
| queue, | |
| size, | |
| surface, | |
| surface_format, | |
| pipeline, | |
| }; | |
| // Configure surface for the first time | |
| state.configure_surface(); | |
| state | |
| } | |
| fn configure_surface(&self) { | |
| let surface_config = wgpu::SurfaceConfiguration { | |
| usage: wgpu::TextureUsages::RENDER_ATTACHMENT, | |
| format: self.surface_format, | |
| // Request compatibility with the sRGB-format texture view we‘re going to create later. | |
| view_formats: vec![self.surface_format.add_srgb_suffix()], | |
| alpha_mode: wgpu::CompositeAlphaMode::Auto, | |
| width: self.size.width, | |
| height: self.size.height, | |
| desired_maximum_frame_latency: 2, | |
| present_mode: wgpu::PresentMode::AutoVsync, | |
| }; | |
| self.surface.configure(&self.device, &surface_config); | |
| } | |
| pub fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) { | |
| self.size = new_size; | |
| // reconfigure the surface | |
| self.configure_surface(); | |
| } | |
| pub fn render(&mut self, before_submit: impl FnOnce()) { | |
| // Create texture view | |
| let surface_texture = self.surface.get_current_texture(); | |
| let surface_texture = match surface_texture { | |
| CurrentSurfaceTexture::Success(x) => x, | |
| _ => { | |
| return; | |
| } | |
| }; | |
| let texture_view = surface_texture | |
| .texture | |
| .create_view(&wgpu::TextureViewDescriptor { | |
| // Without add_srgb_suffix() the image we will be working with | |
| // might not be "gamma correct". | |
| format: Some(self.surface_format.add_srgb_suffix()), | |
| ..Default::default() | |
| }); | |
| // Renders a gray screen | |
| let mut encoder = self.device.create_command_encoder(&Default::default()); | |
| // Create the renderpass which will clear the screen. | |
| let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { | |
| label: None, | |
| color_attachments: &[Some(wgpu::RenderPassColorAttachment { | |
| view: &texture_view, | |
| depth_slice: None, | |
| resolve_target: None, | |
| ops: wgpu::Operations { | |
| load: wgpu::LoadOp::Clear(Color { | |
| r: 0.3, | |
| g: 0.3, | |
| b: 0.3, | |
| a: 1.0, | |
| }), | |
| store: wgpu::StoreOp::Store, | |
| }, | |
| })], | |
| depth_stencil_attachment: None, | |
| timestamp_writes: None, | |
| occlusion_query_set: None, | |
| multiview_mask: None, | |
| }); | |
| // pass.set_vertex_buffer(0, self.vertex_buffer.slice(..)); | |
| pass.set_pipeline(&self.pipeline); | |
| pass.draw(0..3, 0..1); | |
| // End the renderpass. | |
| drop(pass); | |
| before_submit(); | |
| self.queue.submit([encoder.finish()]); | |
| surface_texture.present(); | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment