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