Seregon/StratoSDK

StratoSDK is a framework with a declarative approach similar to Flutter/React, written and designed entirely for Rust.

Rust/27.3 KB/No license
crates/strato-ui-renderer/src/rendering/wgpu/texture_with_bind_group.rs
StratoSDK / crates / strato-ui-renderer / src / rendering / wgpu / texture_with_bind_group.rs
1use crate::fonts::RasterizedGlyph;
2 
3use crate::rendering::atlas::AllocatedRegion;
4use wgpu::{
5 BindGroup, BindGroupDescriptor, BindGroupLayout, Extent3d, Queue, Sampler,
6 TexelCopyBufferLayout, Texture, TextureDescriptor, TextureFormat, TextureUsages,
7};
8 
9/// Helper struct that includes a [`Texture`] and its corresponding [`BindGroup`] for use in the
10/// `GlyphCache`.
11pub(super) struct TextureWithBindGroup {
12 texture: Texture,
13 /// The [`BindGroup`] associated with the `texture`. We compute this whenever we need to create
14 /// a new texture as a performance optimization to ensure we don't create it on every render.
15 bind_group: BindGroup,
16}
17 
18impl TextureWithBindGroup {
19 pub(super) fn new(
20 size: usize,
21 device: &wgpu::Device,
22 bind_group_layout: &BindGroupLayout,
23 sampler: &Sampler,
24 ) -> Self {
25 let texture = device.create_texture(&TextureDescriptor {
26 label: Some("Glyph atlas texture"),
27 size: Extent3d {
28 width: size as u32,
29 height: size as u32,
30 depth_or_array_layers: 1,
31 },
32 mip_level_count: 1,
33 sample_count: 1,
34 dimension: wgpu::TextureDimension::D2,
35 format: TextureFormat::Rgba8Unorm,
36 usage: TextureUsages::TEXTURE_BINDING | TextureUsages::COPY_DST,
37 view_formats: &[],
38 });
39 
40 let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
41 let bind_group = device.create_bind_group(&BindGroupDescriptor {
42 layout: bind_group_layout,
43 entries: &[
44 wgpu::BindGroupEntry {
45 binding: 0,
46 resource: wgpu::BindingResource::TextureView(&view),
47 },
48 wgpu::BindGroupEntry {
49 binding: 1,
50 resource: wgpu::BindingResource::Sampler(sampler),
51 },
52 ],
53 label: None,
54 });
55 
56 Self {
57 texture,
58 bind_group,
59 }
60 }
61 
62 pub(super) fn insert_glyph_into_texture(
63 &mut self,
64 region: AllocatedRegion,
65 glyph: &RasterizedGlyph,
66 queue: &Queue,
67 ) {
68 let bytes_per_row: u32 = 4 * (glyph.canvas.size.x() as u32);
69 queue.write_texture(
70 wgpu::TexelCopyTextureInfo {
71 texture: &self.texture,
72 mip_level: 0,
73 origin: wgpu::Origin3d {
74 x: region.pixel_region.origin_x() as u32,
75 y: region.pixel_region.origin_y() as u32,
76 z: 0,
77 },
78 aspect: wgpu::TextureAspect::All,
79 },
80 glyph.canvas.pixels.as_slice(),
81 TexelCopyBufferLayout {
82 offset: 0,
83 bytes_per_row: Some(bytes_per_row),
84 rows_per_image: None,
85 },
86 Extent3d {
87 width: region.pixel_region.width() as u32,
88 height: region.pixel_region.height() as u32,
89 depth_or_array_layers: 1,
90 },
91 );
92 }
93 
94 pub(super) fn bind_group(&self) -> &BindGroup {
95 &self.bind_group
96 }
97}
98