mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-15 14:18:04 +08:00
Fix lifetime of cached textures (#4333)
* Fix in-use textures being destroyed * Remove ImageTexture refs * Review
This commit is contained in:
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -2040,11 +2040,11 @@ dependencies = [
|
||||
"glam",
|
||||
"graphene-resource",
|
||||
"log",
|
||||
"raster-types",
|
||||
"serde",
|
||||
"text-nodes",
|
||||
"vector-types",
|
||||
"web-sys",
|
||||
"wgpu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -231,7 +231,7 @@ impl RenderState {
|
||||
let result = futures::executor::block_on(self.executor.render_vello_scene(&scene, size, &Default::default(), None));
|
||||
match result {
|
||||
Ok(texture) => {
|
||||
self.overlays_texture = Some(texture);
|
||||
self.overlays_texture = Some(texture.into());
|
||||
}
|
||||
Err(e) => {
|
||||
self.overlays_texture = None;
|
||||
|
||||
@@ -8,7 +8,7 @@ use graph_craft::document::value::{RenderOutput, RenderOutputType, TaggedValue};
|
||||
use graph_craft::document::{NodeId, NodeNetwork};
|
||||
use graph_craft::graphene_compiler::Compiler;
|
||||
use graph_craft::proto::GraphErrors;
|
||||
use graphene_std::application_io::{ApplicationIo, ExportFormat, ImageTexture, NodeGraphUpdateMessage, NodeGraphUpdateSender, RenderConfig};
|
||||
use graphene_std::application_io::{ApplicationIo, ExportFormat, NodeGraphUpdateMessage, NodeGraphUpdateSender, RenderConfig, Texture};
|
||||
use graphene_std::bounds::RenderBoundingBox;
|
||||
use graphene_std::list::List;
|
||||
use graphene_std::memo::IORecord;
|
||||
@@ -61,7 +61,7 @@ pub struct NodeRuntime {
|
||||
wasm_canvas_cache: CanvasSurfaceHandle,
|
||||
/// Currently displayed texture, the runtime keeps a reference to it to avoid the texture getting destroyed while it is still in use.
|
||||
#[cfg(all(target_family = "wasm", feature = "gpu", feature = "wasm"))]
|
||||
current_viewport_texture: Option<ImageTexture>,
|
||||
current_viewport_texture: Option<Texture>,
|
||||
}
|
||||
|
||||
/// Messages passed from the editor thread to the node runtime thread.
|
||||
@@ -157,7 +157,7 @@ impl NodeRuntime {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn run(&mut self) -> Option<ImageTexture> {
|
||||
pub async fn run(&mut self) -> Option<Texture> {
|
||||
let mut preferences = None;
|
||||
let mut graph = None;
|
||||
let mut eyedropper = None;
|
||||
@@ -250,7 +250,7 @@ impl NodeRuntime {
|
||||
|
||||
let (result, texture) = match result {
|
||||
Ok(TaggedValue::RenderOutput(RenderOutput {
|
||||
data: RenderOutputType::Texture(image_texture),
|
||||
data: RenderOutputType::Texture(texture),
|
||||
metadata,
|
||||
})) if render_config.for_export => {
|
||||
let executor = self
|
||||
@@ -261,7 +261,7 @@ impl NodeRuntime {
|
||||
.gpu_executor()
|
||||
.expect("GPU executor should be available when we receive a texture");
|
||||
|
||||
let raster_cpu = Raster::new_gpu(image_texture.as_ref().clone()).convert(Footprint::BOUNDLESS, executor).await;
|
||||
let raster_cpu = Raster::new_gpu(texture).convert(Footprint::BOUNDLESS, executor).await;
|
||||
|
||||
let (data, width, height) = raster_cpu.to_flat_u8();
|
||||
|
||||
@@ -274,7 +274,7 @@ impl NodeRuntime {
|
||||
)
|
||||
}
|
||||
Ok(TaggedValue::RenderOutput(RenderOutput {
|
||||
data: RenderOutputType::Texture(image_texture),
|
||||
data: RenderOutputType::Texture(texture),
|
||||
metadata: _,
|
||||
})) if render_config.for_eyedropper => {
|
||||
let executor = self
|
||||
@@ -285,7 +285,7 @@ impl NodeRuntime {
|
||||
.gpu_executor()
|
||||
.expect("GPU executor should be available when we receive a texture");
|
||||
|
||||
let raster_cpu = Raster::new_gpu(image_texture.as_ref().clone()).convert(Footprint::BOUNDLESS, executor).await;
|
||||
let raster_cpu = Raster::new_gpu(texture).convert(Footprint::BOUNDLESS, executor).await;
|
||||
|
||||
self.sender.send_eyedropper_preview(raster_cpu);
|
||||
continue;
|
||||
@@ -296,15 +296,15 @@ impl NodeRuntime {
|
||||
}
|
||||
#[cfg(all(target_family = "wasm", feature = "gpu"))]
|
||||
Ok(TaggedValue::RenderOutput(RenderOutput {
|
||||
data: RenderOutputType::Texture(image_texture),
|
||||
data: RenderOutputType::Texture(texture),
|
||||
metadata,
|
||||
})) if !render_config.for_export => {
|
||||
self.current_viewport_texture = Some(image_texture.clone());
|
||||
self.current_viewport_texture = Some(texture.clone());
|
||||
|
||||
let app_io = self.editor_api.application_io.as_ref().unwrap();
|
||||
let executor = app_io.gpu_executor().expect("GPU executor should be available when we receive a texture");
|
||||
|
||||
self.wasm_canvas_cache.present(&image_texture, executor);
|
||||
self.wasm_canvas_cache.present(&texture, executor);
|
||||
|
||||
let logical_resolution = render_config.viewport.resolution.as_dvec2() / render_config.scale;
|
||||
(
|
||||
@@ -552,7 +552,7 @@ pub async fn introspect_node(path: &[NodeId]) -> Result<Arc<dyn std::any::Any +
|
||||
Err(IntrospectError::RuntimeNotReady)
|
||||
}
|
||||
|
||||
pub async fn run_node_graph() -> (bool, Option<ImageTexture>) {
|
||||
pub async fn run_node_graph() -> (bool, Option<Texture>) {
|
||||
let Some(mut runtime) = NODE_RUNTIME.try_lock() else { return (false, None) };
|
||||
if let Some(ref mut runtime) = runtime.as_mut() {
|
||||
return (true, runtime.run().await);
|
||||
|
||||
@@ -726,7 +726,7 @@ pub struct RenderOutput {
|
||||
#[derive(Debug, Clone, PartialEq, dyn_any::DynAny, serde::Serialize, serde::Deserialize)]
|
||||
pub enum RenderOutputType {
|
||||
#[serde(skip)]
|
||||
Texture(graphene_application_io::ImageTexture),
|
||||
Texture(graphene_application_io::Texture),
|
||||
#[serde(skip)]
|
||||
Buffer {
|
||||
data: Vec<u8>,
|
||||
|
||||
@@ -67,13 +67,11 @@ pub async fn export_document(
|
||||
std::fs::write(&output_path, svg)?;
|
||||
log::info!("Exported SVG to: {}", output_path.display());
|
||||
}
|
||||
RenderOutputType::Texture(image_texture) => {
|
||||
RenderOutputType::Texture(texture) => {
|
||||
// Convert GPU texture to CPU buffer
|
||||
let gpu_raster = Raster::<GPU>::new_gpu(image_texture.as_ref().clone());
|
||||
let gpu_raster = Raster::<GPU>::new_gpu(texture);
|
||||
let cpu_raster: Raster<CPU> = gpu_raster.convert(Footprint::BOUNDLESS, wgpu_executor).await;
|
||||
let (data, width, height) = cpu_raster.to_flat_u8();
|
||||
// Explicitly drop texture to make sure it lives long enough
|
||||
std::mem::drop(image_texture);
|
||||
|
||||
// Encode and write raster image
|
||||
write_raster_image(output_path, file_type, data, width, height, transparent)?;
|
||||
@@ -202,11 +200,9 @@ pub async fn export_gif(
|
||||
// Extract RGBA data from result
|
||||
let (data, img_width, img_height) = match result {
|
||||
TaggedValue::RenderOutput(output) => match output.data {
|
||||
RenderOutputType::Texture(image_texture) => {
|
||||
let gpu_raster = Raster::<GPU>::new_gpu(image_texture.as_ref().clone());
|
||||
RenderOutputType::Texture(texture) => {
|
||||
let gpu_raster = Raster::<GPU>::new_gpu(texture);
|
||||
let cpu_raster: Raster<CPU> = gpu_raster.convert(Footprint::BOUNDLESS, wgpu_executor).await;
|
||||
// Explicitly drop texture to make sure it lives long enough
|
||||
std::mem::drop(image_texture);
|
||||
cpu_raster.to_flat_u8()
|
||||
}
|
||||
RenderOutputType::Buffer { data, width, height } => (data, width, height),
|
||||
|
||||
@@ -5,7 +5,7 @@ use graph_craft::document::DocumentNode;
|
||||
use graph_craft::document::value::RenderOutput;
|
||||
use graph_craft::proto::{NodeConstructor, TypeErasedBox};
|
||||
use graphene_std::any::DynAnyNode;
|
||||
use graphene_std::application_io::ImageTexture;
|
||||
use graphene_std::application_io::Texture;
|
||||
use graphene_std::brush::brush_stroke::BrushStroke;
|
||||
use graphene_std::gradient::GradientStops;
|
||||
use graphene_std::list::{AttributeDyn, AttributeValueDyn, List, ListDyn};
|
||||
@@ -133,7 +133,7 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeCons
|
||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => u32]),
|
||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => u64]),
|
||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => BlendMode]),
|
||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => ImageTexture]),
|
||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => Texture]),
|
||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => graphene_std::application_io::resource::Resource]),
|
||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => graphene_std::transform::ReferencePoint]),
|
||||
async_node!(graphene_core::memo::MonitorNode<_, _, _>, input: Context, fn_params: [Context => graphene_std::vector::misc::BooleanOperation]),
|
||||
|
||||
@@ -10,7 +10,7 @@ license = "MIT OR Apache-2.0"
|
||||
default = ["serde"]
|
||||
serde = ["dep:serde", "core-types/serde", "vector-types/serde", "text-nodes/serde", "graphene-resource/serde"]
|
||||
wasm = ["dep:web-sys"]
|
||||
wgpu = ["dep:wgpu"]
|
||||
wgpu = ["dep:raster-types", "raster-types/wgpu"]
|
||||
|
||||
[dependencies]
|
||||
# Local dependencies
|
||||
@@ -20,6 +20,9 @@ vector-types = { workspace = true }
|
||||
text-nodes = { workspace = true }
|
||||
graphene-resource = { workspace = true }
|
||||
|
||||
# Optional local dependencies
|
||||
raster-types = { workspace = true, optional = true }
|
||||
|
||||
# Workspace dependencies
|
||||
blake3 = { workspace = true }
|
||||
glam = { workspace = true }
|
||||
@@ -27,7 +30,4 @@ log = { workspace = true }
|
||||
|
||||
# Optional workspace dependencies
|
||||
serde = { workspace = true, optional = true }
|
||||
|
||||
# Optional workspace dependencies
|
||||
web-sys = { workspace = true, optional = true }
|
||||
wgpu = { workspace = true, optional = true }
|
||||
|
||||
@@ -11,35 +11,10 @@ use vector_types::vector::style::RenderMode;
|
||||
pub use graphene_resource as resource;
|
||||
|
||||
#[cfg(feature = "wgpu")]
|
||||
#[derive(Debug, Clone, Hash, PartialEq, Eq, DynAny)]
|
||||
pub struct ImageTexture(Arc<wgpu::Texture>);
|
||||
#[cfg(feature = "wgpu")]
|
||||
impl AsRef<wgpu::Texture> for ImageTexture {
|
||||
fn as_ref(&self) -> &wgpu::Texture {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "wgpu")]
|
||||
impl From<wgpu::Texture> for ImageTexture {
|
||||
fn from(texture: wgpu::Texture) -> Self {
|
||||
Self(Arc::new(texture))
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "wgpu")]
|
||||
impl From<Arc<wgpu::Texture>> for ImageTexture {
|
||||
fn from(texture: Arc<wgpu::Texture>) -> Self {
|
||||
Self(texture)
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "wgpu")]
|
||||
impl From<ImageTexture> for Arc<wgpu::Texture> {
|
||||
fn from(image_texture: ImageTexture) -> Self {
|
||||
image_texture.0
|
||||
}
|
||||
}
|
||||
pub use raster_types::Texture;
|
||||
#[cfg(not(feature = "wgpu"))]
|
||||
#[derive(Debug, Clone, Hash, PartialEq, Eq, DynAny)]
|
||||
pub struct ImageTexture;
|
||||
pub struct Texture; // TODO: Consider removing this
|
||||
|
||||
pub trait ApplicationIo {
|
||||
type Executor;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use dyn_any::DynAny;
|
||||
#[cfg(feature = "wgpu")]
|
||||
use graphene_application_io::ImageTexture;
|
||||
use graphene_application_io::Texture;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::{AtomicU64, Ordering};
|
||||
use web_sys::js_sys::{Object, Reflect};
|
||||
@@ -23,7 +23,7 @@ pub trait Canvas {
|
||||
|
||||
#[cfg(feature = "wgpu")]
|
||||
pub trait CanvasSurface: Canvas {
|
||||
fn present(&mut self, image_texture: &ImageTexture, executor: &WgpuExecutor);
|
||||
fn present(&mut self, texture: &Texture, executor: &WgpuExecutor);
|
||||
}
|
||||
|
||||
#[derive(Clone, DynAny)]
|
||||
@@ -85,10 +85,10 @@ impl Canvas for CanvasSurfaceHandle {
|
||||
}
|
||||
#[cfg(feature = "wgpu")]
|
||||
impl CanvasSurface for CanvasSurfaceHandle {
|
||||
fn present(&mut self, image_texture: &ImageTexture, executor: &WgpuExecutor) {
|
||||
fn present(&mut self, texture: &Texture, executor: &WgpuExecutor) {
|
||||
let context = executor.context();
|
||||
|
||||
let source_texture: &wgpu::Texture = image_texture.as_ref();
|
||||
let source_texture: &wgpu::Texture = texture.as_ref();
|
||||
|
||||
let surface = self.surface(executor);
|
||||
|
||||
|
||||
@@ -139,15 +139,60 @@ mod cpu {
|
||||
}
|
||||
|
||||
pub use gpu::GPU;
|
||||
#[cfg(feature = "wgpu")]
|
||||
pub use gpu::Texture;
|
||||
|
||||
#[cfg(feature = "wgpu")]
|
||||
mod gpu {
|
||||
use super::*;
|
||||
use crate::raster_types::__private::Sealed;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, DynAny)]
|
||||
pub struct Texture(Arc<wgpu::Texture>);
|
||||
|
||||
impl Deref for Texture {
|
||||
type Target = wgpu::Texture;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<wgpu::Texture> for Texture {
|
||||
fn as_ref(&self) -> &wgpu::Texture {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Arc<wgpu::Texture>> for Texture {
|
||||
fn from(texture: Arc<wgpu::Texture>) -> Self {
|
||||
Self(texture)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<wgpu::Texture> for Texture {
|
||||
fn from(texture: wgpu::Texture) -> Self {
|
||||
Self(Arc::new(texture))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Texture> for Arc<wgpu::Texture> {
|
||||
fn from(texture: Texture) -> Self {
|
||||
texture.0
|
||||
}
|
||||
}
|
||||
|
||||
impl core_types::CacheHash for Texture {
|
||||
fn cache_hash<H: ::core::hash::Hasher>(&self, state: &mut H) {
|
||||
use ::core::hash::Hash;
|
||||
self.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Hash)]
|
||||
pub struct GPU {
|
||||
pub texture: wgpu::Texture,
|
||||
pub texture: Texture,
|
||||
}
|
||||
|
||||
impl core_types::CacheHash for GPU {
|
||||
@@ -166,8 +211,8 @@ mod gpu {
|
||||
}
|
||||
|
||||
impl Raster<GPU> {
|
||||
pub fn new_gpu(texture: wgpu::Texture) -> Self {
|
||||
Self::new(GPU { texture })
|
||||
pub fn new_gpu(texture: impl Into<Texture>) -> Self {
|
||||
Self::new(GPU { texture: texture.into() })
|
||||
}
|
||||
|
||||
pub fn data(&self) -> &wgpu::Texture {
|
||||
|
||||
@@ -22,7 +22,7 @@ use glam::{DAffine2, DMat2, DVec2};
|
||||
use graphene_hash::CacheHashWrapper;
|
||||
use graphene_resource::Resource;
|
||||
use graphic_types::graphic::{graphic_list_at, has_paint_at, is_paint_present, set_paint_attribute};
|
||||
use graphic_types::raster_types::{BitmapMut, CPU, GPU, Image, Raster};
|
||||
use graphic_types::raster_types::{BitmapMut, CPU, GPU, Image, Raster, Texture};
|
||||
use graphic_types::vector_types::gradient::{GradientStops, GradientType};
|
||||
use graphic_types::vector_types::subpath::Subpath;
|
||||
use graphic_types::vector_types::vector::click_target::{ClickTarget, FreePoint};
|
||||
@@ -198,7 +198,7 @@ impl Default for SvgRender {
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct RenderContext {
|
||||
pub resource_overrides: Vec<(peniko::ImageBrush, wgpu::Texture)>,
|
||||
pub resource_overrides: Vec<(peniko::ImageBrush, Texture)>,
|
||||
}
|
||||
|
||||
#[derive(Default, Clone, Copy, Hash, graphene_hash::CacheHash)]
|
||||
@@ -1945,7 +1945,7 @@ impl Render for List<Raster<GPU>> {
|
||||
.with_extend(peniko::Extend::Repeat);
|
||||
let image_transform = transform * transform_attribute * DAffine2::from_scale(1. / DVec2::new(width as f64, height as f64));
|
||||
scene.draw_image(&image, kurbo::Affine::new(image_transform.to_cols_array()));
|
||||
context.resource_overrides.push((image, raster.data().clone()));
|
||||
context.resource_overrides.push((image, raster.texture.clone()));
|
||||
|
||||
if layer {
|
||||
scene.pop_layer()
|
||||
|
||||
@@ -12,6 +12,7 @@ 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::{Origin3d, TextureAspect};
|
||||
@@ -67,7 +68,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<Arc<wgpu::Texture>> {
|
||||
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_view = texture.create_view(&wgpu::TextureViewDescriptor::default());
|
||||
@@ -84,7 +85,7 @@ impl WgpuExecutor {
|
||||
let mut renderer = self.inner.vello_renderer.lock().await;
|
||||
for (image_brush, texture) in context.resource_overrides.iter() {
|
||||
let texture_view = wgpu::TexelCopyTextureInfoBase {
|
||||
texture: texture.clone(),
|
||||
texture: (**texture).clone(),
|
||||
mip_level: 0,
|
||||
origin: Origin3d::ZERO,
|
||||
aspect: TextureAspect::All,
|
||||
@@ -108,7 +109,7 @@ impl WgpuExecutor {
|
||||
pipeline.init::<P>(self);
|
||||
}
|
||||
|
||||
pub async fn request_texture(&self, size: UVec2) -> Arc<wgpu::Texture> {
|
||||
pub async fn request_texture(&self, size: UVec2) -> Texture {
|
||||
self.inner.texture_cache.lock().await.request_texture(&self.context().device, size)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,7 +234,7 @@ impl PerPixelAdjustGraphicsPipeline {
|
||||
rp.draw(0..3, 0..1);
|
||||
|
||||
let attributes = textures.clone_item_attributes(index);
|
||||
Item::from_parts(Raster::new(GPU { texture: tex_out }), attributes)
|
||||
Item::from_parts(Raster::new_gpu(tex_out), attributes)
|
||||
})
|
||||
.collect::<List<_>>();
|
||||
context.queue.submit([cmd.finish()]);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use glam::UVec2;
|
||||
use raster_types::Texture;
|
||||
use std::collections::VecDeque;
|
||||
use std::sync::Arc;
|
||||
|
||||
@@ -16,7 +17,7 @@ impl TextureCache {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn request_texture(&mut self, device: &wgpu::Device, size: UVec2) -> Arc<wgpu::Texture> {
|
||||
pub fn request_texture(&mut self, device: &wgpu::Device, size: UVec2) -> Texture {
|
||||
let size = size.max(UVec2::ONE);
|
||||
|
||||
if let Some(pos) = self
|
||||
@@ -27,7 +28,7 @@ impl TextureCache {
|
||||
let entry = self.textures.remove(pos).unwrap();
|
||||
let texture = entry.clone();
|
||||
self.textures.push_back(entry);
|
||||
return texture;
|
||||
return texture.into();
|
||||
}
|
||||
|
||||
let incoming_bytes = size.x as u64 * size.y as u64 * 4;
|
||||
@@ -50,7 +51,7 @@ impl TextureCache {
|
||||
|
||||
self.textures.push_back(texture.clone());
|
||||
|
||||
texture
|
||||
texture.into()
|
||||
}
|
||||
|
||||
fn total_free_bytes(&self) -> u64 {
|
||||
|
||||
@@ -50,6 +50,7 @@ struct RasterGpuToRasterCpuConverter {
|
||||
height: u32,
|
||||
unpadded_bytes_per_row: u32,
|
||||
padded_bytes_per_row: u32,
|
||||
_source: raster_types::Texture,
|
||||
}
|
||||
impl RasterGpuToRasterCpuConverter {
|
||||
fn new(device: &wgpu::Device, encoder: &mut wgpu::CommandEncoder, data_gpu: Raster<GPU>) -> Self {
|
||||
@@ -97,6 +98,8 @@ impl RasterGpuToRasterCpuConverter {
|
||||
height,
|
||||
unpadded_bytes_per_row,
|
||||
padded_bytes_per_row,
|
||||
// Keep source texture alive
|
||||
_source: data_gpu.texture.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,9 +5,9 @@ use core_types::uuid::generate_uuid;
|
||||
use core_types::{Ctx, ExtractFootprint};
|
||||
use glam::{Affine2, UVec2, Vec2};
|
||||
use graph_craft::document::value::{RenderOutput, RenderOutputType};
|
||||
use graphic_types::raster_types::Texture;
|
||||
use rendering::{RenderParams, SvgRender, SvgRenderOutput};
|
||||
use std::fmt::Write;
|
||||
use std::sync::Arc;
|
||||
use wgpu::util::DeviceExt;
|
||||
use wgpu_executor::{AsyncWgpuPipeline, WgpuExecutor, WgpuPipelineCache};
|
||||
|
||||
@@ -147,7 +147,7 @@ pub struct CompositeBackgroundArgs<'a> {
|
||||
|
||||
impl AsyncWgpuPipeline for CompositeBackground {
|
||||
type Args<'a> = CompositeBackgroundArgs<'a>;
|
||||
type Out = Arc<wgpu::Texture>;
|
||||
type Out = Texture;
|
||||
|
||||
fn create(executor: &WgpuExecutor) -> Self {
|
||||
let device = &executor.context().device;
|
||||
|
||||
@@ -6,7 +6,7 @@ use core_types::{CloneVarArgs, Context, Ctx, ExtractAll, ExtractAnimationTime, E
|
||||
use glam::{DAffine2, DVec2, IVec2, UVec2};
|
||||
use graph_craft::application_io::PlatformEditorApi;
|
||||
use graph_craft::document::value::{RenderOutput, RenderOutputType};
|
||||
use graphene_application_io::ImageTexture;
|
||||
use graphene_application_io::Texture;
|
||||
use rendering::{RenderOutputType as RenderOutputTypeRequest, RenderParams};
|
||||
use std::collections::HashSet;
|
||||
use std::hash::Hash;
|
||||
@@ -25,7 +25,7 @@ pub struct TileCoord {
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CachedRegion {
|
||||
pub texture: ImageTexture,
|
||||
pub texture: Texture,
|
||||
pub texture_size: UVec2,
|
||||
pub tiles: Vec<TileCoord>,
|
||||
pub metadata: rendering::RenderMetadata,
|
||||
|
||||
@@ -2,8 +2,8 @@ use core_types::transform::{Footprint, Transform};
|
||||
use core_types::{CloneVarArgs, Context, Ctx, ExtractAll, OwnedContextImpl};
|
||||
use glam::{DAffine2, DVec2, UVec2, Vec2};
|
||||
use graph_craft::document::value::{RenderOutput, RenderOutputType};
|
||||
use graphic_types::raster_types::Texture;
|
||||
use rendering::{RenderOutputType as RenderOutputTypeRequest, RenderParams};
|
||||
use std::sync::Arc;
|
||||
use vector_types::vector::style::RenderMode;
|
||||
use wgpu_executor::{AsyncWgpuPipeline, WgpuExecutor, WgpuPipelineCache};
|
||||
|
||||
@@ -65,7 +65,7 @@ pub async fn render_pixel_preview<'a: 'n>(
|
||||
})
|
||||
.await;
|
||||
|
||||
result.data = RenderOutputType::Texture(resampled.into());
|
||||
result.data = RenderOutputType::Texture(resampled);
|
||||
|
||||
result
|
||||
.metadata
|
||||
@@ -99,7 +99,7 @@ pub struct PixelPreviewArgs<'a> {
|
||||
|
||||
impl AsyncWgpuPipeline for PixelPreview {
|
||||
type Args<'a> = PixelPreviewArgs<'a>;
|
||||
type Out = Arc<wgpu::Texture>;
|
||||
type Out = Texture;
|
||||
|
||||
fn create(executor: &WgpuExecutor) -> Self {
|
||||
let device = &executor.context().device;
|
||||
|
||||
Reference in New Issue
Block a user