1#[cfg(not(any(windows, webgl)))]
86mod egl;
87#[cfg(Emscripten)]
88mod emscripten;
89#[cfg(webgl)]
90mod web;
91#[cfg(windows)]
92mod wgl;
93
94mod adapter;
95mod command;
96mod conv;
97mod device;
98mod queue;
99
100use crate::{CopyExtent, TextureDescriptor};
101
102#[cfg(not(any(windows, webgl)))]
103pub use self::egl::{AdapterContext, AdapterContextLock};
104#[cfg(not(any(windows, webgl)))]
105use self::egl::{Instance, Surface};
106
107#[cfg(webgl)]
108pub use self::web::AdapterContext;
109#[cfg(webgl)]
110use self::web::{Instance, Surface};
111
112#[cfg(windows)]
113use self::wgl::AdapterContext;
114#[cfg(windows)]
115use self::wgl::{Instance, Surface};
116
117use arrayvec::ArrayVec;
118
119use glow::HasContext;
120
121use naga::FastHashMap;
122use parking_lot::Mutex;
123use std::sync::atomic::{AtomicU32, AtomicU8, Ordering};
124use std::{fmt, ops::Range, sync::Arc};
125
126#[derive(Clone, Debug)]
127pub struct Api;
128
129const MAX_TEXTURE_SLOTS: usize = 16;
132const MAX_SAMPLERS: usize = 16;
133const MAX_VERTEX_ATTRIBUTES: usize = 16;
134const ZERO_BUFFER_SIZE: usize = 256 << 10;
135const MAX_PUSH_CONSTANTS: usize = 64;
136const MAX_PUSH_CONSTANT_COMMANDS: usize = MAX_PUSH_CONSTANTS * crate::MAX_CONCURRENT_SHADER_STAGES;
138
139impl crate::Api for Api {
140 type Instance = Instance;
141 type Surface = Surface;
142 type Adapter = Adapter;
143 type Device = Device;
144
145 type Queue = Queue;
146 type CommandEncoder = CommandEncoder;
147 type CommandBuffer = CommandBuffer;
148
149 type Buffer = Buffer;
150 type Texture = Texture;
151 type SurfaceTexture = Texture;
152 type TextureView = TextureView;
153 type Sampler = Sampler;
154 type QuerySet = QuerySet;
155 type Fence = Fence;
156 type AccelerationStructure = AccelerationStructure;
157 type PipelineCache = PipelineCache;
158
159 type BindGroupLayout = BindGroupLayout;
160 type BindGroup = BindGroup;
161 type PipelineLayout = PipelineLayout;
162 type ShaderModule = ShaderModule;
163 type RenderPipeline = RenderPipeline;
164 type ComputePipeline = ComputePipeline;
165}
166
167crate::impl_dyn_resource!(
168 Adapter,
169 AccelerationStructure,
170 BindGroup,
171 BindGroupLayout,
172 Buffer,
173 CommandBuffer,
174 CommandEncoder,
175 ComputePipeline,
176 Device,
177 Fence,
178 Instance,
179 PipelineCache,
180 PipelineLayout,
181 QuerySet,
182 Queue,
183 RenderPipeline,
184 Sampler,
185 ShaderModule,
186 Surface,
187 Texture,
188 TextureView
189);
190
191bitflags::bitflags! {
192 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
195 struct PrivateCapabilities: u32 {
196 const BUFFER_ALLOCATION = 1 << 0;
198 const SHADER_BINDING_LAYOUT = 1 << 1;
200 const SHADER_TEXTURE_SHADOW_LOD = 1 << 2;
202 const MEMORY_BARRIERS = 1 << 3;
204 const VERTEX_BUFFER_LAYOUT = 1 << 4;
206 const INDEX_BUFFER_ROLE_CHANGE = 1 << 5;
209 const GET_BUFFER_SUB_DATA = 1 << 7;
211 const COLOR_BUFFER_HALF_FLOAT = 1 << 8;
213 const COLOR_BUFFER_FLOAT = 1 << 9;
215 const QUERY_BUFFERS = 1 << 11;
217 const QUERY_64BIT = 1 << 12;
219 const TEXTURE_STORAGE = 1 << 13;
221 const DEBUG_FNS = 1 << 14;
223 const INVALIDATE_FRAMEBUFFER = 1 << 15;
225 const FULLY_FEATURED_INSTANCING = 1 << 16;
229 }
230}
231
232bitflags::bitflags! {
233 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
235 struct Workarounds: u32 {
236 const MESA_I915_SRGB_SHADER_CLEAR = 1 << 0;
243 const EMULATE_BUFFER_MAP = 1 << 1;
245 }
246}
247
248type BindTarget = u32;
249
250#[derive(Debug, Clone, Copy)]
251enum VertexAttribKind {
252 Float, Integer, }
256
257impl Default for VertexAttribKind {
258 fn default() -> Self {
259 Self::Float
260 }
261}
262
263#[derive(Clone, Debug)]
264pub struct TextureFormatDesc {
265 pub internal: u32,
266 pub external: u32,
267 pub data_type: u32,
268}
269
270struct AdapterShared {
271 context: AdapterContext,
272 private_caps: PrivateCapabilities,
273 features: wgt::Features,
274 limits: wgt::Limits,
275 workarounds: Workarounds,
276 shading_language_version: naga::back::glsl::Version,
277 next_shader_id: AtomicU32,
278 program_cache: Mutex<ProgramCache>,
279 es: bool,
280
281 max_msaa_samples: i32,
285}
286
287pub struct Adapter {
288 shared: Arc<AdapterShared>,
289}
290
291pub struct Device {
292 shared: Arc<AdapterShared>,
293 main_vao: glow::VertexArray,
294 #[cfg(all(native, feature = "renderdoc"))]
295 render_doc: crate::auxil::renderdoc::RenderDoc,
296 counters: Arc<wgt::HalCounters>,
297}
298
299impl Drop for Device {
300 fn drop(&mut self) {
301 let gl = &self.shared.context.lock();
302 unsafe { gl.delete_vertex_array(self.main_vao) };
303 }
304}
305
306pub struct ShaderClearProgram {
307 pub program: glow::Program,
308 pub color_uniform_location: glow::UniformLocation,
309}
310
311pub struct Queue {
312 shared: Arc<AdapterShared>,
313 features: wgt::Features,
314 draw_fbo: glow::Framebuffer,
315 copy_fbo: glow::Framebuffer,
316 shader_clear_program: Option<ShaderClearProgram>,
319 zero_buffer: glow::Buffer,
322 temp_query_results: Mutex<Vec<u64>>,
323 draw_buffer_count: AtomicU8,
324 current_index_buffer: Mutex<Option<glow::Buffer>>,
325}
326
327impl Drop for Queue {
328 fn drop(&mut self) {
329 let gl = &self.shared.context.lock();
330 unsafe { gl.delete_framebuffer(self.draw_fbo) };
331 unsafe { gl.delete_framebuffer(self.copy_fbo) };
332 unsafe { gl.delete_buffer(self.zero_buffer) };
333 }
334}
335
336#[derive(Clone, Debug)]
337pub struct Buffer {
338 raw: Option<glow::Buffer>,
339 target: BindTarget,
340 size: wgt::BufferAddress,
341 map_flags: u32,
342 data: Option<Arc<std::sync::Mutex<Vec<u8>>>>,
343 offset_of_current_mapping: Arc<std::sync::Mutex<wgt::BufferAddress>>,
344}
345
346#[cfg(send_sync)]
347unsafe impl Sync for Buffer {}
348#[cfg(send_sync)]
349unsafe impl Send for Buffer {}
350
351impl crate::DynBuffer for Buffer {}
352
353#[derive(Clone, Debug)]
354pub enum TextureInner {
355 Renderbuffer {
356 raw: glow::Renderbuffer,
357 },
358 DefaultRenderbuffer,
359 Texture {
360 raw: glow::Texture,
361 target: BindTarget,
362 },
363 #[cfg(webgl)]
364 ExternalFramebuffer {
365 inner: web_sys::WebGlFramebuffer,
366 },
367}
368
369#[cfg(send_sync)]
370unsafe impl Sync for TextureInner {}
371#[cfg(send_sync)]
372unsafe impl Send for TextureInner {}
373
374impl TextureInner {
375 fn as_native(&self) -> (glow::Texture, BindTarget) {
376 match *self {
377 Self::Renderbuffer { .. } | Self::DefaultRenderbuffer => {
378 panic!("Unexpected renderbuffer");
379 }
380 Self::Texture { raw, target } => (raw, target),
381 #[cfg(webgl)]
382 Self::ExternalFramebuffer { .. } => panic!("Unexpected external framebuffer"),
383 }
384 }
385}
386
387#[derive(Debug)]
388pub struct Texture {
389 pub inner: TextureInner,
390 pub drop_guard: Option<crate::DropGuard>,
391 pub mip_level_count: u32,
392 pub array_layer_count: u32,
393 pub format: wgt::TextureFormat,
394 #[allow(unused)]
395 pub format_desc: TextureFormatDesc,
396 pub copy_size: CopyExtent,
397}
398
399impl crate::DynTexture for Texture {}
400impl crate::DynSurfaceTexture for Texture {}
401
402impl std::borrow::Borrow<dyn crate::DynTexture> for Texture {
403 fn borrow(&self) -> &dyn crate::DynTexture {
404 self
405 }
406}
407
408impl Texture {
409 pub fn default_framebuffer(format: wgt::TextureFormat) -> Self {
410 Self {
411 inner: TextureInner::DefaultRenderbuffer,
412 drop_guard: None,
413 mip_level_count: 1,
414 array_layer_count: 1,
415 format,
416 format_desc: TextureFormatDesc {
417 internal: 0,
418 external: 0,
419 data_type: 0,
420 },
421 copy_size: CopyExtent {
422 width: 0,
423 height: 0,
424 depth: 0,
425 },
426 }
427 }
428
429 fn get_info_from_desc(desc: &TextureDescriptor) -> u32 {
431 match desc.dimension {
432 wgt::TextureDimension::D1 => glow::TEXTURE_2D,
435 wgt::TextureDimension::D2 => {
436 match (desc.is_cube_compatible(), desc.size.depth_or_array_layers) {
438 (false, 1) => glow::TEXTURE_2D,
439 (false, _) => glow::TEXTURE_2D_ARRAY,
440 (true, 6) => glow::TEXTURE_CUBE_MAP,
441 (true, _) => glow::TEXTURE_CUBE_MAP_ARRAY,
442 }
443 }
444 wgt::TextureDimension::D3 => glow::TEXTURE_3D,
445 }
446 }
447
448 fn log_failing_target_heuristics(view_dimension: wgt::TextureViewDimension, target: u32) {
450 let expected_target = match view_dimension {
451 wgt::TextureViewDimension::D1 => glow::TEXTURE_2D,
452 wgt::TextureViewDimension::D2 => glow::TEXTURE_2D,
453 wgt::TextureViewDimension::D2Array => glow::TEXTURE_2D_ARRAY,
454 wgt::TextureViewDimension::Cube => glow::TEXTURE_CUBE_MAP,
455 wgt::TextureViewDimension::CubeArray => glow::TEXTURE_CUBE_MAP_ARRAY,
456 wgt::TextureViewDimension::D3 => glow::TEXTURE_3D,
457 };
458
459 if expected_target == target {
460 return;
461 }
462
463 let buffer;
464 let got = match target {
465 glow::TEXTURE_2D => "D2",
466 glow::TEXTURE_2D_ARRAY => "D2Array",
467 glow::TEXTURE_CUBE_MAP => "Cube",
468 glow::TEXTURE_CUBE_MAP_ARRAY => "CubeArray",
469 glow::TEXTURE_3D => "D3",
470 target => {
471 buffer = target.to_string();
472 &buffer
473 }
474 };
475
476 log::error!(
477 concat!(
478 "wgpu-hal heuristics assumed that ",
479 "the view dimension will be equal to `{}` rather than `{:?}`.\n",
480 "`D2` textures with ",
481 "`depth_or_array_layers == 1` ",
482 "are assumed to have view dimension `D2`\n",
483 "`D2` textures with ",
484 "`depth_or_array_layers > 1` ",
485 "are assumed to have view dimension `D2Array`\n",
486 "`D2` textures with ",
487 "`depth_or_array_layers == 6` ",
488 "are assumed to have view dimension `Cube`\n",
489 "`D2` textures with ",
490 "`depth_or_array_layers > 6 && depth_or_array_layers % 6 == 0` ",
491 "are assumed to have view dimension `CubeArray`\n",
492 ),
493 got,
494 view_dimension,
495 );
496 }
497}
498
499#[derive(Clone, Debug)]
500pub struct TextureView {
501 inner: TextureInner,
502 aspects: crate::FormatAspects,
503 mip_levels: Range<u32>,
504 array_layers: Range<u32>,
505 format: wgt::TextureFormat,
506}
507
508impl crate::DynTextureView for TextureView {}
509
510#[derive(Debug)]
511pub struct Sampler {
512 raw: glow::Sampler,
513}
514
515impl crate::DynSampler for Sampler {}
516
517#[derive(Debug)]
518pub struct BindGroupLayout {
519 entries: Arc<[wgt::BindGroupLayoutEntry]>,
520}
521
522impl crate::DynBindGroupLayout for BindGroupLayout {}
523
524#[derive(Debug)]
525struct BindGroupLayoutInfo {
526 entries: Arc<[wgt::BindGroupLayoutEntry]>,
527 binding_to_slot: Box<[u8]>,
533}
534
535#[derive(Debug)]
536pub struct PipelineLayout {
537 group_infos: Box<[BindGroupLayoutInfo]>,
538 naga_options: naga::back::glsl::Options,
539}
540
541impl crate::DynPipelineLayout for PipelineLayout {}
542
543impl PipelineLayout {
544 fn get_slot(&self, br: &naga::ResourceBinding) -> u8 {
545 let group_info = &self.group_infos[br.group as usize];
546 group_info.binding_to_slot[br.binding as usize]
547 }
548}
549
550#[derive(Debug)]
551enum BindingRegister {
552 UniformBuffers,
553 StorageBuffers,
554 Textures,
555 Images,
556}
557
558#[derive(Debug)]
559enum RawBinding {
560 Buffer {
561 raw: glow::Buffer,
562 offset: i32,
563 size: i32,
564 },
565 Texture {
566 raw: glow::Texture,
567 target: BindTarget,
568 aspects: crate::FormatAspects,
569 mip_levels: Range<u32>,
570 },
572 Image(ImageBinding),
573 Sampler(glow::Sampler),
574}
575
576#[derive(Debug)]
577pub struct BindGroup {
578 contents: Box<[RawBinding]>,
579}
580
581impl crate::DynBindGroup for BindGroup {}
582
583type ShaderId = u32;
584
585#[derive(Debug)]
586pub struct ShaderModule {
587 naga: crate::NagaShader,
588 label: Option<String>,
589 id: ShaderId,
590}
591
592impl crate::DynShaderModule for ShaderModule {}
593
594#[derive(Clone, Debug, Default)]
595struct VertexFormatDesc {
596 element_count: i32,
597 element_format: u32,
598 attrib_kind: VertexAttribKind,
599}
600
601#[derive(Clone, Debug, Default)]
602struct AttributeDesc {
603 location: u32,
604 offset: u32,
605 buffer_index: u32,
606 format_desc: VertexFormatDesc,
607}
608
609#[derive(Clone, Debug)]
610struct BufferBinding {
611 raw: glow::Buffer,
612 offset: wgt::BufferAddress,
613}
614
615#[derive(Clone, Debug)]
616struct ImageBinding {
617 raw: glow::Texture,
618 mip_level: u32,
619 array_layer: Option<u32>,
620 access: u32,
621 format: u32,
622}
623
624#[derive(Clone, Debug, Default, PartialEq)]
625struct VertexBufferDesc {
626 step: wgt::VertexStepMode,
627 stride: u32,
628}
629
630#[derive(Clone, Debug)]
631struct PushConstantDesc {
632 location: glow::UniformLocation,
633 ty: naga::TypeInner,
634 offset: u32,
635 size_bytes: u32,
636}
637
638#[cfg(send_sync)]
639unsafe impl Sync for PushConstantDesc {}
640#[cfg(send_sync)]
641unsafe impl Send for PushConstantDesc {}
642
643type SamplerBindMap = [Option<u8>; MAX_TEXTURE_SLOTS];
646
647#[derive(Debug)]
648struct PipelineInner {
649 program: glow::Program,
650 sampler_map: SamplerBindMap,
651 first_instance_location: Option<glow::UniformLocation>,
652 push_constant_descs: ArrayVec<PushConstantDesc, MAX_PUSH_CONSTANT_COMMANDS>,
653}
654
655#[derive(Clone, Debug)]
656struct DepthState {
657 function: u32,
658 mask: bool,
659}
660
661#[derive(Clone, Debug, PartialEq)]
662struct BlendComponent {
663 src: u32,
664 dst: u32,
665 equation: u32,
666}
667
668#[derive(Clone, Debug, PartialEq)]
669struct BlendDesc {
670 alpha: BlendComponent,
671 color: BlendComponent,
672}
673
674#[derive(Clone, Debug, Default, PartialEq)]
675struct ColorTargetDesc {
676 mask: wgt::ColorWrites,
677 blend: Option<BlendDesc>,
678}
679
680#[derive(PartialEq, Eq, Hash)]
681struct ProgramStage {
682 naga_stage: naga::ShaderStage,
683 shader_id: ShaderId,
684 entry_point: String,
685 zero_initialize_workgroup_memory: bool,
686}
687
688#[derive(PartialEq, Eq, Hash)]
689struct ProgramCacheKey {
690 stages: ArrayVec<ProgramStage, 3>,
691 group_to_binding_to_slot: Box<[Box<[u8]>]>,
692}
693
694type ProgramCache = FastHashMap<ProgramCacheKey, Result<Arc<PipelineInner>, crate::PipelineError>>;
695
696#[derive(Debug)]
697pub struct RenderPipeline {
698 inner: Arc<PipelineInner>,
699 primitive: wgt::PrimitiveState,
700 vertex_buffers: Box<[VertexBufferDesc]>,
701 vertex_attributes: Box<[AttributeDesc]>,
702 color_targets: Box<[ColorTargetDesc]>,
703 depth: Option<DepthState>,
704 depth_bias: wgt::DepthBiasState,
705 stencil: Option<StencilState>,
706 alpha_to_coverage_enabled: bool,
707}
708
709impl crate::DynRenderPipeline for RenderPipeline {}
710
711#[cfg(send_sync)]
712unsafe impl Sync for RenderPipeline {}
713#[cfg(send_sync)]
714unsafe impl Send for RenderPipeline {}
715
716#[derive(Debug)]
717pub struct ComputePipeline {
718 inner: Arc<PipelineInner>,
719}
720
721impl crate::DynComputePipeline for ComputePipeline {}
722
723#[cfg(send_sync)]
724unsafe impl Sync for ComputePipeline {}
725#[cfg(send_sync)]
726unsafe impl Send for ComputePipeline {}
727
728#[derive(Debug)]
729pub struct QuerySet {
730 queries: Box<[glow::Query]>,
731 target: BindTarget,
732}
733
734impl crate::DynQuerySet for QuerySet {}
735
736#[derive(Debug)]
737pub struct Fence {
738 last_completed: crate::AtomicFenceValue,
739 pending: Vec<(crate::FenceValue, glow::Fence)>,
740}
741
742impl crate::DynFence for Fence {}
743
744#[cfg(any(
745 not(target_arch = "wasm32"),
746 all(
747 feature = "fragile-send-sync-non-atomic-wasm",
748 not(target_feature = "atomics")
749 )
750))]
751unsafe impl Send for Fence {}
752#[cfg(any(
753 not(target_arch = "wasm32"),
754 all(
755 feature = "fragile-send-sync-non-atomic-wasm",
756 not(target_feature = "atomics")
757 )
758))]
759unsafe impl Sync for Fence {}
760
761impl Fence {
762 fn get_latest(&self, gl: &glow::Context) -> crate::FenceValue {
763 let mut max_value = self.last_completed.load(Ordering::Relaxed);
764 for &(value, sync) in self.pending.iter() {
765 if value <= max_value {
766 continue;
768 }
769 let status = unsafe { gl.get_sync_status(sync) };
770 if status == glow::SIGNALED {
771 max_value = value;
772 } else {
773 break;
775 }
776 }
777
778 self.last_completed.fetch_max(max_value, Ordering::Relaxed);
780
781 max_value
782 }
783
784 fn maintain(&mut self, gl: &glow::Context) {
785 let latest = self.get_latest(gl);
786 for &(value, sync) in self.pending.iter() {
787 if value <= latest {
788 unsafe {
789 gl.delete_sync(sync);
790 }
791 }
792 }
793 self.pending.retain(|&(value, _)| value > latest);
794 }
795}
796
797#[derive(Debug)]
798pub struct AccelerationStructure;
799
800impl crate::DynAccelerationStructure for AccelerationStructure {}
801
802#[derive(Debug)]
803pub struct PipelineCache;
804
805impl crate::DynPipelineCache for PipelineCache {}
806
807#[derive(Clone, Debug, PartialEq)]
808struct StencilOps {
809 pass: u32,
810 fail: u32,
811 depth_fail: u32,
812}
813
814impl Default for StencilOps {
815 fn default() -> Self {
816 Self {
817 pass: glow::KEEP,
818 fail: glow::KEEP,
819 depth_fail: glow::KEEP,
820 }
821 }
822}
823
824#[derive(Clone, Debug, PartialEq)]
825struct StencilSide {
826 function: u32,
827 mask_read: u32,
828 mask_write: u32,
829 reference: u32,
830 ops: StencilOps,
831}
832
833impl Default for StencilSide {
834 fn default() -> Self {
835 Self {
836 function: glow::ALWAYS,
837 mask_read: 0xFF,
838 mask_write: 0xFF,
839 reference: 0,
840 ops: StencilOps::default(),
841 }
842 }
843}
844
845#[derive(Debug, Clone, Default)]
846struct StencilState {
847 front: StencilSide,
848 back: StencilSide,
849}
850
851#[derive(Clone, Debug, Default, PartialEq)]
852struct PrimitiveState {
853 front_face: u32,
854 cull_face: u32,
855 unclipped_depth: bool,
856 polygon_mode: u32,
857}
858
859type InvalidatedAttachments = ArrayVec<u32, { crate::MAX_COLOR_ATTACHMENTS + 2 }>;
860
861#[derive(Debug)]
862enum Command {
863 Draw {
864 topology: u32,
865 first_vertex: u32,
866 vertex_count: u32,
867 first_instance: u32,
868 instance_count: u32,
869 first_instance_location: Option<glow::UniformLocation>,
870 },
871 DrawIndexed {
872 topology: u32,
873 index_type: u32,
874 index_count: u32,
875 index_offset: wgt::BufferAddress,
876 base_vertex: i32,
877 first_instance: u32,
878 instance_count: u32,
879 first_instance_location: Option<glow::UniformLocation>,
880 },
881 DrawIndirect {
882 topology: u32,
883 indirect_buf: glow::Buffer,
884 indirect_offset: wgt::BufferAddress,
885 first_instance_location: Option<glow::UniformLocation>,
886 },
887 DrawIndexedIndirect {
888 topology: u32,
889 index_type: u32,
890 indirect_buf: glow::Buffer,
891 indirect_offset: wgt::BufferAddress,
892 first_instance_location: Option<glow::UniformLocation>,
893 },
894 Dispatch([u32; 3]),
895 DispatchIndirect {
896 indirect_buf: glow::Buffer,
897 indirect_offset: wgt::BufferAddress,
898 },
899 ClearBuffer {
900 dst: Buffer,
901 dst_target: BindTarget,
902 range: crate::MemoryRange,
903 },
904 CopyBufferToBuffer {
905 src: Buffer,
906 src_target: BindTarget,
907 dst: Buffer,
908 dst_target: BindTarget,
909 copy: crate::BufferCopy,
910 },
911 #[cfg(webgl)]
912 CopyExternalImageToTexture {
913 src: wgt::CopyExternalImageSourceInfo,
914 dst: glow::Texture,
915 dst_target: BindTarget,
916 dst_format: wgt::TextureFormat,
917 dst_premultiplication: bool,
918 copy: crate::TextureCopy,
919 },
920 CopyTextureToTexture {
921 src: glow::Texture,
922 src_target: BindTarget,
923 dst: glow::Texture,
924 dst_target: BindTarget,
925 copy: crate::TextureCopy,
926 },
927 CopyBufferToTexture {
928 src: Buffer,
929 #[allow(unused)]
930 src_target: BindTarget,
931 dst: glow::Texture,
932 dst_target: BindTarget,
933 dst_format: wgt::TextureFormat,
934 copy: crate::BufferTextureCopy,
935 },
936 CopyTextureToBuffer {
937 src: glow::Texture,
938 src_target: BindTarget,
939 src_format: wgt::TextureFormat,
940 dst: Buffer,
941 #[allow(unused)]
942 dst_target: BindTarget,
943 copy: crate::BufferTextureCopy,
944 },
945 SetIndexBuffer(glow::Buffer),
946 BeginQuery(glow::Query, BindTarget),
947 EndQuery(BindTarget),
948 TimestampQuery(glow::Query),
949 CopyQueryResults {
950 query_range: Range<u32>,
951 dst: Buffer,
952 dst_target: BindTarget,
953 dst_offset: wgt::BufferAddress,
954 },
955 ResetFramebuffer {
956 is_default: bool,
957 },
958 BindAttachment {
959 attachment: u32,
960 view: TextureView,
961 },
962 ResolveAttachment {
963 attachment: u32,
964 dst: TextureView,
965 size: wgt::Extent3d,
966 },
967 InvalidateAttachments(InvalidatedAttachments),
968 SetDrawColorBuffers(u8),
969 ClearColorF {
970 draw_buffer: u32,
971 color: [f32; 4],
972 is_srgb: bool,
973 },
974 ClearColorU(u32, [u32; 4]),
975 ClearColorI(u32, [i32; 4]),
976 ClearDepth(f32),
977 ClearStencil(u32),
978 ClearDepthAndStencil(f32, u32),
983 BufferBarrier(glow::Buffer, crate::BufferUses),
984 TextureBarrier(crate::TextureUses),
985 SetViewport {
986 rect: crate::Rect<i32>,
987 depth: Range<f32>,
988 },
989 SetScissor(crate::Rect<i32>),
990 SetStencilFunc {
991 face: u32,
992 function: u32,
993 reference: u32,
994 read_mask: u32,
995 },
996 SetStencilOps {
997 face: u32,
998 write_mask: u32,
999 ops: StencilOps,
1000 },
1001 SetDepth(DepthState),
1002 SetDepthBias(wgt::DepthBiasState),
1003 ConfigureDepthStencil(crate::FormatAspects),
1004 SetAlphaToCoverage(bool),
1005 SetVertexAttribute {
1006 buffer: Option<glow::Buffer>,
1007 buffer_desc: VertexBufferDesc,
1008 attribute_desc: AttributeDesc,
1009 },
1010 UnsetVertexAttribute(u32),
1011 SetVertexBuffer {
1012 index: u32,
1013 buffer: BufferBinding,
1014 buffer_desc: VertexBufferDesc,
1015 },
1016 SetProgram(glow::Program),
1017 SetPrimitive(PrimitiveState),
1018 SetBlendConstant([f32; 4]),
1019 SetColorTarget {
1020 draw_buffer_index: Option<u32>,
1021 desc: ColorTargetDesc,
1022 },
1023 BindBuffer {
1024 target: BindTarget,
1025 slot: u32,
1026 buffer: glow::Buffer,
1027 offset: i32,
1028 size: i32,
1029 },
1030 BindSampler(u32, Option<glow::Sampler>),
1031 BindTexture {
1032 slot: u32,
1033 texture: glow::Texture,
1034 target: BindTarget,
1035 aspects: crate::FormatAspects,
1036 mip_levels: Range<u32>,
1037 },
1038 BindImage {
1039 slot: u32,
1040 binding: ImageBinding,
1041 },
1042 InsertDebugMarker(Range<u32>),
1043 PushDebugGroup(Range<u32>),
1044 PopDebugGroup,
1045 SetPushConstants {
1046 uniform: PushConstantDesc,
1047 offset: u32,
1049 },
1050}
1051
1052#[derive(Default)]
1053pub struct CommandBuffer {
1054 label: Option<String>,
1055 commands: Vec<Command>,
1056 data_bytes: Vec<u8>,
1057 queries: Vec<glow::Query>,
1058}
1059
1060impl crate::DynCommandBuffer for CommandBuffer {}
1061
1062impl fmt::Debug for CommandBuffer {
1063 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1064 let mut builder = f.debug_struct("CommandBuffer");
1065 if let Some(ref label) = self.label {
1066 builder.field("label", label);
1067 }
1068 builder.finish()
1069 }
1070}
1071
1072#[cfg(send_sync)]
1073unsafe impl Sync for CommandBuffer {}
1074#[cfg(send_sync)]
1075unsafe impl Send for CommandBuffer {}
1076
1077pub struct CommandEncoder {
1082 cmd_buffer: CommandBuffer,
1083 state: command::State,
1084 private_caps: PrivateCapabilities,
1085 counters: Arc<wgt::HalCounters>,
1086}
1087
1088impl fmt::Debug for CommandEncoder {
1089 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1090 f.debug_struct("CommandEncoder")
1091 .field("cmd_buffer", &self.cmd_buffer)
1092 .finish()
1093 }
1094}
1095
1096#[cfg(send_sync)]
1097unsafe impl Sync for CommandEncoder {}
1098#[cfg(send_sync)]
1099unsafe impl Send for CommandEncoder {}
1100
1101#[cfg(not(webgl))]
1102fn gl_debug_message_callback(source: u32, gltype: u32, id: u32, severity: u32, message: &str) {
1103 let source_str = match source {
1104 glow::DEBUG_SOURCE_API => "API",
1105 glow::DEBUG_SOURCE_WINDOW_SYSTEM => "Window System",
1106 glow::DEBUG_SOURCE_SHADER_COMPILER => "ShaderCompiler",
1107 glow::DEBUG_SOURCE_THIRD_PARTY => "Third Party",
1108 glow::DEBUG_SOURCE_APPLICATION => "Application",
1109 glow::DEBUG_SOURCE_OTHER => "Other",
1110 _ => unreachable!(),
1111 };
1112
1113 let log_severity = match severity {
1114 glow::DEBUG_SEVERITY_HIGH => log::Level::Error,
1115 glow::DEBUG_SEVERITY_MEDIUM => log::Level::Warn,
1116 glow::DEBUG_SEVERITY_LOW => log::Level::Info,
1117 glow::DEBUG_SEVERITY_NOTIFICATION => log::Level::Trace,
1118 _ => unreachable!(),
1119 };
1120
1121 let type_str = match gltype {
1122 glow::DEBUG_TYPE_DEPRECATED_BEHAVIOR => "Deprecated Behavior",
1123 glow::DEBUG_TYPE_ERROR => "Error",
1124 glow::DEBUG_TYPE_MARKER => "Marker",
1125 glow::DEBUG_TYPE_OTHER => "Other",
1126 glow::DEBUG_TYPE_PERFORMANCE => "Performance",
1127 glow::DEBUG_TYPE_POP_GROUP => "Pop Group",
1128 glow::DEBUG_TYPE_PORTABILITY => "Portability",
1129 glow::DEBUG_TYPE_PUSH_GROUP => "Push Group",
1130 glow::DEBUG_TYPE_UNDEFINED_BEHAVIOR => "Undefined Behavior",
1131 _ => unreachable!(),
1132 };
1133
1134 let _ = std::panic::catch_unwind(|| {
1135 log::log!(
1136 log_severity,
1137 "GLES: [{}/{}] ID {} : {}",
1138 source_str,
1139 type_str,
1140 id,
1141 message
1142 );
1143 });
1144
1145 if cfg!(debug_assertions) && log_severity == log::Level::Error {
1146 crate::VALIDATION_CANARY.add(message.to_string());
1148 }
1149}