-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Improve texture caching by allowing weak refs and more formats #4447
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
6156cf5
8298a23
3db158c
773b8fd
c11d2d6
3d9f2a5
9cf30bf
7498f3f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| use std::ops::Deref; | ||
| use std::sync::Arc; | ||
|
|
||
| #[derive(Clone, Debug)] | ||
| pub struct Buffer(Arc<BufferInner>); | ||
|
|
||
| #[derive(Debug)] | ||
| struct BufferInner(wgpu::Buffer); | ||
|
|
||
| impl Drop for BufferInner { | ||
| fn drop(&mut self) { | ||
| self.0.destroy(); | ||
| } | ||
| } | ||
|
|
||
| impl Deref for Buffer { | ||
| type Target = wgpu::Buffer; | ||
|
|
||
| fn deref(&self) -> &Self::Target { | ||
| &self.0.0 | ||
| } | ||
| } | ||
|
|
||
| impl AsRef<wgpu::Buffer> for Buffer { | ||
| fn as_ref(&self) -> &wgpu::Buffer { | ||
| &self.0.0 | ||
| } | ||
| } | ||
|
|
||
| impl From<wgpu::Buffer> for Buffer { | ||
| fn from(buffer: wgpu::Buffer) -> Self { | ||
| Self(Arc::new(BufferInner(buffer))) | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| mod buffer; | ||
| mod context; | ||
| mod pipeline; | ||
| pub mod shader_runtime; | ||
|
|
@@ -12,16 +13,18 @@ use core_types::color::SRGBA8; | |
| use futures::lock::Mutex; | ||
| use glam::UVec2; | ||
| use graphene_application_io::{ApplicationIo, EditorApi}; | ||
| use raster_types::Texture; | ||
| use std::sync::Arc; | ||
| use vello::{AaConfig, AaSupport, RenderParams, Renderer, RendererOptions, Scene}; | ||
| use wgpu::util::DeviceExt; | ||
| use wgpu::{Origin3d, TextureAspect}; | ||
|
|
||
| pub use buffer::Buffer; | ||
| pub use context::Context as WgpuContext; | ||
| pub use context::ContextBuilder as WgpuContextBuilder; | ||
| pub use pipeline::AsyncPipeline as AsyncWgpuPipeline; | ||
| pub use pipeline::Pipeline as WgpuPipeline; | ||
| pub use pipeline::PipelineCache as WgpuPipelineCache; | ||
| pub use raster_types::Texture; | ||
| pub use rendering::RenderContext; | ||
| pub use wgpu::Backends as WgpuBackends; | ||
| pub use wgpu::Features as WgpuFeatures; | ||
|
|
@@ -30,7 +33,10 @@ 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 | ||
| #[cfg(not(target_family = "wasm"))] | ||
| const TEXTURE_CACHE_SIZE: u64 = 1024 * 1024 * 1024; // 1GB | ||
| #[cfg(target_family = "wasm")] | ||
| const TEXTURE_CACHE_SIZE: u64 = 512 * 1024 * 1024; // 512MB | ||
|
|
||
| #[derive(dyn_any::DynAny, Clone)] | ||
| pub struct WgpuExecutor { | ||
|
|
@@ -41,16 +47,12 @@ impl WgpuExecutor { | |
| pub fn context(&self) -> &WgpuContext { | ||
| &self.inner.context | ||
| } | ||
|
|
||
| pub fn shader_runtime(&self) -> &ShaderRuntime { | ||
| &self.inner.shader_runtime | ||
| } | ||
| } | ||
|
|
||
| #[derive(dyn_any::DynAny)] | ||
| pub struct WgpuExecutorInner { | ||
| context: WgpuContext, | ||
| texture_cache: Mutex<TextureCache>, | ||
| texture_cache: std::sync::Mutex<TextureCache>, | ||
| vello_renderer: Mutex<Renderer>, | ||
| shader_runtime: ShaderRuntime, | ||
| } | ||
|
|
@@ -69,7 +71,7 @@ impl<'a, T: ApplicationIo<Executor = WgpuExecutor>> From<&'a EditorApi<T>> for & | |
|
|
||
| impl WgpuExecutor { | ||
| pub async fn render_vello_scene(&self, scene: &Scene, size: UVec2, context: &RenderContext, background: Option<Color>) -> Result<Texture> { | ||
| let texture = self.request_texture(size).await; | ||
| let texture = self.request_texture(size); | ||
|
|
||
| let texture_view = texture.create_view(&wgpu::TextureViewDescriptor::default()); | ||
|
|
||
|
|
@@ -109,8 +111,20 @@ impl WgpuExecutor { | |
| pipeline.init::<P>(self); | ||
| } | ||
|
|
||
| pub async fn request_texture(&self, size: UVec2) -> Texture { | ||
| self.inner.texture_cache.lock().await.request_texture(&self.context().device, size) | ||
| pub fn request_texture(&self, size: UVec2) -> Texture { | ||
| self.request_texture_with_format(size, wgpu::TextureFormat::Rgba8Unorm) | ||
| } | ||
|
|
||
| pub fn request_texture_with_format(&self, size: UVec2, format: wgpu::TextureFormat) -> Texture { | ||
| self.inner.texture_cache.lock().unwrap().request_texture(&self.context().device, size, format) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: Prompt for AI agents |
||
| } | ||
|
|
||
| pub fn create_buffer(&self, desc: &wgpu::BufferDescriptor) -> Buffer { | ||
| self.context().device.create_buffer(desc).into() | ||
| } | ||
|
|
||
| pub fn create_buffer_init(&self, desc: &wgpu::util::BufferInitDescriptor) -> Buffer { | ||
| self.context().device.create_buffer_init(desc).into() | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -134,7 +148,7 @@ impl WgpuExecutor { | |
|
|
||
| let texture_cache = TextureCache::new(TEXTURE_CACHE_SIZE); | ||
|
|
||
| let shader_runtime = ShaderRuntime::new(&context); | ||
| let shader_runtime = ShaderRuntime::default(); | ||
|
|
||
| Some(Self { | ||
| inner: Arc::new(WgpuExecutorInner { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,20 +1,10 @@ | ||
| use crate::WgpuContext; | ||
| use crate::shader_runtime::per_pixel_adjust_runtime::PerPixelAdjustShaderRuntime; | ||
|
|
||
| pub mod per_pixel_adjust_runtime; | ||
|
|
||
| pub const FULLSCREEN_VERTEX_SHADER_NAME: &str = "fullscreen_vertex_fullscreen_vertex"; | ||
|
|
||
| #[derive(Default)] | ||
| pub struct ShaderRuntime { | ||
| context: WgpuContext, | ||
| per_pixel_adjust: PerPixelAdjustShaderRuntime, | ||
| } | ||
|
|
||
| impl ShaderRuntime { | ||
| pub fn new(context: &WgpuContext) -> Self { | ||
| Self { | ||
| context: context.clone(), | ||
| per_pixel_adjust: PerPixelAdjustShaderRuntime::new(), | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P1: On WebGPU, this cap allows 512 MiB of unused textures to remain strongly cached, which can exceed browser GPU budgets and trigger device loss/OOM. Keep the cache cap within a conservative web budget or derive it from the available device budget.
Prompt for AI agents