Implement Convert trait to convert between CPU and GPU images (#3194)

* Add upload texture trait

* Make convert trait use explicit converter

* Add gpu texture download implementation

* Add footprint to convert trait

* Cleanup texture upload / download

* Download wgpu textures aligned

* abstract texture download into converter helper

* rename module

not only doing uploads anymore
conversion looks like a ok name

* Remove into_iter call and intermediate vector allocation

---------

Co-authored-by: Timon Schelling <me@timon.zip>
This commit is contained in:
Dennis Kobert
2025-09-25 20:54:51 +02:00
parent 4bb1d05fc3
commit ffc74273cc
9 changed files with 309 additions and 72 deletions

View File

@@ -1,5 +1,6 @@
use crate::Node;
use graphene_core_shaders::Ctx;
use crate::{ExtractFootprint, Node, transform::Footprint};
use std::marker::PhantomData;
// TODO: Rename to "Passthrough"
@@ -49,16 +50,16 @@ fn into<'i, T: 'i + Send + Into<O>, O: 'i + Send>(_: impl Ctx, value: T, _out_ty
/// The [`Convert`] trait allows for conversion between Rust primitive numeric types.
/// Because number casting is lossy, we cannot use the normal [`Into`] trait like we do for other types.
pub trait Convert<T>: Sized {
pub trait Convert<T, C>: Sized {
/// Converts this type into the (usually inferred) output type.
#[must_use]
fn convert(self) -> T;
fn convert(self, footprint: Footprint, converter: C) -> impl Future<Output = T> + Send;
}
impl<T: ToString> Convert<String> for T {
impl<T: ToString + Send> Convert<String, ()> for T {
/// Converts this type into a `String` using its `ToString` implementation.
#[inline]
fn convert(self) -> String {
async fn convert(self, _: Footprint, _converter: ()) -> String {
self.to_string()
}
}
@@ -66,8 +67,8 @@ impl<T: ToString> Convert<String> for T {
/// Implements the [`Convert`] trait for conversion between the cartesian product of Rust's primitive numeric types.
macro_rules! impl_convert {
($from:ty, $to:ty) => {
impl Convert<$to> for $from {
fn convert(self) -> $to {
impl Convert<$to, ()> for $from {
async fn convert(self, _: Footprint, _: ()) -> $to {
self as $to
}
}
@@ -105,8 +106,8 @@ impl_convert!(isize);
impl_convert!(usize);
#[node_macro::node(skip_impl)]
fn convert<'i, T: 'i + Send + Convert<O>, O: 'i + Send>(_: impl Ctx, value: T, _out_ty: PhantomData<O>) -> O {
value.convert()
async fn convert<'i, T: 'i + Send + Convert<O, C>, O: 'i + Send, C: 'i + Send>(ctx: impl Ctx + ExtractFootprint, value: T, converter: C, _out_ty: PhantomData<O>) -> O {
value.convert(*ctx.try_footprint().unwrap_or(&Footprint::DEFAULT), converter).await
}
#[cfg(test)]

View File

@@ -9,7 +9,7 @@ use std::sync::{LazyLock, Mutex};
pub use graphene_core_shaders::registry::types;
// Translation struct between macro and definition
#[derive(Clone)]
#[derive(Clone, Debug)]
pub struct NodeMetadata {
pub display_name: &'static str,
pub category: Option<&'static str>,