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