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