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