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