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