1extern crate conrod_core;
2#[macro_use]
3extern crate vulkano;
4
5use std::error::Error as StdError;
6use std::fmt;
7use std::sync::Arc;
8
9use conrod_core::mesh::{self, Mesh};
10use conrod_core::text::rt;
11use conrod_core::{image, render, Rect, Scalar};
12use std::ffi::CString;
13use vulkano::buffer::{BufferUsage, CpuBufferPool, ImmutableBuffer};
14use vulkano::descriptor_set::layout::{
15 DescriptorDesc, DescriptorDescImage, DescriptorDescTy, DescriptorSetDesc, DescriptorSetLayout,
16};
17use vulkano::descriptor_set::{DescriptorSet, DescriptorSetError, SingleLayoutDescSetPool};
18use vulkano::device::physical::QueueFamily;
19use vulkano::device::{Device, Queue};
20use vulkano::format::Format;
21use vulkano::image::view::{ImageView, ImageViewType};
22use vulkano::image::{
23 ImageCreateFlags, ImageCreationError, ImageDimensions, ImageUsage, ImmutableImage, StorageImage,
24};
25use vulkano::memory::DeviceMemoryAllocError;
26use vulkano::pipeline::layout::PipelineLayout;
27use vulkano::pipeline::shader::{
28 GraphicsShaderType, ShaderInterface, ShaderInterfaceEntry, ShaderModule, ShaderStages,
29 SpecializationConstants,
30};
31use vulkano::pipeline::viewport::{Scissor, Viewport};
32use vulkano::pipeline::{GraphicsPipeline, GraphicsPipelineCreationError};
33use vulkano::render_pass::Subpass;
34use vulkano::sampler::{Filter, MipmapMode, Sampler, SamplerAddressMode, SamplerCreationError};
35use vulkano::sync::GpuFuture;
36use vulkano::OomError;
37
38pub struct Image {
40 pub image_access: Arc<ImmutableImage>,
44 pub width: u32,
46 pub height: u32,
48}
49
50#[repr(C)]
52#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
53pub struct Vertex {
54 pub position: [f32; 2],
59 pub tex_coords: [f32; 2],
64 pub rgba: [f32; 4],
66 pub mode: u32,
74}
75
76impl_vertex!(Vertex, position, tex_coords, rgba, mode);
77fn create_shader_interface_vs_in() -> ShaderInterface {
79 unsafe {
80 ShaderInterface::new_unchecked(vec![
81 ShaderInterfaceEntry {
82 location: 0..1,
83 format: Format::R32G32_SFLOAT,
84 name: Some(std::borrow::Cow::Borrowed("position")),
85 },
86 ShaderInterfaceEntry {
87 location: 1..2,
88 format: Format::R32G32_SFLOAT,
89 name: Some(std::borrow::Cow::Borrowed("tex_coords")),
90 },
91 ShaderInterfaceEntry {
92 location: 2..3,
93 format: Format::R32G32B32A32_SFLOAT,
94 name: Some(std::borrow::Cow::Borrowed("rgba")),
95 },
96 ShaderInterfaceEntry {
97 location: 3..4,
98 format: Format::R32_UINT,
99 name: Some(std::borrow::Cow::Borrowed("mode")),
100 },
101 ])
102 }
103}
104fn create_shader_interface_vs_out() -> ShaderInterface {
105 unsafe {
106 ShaderInterface::new_unchecked(vec![
107 ShaderInterfaceEntry {
108 location: 0..1,
109 format: Format::R32G32_SFLOAT,
110 name: Some(std::borrow::Cow::Borrowed("v_Uv")),
111 },
112 ShaderInterfaceEntry {
113 location: 1..2,
114 format: Format::R32G32B32A32_SFLOAT,
115 name: Some(std::borrow::Cow::Borrowed("v_Color")),
116 },
117 ShaderInterfaceEntry {
118 location: 2..3,
119 format: Format::R32_UINT,
120 name: Some(std::borrow::Cow::Borrowed("v_Mode")),
121 },
122 ])
123 }
124}
125fn create_shader_interface_fs_out() -> ShaderInterface {
126 unsafe {
127 ShaderInterface::new_unchecked(vec![ShaderInterfaceEntry {
128 location: 0..1,
129 format: Format::R32G32B32A32_SFLOAT,
130 name: Some(std::borrow::Cow::Borrowed("Target0")),
131 }])
132 }
133}
134
135pub struct Renderer {
138 pipeline: Arc<GraphicsPipeline>,
139 glyph_uploads: Arc<CpuBufferPool<u8>>,
140 glyph_cache_tex: Arc<StorageImage>,
141 sampler: Arc<Sampler>,
142 tex_descs: SingleLayoutDescSetPool,
143 mesh: Mesh,
144}
145
146pub struct GlyphCacheCommand<'a> {
148 pub glyph_cache_pixel_buffer: &'a [u8],
150 pub glyph_cpu_buffer_pool: Arc<CpuBufferPool<u8>>,
152 pub glyph_cache_texture: Arc<StorageImage>,
154}
155
156pub struct DrawCommand {
160 pub graphics_pipeline: Arc<GraphicsPipeline>,
161 pub scissor: Scissor,
162 pub viewport: Viewport,
163 pub descriptor_set: Arc<dyn DescriptorSet + Send + Sync>,
164 pub vertex_buffer: Arc<ImmutableBuffer<[Vertex]>>,
165}
166
167#[derive(Debug)]
169pub enum RendererCreationError {
170 SamplerCreation(SamplerCreationError),
171 ShaderLoad(vulkano::OomError),
172 GraphicsPipelineCreation(GraphicsPipelineCreationError),
173 ImageCreation(ImageCreationError),
174}
175
176#[derive(Debug)]
178pub enum DrawError {
179 DescriptorSet(DescriptorSetError),
180
181 VertexBufferAlloc(DeviceMemoryAllocError),
182}
183
184impl mesh::ImageDimensions for Image {
185 fn dimensions(&self) -> [u32; 2] {
186 [self.width, self.height]
187 }
188}
189
190impl Renderer {
191 pub fn new(
196 device: Arc<Device>,
197 subpass: Subpass,
198 graphics_queue_family: QueueFamily,
199 window_dims: [u32; 2],
200 dpi_factor: f64,
201 ) -> Result<Self, RendererCreationError> {
202 let [w, h] = window_dims;
204 let glyph_cache_dims = [
205 (w as f64 * dpi_factor) as u32,
206 (h as f64 * dpi_factor) as u32,
207 ];
208 Self::with_glyph_cache_dimensions(device, subpass, graphics_queue_family, glyph_cache_dims)
209 }
210
211 pub fn with_glyph_cache_dimensions(
213 device: Arc<Device>,
214 subpass: Subpass,
215 graphics_queue_family: QueueFamily,
216 glyph_cache_dims: [u32; 2],
217 ) -> Result<Self, RendererCreationError> {
218 let sampler = Sampler::new(
219 device.clone(),
220 Filter::Linear,
221 Filter::Linear,
222 MipmapMode::Nearest,
223 SamplerAddressMode::ClampToEdge,
224 SamplerAddressMode::ClampToEdge,
225 SamplerAddressMode::ClampToEdge,
226 0.0,
227 1.0,
228 0.0,
229 0.0,
230 )?;
231 let descriptor_set_desc = DescriptorSetDesc::new(vec![Some(DescriptorDesc {
232 ty: DescriptorDescTy::CombinedImageSampler {
233 image_desc: DescriptorDescImage {
234 format: None,
235 multisampled: false,
236 view_type: ImageViewType::Dim2d,
237 },
238 immutable_samplers: vec![],
239 },
240 stages: ShaderStages {
241 vertex: false,
242 tessellation_control: false,
243 tessellation_evaluation: false,
244 geometry: false,
245 fragment: true,
246 compute: false,
247 },
248 variable_count: false,
249 descriptor_count: 1,
250 mutable: false,
251 })]);
252 let descriptor_set_layout = Arc::new(
253 DescriptorSetLayout::new(device.clone(), descriptor_set_desc.clone()).unwrap(),
254 );
255 let layout = Arc::new(
256 PipelineLayout::new(device.clone(), vec![descriptor_set_layout], vec![]).unwrap(),
257 );
258 let vs_module =
259 unsafe { ShaderModule::new(device.clone(), include_bytes!("shaders/vert.spv")) }?;
260
261 let fs_module =
262 unsafe { ShaderModule::new(device.clone(), include_bytes!("shaders/frag.spv")) }?;
263 let main = CString::new("main").unwrap();
264 let vs_in = create_shader_interface_vs_in();
265 let vs_out = create_shader_interface_vs_out();
266 let fs_out = create_shader_interface_fs_out();
267 let vs = unsafe {
268 vs_module.graphics_entry_point(
269 &main,
270 vec![descriptor_set_desc.clone()],
271 None,
272 <()>::descriptors(),
273 vs_in,
274 vs_out.clone(),
275 GraphicsShaderType::Vertex,
276 )
277 };
278 let fs = unsafe {
279 fs_module.graphics_entry_point(
280 &main,
281 vec![descriptor_set_desc.clone()],
282 None,
283 <()>::descriptors(),
284 vs_out,
285 fs_out,
286 GraphicsShaderType::Fragment,
287 )
288 };
289
290 let pipeline = Arc::new(
291 GraphicsPipeline::start()
292 .vertex_input_single_buffer::<Vertex>()
293 .vertex_shader(vs, ())
294 .depth_stencil_disabled()
295 .triangle_list()
296 .front_face_clockwise()
297 .viewports_scissors_dynamic(1)
298 .fragment_shader(fs, ())
299 .blend_alpha_blending()
300 .render_pass(subpass)
301 .with_pipeline_layout(device.clone(), layout)?,
302 );
303 let mesh = Mesh::with_glyph_cache_dimensions(glyph_cache_dims);
304
305 let glyph_cache_tex = {
306 let [width, height] = glyph_cache_dims;
307 StorageImage::with_usage(
308 device.clone(),
309 ImageDimensions::Dim2d {
310 width,
311 height,
312 array_layers: 1,
313 },
314 Format::R8_UNORM,
315 ImageUsage {
316 transfer_destination: true,
317 sampled: true,
318 ..ImageUsage::none()
319 },
320 ImageCreateFlags {
321 sparse_binding: false,
322 sparse_residency: false,
323 sparse_aliased: false,
324 mutable_format: false,
325 cube_compatible: false,
326 array_2d_compatible: false,
327 block_texel_view_compatible: false,
328 },
329 vec![graphics_queue_family],
330 )?
331 };
332
333 let tex_descs =
334 SingleLayoutDescSetPool::new(pipeline.layout().descriptor_set_layouts()[0].clone());
335 let glyph_uploads = Arc::new(CpuBufferPool::upload(device));
336
337 Ok(Renderer {
338 pipeline,
339 glyph_uploads,
340 glyph_cache_tex,
341 sampler,
342 tex_descs,
343 mesh,
344 })
345 }
346
347 pub fn commands(&self) -> mesh::Commands {
349 self.mesh.commands()
350 }
351
352 pub fn fill<P: render::PrimitiveWalker>(
358 &mut self,
359 image_map: &image::Map<Image>,
360 viewport: [f32; 4],
361 dpi_factor: f64,
362 primitives: P,
363 ) -> Result<Option<GlyphCacheCommand>, rt::gpu_cache::CacheWriteErr> {
364 let Renderer {
365 ref glyph_uploads,
366 ref glyph_cache_tex,
367 ref mut mesh,
368 ..
369 } = *self;
370 let [vp_l, vp_t, vp_r, vp_b] = viewport;
371 let lt = [vp_l as Scalar, vp_t as Scalar];
372 let rb = [vp_r as Scalar, vp_b as Scalar];
373 let viewport = Rect::from_corners(lt, rb);
374 let fill = mesh.fill(viewport, dpi_factor, image_map, primitives)?;
375 let glyph_cache_cmd = match fill.glyph_cache_requires_upload {
376 false => None,
377 true => Some(GlyphCacheCommand {
378 glyph_cache_pixel_buffer: mesh.glyph_cache_pixel_buffer(),
379 glyph_cpu_buffer_pool: glyph_uploads.clone(),
380 glyph_cache_texture: glyph_cache_tex.clone(),
381 }),
382 };
383 Ok(glyph_cache_cmd)
384 }
385
386 pub fn draw(
396 &mut self,
397 queue: Arc<Queue>,
398 image_map: &image::Map<Image>,
399 viewport: [f32; 4],
400 ) -> Result<Vec<DrawCommand>, DrawError> {
401 let current_viewport = Viewport {
402 origin: [viewport[0], viewport[1]],
403 dimensions: [viewport[2] - viewport[0], viewport[3] - viewport[1]],
404 depth_range: 0.0..1.0,
405 };
406
407 let mut current_scizzor = Scissor {
408 origin: [viewport[0] as u32, viewport[1] as u32],
409 dimensions: [
410 (viewport[2] - viewport[0]) as u32,
411 (viewport[3] - viewport[1]) as u32,
412 ],
413 };
414
415 let conv_scizzor = |s: mesh::Scizzor| Scissor {
416 origin: [s.top_left[0] as u32, s.top_left[1] as u32],
417 dimensions: s.dimensions,
418 };
419 let mut desc_set_builder = self.tex_descs.next();
420 desc_set_builder.add_sampled_image(
421 ImageView::new(self.glyph_cache_tex.clone()).unwrap(),
422 self.sampler.clone(),
423 )?;
424 let desc_cache = Arc::new(desc_set_builder.build()?);
425
426 let commands = self.mesh.commands();
427
428 let mut draw_commands = vec![];
429
430 for command in commands {
431 match command {
432 mesh::Command::Scizzor(scizzor) => current_scizzor = conv_scizzor(scizzor),
434
435 mesh::Command::Draw(draw) => match draw {
437 mesh::Draw::Plain(vert_range) => {
439 if !vert_range.is_empty() {
440 let verts = &self.mesh.vertices()[vert_range];
441 let verts = conv_vertex_buffer(verts);
442 let (vbuf, vbuf_fut) = ImmutableBuffer::<[Vertex]>::from_iter(
443 verts.iter().cloned(),
444 BufferUsage::vertex_buffer(),
445 queue.clone(),
446 )?;
447 vbuf_fut
448 .then_signal_fence_and_flush()
449 .expect("failed to flush future")
450 .wait(None)
451 .unwrap();
452 draw_commands.push(DrawCommand {
453 graphics_pipeline: self.pipeline.clone(),
454 scissor: current_scizzor,
455 viewport: current_viewport.clone(),
456 vertex_buffer: vbuf,
457 descriptor_set: desc_cache.clone(),
458 });
459 }
460 }
461
462 mesh::Draw::Image(image_id, vert_range) => {
465 if vert_range.is_empty() {
466 continue;
467 }
468 if let Some(image) = image_map.get(&image_id) {
469 let mut desc_set_builder = self.tex_descs.next();
470 desc_set_builder.add_sampled_image(
471 ImageView::new(image.image_access.clone()).unwrap(),
472 self.sampler.clone(),
473 )?;
474 let desc_image = Arc::new(desc_set_builder.build()?);
475
476 let verts = &self.mesh.vertices()[vert_range];
477 let verts = conv_vertex_buffer(verts);
478 let (vbuf, vbuf_fut) = ImmutableBuffer::from_iter(
479 verts.iter().cloned(),
480 BufferUsage::vertex_buffer(),
481 queue.clone(),
482 )?;
483 vbuf_fut
484 .then_signal_fence_and_flush()
485 .unwrap()
486 .wait(None)
487 .unwrap();
488 draw_commands.push(DrawCommand {
489 graphics_pipeline: self.pipeline.clone(),
490 scissor: current_scizzor,
491 viewport: current_viewport.clone(),
492 vertex_buffer: vbuf,
493 descriptor_set: desc_image,
494 });
495 }
496 }
497 },
498 }
499 }
500
501 Ok(draw_commands)
502 }
503}
504
505fn conv_vertex_buffer(buffer: &[mesh::Vertex]) -> &[Vertex] {
506 unsafe { &*(buffer as *const [conrod_core::mesh::Vertex] as *const [Vertex]) }
507}
508
509impl From<vulkano::OomError> for RendererCreationError {
510 fn from(err: OomError) -> Self {
511 RendererCreationError::ShaderLoad(err)
512 }
513}
514
515impl From<SamplerCreationError> for RendererCreationError {
516 fn from(err: SamplerCreationError) -> Self {
517 RendererCreationError::SamplerCreation(err)
518 }
519}
520
521impl From<GraphicsPipelineCreationError> for RendererCreationError {
522 fn from(err: GraphicsPipelineCreationError) -> Self {
523 RendererCreationError::GraphicsPipelineCreation(err)
524 }
525}
526
527impl From<ImageCreationError> for RendererCreationError {
528 fn from(err: ImageCreationError) -> Self {
529 RendererCreationError::ImageCreation(err)
530 }
531}
532
533impl From<DescriptorSetError> for DrawError {
534 fn from(err: DescriptorSetError) -> Self {
535 DrawError::DescriptorSet(err)
536 }
537}
538
539impl From<DeviceMemoryAllocError> for DrawError {
540 fn from(err: DeviceMemoryAllocError) -> Self {
541 DrawError::VertexBufferAlloc(err)
542 }
543}
544
545impl StdError for RendererCreationError {
546 fn cause(&self) -> Option<&dyn StdError> {
547 match *self {
548 RendererCreationError::SamplerCreation(ref err) => Some(err),
549 RendererCreationError::ShaderLoad(ref err) => Some(err),
550 RendererCreationError::GraphicsPipelineCreation(ref err) => Some(err),
551 RendererCreationError::ImageCreation(ref err) => Some(err),
552 }
553 }
554}
555
556impl StdError for DrawError {
557 fn cause(&self) -> Option<&dyn StdError> {
558 match *self {
559 DrawError::DescriptorSet(ref err) => Some(err),
560 DrawError::VertexBufferAlloc(ref err) => Some(err),
561 }
562 }
563}
564
565impl fmt::Display for RendererCreationError {
566 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
567 match *self {
568 RendererCreationError::SamplerCreation(ref err) => err.fmt(f),
569 RendererCreationError::ShaderLoad(ref err) => err.fmt(f),
570 RendererCreationError::GraphicsPipelineCreation(ref err) => err.fmt(f),
571 RendererCreationError::ImageCreation(ref err) => err.fmt(f),
572 }
573 }
574}
575
576impl fmt::Display for DrawError {
577 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
578 match *self {
579 DrawError::DescriptorSet(ref err) => err.fmt(f),
580 DrawError::VertexBufferAlloc(ref err) => err.fmt(f),
581 }
582 }
583}