Skip to main content

astrelis_render/
extension.rs

1//! Extension traits for low-level wgpu access.
2//!
3//! This module provides traits that allow accessing the underlying wgpu types
4//! from the Astrelis wrapper types. Use these when you need raw wgpu access
5//! for advanced use cases not covered by the high-level API.
6//!
7//! # Example
8//!
9//! ```ignore
10//! use astrelis_render::{GraphicsContext, AsWgpu};
11//!
12//! let ctx = GraphicsContext::new_owned_sync().expect("Failed to create graphics context");
13//!
14//! // Access raw wgpu device via inherent methods
15//! let device: &wgpu::Device = ctx.device();
16//! let queue: &wgpu::Queue = ctx.queue();
17//!
18//! // Create custom wgpu resources
19//! let buffer = device.create_buffer(&wgpu::BufferDescriptor {
20//!     label: Some("Custom Buffer"),
21//!     size: 1024,
22//!     usage: wgpu::BufferUsages::UNIFORM,
23//!     mapped_at_creation: false,
24//! });
25//! ```
26
27use std::sync::Arc;
28
29use crate::{ComputePass, Framebuffer, GraphicsContext, RenderPass, WindowContext};
30
31// =============================================================================
32// Core Extension Traits
33// =============================================================================
34
35/// Access the underlying wgpu type (immutable).
36///
37/// Implement this trait to expose the underlying wgpu type for advanced access.
38pub trait AsWgpu {
39    /// The underlying wgpu type.
40    type WgpuType;
41
42    /// Get a reference to the underlying wgpu type.
43    fn as_wgpu(&self) -> &Self::WgpuType;
44}
45
46/// Access the underlying wgpu type (mutable).
47///
48/// Implement this trait to expose mutable access to the underlying wgpu type.
49pub trait AsWgpuMut: AsWgpu {
50    /// Get a mutable reference to the underlying wgpu type.
51    fn as_wgpu_mut(&mut self) -> &mut Self::WgpuType;
52}
53
54/// Consume and return the underlying wgpu type.
55///
56/// Implement this trait when ownership of the wgpu type can be transferred.
57pub trait IntoWgpu {
58    /// The underlying wgpu type.
59    type WgpuType;
60
61    /// Consume self and return the underlying wgpu type.
62    fn into_wgpu(self) -> Self::WgpuType;
63}
64
65// =============================================================================
66// AsWgpu Implementations
67// =============================================================================
68
69impl AsWgpu for GraphicsContext {
70    type WgpuType = wgpu::Device;
71
72    fn as_wgpu(&self) -> &Self::WgpuType {
73        self.device()
74    }
75}
76
77impl AsWgpu for Arc<GraphicsContext> {
78    type WgpuType = wgpu::Device;
79
80    fn as_wgpu(&self) -> &Self::WgpuType {
81        self.device()
82    }
83}
84
85// Note: Frame no longer implements AsWgpu for CommandEncoder because each RenderPass
86// now owns its own encoder. Use `frame.create_encoder()` to get an encoder, or
87// access via RenderPass::encoder()/encoder_mut().
88
89impl<'a> AsWgpu for RenderPass<'a> {
90    type WgpuType = wgpu::RenderPass<'static>;
91
92    fn as_wgpu(&self) -> &Self::WgpuType {
93        self.wgpu_pass_ref()
94    }
95}
96
97impl<'a> AsWgpuMut for RenderPass<'a> {
98    fn as_wgpu_mut(&mut self) -> &mut Self::WgpuType {
99        self.wgpu_pass()
100    }
101}
102
103impl<'a> AsWgpu for ComputePass<'a> {
104    type WgpuType = wgpu::ComputePass<'static>;
105
106    fn as_wgpu(&self) -> &Self::WgpuType {
107        self.wgpu_pass_ref()
108    }
109}
110
111impl<'a> AsWgpuMut for ComputePass<'a> {
112    fn as_wgpu_mut(&mut self) -> &mut Self::WgpuType {
113        self.wgpu_pass()
114    }
115}
116
117impl AsWgpu for Framebuffer {
118    type WgpuType = wgpu::Texture;
119
120    fn as_wgpu(&self) -> &Self::WgpuType {
121        self.color_texture()
122    }
123}
124
125impl AsWgpu for WindowContext {
126    type WgpuType = wgpu::Surface<'static>;
127
128    fn as_wgpu(&self) -> &Self::WgpuType {
129        &self.surface
130    }
131}
132
133#[cfg(test)]
134mod tests {
135    use super::*;
136
137    // Note: These tests require a GPU context, so they're integration tests.
138    // Here we just test that the traits compile correctly.
139
140    #[test]
141    fn test_trait_object_safety() {
142        // Ensure the core traits can be used as trait objects where applicable
143        fn _takes_as_wgpu<T: AsWgpu>(_: &T) {}
144        fn _takes_as_wgpu_mut<T: AsWgpuMut>(_: &mut T) {}
145        fn _takes_into_wgpu<T: IntoWgpu>(_: T) {}
146    }
147}