1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
use utils::Extent;
use crate::{
buffer, descriptors, image,
pipelines::VertexElement,
sampler,
shader::{self, Sources},
window, AllocationHandle, BaseBufferHandle, BottomLevelAccelerationStructure, BottomLevelAccelerationStructureHandle,
BufferHandle, CommandBufferHandle, DescriptorSetHandle, DeviceAccesses, DynamicBufferHandle, DynamicImageHandle,
ImageHandle, MeshHandle, PipelineHandle, PresentationModes, QueueHandle, SamplerHandle, ShaderHandle, ShaderTypes,
SwapchainHandle, SynchronizerHandle, TextureCopyHandle, TopLevelAccelerationStructureHandle, Uses,
};
/// The `Context` trait identifies objects that own render resources created from a GPU device.
/// Implementations use the context lifetime to bound the lifetime of owned GPU resources.
///
/// Create resources through [`ContextCreate`], obtain a command
/// buffer with [`Self::command_buffer`], then submit recorded work through a
/// queue returned by [`Self::queue`] or [`Self::queue_reference`].
pub trait Context: ContextCreate {
type Queue: crate::queue::Queue;
type QueueReference<'a>: crate::queue::Queue
where
Self: 'a;
type CommandBuffer<'a>: crate::command_buffer::CommandBuffer
where
Self: 'a;
/// Returns whether the underlying API has encountered any errors.
#[cfg(any(debug_assertions, test))]
fn has_errors(&self) -> bool;
/// Returns whether the GPU supports BC5 and BC7 block-compressed textures.
///
/// Check this value before you create BC-compressed images or samplers.
fn supports_bc_texture_compression(&self) -> bool;
/// Returns an owned queue wrapper that exposes queue-local command submission.
fn queue(&mut self, queue_handle: QueueHandle) -> Self::Queue;
/// Returns a borrowed queue wrapper that exposes queue-local command submission.
fn queue_reference<'a>(&'a mut self, queue_handle: QueueHandle) -> Self::QueueReference<'a>;
/// Returns a command-buffer wrapper that exposes command-buffer-local recording.
fn command_buffer<'a>(&'a mut self, command_buffer_handle: CommandBufferHandle) -> Self::CommandBuffer<'a>;
/// Changes the maximum number of frames in flight.
///
/// This expensive operation can create more frame resources.
fn set_frames_in_flight(&mut self, frames: u8);
/// Returns a device accessible address for the provided buffer handle.
fn get_buffer_address(&self, buffer_handle: BaseBufferHandle) -> u64;
/// Returns a shared view into a typed buffer's contents.
fn get_buffer_slice<T: Copy>(&mut self, buffer_handle: BufferHandle<T>) -> &T;
/// Returns a mutable view into CPU-visible buffer contents.
fn get_mut_buffer_slice<T: Copy>(&self, buffer_handle: BufferHandle<T>) -> &'static mut T;
/// Flushes or uploads pending writes for the provided buffer.
fn sync_buffer(&mut self, buffer_handle: impl Into<BaseBufferHandle>);
/// Returns mutable CPU access to an image's backing bytes.
fn get_texture_slice_mut(&self, texture_handle: ImageHandle) -> &'static mut [u8];
/// Flushes or uploads pending writes for the provided image.
fn sync_texture(&mut self, image_handle: ImageHandle);
/// Enables writes to a texture and queues a copy operation.
///
/// Call `sync` on a command buffer before the GPU uses the texture.
fn write_texture(&mut self, texture_handle: ImageHandle, f: impl FnOnce(&mut [u8]));
/// Updates retained descriptor-set state before command recording.
///
/// Rendering only binds complete retained sets; resource overrides are not recorded per draw.
fn write(&mut self, descriptor_set_writes: &[descriptors::DescriptorWrite]);
/// Writes one top-level acceleration-structure instance into an instance buffer.
fn write_instance(
&mut self,
instances_buffer_handle: BaseBufferHandle,
instance_index: usize,
transform: [[f32; 4]; 3],
custom_index: u16,
mask: u8,
sbt_record_offset: usize,
acceleration_structure: BottomLevelAccelerationStructureHandle,
);
/// Writes one shader binding table entry for the provided pipeline shader.
fn write_sbt_entry(
&mut self,
sbt_buffer_handle: BaseBufferHandle,
sbt_record_offset: usize,
pipeline_handle: PipelineHandle,
shader_handle: ShaderHandle,
);
/// Associates a swapchain with a window.
fn bind_to_window(
&mut self,
window_os_handles: &window::Handles,
presentation_mode: PresentationModes,
fallback_extent: Extent,
uses: Uses,
) -> SwapchainHandle;
/// Returns CPU-visible bytes for an image synchronized by `transfer_textures`.
fn get_image_data(&mut self, texture_copy_handle: TextureCopyHandle) -> &[u8];
/// Resizes a dynamic buffer to the specified size.
fn resize_buffer<T: Copy>(&mut self, buffer_handle: DynamicBufferHandle<T>, size: usize);
/// Starts capturing the underlying's API calls if the application is attached to a graphics debugger.
fn start_frame_capture(&mut self);
/// Ends capturing the underlying's API calls if the application is attached to a graphics debugger.
fn end_frame_capture(&mut self);
/// Waits for all pending operations to complete.
fn wait(&self);
}
/// The `ContextCreate` trait provides creation operations for resources owned by a GHI context.
pub trait ContextCreate {
/// Creates a new allocation from a managed allocator for the underlying GPU allocations.
fn create_allocation(
&mut self,
size: usize,
_resource_uses: Uses,
resource_device_accesses: DeviceAccesses,
) -> AllocationHandle;
/// Uploads indexed mesh data and returns a reusable mesh handle.
fn add_mesh_from_vertices_and_indices(
&mut self,
vertex_count: u32,
index_count: u32,
vertices: &[u8],
indices: &[u8],
vertex_layout: &[VertexElement],
) -> MeshHandle;
/// Creates a shader and returns its handle.
///
/// # Errors
///
/// Returns an error when GLSL compilation fails or SPIR-V input is not aligned
/// to four bytes.
fn create_shader(
&mut self,
name: Option<&str>,
shader_source_type: Sources,
stage: ShaderTypes,
shader_resource_descriptors: impl IntoIterator<Item = shader::ShaderResourceDescriptor>,
) -> Result<ShaderHandle, ()>;
/// Creates an empty retained descriptor set.
///
/// The set is a lifetime/update grouping only. Its shader-visible slots are established by
/// [`Context::write`] calls and validated against the active pipeline when it is bound.
fn create_descriptor_set(&mut self, name: Option<&str>) -> DescriptorSetHandle;
/// Creates a graphics/rasterization pipeline from a builder.
fn create_raster_pipeline(&mut self, builder: crate::pipelines::raster::Builder) -> PipelineHandle;
/// Creates a compute pipeline.
fn create_compute_pipeline(&mut self, builder: crate::pipelines::compute::Builder) -> PipelineHandle;
/// Creates a ray-tracing pipeline.
fn create_ray_tracing_pipeline(&mut self, builder: crate::pipelines::ray_tracing::Builder) -> PipelineHandle;
/// Creates a static fixed-size buffer from a builder.
/// Static buffers are not resizable; use [`ContextCreate::build_dynamic_buffer`] when the allocation must grow.
fn build_buffer<T: Copy>(&mut self, builder: buffer::Builder) -> BufferHandle<T>;
/// Creates a dynamic buffer from a builder.
/// Dynamic buffers can be resized with [`Context::resize_buffer`].
fn build_dynamic_buffer<T: Copy>(&mut self, builder: buffer::Builder) -> DynamicBufferHandle<T>;
/// Creates a dynamic image from a builder.
fn build_dynamic_image(&mut self, builder: image::Builder) -> DynamicImageHandle;
/// Creates an image from a builder.
fn build_image(&mut self, builder: image::Builder) -> ImageHandle;
/// Creates an image sampler from a builder.
///
/// Devices can limit their sampler count. Reuse samplers when possible.
fn build_sampler(&mut self, builder: sampler::Builder) -> SamplerHandle;
/// Creates a buffer that stores top-level acceleration-structure instances.
fn create_acceleration_structure_instance_buffer(
&mut self,
name: Option<&str>,
max_instance_count: u32,
) -> BaseBufferHandle;
/// Creates a top-level acceleration structure for ray tracing.
fn create_top_level_acceleration_structure(
&mut self,
name: Option<&str>,
max_instance_count: u32,
) -> TopLevelAccelerationStructureHandle;
/// Creates a bottom-level acceleration structure from geometry descriptions.
fn create_bottom_level_acceleration_structure(
&mut self,
description: &BottomLevelAccelerationStructure,
) -> BottomLevelAccelerationStructureHandle;
/// Creates a synchronization primitive (implemented as a semaphore/fence/event).\
/// Multiple underlying synchronization primitives are created, one for each frame
fn create_synchronizer(&mut self, name: Option<&str>, signaled: bool) -> SynchronizerHandle;
}