Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ members = [
"frontend/wrapper",
"libraries/dyn-any",
"libraries/math-parser",
"libraries/wgpu-sync",
"node-graph/libraries/graphene-hash",
"node-graph/libraries/*",
"node-graph/nodes/*",
Expand Down Expand Up @@ -98,6 +99,7 @@ graphene-std = { path = "node-graph/nodes/gstd" }
interpreted-executor = { path = "node-graph/interpreted-executor" }
node-macro = { path = "node-graph/node-macro" }
wgpu-executor = { path = "node-graph/libraries/wgpu-executor" }
wgpu-sync = { path = "libraries/wgpu-sync" }
graphite-proc-macros = { path = "proc-macros" }
graphite-editor = { path = "editor" }
graphene-canvas-utils = { path = "node-graph/libraries/canvas-utils" }
Expand Down
54 changes: 26 additions & 28 deletions desktop/src/render/state.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
use wgpu::PresentMode;

use crate::window::Window;
use crate::wrapper::{WgpuContext, WgpuExecutor};
use crate::wrapper::{WgpuContext, WgpuCurrentSurfaceTexture, WgpuExecutor, WgpuSurface};

#[derive(derivative::Derivative)]
#[derivative(Debug)]
pub(crate) struct RenderState {
surface: wgpu::Surface<'static>,
context: WgpuContext,
surface: WgpuSurface,
executor: WgpuExecutor,
config: wgpu::SurfaceConfiguration,
render_pipeline: wgpu::RenderPipeline,
Expand Down Expand Up @@ -162,12 +161,11 @@ impl RenderState {
cache: None,
});

let wgpu_executor = WgpuExecutor::with_context(context.clone()).expect("Failed to create WgpuExecutor");
let executor = WgpuExecutor::with_context(context).expect("Failed to create WgpuExecutor");

Self {
surface,
context,
executor: wgpu_executor,
executor,
config,
render_pipeline,
transparent_texture,
Expand All @@ -193,12 +191,6 @@ impl RenderState {
self.desired_width = width;
self.desired_height = height;
self.surface_outdated = true;

if width > 0 && height > 0 && (self.config.width != width || self.config.height != height) {
self.config.width = width;
self.config.height = height;
self.surface.configure(&self.context.device, &self.config);
}
}

pub(crate) fn bind_viewport_texture(&mut self, viewport_texture: std::sync::Arc<wgpu::Texture>) {
Expand Down Expand Up @@ -254,6 +246,14 @@ impl RenderState {
if !self.surface_outdated {
return Ok(());
}

// Apply resize once per presented frame.
if self.desired_width > 0 && self.desired_height > 0 && (self.config.width != self.desired_width || self.config.height != self.desired_height) {
self.config.width = self.desired_width;
self.config.height = self.desired_height;
self.surface.configure(&self.executor.context().device, &self.config);
}

let ui_scale = if let Some(ui_texture) = &self.ui_texture
&& (self.desired_width != ui_texture.width() || self.desired_height != ui_texture.height())
{
Expand All @@ -266,21 +266,19 @@ impl RenderState {
self.render_overlays(scene);
}

let (output, suboptimal) = match self.surface.get_current_texture() {
wgpu::CurrentSurfaceTexture::Success(t) => (t, false),
// wgpu reports the swapchain no longer matches the underlying surface; present this frame and reconfigure after present, since `Surface::configure` panics while an acquired `SurfaceTexture` is still alive
wgpu::CurrentSurfaceTexture::Suboptimal(t) => (t, true),
// Window is minimized or behind another window: skip the frame silently and try again once it becomes visible
wgpu::CurrentSurfaceTexture::Occluded => return Ok(()),
wgpu::CurrentSurfaceTexture::Lost => return Err(RenderError::SurfaceLost),
wgpu::CurrentSurfaceTexture::Outdated => return Err(RenderError::SurfaceOutdated),
wgpu::CurrentSurfaceTexture::Timeout => return Err(RenderError::SurfaceTimeout),
wgpu::CurrentSurfaceTexture::Validation => return Err(RenderError::SurfaceValidation),
let (surface_texture, suboptimal) = match self.surface.get_current_texture(&self.executor.context().queue) {
WgpuCurrentSurfaceTexture::Success(t) => (t, false),
WgpuCurrentSurfaceTexture::Suboptimal(t) => (t, true),
WgpuCurrentSurfaceTexture::Occluded => return Ok(()),
WgpuCurrentSurfaceTexture::Lost => return Err(RenderError::SurfaceLost),
WgpuCurrentSurfaceTexture::Outdated => return Err(RenderError::SurfaceOutdated),
WgpuCurrentSurfaceTexture::Timeout => return Err(RenderError::SurfaceTimeout),
WgpuCurrentSurfaceTexture::Validation => return Err(RenderError::SurfaceValidation),
};

let view = output.texture.create_view(&wgpu::TextureViewDescriptor::default());
let view = surface_texture.texture.create_view(&wgpu::TextureViewDescriptor::default());

let mut encoder = self.context.device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: Some("Render Encoder") });
let mut encoder = self.executor.context().device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: Some("Render Encoder") });

{
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
Expand Down Expand Up @@ -318,12 +316,12 @@ impl RenderState {
tracing::warn!("No bind group available - showing clear color only");
}
}
self.context.queue.submit(std::iter::once(encoder.finish()));
surface_texture.queue.submit(std::iter::once(encoder.finish()));
window.pre_present_notify();
output.present();
surface_texture.present();

if suboptimal {
self.surface.configure(&self.context.device, &self.config);
self.surface.configure(&self.executor.context().device, &self.config);
}

if ui_scale.is_some() {
Expand All @@ -340,7 +338,7 @@ impl RenderState {
let overlays_texture_view = self.overlays_texture.as_ref().unwrap_or(&self.transparent_texture).create_view(&wgpu::TextureViewDescriptor::default());
let ui_texture_view = self.ui_texture.as_ref().unwrap_or(&self.transparent_texture).create_view(&wgpu::TextureViewDescriptor::default());

let bind_group = self.context.device.create_bind_group(&wgpu::BindGroupDescriptor {
let bind_group = self.executor.context().device.create_bind_group(&wgpu::BindGroupDescriptor {
layout: &self.render_pipeline.get_bind_group_layout(0),
entries: &[
wgpu::BindGroupEntry {
Expand Down
5 changes: 3 additions & 2 deletions desktop/src/window.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::consts::APP_NAME;
use crate::event::AppEventScheduler;
use crate::wrapper::messages::MenuItem;
use crate::wrapper::{WgpuInstance, WgpuSurface};
use std::collections::HashMap;
use std::sync::Arc;
use winit::cursor::{CursorIcon, CustomCursor, CustomCursorSource};
Expand Down Expand Up @@ -86,8 +87,8 @@ impl Window {
self.winit_window.request_redraw();
}

pub(crate) fn create_surface(&self, instance: &wgpu::Instance) -> wgpu::Surface<'static> {
instance.create_surface(self.winit_window.clone()).unwrap()
pub(crate) fn create_surface(&self, instance: &WgpuInstance) -> WgpuSurface {
instance.create_surface(self.winit_window.clone()).expect("Failed to create surface")
Comment thread
timon-schelling marked this conversation as resolved.
}

pub(crate) fn pre_present_notify(&self) {
Expand Down
3 changes: 3 additions & 0 deletions desktop/wrapper/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@ pub use graphite_editor::consts::{DOUBLE_CLICK_MILLISECONDS, FILE_EXTENSION};
pub use wgpu_executor::WgpuBackends;
pub use wgpu_executor::WgpuContext;
pub use wgpu_executor::WgpuContextBuilder;
pub use wgpu_executor::WgpuCurrentSurfaceTexture;
pub use wgpu_executor::WgpuExecutor;
pub use wgpu_executor::WgpuFeatures;
pub use wgpu_executor::WgpuInstance;
pub use wgpu_executor::WgpuSurface;

mod handle_desktop_wrapper_message;
mod intercept_editor_message;
Expand Down
10 changes: 10 additions & 0 deletions libraries/wgpu-sync/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[package]
name = "wgpu-sync"
description = "Helper for working with wgpu in a multi-threaded context"
version.workspace = true
edition.workspace = true
authors.workspace = true
license.workspace = true

[dependencies]
wgpu = { workspace = true }
Loading
Loading