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