astrelis_test_utils/render_context.rs
1//! Trait abstracting GPU operations for testing.
2//!
3//! The `RenderContext` trait provides an abstraction over GPU operations,
4//! allowing for both real GPU usage and mock implementations for testing.
5
6use crate::gpu_types::*;
7use wgpu::{
8 BindGroupDescriptor, BindGroupLayoutDescriptor, BufferDescriptor, ComputePipelineDescriptor,
9 RenderPipelineDescriptor, SamplerDescriptor, ShaderModuleDescriptor, TextureDescriptor,
10};
11
12/// Trait abstracting GPU resource creation and operations.
13///
14/// # Lifetime Considerations
15///
16/// This trait does NOT use lifetimes because:
17/// 1. All returned types are owned (not borrowed from Device)
18/// 2. GPU resources use reference counting internally
19/// 3. Resources live until dropped
20///
21/// This makes the trait object-safe and easy to mock.
22///
23/// # Borrow Checking Pattern
24///
25/// Methods take `&self` (shared reference) and return owned wrapper types.
26/// This allows:
27/// - Multiple components to share the same context (via Arc)
28/// - Mock implementations to use interior mutability (Mutex)
29/// - No lifetime parameters propagating through the codebase
30///
31/// # Example
32///
33/// ```rust,no_run
34/// use astrelis_test_utils::RenderContext;
35/// use wgpu::{BufferDescriptor, BufferUsages};
36///
37/// fn render_scene(ctx: &dyn RenderContext) {
38/// let desc = BufferDescriptor {
39/// label: None,
40/// size: 16,
41/// usage: BufferUsages::VERTEX,
42/// mapped_at_creation: false,
43/// };
44/// let data = vec![0u8; 16];
45/// let buffer = ctx.create_buffer(&desc);
46/// ctx.write_buffer(&buffer, 0, &data);
47/// // buffer is owned, no lifetime issues
48/// }
49/// ```
50pub trait RenderContext: Send + Sync {
51 // Buffer operations
52
53 /// Create a GPU buffer.
54 ///
55 /// Returns an owned `GpuBuffer` which can be either real or mock.
56 fn create_buffer(&self, desc: &BufferDescriptor) -> GpuBuffer;
57
58 /// Write data to a buffer.
59 ///
60 /// For real buffers, this maps to `queue.write_buffer()`.
61 /// For mock buffers, this records the operation for test verification.
62 fn write_buffer(&self, buffer: &GpuBuffer, offset: u64, data: &[u8]);
63
64 // Texture operations
65
66 /// Create a GPU texture.
67 fn create_texture(&self, desc: &TextureDescriptor) -> GpuTexture;
68
69 // Note: write_texture method will be added when needed during migration
70 // It requires wgpu types that aren't in the public API surface we're using
71
72 // Shader operations
73
74 /// Create a shader module from source code.
75 fn create_shader_module(&self, desc: &ShaderModuleDescriptor) -> GpuShaderModule;
76
77 // Pipeline operations
78
79 /// Create a render pipeline.
80 fn create_render_pipeline(&self, desc: &RenderPipelineDescriptor) -> GpuRenderPipeline;
81
82 /// Create a compute pipeline.
83 fn create_compute_pipeline(&self, desc: &ComputePipelineDescriptor) -> GpuComputePipeline;
84
85 // Bind group operations
86
87 /// Create a bind group layout.
88 fn create_bind_group_layout(&self, desc: &BindGroupLayoutDescriptor) -> GpuBindGroupLayout;
89
90 /// Create a bind group.
91 fn create_bind_group(&self, desc: &BindGroupDescriptor) -> GpuBindGroup;
92
93 // Sampler operations
94
95 /// Create a texture sampler.
96 fn create_sampler(&self, desc: &SamplerDescriptor) -> GpuSampler;
97}
98
99/// Helper trait for converting WGPU descriptors that reference GPU resources.
100///
101/// This is needed because WGPU descriptors contain references to concrete types
102/// like `&wgpu::Buffer`, but our wrappers contain `GpuBuffer`.
103///
104/// We'll implement conversion helpers as needed.
105pub trait DescriptorHelper {
106 /// Convert a descriptor that references wrapped GPU types to one that
107 /// references WGPU types (for real GPU operations).
108 type WgpuDescriptor<'a>
109 where
110 Self: 'a;
111
112 fn to_wgpu(&self) -> Self::WgpuDescriptor<'_>;
113}
114
115// Note: We'll implement DescriptorHelper for specific descriptors as needed
116// during the migration. For now, most descriptors don't reference GPU resources
117// directly and can be used as-is.