Skip to content

Shaders: graster-nodes no-std fixups #2984

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

Merged
merged 4 commits into from
Aug 6, 2025
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
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ kurbo = { version = "0.11.0", features = ["serde"] }
petgraph = { version = "0.7.1", default-features = false, features = [
"graphmap",
] }
half = { version = "2.4.1", default-features = false, features = ["bytemuck", "serde"] }
half = { version = "2.4.1", default-features = false, features = ["bytemuck"] }
tinyvec = { version = "1", features = ["std"] }
criterion = { version = "0.5", features = ["html_reports"] }
iai-callgrind = { version = "0.12.3" }
Expand Down
4 changes: 2 additions & 2 deletions node-graph/gcore-shaders/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ authors = ["Graphite Authors <[email protected]>"]
license = "MIT OR Apache-2.0"

[features]
std = ["dep:dyn-any", "dep:serde", "dep:specta", "dep:log"]
std = ["dep:dyn-any", "dep:serde", "dep:specta", "dep:log", "half/std", "half/serde"]

[dependencies]
# Local std dependencies
Expand All @@ -16,7 +16,7 @@ dyn-any = { workspace = true, optional = true }
# Workspace dependencies
bytemuck = { workspace = true }
glam = { version = "0.29", default-features = false, features = ["nostd-libm", "scalar-math"] }
half = { workspace = true }
half = { workspace = true, default-features = false }
num-derive = { workspace = true }
num-traits = { workspace = true }

Expand Down
6 changes: 4 additions & 2 deletions node-graph/gcore-shaders/src/blending.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use core::fmt::Display;
use core::hash::{Hash, Hasher};
#[cfg(target_arch = "spirv")]
use num_traits::float::Float;

#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "std", derive(dyn_any::DynAny, specta::Type, serde::Serialize, serde::Deserialize))]
Expand All @@ -24,7 +26,7 @@ impl Hash for AlphaBlending {
}
}
impl Display for AlphaBlending {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let round = |x: f32| (x * 1e3).round() / 1e3;
write!(
f,
Expand Down Expand Up @@ -203,7 +205,7 @@ impl BlendMode {
}

impl Display for BlendMode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
// Normal group
BlendMode::Normal => write!(f, "Normal"),
Expand Down
23 changes: 18 additions & 5 deletions node-graph/gcore-shaders/src/color/color.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
use super::color_traits::{Alpha, AlphaMut, AssociatedAlpha, Luminance, LuminanceMut, Pixel, RGB, RGBMut, Rec709Primaries, SRGB};
use super::discrete_srgb::{float_to_srgb_u8, srgb_u8_to_float};
use bytemuck::{Pod, Zeroable};
use core::fmt::Debug;
use core::hash::Hash;
use half::f16;
#[cfg(target_arch = "spirv")]
use spirv_std::num_traits::Euclid;
use num_traits::Euclid;
#[cfg(target_arch = "spirv")]
use spirv_std::num_traits::float::Float;
use num_traits::float::Float;

#[repr(C)]
#[derive(Debug, Default, Clone, Copy, PartialEq, Pod, Zeroable)]
#[derive(Default, Clone, Copy, PartialEq, Pod, Zeroable)]
#[cfg_attr(not(target_arch = "spirv"), derive(Debug))]
#[cfg_attr(feature = "std", derive(dyn_any::DynAny, serde::Serialize, serde::Deserialize))]
pub struct RGBA16F {
red: f16,
Expand All @@ -18,6 +20,14 @@ pub struct RGBA16F {
alpha: f16,
}

/// hack around half still masking out impl Debug for f16 on spirv
#[cfg(target_arch = "spirv")]
impl core::fmt::Debug for RGBA16F {
fn fmt(&self, _f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
Ok(())
}
}

impl From<Color> for RGBA16F {
#[inline(always)]
fn from(c: Color) -> Self {
Expand Down Expand Up @@ -215,7 +225,7 @@ pub struct Color {

#[allow(clippy::derived_hash_with_manual_eq)]
impl Hash for Color {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.red.to_bits().hash(state);
self.green.to_bits().hash(state);
self.blue.to_bits().hash(state);
Expand Down Expand Up @@ -256,7 +266,7 @@ impl AlphaMut for Color {
}

impl Pixel for Color {
#[cfg(not(target_arch = "spirv"))]
#[cfg(feature = "std")]
fn to_bytes(&self) -> Vec<u8> {
self.to_rgba8_srgb().to_vec()
}
Expand Down Expand Up @@ -793,6 +803,7 @@ impl Color {
/// let color = Color::from_rgba8_srgb(0x52, 0x67, 0xFA, 0x61); // Premultiplied alpha
/// assert_eq!("3240a261", color.to_rgba_hex_srgb()); // Equivalent hex incorporating premultiplied alpha
/// ```
#[cfg(feature = "std")]
pub fn to_rgba_hex_srgb(&self) -> String {
let gamma = self.to_gamma_srgb();
format!(
Expand All @@ -810,6 +821,7 @@ impl Color {
/// let color = Color::from_rgba8_srgb(0x52, 0x67, 0xFA, 0x61); // Premultiplied alpha
/// assert_eq!("3240a2", color.to_rgb_hex_srgb()); // Equivalent hex incorporating premultiplied alpha
/// ```
#[cfg(feature = "std")]
pub fn to_rgb_hex_srgb(&self) -> String {
self.to_gamma_srgb().to_rgb_hex_srgb_from_gamma()
}
Expand All @@ -820,6 +832,7 @@ impl Color {
/// let color = Color::from_rgba8_srgb(0x52, 0x67, 0xFA, 0x61); // Premultiplied alpha
/// assert_eq!("3240a2", color.to_rgb_hex_srgb()); // Equivalent hex incorporating premultiplied alpha
/// ```
#[cfg(feature = "std")]
pub fn to_rgb_hex_srgb_from_gamma(&self) -> String {
format!("{:02x?}{:02x?}{:02x?}", (self.r() * 255.) as u8, (self.g() * 255.) as u8, (self.b() * 255.) as u8)
}
Expand Down
8 changes: 4 additions & 4 deletions node-graph/gcore-shaders/src/color/color_traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ pub trait Linear {
fn lerp(self, other: Self, value: Self) -> Self
where
Self: Sized + Copy,
Self: std::ops::Sub<Self, Output = Self>,
Self: std::ops::Mul<Self, Output = Self>,
Self: std::ops::Add<Self, Output = Self>,
Self: core::ops::Sub<Self, Output = Self>,
Self: core::ops::Mul<Self, Output = Self>,
Self: core::ops::Add<Self, Output = Self>,
{
self + (other - self) * value
}
Expand Down Expand Up @@ -97,7 +97,7 @@ pub trait SRGB: Rec709Primaries {}

// TODO: Come up with a better name for this trait
pub trait Pixel: Clone + Pod + Zeroable + Default {
#[cfg(not(target_arch = "spirv"))]
#[cfg(feature = "std")]
fn to_bytes(&self) -> Vec<u8> {
bytemuck::bytes_of(self).to_vec()
}
Expand Down
2 changes: 1 addition & 1 deletion node-graph/gcore-shaders/src/color/discrete_srgb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ pub fn float_to_srgb_u8(mut f: f32) -> u8 {
// We clamped f to [0, 1], and the integer representations
// of the positive finite non-NaN floats are monotonic.
// This makes the later LUT lookup panicless.
unsafe { std::hint::unreachable_unchecked() }
unsafe { core::hint::unreachable_unchecked() }
}

// Compute a piecewise linear interpolation that is always
Expand Down
2 changes: 2 additions & 0 deletions node-graph/gcore-shaders/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#![cfg_attr(not(feature = "std"), no_std)]

pub mod blending;
pub mod choice_type;
pub mod color;
Expand Down
1 change: 1 addition & 0 deletions node-graph/gcore-shaders/src/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@ pub mod types {
/// DVec2 with px unit
pub type PixelSize = glam::DVec2;
/// String with one or more than one line
#[cfg(feature = "std")]
pub type TextArea = String;
}
2 changes: 0 additions & 2 deletions node-graph/graphene-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ license = "MIT OR Apache-2.0"
default = ["wgpu"]
wgpu = ["wgpu-executor", "gpu", "graphene-std/wgpu"]
wayland = ["graphene-std/wayland"]
profiling = ["wgpu-executor/profiling"]
passthrough = ["wgpu-executor/passthrough"]
gpu = ["interpreted-executor/gpu", "graphene-std/gpu", "wgpu-executor"]

[dependencies]
Expand Down
6 changes: 3 additions & 3 deletions node-graph/gstd/src/wasm_application_io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ use graphene_svg_renderer::{Render, RenderParams, RenderSvgSegmentList, SvgRende

#[cfg(target_family = "wasm")]
use base64::Engine;
#[cfg(target_family = "wasm")]
use glam::DAffine2;
use std::sync::Arc;
#[cfg(target_family = "wasm")]
Expand Down Expand Up @@ -169,7 +168,8 @@ fn render_svg(data: impl Render, mut render: SvgRender, render_params: RenderPar
async fn render_canvas(render_config: RenderConfig, data: impl Render, editor: &WasmEditorApi, surface_handle: Option<wgpu_executor::WgpuSurface>, render_params: RenderParams) -> RenderOutputType {
use graphene_application_io::{ImageTexture, SurfaceFrame};

let footprint = render_config.viewport;
let mut footprint = render_config.viewport;
footprint.resolution = footprint.resolution.max(glam::UVec2::splat(1));
let Some(exec) = editor.application_io.as_ref().unwrap().gpu_executor() else {
unreachable!("Attempted to render with Vello when no GPU executor is available");
};
Expand All @@ -196,7 +196,7 @@ async fn render_canvas(render_config: RenderConfig, data: impl Render, editor: &
let frame = SurfaceFrame {
surface_id: surface_handle.window_id,
resolution: render_config.viewport.resolution,
transform: glam::DAffine2::IDENTITY,
transform: DAffine2::IDENTITY,
};

RenderOutputType::CanvasFrame(frame)
Expand Down
5 changes: 0 additions & 5 deletions node-graph/wgpu-executor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,6 @@ version = "0.1.0"
edition = "2024"
license = "MIT OR Apache-2.0"

[features]
default = []
profiling = []
passthrough = []

[dependencies]
# Local dependencies
graphene-core = { workspace = true, features = ["wgpu"] }
Expand Down
5 changes: 0 additions & 5 deletions node-graph/wgpu-executor/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,10 @@ impl Context {
let (device, queue) = adapter
.request_device(&wgpu::DeviceDescriptor {
label: None,
// #[cfg(not(feature = "passthrough"))]
#[cfg(target_family = "wasm")]
required_features: wgpu::Features::empty(),
#[cfg(not(target_family = "wasm"))]
required_features: wgpu::Features::PUSH_CONSTANTS,
// Currently disabled because not all backend support passthrough.
// TODO: reenable only when vulkan adapter is available
// #[cfg(feature = "passthrough")]
// required_features: wgpu::Features::SPIRV_SHADER_PASSTHROUGH,
required_limits,
memory_hints: Default::default(),
trace: wgpu::Trace::Off,
Expand Down
Loading
Loading