1#![allow(unused_variables)]
2
3use alloc::{string::String, vec, vec::Vec};
4use core::{ptr, sync::atomic::Ordering, time::Duration};
5
6#[cfg(supports_64bit_atomics)]
7use core::sync::atomic::AtomicU64;
8#[cfg(not(supports_64bit_atomics))]
9use portable_atomic::AtomicU64;
10
11use crate::TlasInstance;
12
13mod buffer;
14pub use buffer::Buffer;
15mod command;
16pub use command::CommandBuffer;
17
18#[derive(Clone, Debug)]
19pub struct Api;
20pub struct Context;
21#[derive(Debug)]
22pub struct Encoder;
23#[derive(Debug)]
24pub struct Resource;
25
26#[derive(Debug)]
27pub struct Fence {
28 value: AtomicU64,
29}
30
31type DeviceResult<T> = Result<T, crate::DeviceError>;
32
33impl crate::Api for Api {
34 type Instance = Context;
35 type Surface = Context;
36 type Adapter = Context;
37 type Device = Context;
38
39 type Queue = Context;
40 type CommandEncoder = CommandBuffer;
41 type CommandBuffer = CommandBuffer;
42
43 type Buffer = Buffer;
44 type Texture = Resource;
45 type SurfaceTexture = Resource;
46 type TextureView = Resource;
47 type Sampler = Resource;
48 type QuerySet = Resource;
49 type Fence = Fence;
50 type AccelerationStructure = Resource;
51 type PipelineCache = Resource;
52
53 type BindGroupLayout = Resource;
54 type BindGroup = Resource;
55 type PipelineLayout = Resource;
56 type ShaderModule = Resource;
57 type RenderPipeline = Resource;
58 type ComputePipeline = Resource;
59}
60
61crate::impl_dyn_resource!(Buffer, CommandBuffer, Context, Fence, Resource);
62
63impl crate::DynAccelerationStructure for Resource {}
64impl crate::DynBindGroup for Resource {}
65impl crate::DynBindGroupLayout for Resource {}
66impl crate::DynBuffer for Buffer {}
67impl crate::DynCommandBuffer for CommandBuffer {}
68impl crate::DynComputePipeline for Resource {}
69impl crate::DynFence for Fence {}
70impl crate::DynPipelineCache for Resource {}
71impl crate::DynPipelineLayout for Resource {}
72impl crate::DynQuerySet for Resource {}
73impl crate::DynRenderPipeline for Resource {}
74impl crate::DynSampler for Resource {}
75impl crate::DynShaderModule for Resource {}
76impl crate::DynSurfaceTexture for Resource {}
77impl crate::DynTexture for Resource {}
78impl crate::DynTextureView for Resource {}
79
80impl core::borrow::Borrow<dyn crate::DynTexture> for Resource {
81 fn borrow(&self) -> &dyn crate::DynTexture {
82 self
83 }
84}
85
86impl crate::Instance for Context {
87 type A = Api;
88
89 unsafe fn init(desc: &crate::InstanceDescriptor) -> Result<Self, crate::InstanceError> {
90 let crate::InstanceDescriptor {
91 backend_options:
92 wgt::BackendOptions {
93 noop: wgt::NoopBackendOptions { enable },
94 ..
95 },
96 name: _,
97 flags: _,
98 memory_budget_thresholds: _,
99 } = *desc;
100 if enable {
101 Ok(Context)
102 } else {
103 Err(crate::InstanceError::new(String::from(
104 "noop backend disabled because NoopBackendOptions::enable is false",
105 )))
106 }
107 }
108 unsafe fn create_surface(
109 &self,
110 _display_handle: raw_window_handle::RawDisplayHandle,
111 _window_handle: raw_window_handle::RawWindowHandle,
112 ) -> Result<Context, crate::InstanceError> {
113 Ok(Context)
114 }
115 unsafe fn enumerate_adapters(
116 &self,
117 _surface_hint: Option<&Context>,
118 ) -> Vec<crate::ExposedAdapter<Api>> {
119 vec![crate::ExposedAdapter {
120 adapter: Context,
121 info: wgt::AdapterInfo {
122 name: String::from("noop wgpu backend"),
123 vendor: 0,
124 device: 0,
125 device_type: wgt::DeviceType::Cpu,
126 driver: String::from("wgpu"),
127 driver_info: String::new(),
128 backend: wgt::Backend::Noop,
129 },
130 features: wgt::Features::all(),
131 capabilities: CAPABILITIES,
132 }]
133 }
134}
135
136const CAPABILITIES: crate::Capabilities = {
137 const ALLOC_MAX_U32: u32 = i32::MAX as u32;
140
141 crate::Capabilities {
142 limits: wgt::Limits {
143 max_texture_dimension_1d: ALLOC_MAX_U32,
145 max_texture_dimension_2d: ALLOC_MAX_U32,
146 max_texture_dimension_3d: ALLOC_MAX_U32,
147 max_texture_array_layers: ALLOC_MAX_U32,
148 max_bind_groups: ALLOC_MAX_U32,
149 max_bindings_per_bind_group: ALLOC_MAX_U32,
150 max_dynamic_uniform_buffers_per_pipeline_layout: ALLOC_MAX_U32,
151 max_dynamic_storage_buffers_per_pipeline_layout: ALLOC_MAX_U32,
152 max_sampled_textures_per_shader_stage: ALLOC_MAX_U32,
153 max_samplers_per_shader_stage: ALLOC_MAX_U32,
154 max_storage_buffers_per_shader_stage: ALLOC_MAX_U32,
155 max_storage_textures_per_shader_stage: ALLOC_MAX_U32,
156 max_uniform_buffers_per_shader_stage: ALLOC_MAX_U32,
157 max_binding_array_elements_per_shader_stage: ALLOC_MAX_U32,
158 max_binding_array_sampler_elements_per_shader_stage: ALLOC_MAX_U32,
159 max_uniform_buffer_binding_size: ALLOC_MAX_U32,
160 max_storage_buffer_binding_size: ALLOC_MAX_U32,
161 max_vertex_buffers: ALLOC_MAX_U32,
162 max_buffer_size: ALLOC_MAX_U32 as u64,
163 max_vertex_attributes: ALLOC_MAX_U32,
164 max_vertex_buffer_array_stride: ALLOC_MAX_U32,
165 min_uniform_buffer_offset_alignment: 1,
166 min_storage_buffer_offset_alignment: 1,
167 max_inter_stage_shader_components: ALLOC_MAX_U32,
168 max_color_attachments: ALLOC_MAX_U32,
169 max_color_attachment_bytes_per_sample: ALLOC_MAX_U32,
170 max_compute_workgroup_storage_size: ALLOC_MAX_U32,
171 max_compute_invocations_per_workgroup: ALLOC_MAX_U32,
172 max_compute_workgroup_size_x: ALLOC_MAX_U32,
173 max_compute_workgroup_size_y: ALLOC_MAX_U32,
174 max_compute_workgroup_size_z: ALLOC_MAX_U32,
175 max_compute_workgroups_per_dimension: ALLOC_MAX_U32,
176 min_subgroup_size: 1,
177 max_subgroup_size: ALLOC_MAX_U32,
178 max_push_constant_size: ALLOC_MAX_U32,
179 max_non_sampler_bindings: ALLOC_MAX_U32,
180 max_blas_primitive_count: ALLOC_MAX_U32,
181 max_blas_geometry_count: ALLOC_MAX_U32,
182 max_tlas_instance_count: ALLOC_MAX_U32,
183 max_acceleration_structures_per_shader_stage: ALLOC_MAX_U32,
184 },
185 alignments: crate::Alignments {
186 buffer_copy_offset: wgt::BufferSize::MIN,
188 buffer_copy_pitch: wgt::BufferSize::MIN,
189 uniform_bounds_check_alignment: wgt::BufferSize::MIN,
190 raw_tlas_instance_size: 0,
191 ray_tracing_scratch_buffer_alignment: 1,
192 },
193 downlevel: wgt::DownlevelCapabilities {
194 flags: wgt::DownlevelFlags::all(),
195 limits: wgt::DownlevelLimits {},
196 shader_model: wgt::ShaderModel::Sm5,
197 },
198 }
199};
200
201impl crate::Surface for Context {
202 type A = Api;
203
204 unsafe fn configure(
205 &self,
206 device: &Context,
207 config: &crate::SurfaceConfiguration,
208 ) -> Result<(), crate::SurfaceError> {
209 Ok(())
210 }
211
212 unsafe fn unconfigure(&self, device: &Context) {}
213
214 unsafe fn acquire_texture(
215 &self,
216 timeout: Option<Duration>,
217 fence: &Fence,
218 ) -> Result<Option<crate::AcquiredSurfaceTexture<Api>>, crate::SurfaceError> {
219 Ok(None)
220 }
221 unsafe fn discard_texture(&self, texture: Resource) {}
222}
223
224impl crate::Adapter for Context {
225 type A = Api;
226
227 unsafe fn open(
228 &self,
229 features: wgt::Features,
230 _limits: &wgt::Limits,
231 _memory_hints: &wgt::MemoryHints,
232 ) -> DeviceResult<crate::OpenDevice<Api>> {
233 Ok(crate::OpenDevice {
234 device: Context,
235 queue: Context,
236 })
237 }
238 unsafe fn texture_format_capabilities(
239 &self,
240 format: wgt::TextureFormat,
241 ) -> crate::TextureFormatCapabilities {
242 crate::TextureFormatCapabilities::empty()
243 }
244
245 unsafe fn surface_capabilities(&self, surface: &Context) -> Option<crate::SurfaceCapabilities> {
246 None
247 }
248
249 unsafe fn get_presentation_timestamp(&self) -> wgt::PresentationTimestamp {
250 wgt::PresentationTimestamp::INVALID_TIMESTAMP
251 }
252}
253
254impl crate::Queue for Context {
255 type A = Api;
256
257 unsafe fn submit(
258 &self,
259 command_buffers: &[&CommandBuffer],
260 surface_textures: &[&Resource],
261 (fence, fence_value): (&mut Fence, crate::FenceValue),
262 ) -> DeviceResult<()> {
263 for cb in command_buffers {
265 unsafe {
268 cb.execute();
269 }
270 }
271 fence.value.store(fence_value, Ordering::Release);
272 Ok(())
273 }
274 unsafe fn present(
275 &self,
276 surface: &Context,
277 texture: Resource,
278 ) -> Result<(), crate::SurfaceError> {
279 Ok(())
280 }
281
282 unsafe fn get_timestamp_period(&self) -> f32 {
283 1.0
284 }
285}
286
287impl crate::Device for Context {
288 type A = Api;
289
290 unsafe fn create_buffer(&self, desc: &crate::BufferDescriptor) -> DeviceResult<Buffer> {
291 Buffer::new(desc)
292 }
293
294 unsafe fn destroy_buffer(&self, buffer: Buffer) {}
295 unsafe fn add_raw_buffer(&self, _buffer: &Buffer) {}
296
297 unsafe fn map_buffer(
298 &self,
299 buffer: &Buffer,
300 range: crate::MemoryRange,
301 ) -> DeviceResult<crate::BufferMapping> {
302 Ok(crate::BufferMapping {
306 ptr: ptr::NonNull::new(buffer.get_slice_ptr(range).cast::<u8>()).unwrap(),
307 is_coherent: true,
308 })
309 }
310 unsafe fn unmap_buffer(&self, buffer: &Buffer) {}
311 unsafe fn flush_mapped_ranges<I>(&self, buffer: &Buffer, ranges: I) {}
312 unsafe fn invalidate_mapped_ranges<I>(&self, buffer: &Buffer, ranges: I) {}
313
314 unsafe fn create_texture(&self, desc: &crate::TextureDescriptor) -> DeviceResult<Resource> {
315 Ok(Resource)
316 }
317 unsafe fn destroy_texture(&self, texture: Resource) {}
318 unsafe fn add_raw_texture(&self, _texture: &Resource) {}
319
320 unsafe fn create_texture_view(
321 &self,
322 texture: &Resource,
323 desc: &crate::TextureViewDescriptor,
324 ) -> DeviceResult<Resource> {
325 Ok(Resource)
326 }
327 unsafe fn destroy_texture_view(&self, view: Resource) {}
328 unsafe fn create_sampler(&self, desc: &crate::SamplerDescriptor) -> DeviceResult<Resource> {
329 Ok(Resource)
330 }
331 unsafe fn destroy_sampler(&self, sampler: Resource) {}
332
333 unsafe fn create_command_encoder(
334 &self,
335 desc: &crate::CommandEncoderDescriptor<Context>,
336 ) -> DeviceResult<CommandBuffer> {
337 Ok(CommandBuffer::new())
338 }
339
340 unsafe fn create_bind_group_layout(
341 &self,
342 desc: &crate::BindGroupLayoutDescriptor,
343 ) -> DeviceResult<Resource> {
344 Ok(Resource)
345 }
346 unsafe fn destroy_bind_group_layout(&self, bg_layout: Resource) {}
347 unsafe fn create_pipeline_layout(
348 &self,
349 desc: &crate::PipelineLayoutDescriptor<Resource>,
350 ) -> DeviceResult<Resource> {
351 Ok(Resource)
352 }
353 unsafe fn destroy_pipeline_layout(&self, pipeline_layout: Resource) {}
354 unsafe fn create_bind_group(
355 &self,
356 desc: &crate::BindGroupDescriptor<Resource, Buffer, Resource, Resource, Resource>,
357 ) -> DeviceResult<Resource> {
358 Ok(Resource)
359 }
360 unsafe fn destroy_bind_group(&self, group: Resource) {}
361
362 unsafe fn create_shader_module(
363 &self,
364 desc: &crate::ShaderModuleDescriptor,
365 shader: crate::ShaderInput,
366 ) -> Result<Resource, crate::ShaderError> {
367 Ok(Resource)
368 }
369 unsafe fn destroy_shader_module(&self, module: Resource) {}
370 unsafe fn create_render_pipeline(
371 &self,
372 desc: &crate::RenderPipelineDescriptor<Resource, Resource, Resource>,
373 ) -> Result<Resource, crate::PipelineError> {
374 Ok(Resource)
375 }
376 unsafe fn create_mesh_pipeline(
377 &self,
378 desc: &crate::MeshPipelineDescriptor<
379 <Self::A as crate::Api>::PipelineLayout,
380 <Self::A as crate::Api>::ShaderModule,
381 <Self::A as crate::Api>::PipelineCache,
382 >,
383 ) -> Result<<Self::A as crate::Api>::RenderPipeline, crate::PipelineError> {
384 Ok(Resource)
385 }
386 unsafe fn destroy_render_pipeline(&self, pipeline: Resource) {}
387 unsafe fn create_compute_pipeline(
388 &self,
389 desc: &crate::ComputePipelineDescriptor<Resource, Resource, Resource>,
390 ) -> Result<Resource, crate::PipelineError> {
391 Ok(Resource)
392 }
393 unsafe fn destroy_compute_pipeline(&self, pipeline: Resource) {}
394 unsafe fn create_pipeline_cache(
395 &self,
396 desc: &crate::PipelineCacheDescriptor<'_>,
397 ) -> Result<Resource, crate::PipelineCacheError> {
398 Ok(Resource)
399 }
400 unsafe fn destroy_pipeline_cache(&self, cache: Resource) {}
401
402 unsafe fn create_query_set(
403 &self,
404 desc: &wgt::QuerySetDescriptor<crate::Label>,
405 ) -> DeviceResult<Resource> {
406 Ok(Resource)
407 }
408 unsafe fn destroy_query_set(&self, set: Resource) {}
409 unsafe fn create_fence(&self) -> DeviceResult<Fence> {
410 Ok(Fence {
411 value: AtomicU64::new(0),
412 })
413 }
414 unsafe fn destroy_fence(&self, fence: Fence) {}
415 unsafe fn get_fence_value(&self, fence: &Fence) -> DeviceResult<crate::FenceValue> {
416 Ok(fence.value.load(Ordering::Acquire))
417 }
418 unsafe fn wait(
419 &self,
420 fence: &Fence,
421 value: crate::FenceValue,
422 timeout_ms: u32,
423 ) -> DeviceResult<bool> {
424 assert!(
428 fence.value.load(Ordering::Acquire) >= value,
429 "submission must have already been done"
430 );
431 Ok(true)
432 }
433
434 unsafe fn start_graphics_debugger_capture(&self) -> bool {
435 false
436 }
437 unsafe fn stop_graphics_debugger_capture(&self) {}
438 unsafe fn create_acceleration_structure(
439 &self,
440 desc: &crate::AccelerationStructureDescriptor,
441 ) -> DeviceResult<Resource> {
442 Ok(Resource)
443 }
444 unsafe fn get_acceleration_structure_build_sizes<'a>(
445 &self,
446 _desc: &crate::GetAccelerationStructureBuildSizesDescriptor<'a, Buffer>,
447 ) -> crate::AccelerationStructureBuildSizes {
448 Default::default()
449 }
450 unsafe fn get_acceleration_structure_device_address(
451 &self,
452 _acceleration_structure: &Resource,
453 ) -> wgt::BufferAddress {
454 Default::default()
455 }
456 unsafe fn destroy_acceleration_structure(&self, _acceleration_structure: Resource) {}
457
458 fn tlas_instance_to_bytes(&self, instance: TlasInstance) -> Vec<u8> {
459 vec![]
460 }
461
462 fn get_internal_counters(&self) -> wgt::HalCounters {
463 Default::default()
464 }
465
466 fn check_if_oom(&self) -> DeviceResult<()> {
467 Ok(())
468 }
469}