2022-11-28 07:18:45 -03:30
|
|
|
use crate::{
|
2024-05-08 16:17:58 +02:00
|
|
|
ColorMode, FontSystem, GlyphDetails, GlyphToRender, GpuCacheStatus, PrepareError, RenderError,
|
|
|
|
|
SwashCache, SwashContent, TextArea, TextAtlas, Viewport,
|
2022-11-28 07:18:45 -03:30
|
|
|
};
|
2025-02-05 03:04:11 +01:00
|
|
|
use std::{num::NonZeroU64, slice};
|
2024-03-29 03:55:20 +01:00
|
|
|
use wgpu::util::StagingBelt;
|
2022-10-06 12:13:43 -04:00
|
|
|
use wgpu::{
|
2024-03-29 03:55:20 +01:00
|
|
|
Buffer, BufferDescriptor, BufferUsages, CommandEncoder, DepthStencilState, Device, Extent3d,
|
2025-01-22 20:26:52 -03:00
|
|
|
MultisampleState, Origin3d, Queue, RenderPass, RenderPipeline, TexelCopyBufferLayout,
|
|
|
|
|
TexelCopyTextureInfo, TextureAspect, COPY_BUFFER_ALIGNMENT,
|
2022-10-06 12:13:43 -04:00
|
|
|
};
|
|
|
|
|
|
2022-10-18 13:17:35 -02:30
|
|
|
/// A text renderer that uses cached glyphs to render text into an existing render pass.
|
2022-10-06 12:13:43 -04:00
|
|
|
pub struct TextRenderer {
|
2024-03-29 03:55:20 +01:00
|
|
|
staging_belt: StagingBelt,
|
2022-10-06 12:13:43 -04:00
|
|
|
vertex_buffer: Buffer,
|
|
|
|
|
vertex_buffer_size: u64,
|
2025-02-05 03:04:11 +01:00
|
|
|
pipeline: RenderPipeline,
|
2024-03-29 23:46:42 +01:00
|
|
|
glyph_vertices: Vec<GlyphToRender>,
|
2024-03-12 18:19:14 +02:00
|
|
|
glyphs_to_render: u32,
|
2022-10-06 12:13:43 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl TextRenderer {
|
2022-10-18 13:17:35 -02:30
|
|
|
/// Creates a new `TextRenderer`.
|
2023-02-13 22:35:04 -03:30
|
|
|
pub fn new(
|
|
|
|
|
atlas: &mut TextAtlas,
|
|
|
|
|
device: &Device,
|
|
|
|
|
multisample: MultisampleState,
|
|
|
|
|
depth_stencil: Option<DepthStencilState>,
|
|
|
|
|
) -> Self {
|
2022-10-06 12:13:43 -04:00
|
|
|
let vertex_buffer_size = next_copy_buffer_size(4096);
|
|
|
|
|
let vertex_buffer = device.create_buffer(&BufferDescriptor {
|
|
|
|
|
label: Some("glyphon vertices"),
|
|
|
|
|
size: vertex_buffer_size,
|
|
|
|
|
usage: BufferUsages::VERTEX | BufferUsages::COPY_DST,
|
|
|
|
|
mapped_at_creation: false,
|
|
|
|
|
});
|
|
|
|
|
|
2024-05-08 15:39:19 +02:00
|
|
|
let pipeline = atlas.get_or_create_pipeline(device, multisample, depth_stencil);
|
2024-03-26 02:25:57 +02:00
|
|
|
|
2022-10-06 12:13:43 -04:00
|
|
|
Self {
|
2024-03-29 03:55:20 +01:00
|
|
|
staging_belt: StagingBelt::new(vertex_buffer_size),
|
2022-10-06 12:13:43 -04:00
|
|
|
vertex_buffer,
|
|
|
|
|
vertex_buffer_size,
|
2023-02-13 22:35:04 -03:30
|
|
|
pipeline,
|
2024-03-29 23:46:42 +01:00
|
|
|
glyph_vertices: Vec::new(),
|
2024-03-12 18:19:14 +02:00
|
|
|
glyphs_to_render: 0,
|
2022-10-06 12:13:43 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-26 00:07:05 -03:30
|
|
|
/// Prepares all of the provided text areas for rendering.
|
2023-02-05 18:22:56 +01:00
|
|
|
pub fn prepare_with_depth<'a>(
|
2022-10-06 12:13:43 -04:00
|
|
|
&mut self,
|
|
|
|
|
device: &Device,
|
|
|
|
|
queue: &Queue,
|
2024-03-29 03:55:20 +01:00
|
|
|
encoder: &mut CommandEncoder,
|
2023-03-19 15:05:53 +01:00
|
|
|
font_system: &mut FontSystem,
|
2022-10-06 12:13:43 -04:00
|
|
|
atlas: &mut TextAtlas,
|
2024-05-08 16:17:58 +02:00
|
|
|
viewport: &Viewport,
|
2023-07-07 07:04:00 +02:00
|
|
|
text_areas: impl IntoIterator<Item = TextArea<'a>>,
|
2022-10-28 01:14:07 -02:30
|
|
|
cache: &mut SwashCache,
|
2023-02-14 14:44:09 -03:30
|
|
|
mut metadata_to_depth: impl FnMut(usize) -> f32,
|
2022-10-06 12:13:43 -04:00
|
|
|
) -> Result<(), PrepareError> {
|
2024-03-29 03:55:20 +01:00
|
|
|
self.staging_belt.recall();
|
2024-03-29 23:46:42 +01:00
|
|
|
self.glyph_vertices.clear();
|
2023-03-28 12:37:31 +02:00
|
|
|
|
2024-05-08 16:17:58 +02:00
|
|
|
let resolution = viewport.resolution();
|
|
|
|
|
|
2023-03-28 12:37:31 +02:00
|
|
|
for text_area in text_areas {
|
2024-07-29 11:59:26 -02:30
|
|
|
let bounds_min_x = text_area.bounds.left.max(0);
|
|
|
|
|
let bounds_min_y = text_area.bounds.top.max(0);
|
|
|
|
|
let bounds_max_x = text_area.bounds.right.min(resolution.width as i32);
|
|
|
|
|
let bounds_max_y = text_area.bounds.bottom.min(resolution.height as i32);
|
|
|
|
|
|
|
|
|
|
let is_run_visible = |run: &cosmic_text::LayoutRun| {
|
2025-03-04 19:36:29 -07:00
|
|
|
let start_y_physical = (text_area.top + (run.line_top * text_area.scale)) as i32;
|
|
|
|
|
let end_y_physical = start_y_physical + (run.line_height * text_area.scale) as i32;
|
2025-03-09 01:00:26 +01:00
|
|
|
|
|
|
|
|
start_y_physical <= text_area.bounds.bottom
|
|
|
|
|
&& text_area.bounds.top <= end_y_physical
|
2024-07-29 11:59:26 -02:30
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let layout_runs = text_area
|
|
|
|
|
.buffer
|
|
|
|
|
.layout_runs()
|
|
|
|
|
.skip_while(|run| !is_run_visible(run))
|
|
|
|
|
.take_while(is_run_visible);
|
|
|
|
|
|
|
|
|
|
for run in layout_runs {
|
2022-10-25 22:38:12 -02:30
|
|
|
for glyph in run.glyphs.iter() {
|
2023-06-20 06:08:41 +02:00
|
|
|
let physical_glyph =
|
|
|
|
|
glyph.physical((text_area.left, text_area.top), text_area.scale);
|
|
|
|
|
|
2024-11-28 22:36:23 +09:00
|
|
|
let cache_key = physical_glyph.cache_key;
|
|
|
|
|
|
|
|
|
|
let details = if let Some(details) =
|
|
|
|
|
atlas.mask_atlas.glyph_cache.get(&cache_key)
|
2023-06-20 06:08:41 +02:00
|
|
|
{
|
2024-11-28 22:36:23 +09:00
|
|
|
atlas.mask_atlas.glyphs_in_use.insert(cache_key);
|
|
|
|
|
details
|
|
|
|
|
} else if let Some(details) = atlas.color_atlas.glyph_cache.get(&cache_key) {
|
|
|
|
|
atlas.color_atlas.glyphs_in_use.insert(cache_key);
|
|
|
|
|
details
|
2023-03-28 12:37:31 +02:00
|
|
|
} else {
|
2023-12-03 16:23:17 -06:00
|
|
|
let Some(image) =
|
|
|
|
|
cache.get_image_uncached(font_system, physical_glyph.cache_key)
|
|
|
|
|
else {
|
|
|
|
|
continue;
|
|
|
|
|
};
|
2023-03-28 12:37:31 +02:00
|
|
|
|
|
|
|
|
let content_type = match image.content {
|
|
|
|
|
SwashContent::Color => ContentType::Color,
|
|
|
|
|
SwashContent::Mask => ContentType::Mask,
|
|
|
|
|
SwashContent::SubpixelMask => {
|
|
|
|
|
// Not implemented yet, but don't panic if this happens.
|
|
|
|
|
ContentType::Mask
|
|
|
|
|
}
|
|
|
|
|
};
|
2022-11-28 07:18:45 -03:30
|
|
|
|
2023-03-28 12:37:31 +02:00
|
|
|
let width = image.placement.width as usize;
|
|
|
|
|
let height = image.placement.height as usize;
|
|
|
|
|
|
|
|
|
|
let should_rasterize = width > 0 && height > 0;
|
|
|
|
|
|
|
|
|
|
let (gpu_cache, atlas_id, inner) = if should_rasterize {
|
|
|
|
|
let mut inner = atlas.inner_for_content_mut(content_type);
|
|
|
|
|
|
|
|
|
|
// Find a position in the packer
|
|
|
|
|
let allocation = loop {
|
|
|
|
|
match inner.try_allocate(width, height) {
|
|
|
|
|
Some(a) => break a,
|
|
|
|
|
None => {
|
|
|
|
|
if !atlas.grow(
|
|
|
|
|
device,
|
|
|
|
|
queue,
|
|
|
|
|
font_system,
|
|
|
|
|
cache,
|
|
|
|
|
content_type,
|
|
|
|
|
) {
|
|
|
|
|
return Err(PrepareError::AtlasFull);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inner = atlas.inner_for_content_mut(content_type);
|
2023-06-15 18:23:36 +02:00
|
|
|
}
|
|
|
|
|
}
|
2023-03-28 12:37:31 +02:00
|
|
|
};
|
|
|
|
|
let atlas_min = allocation.rectangle.min;
|
|
|
|
|
|
|
|
|
|
queue.write_texture(
|
2025-01-22 20:26:52 -03:00
|
|
|
TexelCopyTextureInfo {
|
2023-03-28 12:37:31 +02:00
|
|
|
texture: &inner.texture,
|
|
|
|
|
mip_level: 0,
|
|
|
|
|
origin: Origin3d {
|
|
|
|
|
x: atlas_min.x as u32,
|
|
|
|
|
y: atlas_min.y as u32,
|
|
|
|
|
z: 0,
|
|
|
|
|
},
|
|
|
|
|
aspect: TextureAspect::All,
|
2023-02-08 21:21:54 +01:00
|
|
|
},
|
2023-03-28 12:37:31 +02:00
|
|
|
&image.data,
|
2025-01-22 20:26:52 -03:00
|
|
|
TexelCopyBufferLayout {
|
2023-03-28 12:37:31 +02:00
|
|
|
offset: 0,
|
|
|
|
|
bytes_per_row: Some(width as u32 * inner.num_channels() as u32),
|
|
|
|
|
rows_per_image: None,
|
|
|
|
|
},
|
|
|
|
|
Extent3d {
|
|
|
|
|
width: width as u32,
|
|
|
|
|
height: height as u32,
|
|
|
|
|
depth_or_array_layers: 1,
|
|
|
|
|
},
|
|
|
|
|
);
|
2022-10-06 12:13:43 -04:00
|
|
|
|
2023-03-28 12:37:31 +02:00
|
|
|
(
|
|
|
|
|
GpuCacheStatus::InAtlas {
|
|
|
|
|
x: atlas_min.x as u16,
|
|
|
|
|
y: atlas_min.y as u16,
|
|
|
|
|
content_type,
|
|
|
|
|
},
|
|
|
|
|
Some(allocation.id),
|
|
|
|
|
inner,
|
|
|
|
|
)
|
|
|
|
|
} else {
|
|
|
|
|
let inner = &mut atlas.color_atlas;
|
|
|
|
|
(GpuCacheStatus::SkipRasterization, None, inner)
|
|
|
|
|
};
|
2022-10-06 12:13:43 -04:00
|
|
|
|
2024-11-28 22:36:23 +09:00
|
|
|
inner.glyphs_in_use.insert(cache_key);
|
|
|
|
|
// Insert the glyph into the cache and return the details reference
|
|
|
|
|
inner.glyph_cache.get_or_insert(cache_key, || GlyphDetails {
|
|
|
|
|
width: image.placement.width as u16,
|
|
|
|
|
height: image.placement.height as u16,
|
|
|
|
|
gpu_cache,
|
|
|
|
|
atlas_id,
|
|
|
|
|
top: image.placement.top as i16,
|
|
|
|
|
left: image.placement.left as i16,
|
|
|
|
|
})
|
|
|
|
|
};
|
2022-10-25 22:38:12 -02:30
|
|
|
|
2023-06-20 06:08:41 +02:00
|
|
|
let mut x = physical_glyph.x + details.left as i32;
|
|
|
|
|
let mut y = (run.line_y * text_area.scale).round() as i32 + physical_glyph.y
|
|
|
|
|
- details.top as i32;
|
2022-10-25 22:38:12 -02:30
|
|
|
|
2022-11-28 07:18:45 -03:30
|
|
|
let (mut atlas_x, mut atlas_y, content_type) = match details.gpu_cache {
|
|
|
|
|
GpuCacheStatus::InAtlas { x, y, content_type } => (x, y, content_type),
|
|
|
|
|
GpuCacheStatus::SkipRasterization => continue,
|
2022-10-25 22:38:12 -02:30
|
|
|
};
|
|
|
|
|
|
2022-10-25 23:38:12 -02:30
|
|
|
let mut width = details.width as i32;
|
|
|
|
|
let mut height = details.height as i32;
|
2022-10-25 01:11:57 -02:30
|
|
|
|
2023-01-26 00:07:05 -03:30
|
|
|
// Starts beyond right edge or ends beyond left edge
|
|
|
|
|
let max_x = x + width;
|
|
|
|
|
if x > bounds_max_x || max_x < bounds_min_x {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2022-10-25 22:38:12 -02:30
|
|
|
|
2023-01-26 00:07:05 -03:30
|
|
|
// Starts beyond bottom edge or ends beyond top edge
|
|
|
|
|
let max_y = y + height;
|
|
|
|
|
if y > bounds_max_y || max_y < bounds_min_y {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2022-10-25 22:38:12 -02:30
|
|
|
|
2023-01-26 00:07:05 -03:30
|
|
|
// Clip left ege
|
|
|
|
|
if x < bounds_min_x {
|
|
|
|
|
let right_shift = bounds_min_x - x;
|
2022-10-25 22:38:12 -02:30
|
|
|
|
2023-01-26 00:07:05 -03:30
|
|
|
x = bounds_min_x;
|
|
|
|
|
width = max_x - bounds_min_x;
|
|
|
|
|
atlas_x += right_shift as u16;
|
|
|
|
|
}
|
2022-10-25 22:38:12 -02:30
|
|
|
|
2023-01-26 00:07:05 -03:30
|
|
|
// Clip right edge
|
|
|
|
|
if x + width > bounds_max_x {
|
|
|
|
|
width = bounds_max_x - x;
|
|
|
|
|
}
|
2022-10-25 22:38:12 -02:30
|
|
|
|
2023-01-26 00:07:05 -03:30
|
|
|
// Clip top edge
|
|
|
|
|
if y < bounds_min_y {
|
|
|
|
|
let bottom_shift = bounds_min_y - y;
|
2022-10-25 01:11:57 -02:30
|
|
|
|
2023-01-26 00:07:05 -03:30
|
|
|
y = bounds_min_y;
|
|
|
|
|
height = max_y - bounds_min_y;
|
|
|
|
|
atlas_y += bottom_shift as u16;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Clip bottom edge
|
|
|
|
|
if y + height > bounds_max_y {
|
|
|
|
|
height = bounds_max_y - y;
|
2022-10-06 12:13:43 -04:00
|
|
|
}
|
2022-10-25 22:38:12 -02:30
|
|
|
|
2023-02-14 14:44:09 -03:30
|
|
|
let color = match glyph.color_opt {
|
|
|
|
|
Some(some) => some,
|
2023-02-27 03:31:34 +01:00
|
|
|
None => text_area.default_color,
|
2023-02-14 14:44:09 -03:30
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let depth = metadata_to_depth(glyph.metadata);
|
|
|
|
|
|
2024-03-12 18:19:14 +02:00
|
|
|
self.glyph_vertices.push(GlyphToRender {
|
|
|
|
|
pos: [x, y],
|
|
|
|
|
dim: [width as u16, height as u16],
|
|
|
|
|
uv: [atlas_x, atlas_y],
|
|
|
|
|
color: color.0,
|
|
|
|
|
content_type_with_srgb: [
|
|
|
|
|
content_type as u16,
|
|
|
|
|
match atlas.color_mode {
|
|
|
|
|
ColorMode::Accurate => TextColorConversion::ConvertToLinear,
|
|
|
|
|
ColorMode::Web => TextColorConversion::None,
|
|
|
|
|
} as u16,
|
|
|
|
|
],
|
|
|
|
|
depth,
|
|
|
|
|
});
|
2022-10-06 12:13:43 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-12 18:19:14 +02:00
|
|
|
self.glyphs_to_render = self.glyph_vertices.len() as u32;
|
2022-10-06 12:13:43 -04:00
|
|
|
|
2024-03-12 18:19:14 +02:00
|
|
|
let will_render = !self.glyph_vertices.is_empty();
|
2022-10-06 12:13:43 -04:00
|
|
|
if !will_render {
|
|
|
|
|
return Ok(());
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-29 23:46:42 +01:00
|
|
|
let vertices = self.glyph_vertices.as_slice();
|
2022-10-06 12:13:43 -04:00
|
|
|
let vertices_raw = unsafe {
|
|
|
|
|
slice::from_raw_parts(
|
|
|
|
|
vertices as *const _ as *const u8,
|
2023-12-03 16:20:47 -06:00
|
|
|
std::mem::size_of_val(vertices),
|
2022-10-06 12:13:43 -04:00
|
|
|
)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if self.vertex_buffer_size >= vertices_raw.len() as u64 {
|
2024-03-29 03:55:20 +01:00
|
|
|
self.staging_belt
|
|
|
|
|
.write_buffer(
|
|
|
|
|
encoder,
|
|
|
|
|
&self.vertex_buffer,
|
|
|
|
|
0,
|
|
|
|
|
NonZeroU64::new(vertices_raw.len() as u64).expect("Non-empty vertices"),
|
|
|
|
|
device,
|
|
|
|
|
)
|
|
|
|
|
.copy_from_slice(vertices_raw);
|
2022-10-06 12:13:43 -04:00
|
|
|
} else {
|
|
|
|
|
self.vertex_buffer.destroy();
|
|
|
|
|
|
|
|
|
|
let (buffer, buffer_size) = create_oversized_buffer(
|
|
|
|
|
device,
|
|
|
|
|
Some("glyphon vertices"),
|
|
|
|
|
vertices_raw,
|
|
|
|
|
BufferUsages::VERTEX | BufferUsages::COPY_DST,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
self.vertex_buffer = buffer;
|
|
|
|
|
self.vertex_buffer_size = buffer_size;
|
2024-03-29 03:55:20 +01:00
|
|
|
|
|
|
|
|
self.staging_belt.finish();
|
|
|
|
|
self.staging_belt = StagingBelt::new(buffer_size);
|
2022-10-06 12:13:43 -04:00
|
|
|
}
|
|
|
|
|
|
2024-03-29 03:55:20 +01:00
|
|
|
self.staging_belt.finish();
|
|
|
|
|
|
2022-10-06 12:13:43 -04:00
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-05 18:22:56 +01:00
|
|
|
pub fn prepare<'a>(
|
2023-02-14 14:44:09 -03:30
|
|
|
&mut self,
|
|
|
|
|
device: &Device,
|
|
|
|
|
queue: &Queue,
|
2024-03-29 03:55:20 +01:00
|
|
|
encoder: &mut CommandEncoder,
|
2023-03-19 15:05:53 +01:00
|
|
|
font_system: &mut FontSystem,
|
2023-02-14 14:44:09 -03:30
|
|
|
atlas: &mut TextAtlas,
|
2024-05-08 16:17:58 +02:00
|
|
|
viewport: &Viewport,
|
2023-07-07 07:04:00 +02:00
|
|
|
text_areas: impl IntoIterator<Item = TextArea<'a>>,
|
2023-02-14 14:44:09 -03:30
|
|
|
cache: &mut SwashCache,
|
|
|
|
|
) -> Result<(), PrepareError> {
|
|
|
|
|
self.prepare_with_depth(
|
|
|
|
|
device,
|
|
|
|
|
queue,
|
2024-03-29 03:55:20 +01:00
|
|
|
encoder,
|
2023-03-19 15:05:53 +01:00
|
|
|
font_system,
|
2023-02-14 14:44:09 -03:30
|
|
|
atlas,
|
2024-05-08 16:17:58 +02:00
|
|
|
viewport,
|
2023-02-14 14:44:09 -03:30
|
|
|
text_areas,
|
|
|
|
|
cache,
|
|
|
|
|
zero_depth,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-18 13:17:35 -02:30
|
|
|
/// Renders all layouts that were previously provided to `prepare`.
|
2024-09-30 21:55:17 +03:00
|
|
|
pub fn render(
|
|
|
|
|
&self,
|
|
|
|
|
atlas: &TextAtlas,
|
|
|
|
|
viewport: &Viewport,
|
|
|
|
|
pass: &mut RenderPass<'_>,
|
2022-10-06 12:13:43 -04:00
|
|
|
) -> Result<(), RenderError> {
|
2024-03-12 18:19:14 +02:00
|
|
|
if self.glyphs_to_render == 0 {
|
2022-10-06 12:13:43 -04:00
|
|
|
return Ok(());
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-13 22:35:04 -03:30
|
|
|
pass.set_pipeline(&self.pipeline);
|
2024-05-08 15:39:19 +02:00
|
|
|
pass.set_bind_group(0, &atlas.bind_group, &[]);
|
2024-05-08 16:17:58 +02:00
|
|
|
pass.set_bind_group(1, &viewport.bind_group, &[]);
|
2022-10-06 12:13:43 -04:00
|
|
|
pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
|
2024-03-12 18:19:14 +02:00
|
|
|
pass.draw(0..4, 0..self.glyphs_to_render);
|
2022-10-06 12:13:43 -04:00
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-15 21:13:50 -03:30
|
|
|
#[repr(u16)]
|
2023-02-08 23:08:37 +01:00
|
|
|
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
|
|
|
|
pub enum ContentType {
|
2022-11-28 07:18:45 -03:30
|
|
|
Color = 0,
|
|
|
|
|
Mask = 1,
|
2022-10-06 12:13:43 -04:00
|
|
|
}
|
|
|
|
|
|
2024-01-15 21:13:50 -03:30
|
|
|
#[repr(u16)]
|
|
|
|
|
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
|
|
|
|
enum TextColorConversion {
|
|
|
|
|
None = 0,
|
|
|
|
|
ConvertToLinear = 1,
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-06 12:13:43 -04:00
|
|
|
fn next_copy_buffer_size(size: u64) -> u64 {
|
|
|
|
|
let align_mask = COPY_BUFFER_ALIGNMENT - 1;
|
|
|
|
|
((size.next_power_of_two() + align_mask) & !align_mask).max(COPY_BUFFER_ALIGNMENT)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn create_oversized_buffer(
|
|
|
|
|
device: &Device,
|
|
|
|
|
label: Option<&str>,
|
|
|
|
|
contents: &[u8],
|
|
|
|
|
usage: BufferUsages,
|
|
|
|
|
) -> (Buffer, u64) {
|
|
|
|
|
let size = next_copy_buffer_size(contents.len() as u64);
|
|
|
|
|
let buffer = device.create_buffer(&BufferDescriptor {
|
|
|
|
|
label,
|
|
|
|
|
size,
|
|
|
|
|
usage,
|
|
|
|
|
mapped_at_creation: true,
|
|
|
|
|
});
|
|
|
|
|
buffer.slice(..).get_mapped_range_mut()[..contents.len()].copy_from_slice(contents);
|
|
|
|
|
buffer.unmap();
|
|
|
|
|
(buffer, size)
|
|
|
|
|
}
|
2023-02-14 14:44:09 -03:30
|
|
|
|
|
|
|
|
fn zero_depth(_: usize) -> f32 {
|
|
|
|
|
0f32
|
|
|
|
|
}
|