mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-15 22:28:10 +08:00
Desktop: Fix crash caused by submitting work mid surface-reconfigure (#4317)
Implement wgpu-sync
This commit is contained in:
@@ -7,7 +7,7 @@ use web_sys::js_sys::{Object, Reflect};
|
||||
use web_sys::wasm_bindgen::{JsCast, JsValue};
|
||||
use web_sys::{CanvasRenderingContext2d, HtmlCanvasElement, window};
|
||||
#[cfg(feature = "wgpu")]
|
||||
use wgpu_executor::WgpuExecutor;
|
||||
use wgpu_executor::{WgpuCurrentSurfaceTexture, WgpuExecutor, WgpuSurface};
|
||||
|
||||
const CANVASES_OBJECT_KEY: &str = "imageCanvases";
|
||||
|
||||
@@ -52,13 +52,13 @@ impl Canvas for CanvasHandle {
|
||||
}
|
||||
|
||||
#[cfg(feature = "wgpu")]
|
||||
pub struct CanvasSurfaceHandle(CanvasHandle, Option<Arc<wgpu::Surface<'static>>>);
|
||||
pub struct CanvasSurfaceHandle(CanvasHandle, Option<Arc<WgpuSurface>>);
|
||||
#[cfg(feature = "wgpu")]
|
||||
impl CanvasSurfaceHandle {
|
||||
pub fn new() -> Self {
|
||||
Self(CanvasHandle::new(), None)
|
||||
}
|
||||
fn surface(&mut self, executor: &WgpuExecutor) -> &wgpu::Surface<'_> {
|
||||
fn surface(&mut self, executor: &WgpuExecutor) -> &WgpuSurface {
|
||||
if self.1.is_none() {
|
||||
let canvas = self.0.get().canvas.clone();
|
||||
let surface = executor
|
||||
@@ -115,9 +115,9 @@ impl CanvasSurface for CanvasSurfaceHandle {
|
||||
},
|
||||
);
|
||||
|
||||
let surface_texture = match surface.get_current_texture() {
|
||||
wgpu::CurrentSurfaceTexture::Success(t) | wgpu::CurrentSurfaceTexture::Suboptimal(t) => t,
|
||||
other => panic!("Failed to get surface texture: {other:?}"),
|
||||
let surface_texture = match surface.get_current_texture(&context.queue) {
|
||||
WgpuCurrentSurfaceTexture::Success(t) | WgpuCurrentSurfaceTexture::Suboptimal(t) => t,
|
||||
_ => panic!("Failed to get surface texture"),
|
||||
};
|
||||
|
||||
encoder.copy_texture_to_texture(
|
||||
@@ -136,7 +136,7 @@ impl CanvasSurface for CanvasSurfaceHandle {
|
||||
source_texture.size(),
|
||||
);
|
||||
|
||||
context.queue.submit([encoder.finish()]);
|
||||
surface_texture.queue.submit([encoder.finish()]);
|
||||
surface_texture.present();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ node-macro = { workspace = true }
|
||||
glam = { workspace = true }
|
||||
anyhow = { workspace = true }
|
||||
wgpu = { workspace = true }
|
||||
wgpu-sync = { workspace = true }
|
||||
futures = { workspace = true }
|
||||
web-sys = { workspace = true }
|
||||
vello = { workspace = true }
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use wgpu::{Adapter, Backends, Device, Features, Instance, Queue};
|
||||
use wgpu::{Backends, Device, Features};
|
||||
use wgpu_sync::{Adapter, Instance, Queue};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Context {
|
||||
@@ -77,10 +78,10 @@ impl ContextBuilder {
|
||||
}
|
||||
impl ContextBuilder {
|
||||
fn build_instance(&self) -> Instance {
|
||||
Instance::new(wgpu::InstanceDescriptor {
|
||||
Instance::new(wgpu::Instance::new(wgpu::InstanceDescriptor {
|
||||
backends: self.backends,
|
||||
..wgpu::InstanceDescriptor::new_without_display_handle()
|
||||
})
|
||||
}))
|
||||
}
|
||||
#[cfg(target_family = "wasm")]
|
||||
async fn request_adapter(&self, instance: &Instance) -> Option<Adapter> {
|
||||
|
||||
@@ -4,8 +4,6 @@ pub mod shader_runtime;
|
||||
mod texture_cache;
|
||||
pub mod texture_conversion;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::shader_runtime::ShaderRuntime;
|
||||
use crate::texture_cache::TextureCache;
|
||||
use anyhow::Result;
|
||||
@@ -14,6 +12,7 @@ use core_types::color::SRGBA8;
|
||||
use futures::lock::Mutex;
|
||||
use glam::UVec2;
|
||||
use graphene_application_io::{ApplicationIo, EditorApi};
|
||||
use std::sync::Arc;
|
||||
use vello::{AaConfig, AaSupport, RenderParams, Renderer, RendererOptions, Scene};
|
||||
use wgpu::{Origin3d, TextureAspect};
|
||||
|
||||
@@ -25,6 +24,10 @@ pub use pipeline::PipelineCache as WgpuPipelineCache;
|
||||
pub use rendering::RenderContext;
|
||||
pub use wgpu::Backends as WgpuBackends;
|
||||
pub use wgpu::Features as WgpuFeatures;
|
||||
pub use wgpu_sync::CurrentSurfaceTexture as WgpuCurrentSurfaceTexture;
|
||||
pub use wgpu_sync::Instance as WgpuInstance;
|
||||
pub use wgpu_sync::Queue as WgpuQueue;
|
||||
pub use wgpu_sync::Surface as WgpuSurface;
|
||||
|
||||
const TEXTURE_CACHE_SIZE: u64 = 256 * 1024 * 1024; // 256 MiB
|
||||
|
||||
@@ -88,7 +91,11 @@ impl WgpuExecutor {
|
||||
};
|
||||
renderer.override_image(&image_brush.image, Some(texture_view));
|
||||
}
|
||||
renderer.render_to_texture(&self.context().device, &self.context().queue, scene, &texture_view, &render_params)?;
|
||||
|
||||
{
|
||||
let queue = self.context().queue.lock();
|
||||
renderer.render_to_texture(&self.context().device, &queue, scene, &texture_view, &render_params)?;
|
||||
}
|
||||
for (image_brush, _) in context.resource_overrides.iter() {
|
||||
renderer.override_image(&image_brush.image, None);
|
||||
}
|
||||
|
||||
@@ -150,12 +150,12 @@ impl<'i> Convert<List<Raster<GPU>>, &'i WgpuExecutor> for List<Raster<GPU>> {
|
||||
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;
|
||||
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(device, &queue, &image);
|
||||
|
||||
Item::from_parts(Raster::new_gpu(texture), attributes)
|
||||
})
|
||||
@@ -170,8 +170,8 @@ impl<'i> Convert<List<Raster<GPU>>, &'i WgpuExecutor> for List<Raster<CPU>> {
|
||||
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;
|
||||
let texture = upload_to_texture(device, queue, &self);
|
||||
let queue = executor.context().queue.lock();
|
||||
let texture = upload_to_texture(device, &queue, &self);
|
||||
|
||||
queue.submit([]);
|
||||
Raster::new_gpu(texture)
|
||||
|
||||
Reference in New Issue
Block a user