1use super::*;
2
3impl RenderCore {
4 pub fn new(device: wgpu::Device, queue: wgpu::Queue, format: wgpu::TextureFormat) -> Self {
5 let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
6 label: Some("brep-render shaders"),
7 source: wgpu::ShaderSource::Wgsl(include_str!("../shaders.wgsl").into()),
8 });
9
10 let globals_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
11 label: Some("globals"),
12 entries: &[wgpu::BindGroupLayoutEntry {
13 binding: 0,
14 visibility: wgpu::ShaderStages::VERTEX_FRAGMENT,
15 ty: wgpu::BindingType::Buffer {
16 ty: wgpu::BufferBindingType::Uniform,
17 has_dynamic_offset: false,
18 min_binding_size: None,
19 },
20 count: None,
21 }],
22 });
23 let style_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
24 label: Some("style"),
25 entries: &[wgpu::BindGroupLayoutEntry {
26 binding: 0,
27 visibility: wgpu::ShaderStages::VERTEX_FRAGMENT,
28 ty: wgpu::BindingType::Buffer {
29 ty: wgpu::BufferBindingType::Uniform,
30 has_dynamic_offset: false,
31 min_binding_size: None,
32 },
33 count: None,
34 }],
35 });
36 let model_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
37 label: Some("model"),
38 entries: &[wgpu::BindGroupLayoutEntry {
39 binding: 0,
40 visibility: wgpu::ShaderStages::VERTEX,
41 ty: wgpu::BindingType::Buffer {
42 ty: wgpu::BufferBindingType::Uniform,
43 has_dynamic_offset: true,
44 min_binding_size: std::num::NonZeroU64::new(std::mem::size_of::<ModelParams>() as u64),
45 },
46 count: None,
47 }],
48 });
49 let globals_buf = device.create_buffer(&wgpu::BufferDescriptor {
50 label: Some("globals"),
51 size: std::mem::size_of::<Globals>() as u64,
52 usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
53 mapped_at_creation: false,
54 });
55 let globals_bind = device.create_bind_group(&wgpu::BindGroupDescriptor {
56 label: Some("globals"),
57 layout: &globals_layout,
58 entries: &[wgpu::BindGroupEntry {
59 binding: 0,
60 resource: globals_buf.as_entire_binding(),
61 }],
62 });
63
64 let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
65 label: Some("brep-render"),
66 bind_group_layouts: &[Some(&globals_layout), Some(&style_layout)],
67 immediate_size: 0,
68 });
69 let solid_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
71 label: Some("brep-render solids"),
72 bind_group_layouts: &[Some(&globals_layout), Some(&style_layout), Some(&model_layout)],
73 immediate_size: 0,
74 });
75
76 const ALPHA_BLEND: wgpu::BlendState = wgpu::BlendState::ALPHA_BLENDING;
77 let color_target = |blend: Option<wgpu::BlendState>| {
78 Some(wgpu::ColorTargetState {
79 format,
80 blend,
81 write_mask: wgpu::ColorWrites::ALL,
82 })
83 };
84 let multisample = wgpu::MultisampleState {
85 count: SAMPLES,
86 ..Default::default()
87 };
88
89 let mesh_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
90 label: Some("mesh"),
91 layout: Some(&solid_layout),
92 vertex: wgpu::VertexState {
93 module: &shader,
94 entry_point: Some("vs_mesh"),
95 compilation_options: Default::default(),
96 buffers: &[wgpu::VertexBufferLayout {
97 array_stride: std::mem::size_of::<MeshVertex>() as u64,
98 step_mode: wgpu::VertexStepMode::Vertex,
99 attributes: &wgpu::vertex_attr_array![0 => Float32x3, 1 => Float32x3],
100 }],
101 },
102 fragment: Some(wgpu::FragmentState {
103 module: &shader,
104 entry_point: Some("fs_mesh"),
105 compilation_options: Default::default(),
106 targets: &[color_target(None)],
107 }),
108 primitive: wgpu::PrimitiveState {
109 topology: wgpu::PrimitiveTopology::TriangleList,
110 front_face: wgpu::FrontFace::Ccw,
111 cull_mode: None,
114 ..Default::default()
115 },
116 depth_stencil: Some(wgpu::DepthStencilState {
117 format: DEPTH_FORMAT,
118 depth_write_enabled: Some(true),
119 depth_compare: Some(wgpu::CompareFunction::Less),
120 stencil: Default::default(),
121 bias: wgpu::DepthBiasState {
124 constant: 4,
125 slope_scale: 2.0,
126 clamp: 0.0,
127 },
128 }),
129 multisample,
130 multiview_mask: None,
131 cache: None,
132 });
133
134 let hull_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
139 label: Some("line art outline"),
140 layout: Some(&solid_layout),
141 vertex: wgpu::VertexState {
142 module: &shader,
143 entry_point: Some("vs_hull"),
144 compilation_options: Default::default(),
145 buffers: &[wgpu::VertexBufferLayout {
146 array_stride: std::mem::size_of::<MeshVertex>() as u64,
147 step_mode: wgpu::VertexStepMode::Vertex,
148 attributes: &wgpu::vertex_attr_array![0 => Float32x3, 1 => Float32x3],
149 }],
150 },
151 fragment: Some(wgpu::FragmentState {
152 module: &shader,
153 entry_point: Some("fs_hull"),
154 compilation_options: Default::default(),
155 targets: &[color_target(None)],
156 }),
157 primitive: wgpu::PrimitiveState {
158 topology: wgpu::PrimitiveTopology::TriangleList,
159 front_face: wgpu::FrontFace::Ccw,
160 cull_mode: None,
161 ..Default::default()
162 },
163 depth_stencil: Some(wgpu::DepthStencilState {
164 format: DEPTH_FORMAT,
165 depth_write_enabled: Some(false),
166 depth_compare: Some(wgpu::CompareFunction::LessEqual),
167 stencil: Default::default(),
168 bias: Default::default(),
169 }),
170 multisample,
171 multiview_mask: None,
172 cache: None,
173 });
174
175 let context_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
176 label: Some("work part context"),
177 layout: Some(&solid_layout),
178 vertex: wgpu::VertexState {
179 module: &shader,
180 entry_point: Some("vs_mesh"),
181 compilation_options: Default::default(),
182 buffers: &[wgpu::VertexBufferLayout {
183 array_stride: std::mem::size_of::<MeshVertex>() as u64,
184 step_mode: wgpu::VertexStepMode::Vertex,
185 attributes: &wgpu::vertex_attr_array![0 => Float32x3, 1 => Float32x3],
186 }],
187 },
188 fragment: Some(wgpu::FragmentState {
189 module: &shader,
190 entry_point: Some("fs_context"),
191 compilation_options: Default::default(),
192 targets: &[color_target(Some(ALPHA_BLEND))],
193 }),
194 primitive: wgpu::PrimitiveState {
195 topology: wgpu::PrimitiveTopology::TriangleList,
196 front_face: wgpu::FrontFace::Ccw,
197 cull_mode: None,
200 ..Default::default()
201 },
202 depth_stencil: Some(wgpu::DepthStencilState {
203 format: DEPTH_FORMAT,
204 depth_write_enabled: Some(false),
205 depth_compare: Some(wgpu::CompareFunction::Less),
206 stencil: Default::default(),
207 bias: wgpu::DepthBiasState {
210 constant: 4,
211 slope_scale: 2.0,
212 clamp: 0.0,
213 },
214 }),
215 multisample,
216 multiview_mask: None,
217 cache: None,
218 });
219
220 let wire_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
224 label: Some("wireframe"),
225 layout: Some(&solid_layout),
226 vertex: wgpu::VertexState {
227 module: &shader,
228 entry_point: Some("vs_mesh"),
229 compilation_options: Default::default(),
230 buffers: &[wgpu::VertexBufferLayout {
231 array_stride: std::mem::size_of::<MeshVertex>() as u64,
232 step_mode: wgpu::VertexStepMode::Vertex,
233 attributes: &wgpu::vertex_attr_array![0 => Float32x3, 1 => Float32x3],
234 }],
235 },
236 fragment: Some(wgpu::FragmentState {
237 module: &shader,
238 entry_point: Some("fs_wire"),
239 compilation_options: Default::default(),
240 targets: &[color_target(None)],
241 }),
242 primitive: wgpu::PrimitiveState {
243 topology: wgpu::PrimitiveTopology::LineList,
244 front_face: wgpu::FrontFace::Ccw,
245 cull_mode: None,
246 ..Default::default()
247 },
248 depth_stencil: Some(wgpu::DepthStencilState {
249 format: DEPTH_FORMAT,
250 depth_write_enabled: Some(true),
251 depth_compare: Some(wgpu::CompareFunction::Less),
252 stencil: Default::default(),
253 bias: Default::default(),
254 }),
255 multisample,
256 multiview_mask: None,
257 cache: None,
258 });
259
260 let edge_pipeline = |label: &str, depth_compare: wgpu::CompareFunction| {
261 device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
262 label: Some(label),
263 layout: Some(&solid_layout),
264 vertex: wgpu::VertexState {
265 module: &shader,
266 entry_point: Some("vs_edge"),
267 compilation_options: Default::default(),
268 buffers: &[wgpu::VertexBufferLayout {
269 array_stride: std::mem::size_of::<EdgeInstance>() as u64,
270 step_mode: wgpu::VertexStepMode::Instance,
271 attributes: &wgpu::vertex_attr_array![0 => Float32x3, 1 => Float32x3],
272 }],
273 },
274 fragment: Some(wgpu::FragmentState {
275 module: &shader,
276 entry_point: Some("fs_edge"),
277 compilation_options: Default::default(),
278 targets: &[color_target(Some(ALPHA_BLEND))],
279 }),
280 primitive: wgpu::PrimitiveState {
281 topology: wgpu::PrimitiveTopology::TriangleList,
282 front_face: wgpu::FrontFace::Ccw,
283 cull_mode: None,
284 ..Default::default()
285 },
286 depth_stencil: Some(wgpu::DepthStencilState {
287 format: DEPTH_FORMAT,
288 depth_write_enabled: Some(false),
291 depth_compare: Some(depth_compare),
292 stencil: Default::default(),
293 bias: Default::default(),
294 }),
295 multisample,
296 multiview_mask: None,
297 cache: None,
298 })
299 };
300 let edge_visible_pipeline = edge_pipeline("edges", wgpu::CompareFunction::LessEqual);
303 let edge_hidden_pipeline = edge_pipeline("edges-hidden", wgpu::CompareFunction::Greater);
304
305 let point_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
306 label: Some("points"),
307 layout: Some(&solid_layout),
308 vertex: wgpu::VertexState {
309 module: &shader,
310 entry_point: Some("vs_point"),
311 compilation_options: Default::default(),
312 buffers: &[wgpu::VertexBufferLayout {
313 array_stride: std::mem::size_of::<PointInstance>() as u64,
314 step_mode: wgpu::VertexStepMode::Instance,
315 attributes: &wgpu::vertex_attr_array![0 => Float32x3],
316 }],
317 },
318 fragment: Some(wgpu::FragmentState {
319 module: &shader,
320 entry_point: Some("fs_point"),
321 compilation_options: Default::default(),
322 targets: &[color_target(Some(ALPHA_BLEND))],
323 }),
324 primitive: wgpu::PrimitiveState {
325 topology: wgpu::PrimitiveTopology::TriangleList,
326 front_face: wgpu::FrontFace::Ccw,
327 cull_mode: None,
328 ..Default::default()
329 },
330 depth_stencil: Some(wgpu::DepthStencilState {
331 format: DEPTH_FORMAT,
332 depth_write_enabled: Some(false),
333 depth_compare: Some(wgpu::CompareFunction::LessEqual),
334 stencil: Default::default(),
335 bias: Default::default(),
336 }),
337 multisample,
338 multiview_mask: None,
339 cache: None,
340 });
341
342 let overlay_tri_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
347 label: Some("overlay-tri"),
348 layout: Some(&pipeline_layout),
349 vertex: wgpu::VertexState {
350 module: &shader,
351 entry_point: Some("vs_overlay_tri"),
352 compilation_options: Default::default(),
353 buffers: &[wgpu::VertexBufferLayout {
354 array_stride: std::mem::size_of::<OverlayTriVertex>() as u64,
355 step_mode: wgpu::VertexStepMode::Vertex,
356 attributes: &wgpu::vertex_attr_array![0 => Float32x3, 1 => Float32x3, 2 => Float32x4],
357 }],
358 },
359 fragment: Some(wgpu::FragmentState {
360 module: &shader,
361 entry_point: Some("fs_overlay_tri"),
362 compilation_options: Default::default(),
363 targets: &[color_target(Some(ALPHA_BLEND))],
364 }),
365 primitive: wgpu::PrimitiveState {
366 topology: wgpu::PrimitiveTopology::TriangleList,
367 front_face: wgpu::FrontFace::Ccw,
368 cull_mode: None,
369 ..Default::default()
370 },
371 depth_stencil: Some(wgpu::DepthStencilState {
372 format: DEPTH_FORMAT,
373 depth_write_enabled: Some(true),
374 depth_compare: Some(wgpu::CompareFunction::LessEqual),
375 stencil: Default::default(),
376 bias: Default::default(),
377 }),
378 multisample,
379 multiview_mask: None,
380 cache: None,
381 });
382 let overlay_tri_nodepth_pipeline =
386 device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
387 label: Some("overlay-tri-nodepth"),
388 layout: Some(&pipeline_layout),
389 vertex: wgpu::VertexState {
390 module: &shader,
391 entry_point: Some("vs_overlay_tri"),
392 compilation_options: Default::default(),
393 buffers: &[wgpu::VertexBufferLayout {
394 array_stride: std::mem::size_of::<OverlayTriVertex>() as u64,
395 step_mode: wgpu::VertexStepMode::Vertex,
396 attributes: &wgpu::vertex_attr_array![0 => Float32x3, 1 => Float32x3, 2 => Float32x4],
397 }],
398 },
399 fragment: Some(wgpu::FragmentState {
400 module: &shader,
401 entry_point: Some("fs_overlay_tri"),
402 compilation_options: Default::default(),
403 targets: &[color_target(Some(ALPHA_BLEND))],
404 }),
405 primitive: wgpu::PrimitiveState {
406 topology: wgpu::PrimitiveTopology::TriangleList,
407 front_face: wgpu::FrontFace::Ccw,
408 cull_mode: None,
409 ..Default::default()
410 },
411 depth_stencil: Some(wgpu::DepthStencilState {
412 format: DEPTH_FORMAT,
413 depth_write_enabled: Some(false),
414 depth_compare: Some(wgpu::CompareFunction::LessEqual),
415 stencil: Default::default(),
416 bias: Default::default(),
417 }),
418 multisample,
419 multiview_mask: None,
420 cache: None,
421 });
422 let overlay_line_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
423 label: Some("overlay-line"),
424 layout: Some(&pipeline_layout),
425 vertex: wgpu::VertexState {
426 module: &shader,
427 entry_point: Some("vs_overlay_line"),
428 compilation_options: Default::default(),
429 buffers: &[wgpu::VertexBufferLayout {
430 array_stride: std::mem::size_of::<OverlayLineInstance>() as u64,
431 step_mode: wgpu::VertexStepMode::Instance,
432 attributes: &wgpu::vertex_attr_array![0 => Float32x3, 1 => Float32x3, 2 => Float32x4],
433 }],
434 },
435 fragment: Some(wgpu::FragmentState {
436 module: &shader,
437 entry_point: Some("fs_overlay_line"),
438 compilation_options: Default::default(),
439 targets: &[color_target(Some(ALPHA_BLEND))],
440 }),
441 primitive: wgpu::PrimitiveState {
442 topology: wgpu::PrimitiveTopology::TriangleList,
443 front_face: wgpu::FrontFace::Ccw,
444 cull_mode: None,
445 ..Default::default()
446 },
447 depth_stencil: Some(wgpu::DepthStencilState {
448 format: DEPTH_FORMAT,
449 depth_write_enabled: Some(false),
450 depth_compare: Some(wgpu::CompareFunction::LessEqual),
451 stencil: Default::default(),
452 bias: Default::default(),
453 }),
454 multisample,
455 multiview_mask: None,
456 cache: None,
457 });
458
459 let vc_globals_buf = device.create_buffer(&wgpu::BufferDescriptor {
461 label: Some("viewcube globals"),
462 size: std::mem::size_of::<Globals>() as u64,
463 usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
464 mapped_at_creation: false,
465 });
466 let vc_globals_bind = device.create_bind_group(&wgpu::BindGroupDescriptor {
467 label: Some("viewcube globals"),
468 layout: &globals_layout,
469 entries: &[wgpu::BindGroupEntry {
470 binding: 0,
471 resource: vc_globals_buf.as_entire_binding(),
472 }],
473 });
474
475 let styles = GlobalStyles {
476 face_selected: StyleBuf::new(&device, &style_layout, "face-selected"),
477 face_hovered: StyleBuf::new(&device, &style_layout, "face-hovered"),
478 edge_base: StyleBuf::new(&device, &style_layout, "edge-base"),
479 edge_selected: StyleBuf::new(&device, &style_layout, "edge-selected"),
480 edge_hovered: StyleBuf::new(&device, &style_layout, "edge-hovered"),
481 edge_hidden: StyleBuf::new(&device, &style_layout, "edge-hidden"),
482 edge_aux: StyleBuf::new(&device, &style_layout, "edge-aux"),
483 boundary: StyleBuf::new(&device, &style_layout, "boundary"),
484 point_base: StyleBuf::new(&device, &style_layout, "point-base"),
485 point_selected: StyleBuf::new(&device, &style_layout, "point-selected"),
486 point_hovered: StyleBuf::new(&device, &style_layout, "point-hovered"),
487 axis_x: StyleBuf::new(&device, &style_layout, "axis-x"),
488 axis_y: StyleBuf::new(&device, &style_layout, "axis-y"),
489 axis_z: StyleBuf::new(&device, &style_layout, "axis-z"),
490 overlay_line: StyleBuf::new(&device, &style_layout, "overlay-line"),
491 line_art_placed_face: StyleBuf::new(&device, &style_layout, "line-art-placed-face"),
492 line_art_adding_face: StyleBuf::new(&device, &style_layout, "line-art-adding-face"),
493 line_art_placed_edge: StyleBuf::new(&device, &style_layout, "line-art-placed-edge"),
494 line_art_adding_edge: StyleBuf::new(&device, &style_layout, "line-art-adding-edge"),
495 line_art_placed_outline: StyleBuf::new(&device, &style_layout, "line-art-placed-outline"),
496 line_art_adding_outline: StyleBuf::new(&device, &style_layout, "line-art-adding-outline"),
497 };
498
499 let identity_model = IdentityModel::new(&device, &queue, &model_layout);
500 let context_style = StyleBuf::new(&device, &style_layout, "work part context");
501 context_style.write(&queue, super::WORK_PART_CONTEXT_RGBA, [0.0; 4]);
502 let context_selected = StyleBuf::new(&device, &style_layout, "work part context selected");
503 let context_hovered = StyleBuf::new(&device, &style_layout, "work part context hovered");
504
505 Self {
506 context_pipeline,
507 context_style,
508 context_selected,
509 context_hovered,
510 device,
511 queue,
512 format,
513 globals_buf,
514 globals_bind,
515 style_layout,
516 model_layout,
517 identity_model,
518 mesh_pipeline,
519 hull_pipeline,
520 wire_pipeline,
521 edge_visible_pipeline,
522 edge_hidden_pipeline,
523 point_pipeline,
524 overlay_tri_pipeline,
525 overlay_tri_nodepth_pipeline,
526 overlay_line_pipeline,
527 vc_globals_buf,
528 vc_globals_bind,
529 styles,
530 targets: None,
531 }
532 }
533}