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