khora_core/renderer/traits/graphics_device.rs
1// Copyright 2025 eraflo
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use crate::math::dimension;
16use crate::renderer::api::*;
17use crate::renderer::error::ResourceError;
18use crate::renderer::traits::CommandEncoder;
19use std::fmt::Debug;
20use std::future::Future;
21
22/// Defines the abstract interface for a graphics device.
23///
24/// This trait is the central point of interaction with the underlying graphics API
25/// (like WGPU, Vulkan, etc.). It abstracts away the specifics of the backend and
26/// provides a unified API for creating, managing, and destroying GPU resources such
27/// as buffers, textures, and pipelines.
28///
29/// It is the cornerstone of the `khora-infra` crate's responsibility, where a
30/// concrete type will implement this trait to provide actual rendering capabilities.
31pub trait GraphicsDevice: Send + Sync + Debug + 'static {
32 // --- Shader Management ---
33
34 /// Creates a shader module from a descriptor.
35 ///
36 /// # Errors
37 /// Returns a [`ResourceError`] if the shader source is invalid or fails to compile.
38 fn create_shader_module(
39 &self,
40 descriptor: &ShaderModuleDescriptor,
41 ) -> Result<ShaderModuleId, ResourceError>;
42
43 /// Destroys a shader module, releasing its GPU resources.
44 fn destroy_shader_module(&self, id: ShaderModuleId) -> Result<(), ResourceError>;
45
46 // --- Pipeline Management ---
47
48 /// Creates a render pipeline from a descriptor.
49 ///
50 /// A render pipeline represents the entire configurable state of the GPU for a
51 /// draw call, including shaders, vertex layouts, and blend states.
52 ///
53 /// # Errors
54 /// Returns a [`ResourceError`] if the pipeline configuration is invalid or compilation fails.
55 fn create_render_pipeline(
56 &self,
57 descriptor: &RenderPipelineDescriptor,
58 ) -> Result<RenderPipelineId, ResourceError>;
59
60 /// Creates a pipeline layout from a descriptor.
61 ///
62 /// The pipeline layout defines the set of resource bindings (e.g., uniform buffers,
63 /// textures) that a pipeline can access.
64 ///
65 /// # Errors
66 /// Returns a [`ResourceError`] if the layout is invalid.
67 fn create_pipeline_layout(
68 &self,
69 descriptor: &PipelineLayoutDescriptor,
70 ) -> Result<PipelineLayoutId, ResourceError>;
71
72 /// Destroys a render pipeline, releasing its GPU resources.
73 fn destroy_render_pipeline(&self, id: RenderPipelineId) -> Result<(), ResourceError>;
74
75 // --- Buffer Management ---
76
77 /// Creates a new GPU buffer.
78 fn create_buffer(&self, descriptor: &BufferDescriptor) -> Result<BufferId, ResourceError>;
79
80 /// Creates a new GPU buffer and initializes it with the provided data.
81 /// This is often more efficient than `create_buffer` followed by `write_buffer` for static data.
82 fn create_buffer_with_data(
83 &self,
84 descriptor: &BufferDescriptor,
85 data: &[u8],
86 ) -> Result<BufferId, ResourceError>;
87
88 /// Destroys a GPU buffer, releasing its memory.
89 fn destroy_buffer(&self, id: BufferId) -> Result<(), ResourceError>;
90
91 /// Writes data to a specific region of a GPU buffer.
92 ///
93 /// # Arguments
94 /// * `id`: The identifier of the buffer to write to.
95 /// * `offset`: The offset in bytes from the beginning of the buffer to start writing.
96 /// * `data`: The slice of bytes to write into the buffer.
97 fn write_buffer(&self, id: BufferId, offset: u64, data: &[u8]) -> Result<(), ResourceError>;
98
99 /// Asynchronously writes data to a GPU buffer.
100 /// This can be more performant for large data uploads by avoiding stalls.
101 fn write_buffer_async<'a>(
102 &'a self,
103 id: BufferId,
104 offset: u64,
105 data: &'a [u8],
106 ) -> Box<dyn Future<Output = Result<(), ResourceError>> + Send + 'static>;
107
108 // --- Texture & Sampler Management ---
109
110 /// Creates a new GPU texture.
111 fn create_texture(&self, descriptor: &TextureDescriptor) -> Result<TextureId, ResourceError>;
112
113 /// Destroys a GPU texture, releasing its memory.
114 fn destroy_texture(&self, id: TextureId) -> Result<(), ResourceError>;
115
116 /// Writes data to a specific region of a GPU texture.
117 ///
118 /// # Arguments
119 /// * `texture_id`: The identifier of the texture to write to.
120 /// * `data`: The raw image data to write.
121 /// * `bytes_per_row`: The number of bytes for a single row of texels in `data`.
122 /// * `offset`: The 3D offset (x, y, z/layer) in the texture to start writing.
123 /// * `size`: The 3D extent (width, height, depth/layers) of the data to write.
124 fn write_texture(
125 &self,
126 texture_id: TextureId,
127 data: &[u8],
128 bytes_per_row: Option<u32>,
129 offset: dimension::Origin3D,
130 size: dimension::Extent3D,
131 ) -> Result<(), ResourceError>;
132
133 /// Creates a new texture view for a given texture.
134 /// A view describes how a shader will interpret a texture's data (e.g., its format, mip levels).
135 fn create_texture_view(
136 &self,
137 texture_id: TextureId,
138 descriptor: &TextureViewDescriptor,
139 ) -> Result<TextureViewId, ResourceError>;
140
141 /// Destroys a texture view.
142 fn destroy_texture_view(&self, id: TextureViewId) -> Result<(), ResourceError>;
143
144 /// Creates a new sampler.
145 /// A sampler defines how a shader will sample from a texture (e.g., filtering, wrapping).
146 fn create_sampler(&self, descriptor: &SamplerDescriptor) -> Result<SamplerId, ResourceError>;
147
148 /// Destroys a sampler.
149 fn destroy_sampler(&self, id: SamplerId) -> Result<(), ResourceError>;
150
151 // --- Command Management ---
152
153 /// Creates a new command encoder to record GPU commands.
154 ///
155 /// # Arguments
156 /// * `label`: An optional debug label for the command encoder.
157 fn create_command_encoder(&self, label: Option<&str>) -> Box<dyn CommandEncoder>;
158
159 /// Submits a previously recorded command buffer to the GPU's command queue for execution.
160 fn submit_command_buffer(&self, command_buffer: CommandBufferId);
161
162 // --- Device Introspection ---
163
164 /// Gets the texture format of the primary render surface.
165 fn get_surface_format(&self) -> Option<TextureFormat>;
166
167 /// Gets information about the active graphics adapter (GPU).
168 fn get_adapter_info(&self) -> RendererAdapterInfo;
169
170 /// Checks if a specific, optional rendering feature is supported by the backend.
171 fn supports_feature(&self, feature_name: &str) -> bool;
172}