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