dfg.rs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. use std::iter;
  2. use rand::Rng;
  3. use wgpu::util::DeviceExt;
  4. use winit::{
  5. event::*,
  6. event_loop::{ControlFlow, EventLoop},
  7. window::{Window, WindowBuilder},
  8. };
  9. use sapvi::gui::texture;
  10. #[repr(C)]
  11. #[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]
  12. struct Vertex {
  13. position: [f32; 3],
  14. tex_coords: [f32; 2],
  15. }
  16. impl Vertex {
  17. fn desc<'a>() -> wgpu::VertexBufferLayout<'a> {
  18. use std::mem;
  19. wgpu::VertexBufferLayout {
  20. array_stride: mem::size_of::<Vertex>() as wgpu::BufferAddress,
  21. step_mode: wgpu::InputStepMode::Vertex,
  22. attributes: &[
  23. wgpu::VertexAttribute {
  24. offset: 0,
  25. shader_location: 0,
  26. format: wgpu::VertexFormat::Float3,
  27. },
  28. wgpu::VertexAttribute {
  29. offset: mem::size_of::<[f32; 3]>() as wgpu::BufferAddress,
  30. shader_location: 1,
  31. format: wgpu::VertexFormat::Float2,
  32. },
  33. ],
  34. }
  35. }
  36. }
  37. // (-1, 1) (1, 1)
  38. // +-----------------------+
  39. // | |
  40. // | |
  41. // | |
  42. // | |
  43. // | |
  44. // | |
  45. // | |
  46. // +-----------------------+
  47. // (-1, -1) (1, -1)
  48. const VERTICES: &[Vertex] = &[
  49. Vertex {
  50. position: [-1.0, 1.0, 0.0],
  51. tex_coords: [0.0, 0.0],
  52. },
  53. Vertex {
  54. position: [-1.0, -1.0, 0.0],
  55. tex_coords: [0.0, 1.0],
  56. },
  57. Vertex {
  58. position: [1.0, -1.0, 0.0],
  59. tex_coords: [1.0, 1.0],
  60. },
  61. Vertex {
  62. position: [1.0, 1.0, 0.0],
  63. tex_coords: [1.0, 0.0],
  64. },
  65. /*
  66. Vertex {
  67. position: [-0.0868241, 0.49240386, 0.0],
  68. tex_coords: [0.4131759, 0.00759614],
  69. }, // A
  70. Vertex {
  71. position: [-0.49513406, 0.06958647, 0.0],
  72. tex_coords: [0.0048659444, 0.43041354],
  73. }, // B
  74. Vertex {
  75. position: [-0.21918549, -0.44939706, 0.0],
  76. tex_coords: [0.28081453, 0.949397057],
  77. }, // C
  78. Vertex {
  79. position: [0.35966998, -0.3473291, 0.0],
  80. tex_coords: [0.85967, 0.84732911],
  81. }, // D
  82. Vertex {
  83. position: [0.44147372, 0.2347359, 0.0],
  84. tex_coords: [0.9414737, 0.2652641],
  85. }, // E
  86. */
  87. ];
  88. //const INDICES: &[u16] = &[0, 1, 4, 1, 2, 4, 2, 3, 4];
  89. const INDICES: &[u16] = &[0, 1, 2, 0, 2, 3];
  90. struct State {
  91. surface: wgpu::Surface,
  92. device: wgpu::Device,
  93. queue: wgpu::Queue,
  94. sc_desc: wgpu::SwapChainDescriptor,
  95. swap_chain: wgpu::SwapChain,
  96. size: winit::dpi::PhysicalSize<u32>,
  97. render_pipeline: wgpu::RenderPipeline,
  98. vertex_buffer: wgpu::Buffer,
  99. index_buffer: wgpu::Buffer,
  100. num_indices: u32,
  101. #[allow(dead_code)]
  102. diffuse_texture: texture::Texture,
  103. diffuse_bind_group: wgpu::BindGroup,
  104. #[allow(dead_code)]
  105. cartoon_texture: texture::Texture,
  106. cartoon_bind_group: wgpu::BindGroup,
  107. is_space_pressed: bool,
  108. }
  109. impl State {
  110. async fn new(window: &Window) -> Self {
  111. let size = window.inner_size();
  112. // The instance is a handle to our GPU
  113. // BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
  114. let instance = wgpu::Instance::new(wgpu::BackendBit::PRIMARY);
  115. let surface = unsafe { instance.create_surface(window) };
  116. let adapter = instance
  117. .request_adapter(&wgpu::RequestAdapterOptions {
  118. power_preference: wgpu::PowerPreference::default(),
  119. compatible_surface: Some(&surface),
  120. })
  121. .await
  122. .unwrap();
  123. let (device, queue) = adapter
  124. .request_device(
  125. &wgpu::DeviceDescriptor {
  126. label: None,
  127. features: wgpu::Features::empty(),
  128. limits: wgpu::Limits::default(),
  129. },
  130. None, // Trace path
  131. )
  132. .await
  133. .unwrap();
  134. let sc_desc = wgpu::SwapChainDescriptor {
  135. usage: wgpu::TextureUsage::RENDER_ATTACHMENT,
  136. format: adapter.get_swap_chain_preferred_format(&surface),
  137. width: size.width,
  138. height: size.height,
  139. present_mode: wgpu::PresentMode::Fifo,
  140. };
  141. let swap_chain = device.create_swap_chain(&surface, &sc_desc);
  142. let texture_bind_group_layout =
  143. device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
  144. entries: &[
  145. wgpu::BindGroupLayoutEntry {
  146. binding: 0,
  147. visibility: wgpu::ShaderStage::FRAGMENT,
  148. ty: wgpu::BindingType::Texture {
  149. multisampled: false,
  150. view_dimension: wgpu::TextureViewDimension::D2,
  151. sample_type: wgpu::TextureSampleType::Float { filterable: false },
  152. },
  153. count: None,
  154. },
  155. wgpu::BindGroupLayoutEntry {
  156. binding: 1,
  157. visibility: wgpu::ShaderStage::FRAGMENT,
  158. ty: wgpu::BindingType::Sampler {
  159. comparison: false,
  160. filtering: true,
  161. },
  162. count: None,
  163. },
  164. ],
  165. label: Some("texture_bind_group_layout"),
  166. });
  167. let diffuse_bytes = include_bytes!("assets/absolutely-proprietary.png");
  168. let diffuse_texture =
  169. texture::Texture::from_bytes(&device, &queue, diffuse_bytes, "assets/absolutely-proprietary.png").unwrap();
  170. let diffuse_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
  171. layout: &texture_bind_group_layout,
  172. entries: &[
  173. wgpu::BindGroupEntry {
  174. binding: 0,
  175. resource: wgpu::BindingResource::TextureView(&diffuse_texture.view),
  176. },
  177. wgpu::BindGroupEntry {
  178. binding: 1,
  179. resource: wgpu::BindingResource::Sampler(&diffuse_texture.sampler),
  180. },
  181. ],
  182. label: Some("diffuse_bind_group"),
  183. });
  184. let cartoon_bytes = include_bytes!("assets/absolutely-proprietary2.png");
  185. let cartoon_texture =
  186. texture::Texture::from_bytes(&device, &queue, cartoon_bytes, "happy-tree-cartoon.png")
  187. .unwrap();
  188. let cartoon_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
  189. layout: &texture_bind_group_layout,
  190. entries: &[
  191. wgpu::BindGroupEntry {
  192. binding: 0,
  193. resource: wgpu::BindingResource::TextureView(&cartoon_texture.view),
  194. },
  195. wgpu::BindGroupEntry {
  196. binding: 1,
  197. resource: wgpu::BindingResource::Sampler(&cartoon_texture.sampler),
  198. },
  199. ],
  200. label: Some("cartoon_bind_group"),
  201. });
  202. let vs_module = device.create_shader_module(&wgpu::include_spirv!("assets/shader.vert.spv"));
  203. let fs_module = device.create_shader_module(&wgpu::include_spirv!("assets/shader.frag.spv"));
  204. let render_pipeline_layout =
  205. device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
  206. label: Some("Render Pipeline Layout"),
  207. bind_group_layouts: &[&texture_bind_group_layout],
  208. push_constant_ranges: &[],
  209. });
  210. let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
  211. label: Some("Render Pipeline"),
  212. layout: Some(&render_pipeline_layout),
  213. vertex: wgpu::VertexState {
  214. module: &vs_module,
  215. entry_point: "main",
  216. buffers: &[Vertex::desc()],
  217. },
  218. fragment: Some(wgpu::FragmentState {
  219. module: &fs_module,
  220. entry_point: "main",
  221. targets: &[wgpu::ColorTargetState {
  222. format: sc_desc.format,
  223. alpha_blend: wgpu::BlendState::REPLACE,
  224. color_blend: wgpu::BlendState::REPLACE,
  225. write_mask: wgpu::ColorWrite::ALL,
  226. }],
  227. }),
  228. primitive: wgpu::PrimitiveState {
  229. topology: wgpu::PrimitiveTopology::TriangleList,
  230. strip_index_format: None,
  231. front_face: wgpu::FrontFace::Ccw,
  232. cull_mode: wgpu::CullMode::Back,
  233. // Setting this to anything other than Fill requires Features::NON_FILL_POLYGON_MODE
  234. polygon_mode: wgpu::PolygonMode::Fill,
  235. },
  236. depth_stencil: None,
  237. multisample: wgpu::MultisampleState {
  238. count: 1,
  239. mask: !0,
  240. alpha_to_coverage_enabled: false,
  241. },
  242. });
  243. let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
  244. label: Some("Vertex Buffer"),
  245. contents: bytemuck::cast_slice(VERTICES),
  246. usage: wgpu::BufferUsage::VERTEX,
  247. });
  248. let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
  249. label: Some("Index Buffer"),
  250. contents: bytemuck::cast_slice(INDICES),
  251. usage: wgpu::BufferUsage::INDEX,
  252. });
  253. let num_indices = INDICES.len() as u32;
  254. Self {
  255. surface,
  256. device,
  257. queue,
  258. sc_desc,
  259. swap_chain,
  260. render_pipeline,
  261. vertex_buffer,
  262. index_buffer,
  263. num_indices,
  264. diffuse_texture,
  265. diffuse_bind_group,
  266. cartoon_texture,
  267. cartoon_bind_group,
  268. size,
  269. is_space_pressed: false,
  270. }
  271. }
  272. fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
  273. self.size = new_size;
  274. self.sc_desc.width = new_size.width;
  275. self.sc_desc.height = new_size.height;
  276. self.swap_chain = self.device.create_swap_chain(&self.surface, &self.sc_desc);
  277. }
  278. fn input(&mut self, event: &WindowEvent) -> bool {
  279. match event {
  280. WindowEvent::KeyboardInput {
  281. input:
  282. KeyboardInput {
  283. state,
  284. virtual_keycode: Some(VirtualKeyCode::Space),
  285. ..
  286. },
  287. ..
  288. } => {
  289. self.is_space_pressed = *state == ElementState::Pressed;
  290. true
  291. }
  292. _ => false,
  293. }
  294. }
  295. fn update(&mut self) {
  296. if rand::thread_rng().gen_range(0, 10) == 0 {
  297. self.is_space_pressed = !self.is_space_pressed;
  298. }
  299. }
  300. fn render(&mut self) -> Result<(), wgpu::SwapChainError> {
  301. let frame = self.swap_chain.get_current_frame()?.output;
  302. let mut encoder = self
  303. .device
  304. .create_command_encoder(&wgpu::CommandEncoderDescriptor {
  305. label: Some("Render Encoder"),
  306. });
  307. {
  308. let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
  309. label: Some("Render Pass"),
  310. color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
  311. attachment: &frame.view,
  312. resolve_target: None,
  313. ops: wgpu::Operations {
  314. load: wgpu::LoadOp::Clear(wgpu::Color {
  315. r: 0.1,
  316. g: 0.2,
  317. b: 0.3,
  318. a: 1.0,
  319. }),
  320. store: true,
  321. },
  322. }],
  323. depth_stencil_attachment: None,
  324. });
  325. let bind_group = if self.is_space_pressed {
  326. &self.cartoon_bind_group
  327. } else {
  328. &self.diffuse_bind_group
  329. };
  330. render_pass.set_pipeline(&self.render_pipeline);
  331. render_pass.set_bind_group(0, bind_group, &[]);
  332. render_pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
  333. render_pass.set_index_buffer(self.index_buffer.slice(..), wgpu::IndexFormat::Uint16);
  334. render_pass.draw_indexed(0..self.num_indices, 0, 0..1);
  335. }
  336. self.queue.submit(iter::once(encoder.finish()));
  337. Ok(())
  338. }
  339. }
  340. fn main() {
  341. env_logger::init();
  342. let event_loop = EventLoop::new();
  343. let window = WindowBuilder::new().build(&event_loop).unwrap();
  344. use futures::executor::block_on;
  345. // Since main can't be async, we're going to need to block
  346. let mut state = block_on(State::new(&window));
  347. event_loop.run(move |event, _, control_flow| {
  348. match event {
  349. Event::WindowEvent {
  350. ref event,
  351. window_id,
  352. } if window_id == window.id() => {
  353. if !state.input(event) {
  354. match event {
  355. WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
  356. WindowEvent::KeyboardInput { input, .. } => match input {
  357. KeyboardInput {
  358. state: ElementState::Pressed,
  359. virtual_keycode: Some(VirtualKeyCode::Escape),
  360. ..
  361. } => *control_flow = ControlFlow::Exit,
  362. _ => {}
  363. },
  364. WindowEvent::Resized(physical_size) => {
  365. state.resize(*physical_size);
  366. }
  367. WindowEvent::ScaleFactorChanged { new_inner_size, .. } => {
  368. // new_inner_size is &mut so w have to dereference it twice
  369. state.resize(**new_inner_size);
  370. }
  371. _ => {}
  372. }
  373. }
  374. }
  375. Event::RedrawRequested(_) => {
  376. state.update();
  377. match state.render() {
  378. Ok(_) => {}
  379. // Recreate the swap_chain if lost
  380. Err(wgpu::SwapChainError::Lost) => state.resize(state.size),
  381. // The system is out of memory, we should probably quit
  382. Err(wgpu::SwapChainError::OutOfMemory) => *control_flow = ControlFlow::Exit,
  383. // All other errors (Outdated, Timeout) should be resolved by the next frame
  384. Err(e) => eprintln!("{:?}", e),
  385. }
  386. }
  387. Event::MainEventsCleared => {
  388. // RedrawRequested will only trigger once, unless we manually
  389. // request it.
  390. window.request_redraw();
  391. }
  392. _ => {}
  393. }
  394. });
  395. }