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