mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-15 22:28:10 +08:00
Improve texture caching by allowing weak refs and more formats (#4447)
* Destroy GPU textures when the last reference drops * Request pooled textures synchronously * Pool cached textures by format * Add the owned GPU buffer type * Route the remaining GPU allocations through the executor * Add weak texture parking to the texture cache * Raise the texture cache budget to 1GB for native and 512MB for wasm
This commit is contained in:
@@ -1,40 +1,33 @@
|
||||
use crate::WgpuExecutor;
|
||||
use crate::{Buffer, WgpuExecutor};
|
||||
use core_types::Color;
|
||||
use core_types::color::SRGBA8;
|
||||
use core_types::list::{Item, List};
|
||||
use core_types::ops::Convert;
|
||||
use core_types::transform::Footprint;
|
||||
use raster_types::Image;
|
||||
use raster_types::{CPU, GPU, Raster};
|
||||
use wgpu::util::{DeviceExt, TextureDataOrder};
|
||||
use wgpu::{Extent3d, TextureDescriptor, TextureDimension, TextureFormat, TextureUsages};
|
||||
use raster_types::{CPU, GPU, Raster, Texture};
|
||||
use wgpu::{Extent3d, TextureFormat};
|
||||
|
||||
/// Uploads CPU image data to a GPU texture
|
||||
///
|
||||
/// Creates a new WGPU texture with RGBA8UnormSrgb format and uploads the provided
|
||||
/// image data. The texture is configured for binding, copying, and source operations.
|
||||
fn upload_to_texture(device: &wgpu::Device, queue: &wgpu::Queue, image: &Raster<CPU>) -> wgpu::Texture {
|
||||
fn upload_to_texture(executor: &WgpuExecutor, queue: &wgpu::Queue, image: &Raster<CPU>) -> Texture {
|
||||
let rgba8_data: Vec<SRGBA8> = image.data.iter().map(|x| (*x).into()).collect();
|
||||
|
||||
device.create_texture_with_data(
|
||||
queue,
|
||||
&TextureDescriptor {
|
||||
label: Some("upload_to_texture staging texture"),
|
||||
size: Extent3d {
|
||||
width: image.width,
|
||||
height: image.height,
|
||||
depth_or_array_layers: 1,
|
||||
},
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
dimension: TextureDimension::D2,
|
||||
format: TextureFormat::Rgba8UnormSrgb,
|
||||
usage: TextureUsages::TEXTURE_BINDING | TextureUsages::COPY_DST | TextureUsages::COPY_SRC,
|
||||
view_formats: &[],
|
||||
},
|
||||
TextureDataOrder::LayerMajor,
|
||||
let texture = executor.request_texture_with_format(glam::UVec2::new(image.width, image.height), TextureFormat::Rgba8UnormSrgb);
|
||||
queue.write_texture(
|
||||
texture.as_image_copy(),
|
||||
bytemuck::cast_slice(rgba8_data.as_slice()),
|
||||
)
|
||||
wgpu::TexelCopyBufferLayout {
|
||||
offset: 0,
|
||||
bytes_per_row: Some(4 * image.width),
|
||||
rows_per_image: Some(image.height),
|
||||
},
|
||||
Extent3d {
|
||||
width: image.width,
|
||||
height: image.height,
|
||||
depth_or_array_layers: 1,
|
||||
},
|
||||
);
|
||||
texture
|
||||
}
|
||||
|
||||
/// Converts a Raster<GPU> texture to Raster<CPU> by downloading the underlying texture data.
|
||||
@@ -44,7 +37,7 @@ fn upload_to_texture(device: &wgpu::Device, queue: &wgpu::Queue, image: &Raster<
|
||||
/// - 4 bytes-per-pixel RGBA8
|
||||
/// - Texture has COPY_SRC usage
|
||||
struct RasterGpuToRasterCpuConverter {
|
||||
buffer: wgpu::Buffer,
|
||||
buffer: Buffer,
|
||||
width: u32,
|
||||
height: u32,
|
||||
unpadded_bytes_per_row: u32,
|
||||
@@ -52,7 +45,7 @@ struct RasterGpuToRasterCpuConverter {
|
||||
_source: raster_types::Texture,
|
||||
}
|
||||
impl RasterGpuToRasterCpuConverter {
|
||||
fn new(device: &wgpu::Device, encoder: &mut wgpu::CommandEncoder, data_gpu: Raster<GPU>) -> Self {
|
||||
fn new(executor: &WgpuExecutor, encoder: &mut wgpu::CommandEncoder, data_gpu: Raster<GPU>) -> Self {
|
||||
let texture = data_gpu.data();
|
||||
let width = texture.width();
|
||||
let height = texture.height();
|
||||
@@ -62,7 +55,7 @@ impl RasterGpuToRasterCpuConverter {
|
||||
let padded_bytes_per_row = unpadded_bytes_per_row.div_ceil(align) * align;
|
||||
let buffer_size = padded_bytes_per_row as u64 * height as u64;
|
||||
|
||||
let buffer = device.create_buffer(&wgpu::BufferDescriptor {
|
||||
let buffer = executor.create_buffer(&wgpu::BufferDescriptor {
|
||||
label: Some("texture_download_buffer"),
|
||||
size: buffer_size,
|
||||
usage: wgpu::BufferUsages::COPY_DST | wgpu::BufferUsages::MAP_READ,
|
||||
@@ -151,13 +144,12 @@ impl<'i> Convert<List<Raster<GPU>>, &'i WgpuExecutor> for List<Raster<GPU>> {
|
||||
/// Converts a `List<Raster<CPU>>` to `List<Raster<GPU>>` by uploading each image to a texture
|
||||
impl<'i> Convert<List<Raster<GPU>>, &'i WgpuExecutor> for List<Raster<CPU>> {
|
||||
async fn convert(self, _: Footprint, executor: &'i WgpuExecutor) -> List<Raster<GPU>> {
|
||||
let device = &executor.context().device;
|
||||
let queue = executor.context().queue.lock();
|
||||
let list = self
|
||||
.into_iter()
|
||||
.map(|row| {
|
||||
let (image, attributes) = row.into_parts();
|
||||
let texture = upload_to_texture(device, &queue, &image);
|
||||
let texture = upload_to_texture(executor, &queue, &image);
|
||||
|
||||
Item::from_parts(Raster::new_gpu(texture), attributes)
|
||||
})
|
||||
@@ -171,9 +163,8 @@ impl<'i> Convert<List<Raster<GPU>>, &'i WgpuExecutor> for List<Raster<CPU>> {
|
||||
/// Converts single CPU raster to GPU by uploading to texture
|
||||
impl<'i> Convert<Raster<GPU>, &'i WgpuExecutor> for Raster<CPU> {
|
||||
async fn convert(self, _: Footprint, executor: &'i WgpuExecutor) -> Raster<GPU> {
|
||||
let device = &executor.context().device;
|
||||
let queue = executor.context().queue.lock();
|
||||
let texture = upload_to_texture(device, &queue, &self);
|
||||
let texture = upload_to_texture(executor, &queue, &self);
|
||||
|
||||
queue.submit([]);
|
||||
Raster::new_gpu(texture)
|
||||
@@ -202,7 +193,7 @@ impl<'i> Convert<List<Raster<CPU>>, &'i WgpuExecutor> for List<Raster<GPU>> {
|
||||
|
||||
for row in self {
|
||||
let (element, attributes) = row.into_parts();
|
||||
converters.push(RasterGpuToRasterCpuConverter::new(device, &mut encoder, element));
|
||||
converters.push(RasterGpuToRasterCpuConverter::new(executor, &mut encoder, element));
|
||||
rows_meta.push(Item::from_parts((), attributes));
|
||||
}
|
||||
|
||||
@@ -239,7 +230,7 @@ impl<'i> Convert<Raster<CPU>, &'i WgpuExecutor> for Raster<GPU> {
|
||||
label: Some("single_texture_download_encoder"),
|
||||
});
|
||||
|
||||
let converter = RasterGpuToRasterCpuConverter::new(device, &mut encoder, self);
|
||||
let converter = RasterGpuToRasterCpuConverter::new(executor, &mut encoder, self);
|
||||
|
||||
queue.submit([encoder.finish()]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user