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 context_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
135 label: Some("work part context"),
136 layout: Some(&solid_layout),
137 vertex: wgpu::VertexState {
138 module: &shader,
139 entry_point: Some("vs_mesh"),
140 compilation_options: Default::default(),
141 buffers: &[wgpu::VertexBufferLayout {
142 array_stride: std::mem::size_of::<MeshVertex>() as u64,
143 step_mode: wgpu::VertexStepMode::Vertex,
144 attributes: &wgpu::vertex_attr_array![0 => Float32x3, 1 => Float32x3],
145 }],
146 },
147 fragment: Some(wgpu::FragmentState {
148 module: &shader,
149 entry_point: Some("fs_context"),
150 compilation_options: Default::default(),
151 targets: &[color_target(Some(ALPHA_BLEND))],
152 }),
153 primitive: wgpu::PrimitiveState {
154 topology: wgpu::PrimitiveTopology::TriangleList,
155 front_face: wgpu::FrontFace::Ccw,
156 cull_mode: None,
159 ..Default::default()
160 },
161 depth_stencil: Some(wgpu::DepthStencilState {
162 format: DEPTH_FORMAT,
163 depth_write_enabled: Some(false),
164 depth_compare: Some(wgpu::CompareFunction::Less),
165 stencil: Default::default(),
166 bias: wgpu::DepthBiasState {
169 constant: 4,
170 slope_scale: 2.0,
171 clamp: 0.0,
172 },
173 }),
174 multisample,
175 multiview_mask: None,
176 cache: None,
177 });
178
179 let wire_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
183 label: Some("wireframe"),
184 layout: Some(&solid_layout),
185 vertex: wgpu::VertexState {
186 module: &shader,
187 entry_point: Some("vs_mesh"),
188 compilation_options: Default::default(),
189 buffers: &[wgpu::VertexBufferLayout {
190 array_stride: std::mem::size_of::<MeshVertex>() as u64,
191 step_mode: wgpu::VertexStepMode::Vertex,
192 attributes: &wgpu::vertex_attr_array![0 => Float32x3, 1 => Float32x3],
193 }],
194 },
195 fragment: Some(wgpu::FragmentState {
196 module: &shader,
197 entry_point: Some("fs_wire"),
198 compilation_options: Default::default(),
199 targets: &[color_target(None)],
200 }),
201 primitive: wgpu::PrimitiveState {
202 topology: wgpu::PrimitiveTopology::LineList,
203 front_face: wgpu::FrontFace::Ccw,
204 cull_mode: None,
205 ..Default::default()
206 },
207 depth_stencil: Some(wgpu::DepthStencilState {
208 format: DEPTH_FORMAT,
209 depth_write_enabled: Some(true),
210 depth_compare: Some(wgpu::CompareFunction::Less),
211 stencil: Default::default(),
212 bias: Default::default(),
213 }),
214 multisample,
215 multiview_mask: None,
216 cache: None,
217 });
218
219 let edge_pipeline = |label: &str, depth_compare: wgpu::CompareFunction| {
220 device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
221 label: Some(label),
222 layout: Some(&solid_layout),
223 vertex: wgpu::VertexState {
224 module: &shader,
225 entry_point: Some("vs_edge"),
226 compilation_options: Default::default(),
227 buffers: &[wgpu::VertexBufferLayout {
228 array_stride: std::mem::size_of::<EdgeInstance>() as u64,
229 step_mode: wgpu::VertexStepMode::Instance,
230 attributes: &wgpu::vertex_attr_array![0 => Float32x3, 1 => Float32x3],
231 }],
232 },
233 fragment: Some(wgpu::FragmentState {
234 module: &shader,
235 entry_point: Some("fs_edge"),
236 compilation_options: Default::default(),
237 targets: &[color_target(Some(ALPHA_BLEND))],
238 }),
239 primitive: wgpu::PrimitiveState {
240 topology: wgpu::PrimitiveTopology::TriangleList,
241 front_face: wgpu::FrontFace::Ccw,
242 cull_mode: None,
243 ..Default::default()
244 },
245 depth_stencil: Some(wgpu::DepthStencilState {
246 format: DEPTH_FORMAT,
247 depth_write_enabled: Some(false),
250 depth_compare: Some(depth_compare),
251 stencil: Default::default(),
252 bias: Default::default(),
253 }),
254 multisample,
255 multiview_mask: None,
256 cache: None,
257 })
258 };
259 let edge_visible_pipeline = edge_pipeline("edges", wgpu::CompareFunction::LessEqual);
262 let edge_hidden_pipeline = edge_pipeline("edges-hidden", wgpu::CompareFunction::Greater);
263
264 let point_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
265 label: Some("points"),
266 layout: Some(&solid_layout),
267 vertex: wgpu::VertexState {
268 module: &shader,
269 entry_point: Some("vs_point"),
270 compilation_options: Default::default(),
271 buffers: &[wgpu::VertexBufferLayout {
272 array_stride: std::mem::size_of::<PointInstance>() as u64,
273 step_mode: wgpu::VertexStepMode::Instance,
274 attributes: &wgpu::vertex_attr_array![0 => Float32x3],
275 }],
276 },
277 fragment: Some(wgpu::FragmentState {
278 module: &shader,
279 entry_point: Some("fs_point"),
280 compilation_options: Default::default(),
281 targets: &[color_target(Some(ALPHA_BLEND))],
282 }),
283 primitive: wgpu::PrimitiveState {
284 topology: wgpu::PrimitiveTopology::TriangleList,
285 front_face: wgpu::FrontFace::Ccw,
286 cull_mode: None,
287 ..Default::default()
288 },
289 depth_stencil: Some(wgpu::DepthStencilState {
290 format: DEPTH_FORMAT,
291 depth_write_enabled: Some(false),
292 depth_compare: Some(wgpu::CompareFunction::LessEqual),
293 stencil: Default::default(),
294 bias: Default::default(),
295 }),
296 multisample,
297 multiview_mask: None,
298 cache: None,
299 });
300
301 let overlay_tri_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
306 label: Some("overlay-tri"),
307 layout: Some(&pipeline_layout),
308 vertex: wgpu::VertexState {
309 module: &shader,
310 entry_point: Some("vs_overlay_tri"),
311 compilation_options: Default::default(),
312 buffers: &[wgpu::VertexBufferLayout {
313 array_stride: std::mem::size_of::<OverlayTriVertex>() as u64,
314 step_mode: wgpu::VertexStepMode::Vertex,
315 attributes: &wgpu::vertex_attr_array![0 => Float32x3, 1 => Float32x3, 2 => Float32x4],
316 }],
317 },
318 fragment: Some(wgpu::FragmentState {
319 module: &shader,
320 entry_point: Some("fs_overlay_tri"),
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(true),
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 let overlay_tri_nodepth_pipeline =
345 device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
346 label: Some("overlay-tri-nodepth"),
347 layout: Some(&pipeline_layout),
348 vertex: wgpu::VertexState {
349 module: &shader,
350 entry_point: Some("vs_overlay_tri"),
351 compilation_options: Default::default(),
352 buffers: &[wgpu::VertexBufferLayout {
353 array_stride: std::mem::size_of::<OverlayTriVertex>() as u64,
354 step_mode: wgpu::VertexStepMode::Vertex,
355 attributes: &wgpu::vertex_attr_array![0 => Float32x3, 1 => Float32x3, 2 => Float32x4],
356 }],
357 },
358 fragment: Some(wgpu::FragmentState {
359 module: &shader,
360 entry_point: Some("fs_overlay_tri"),
361 compilation_options: Default::default(),
362 targets: &[color_target(Some(ALPHA_BLEND))],
363 }),
364 primitive: wgpu::PrimitiveState {
365 topology: wgpu::PrimitiveTopology::TriangleList,
366 front_face: wgpu::FrontFace::Ccw,
367 cull_mode: None,
368 ..Default::default()
369 },
370 depth_stencil: Some(wgpu::DepthStencilState {
371 format: DEPTH_FORMAT,
372 depth_write_enabled: Some(false),
373 depth_compare: Some(wgpu::CompareFunction::LessEqual),
374 stencil: Default::default(),
375 bias: Default::default(),
376 }),
377 multisample,
378 multiview_mask: None,
379 cache: None,
380 });
381 let overlay_line_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
382 label: Some("overlay-line"),
383 layout: Some(&pipeline_layout),
384 vertex: wgpu::VertexState {
385 module: &shader,
386 entry_point: Some("vs_overlay_line"),
387 compilation_options: Default::default(),
388 buffers: &[wgpu::VertexBufferLayout {
389 array_stride: std::mem::size_of::<OverlayLineInstance>() as u64,
390 step_mode: wgpu::VertexStepMode::Instance,
391 attributes: &wgpu::vertex_attr_array![0 => Float32x3, 1 => Float32x3, 2 => Float32x4],
392 }],
393 },
394 fragment: Some(wgpu::FragmentState {
395 module: &shader,
396 entry_point: Some("fs_overlay_line"),
397 compilation_options: Default::default(),
398 targets: &[color_target(Some(ALPHA_BLEND))],
399 }),
400 primitive: wgpu::PrimitiveState {
401 topology: wgpu::PrimitiveTopology::TriangleList,
402 front_face: wgpu::FrontFace::Ccw,
403 cull_mode: None,
404 ..Default::default()
405 },
406 depth_stencil: Some(wgpu::DepthStencilState {
407 format: DEPTH_FORMAT,
408 depth_write_enabled: Some(false),
409 depth_compare: Some(wgpu::CompareFunction::LessEqual),
410 stencil: Default::default(),
411 bias: Default::default(),
412 }),
413 multisample,
414 multiview_mask: None,
415 cache: None,
416 });
417
418 let vc_globals_buf = device.create_buffer(&wgpu::BufferDescriptor {
420 label: Some("viewcube globals"),
421 size: std::mem::size_of::<Globals>() as u64,
422 usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
423 mapped_at_creation: false,
424 });
425 let vc_globals_bind = device.create_bind_group(&wgpu::BindGroupDescriptor {
426 label: Some("viewcube globals"),
427 layout: &globals_layout,
428 entries: &[wgpu::BindGroupEntry {
429 binding: 0,
430 resource: vc_globals_buf.as_entire_binding(),
431 }],
432 });
433
434 let styles = GlobalStyles {
435 face_selected: StyleBuf::new(&device, &style_layout, "face-selected"),
436 face_hovered: StyleBuf::new(&device, &style_layout, "face-hovered"),
437 edge_base: StyleBuf::new(&device, &style_layout, "edge-base"),
438 edge_selected: StyleBuf::new(&device, &style_layout, "edge-selected"),
439 edge_hovered: StyleBuf::new(&device, &style_layout, "edge-hovered"),
440 edge_hidden: StyleBuf::new(&device, &style_layout, "edge-hidden"),
441 edge_aux: StyleBuf::new(&device, &style_layout, "edge-aux"),
442 boundary: StyleBuf::new(&device, &style_layout, "boundary"),
443 point_base: StyleBuf::new(&device, &style_layout, "point-base"),
444 point_selected: StyleBuf::new(&device, &style_layout, "point-selected"),
445 point_hovered: StyleBuf::new(&device, &style_layout, "point-hovered"),
446 axis_x: StyleBuf::new(&device, &style_layout, "axis-x"),
447 axis_y: StyleBuf::new(&device, &style_layout, "axis-y"),
448 axis_z: StyleBuf::new(&device, &style_layout, "axis-z"),
449 overlay_line: StyleBuf::new(&device, &style_layout, "overlay-line"),
450 };
451
452 let identity_model = IdentityModel::new(&device, &queue, &model_layout);
453 let context_style = StyleBuf::new(&device, &style_layout, "work part context");
454 context_style.write(&queue, super::WORK_PART_CONTEXT_RGBA, [0.0; 4]);
455 let context_selected = StyleBuf::new(&device, &style_layout, "work part context selected");
456 let context_hovered = StyleBuf::new(&device, &style_layout, "work part context hovered");
457
458 Self {
459 context_pipeline,
460 context_style,
461 context_selected,
462 context_hovered,
463 device,
464 queue,
465 format,
466 globals_buf,
467 globals_bind,
468 style_layout,
469 model_layout,
470 identity_model,
471 mesh_pipeline,
472 wire_pipeline,
473 edge_visible_pipeline,
474 edge_hidden_pipeline,
475 point_pipeline,
476 overlay_tri_pipeline,
477 overlay_tri_nodepth_pipeline,
478 overlay_line_pipeline,
479 vc_globals_buf,
480 vc_globals_bind,
481 styles,
482 targets: None,
483 }
484 }
485}