astrelis_render/
context_impl.rs

1// ! Implementation of RenderContext trait for GraphicsContext.
2//!
3//! This allows GraphicsContext to be used polymorphically with the
4//! RenderContext trait, enabling testing with MockRenderContext.
5
6use crate::context::GraphicsContext;
7use astrelis_test_utils::{
8    GpuBindGroup, GpuBindGroupLayout, GpuBuffer, GpuComputePipeline, GpuRenderPipeline,
9    GpuSampler, GpuShaderModule, GpuTexture, RenderContext,
10};
11use wgpu::{
12    BindGroupDescriptor, BindGroupLayoutDescriptor, BufferDescriptor, ComputePipelineDescriptor,
13    RenderPipelineDescriptor, SamplerDescriptor, ShaderModuleDescriptor, TextureDescriptor,
14};
15
16impl RenderContext for GraphicsContext {
17    fn create_buffer(&self, desc: &BufferDescriptor) -> GpuBuffer {
18        let buffer = self.device.create_buffer(desc);
19        GpuBuffer::from_wgpu(buffer)
20    }
21
22    fn write_buffer(&self, buffer: &GpuBuffer, offset: u64, data: &[u8]) {
23        let wgpu_buffer = buffer.as_wgpu();
24        self.queue.write_buffer(wgpu_buffer, offset, data);
25    }
26
27    fn create_texture(&self, desc: &TextureDescriptor) -> GpuTexture {
28        let texture = self.device.create_texture(desc);
29        GpuTexture::from_wgpu(texture)
30    }
31
32    fn create_shader_module(&self, desc: &ShaderModuleDescriptor) -> GpuShaderModule {
33        let module = self.device.create_shader_module(desc.clone());
34        GpuShaderModule::from_wgpu(module)
35    }
36
37    fn create_render_pipeline(&self, desc: &RenderPipelineDescriptor) -> GpuRenderPipeline {
38        let pipeline = self.device.create_render_pipeline(desc);
39        GpuRenderPipeline::from_wgpu(pipeline)
40    }
41
42    fn create_compute_pipeline(&self, desc: &ComputePipelineDescriptor) -> GpuComputePipeline {
43        let pipeline = self.device.create_compute_pipeline(desc);
44        GpuComputePipeline::from_wgpu(pipeline)
45    }
46
47    fn create_bind_group_layout(&self, desc: &BindGroupLayoutDescriptor) -> GpuBindGroupLayout {
48        let layout = self.device.create_bind_group_layout(desc);
49        GpuBindGroupLayout::from_wgpu(layout)
50    }
51
52    fn create_bind_group(&self, desc: &BindGroupDescriptor) -> GpuBindGroup {
53        let bind_group = self.device.create_bind_group(desc);
54        GpuBindGroup::from_wgpu(bind_group)
55    }
56
57    fn create_sampler(&self, desc: &SamplerDescriptor) -> GpuSampler {
58        let sampler = self.device.create_sampler(desc);
59        GpuSampler::from_wgpu(sampler)
60    }
61}
62
63#[cfg(test)]
64mod tests {
65    use super::*;
66    #[cfg(feature = "mock")]
67    use astrelis_test_utils::MockRenderContext;
68
69    #[test]
70    #[cfg(feature = "mock")]
71    fn test_render_context_trait_object() {
72        // Test that we can use both GraphicsContext and MockRenderContext
73        // polymorphically through the RenderContext trait
74
75        let mock_ctx = MockRenderContext::new();
76
77        fn uses_render_context(ctx: &dyn RenderContext) {
78            let buffer = ctx.create_buffer(&BufferDescriptor {
79                label: Some("Test Buffer"),
80                size: 256,
81                usage: wgpu::BufferUsages::UNIFORM,
82                mapped_at_creation: false,
83            });
84
85            ctx.write_buffer(&buffer, 0, &[0u8; 256]);
86        }
87
88        // Should work with mock context
89        uses_render_context(&mock_ctx);
90
91        // Verify the mock recorded the calls
92        let calls = mock_ctx.calls();
93        assert_eq!(calls.len(), 2); // create_buffer + write_buffer
94    }
95}