1#[cfg(not(any(windows, webgl)))]
86mod egl;
87#[cfg(Emscripten)]
88mod emscripten;
89#[cfg(webgl)]
90mod web;
91#[cfg(windows)]
92mod wgl;
93
94mod adapter;
95mod command;
96mod conv;
97mod device;
98mod fence;
99mod queue;
100
101pub use fence::Fence;
102
103#[cfg(not(any(windows, webgl)))]
104pub use self::egl::{AdapterContext, AdapterContextLock};
105#[cfg(not(any(windows, webgl)))]
106use self::egl::{Instance, Surface};
107
108#[cfg(webgl)]
109pub use self::web::AdapterContext;
110#[cfg(webgl)]
111use self::web::{Instance, Surface};
112
113#[cfg(windows)]
114use self::wgl::AdapterContext;
115#[cfg(windows)]
116use self::wgl::{Instance, Surface};
117
118use alloc::{boxed::Box, string::String, string::ToString as _, sync::Arc, vec::Vec};
119use core::{
120 fmt,
121 ops::Range,
122 sync::atomic::{AtomicU32, AtomicU8},
123};
124use parking_lot::Mutex;
125
126use arrayvec::ArrayVec;
127use glow::HasContext;
128use naga::FastHashMap;
129
130use crate::{CopyExtent, TextureDescriptor};
131
132#[derive(Clone, Debug)]
133pub struct Api;
134
135const MAX_TEXTURE_SLOTS: usize = 16;
138const MAX_SAMPLERS: usize = 16;
139const MAX_VERTEX_ATTRIBUTES: usize = 16;
140const ZERO_BUFFER_SIZE: usize = 256 << 10;
141const MAX_PUSH_CONSTANTS: usize = 64;
142const MAX_PUSH_CONSTANT_COMMANDS: usize = MAX_PUSH_CONSTANTS * crate::MAX_CONCURRENT_SHADER_STAGES;
144
145impl crate::Api for Api {
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 {
372 inner: web_sys::WebGlFramebuffer,
373 },
374}
375
376#[cfg(send_sync)]
377unsafe impl Sync for TextureInner {}
378#[cfg(send_sync)]
379unsafe impl Send for TextureInner {}
380
381impl TextureInner {
382 fn as_native(&self) -> (glow::Texture, BindTarget) {
383 match *self {
384 Self::Renderbuffer { .. } | Self::DefaultRenderbuffer => {
385 panic!("Unexpected renderbuffer");
386 }
387 Self::Texture { raw, target } => (raw, target),
388 #[cfg(webgl)]
389 Self::ExternalFramebuffer { .. } => panic!("Unexpected external framebuffer"),
390 }
391 }
392}
393
394#[derive(Debug)]
395pub struct Texture {
396 pub inner: TextureInner,
397 pub drop_guard: Option<crate::DropGuard>,
398 pub mip_level_count: u32,
399 pub array_layer_count: u32,
400 pub format: wgt::TextureFormat,
401 #[allow(unused)]
402 pub format_desc: TextureFormatDesc,
403 pub copy_size: CopyExtent,
404}
405
406impl crate::DynTexture for Texture {}
407impl crate::DynSurfaceTexture for Texture {}
408
409impl core::borrow::Borrow<dyn crate::DynTexture> for Texture {
410 fn borrow(&self) -> &dyn crate::DynTexture {
411 self
412 }
413}
414
415impl Texture {
416 pub fn default_framebuffer(format: wgt::TextureFormat) -> Self {
417 Self {
418 inner: TextureInner::DefaultRenderbuffer,
419 drop_guard: None,
420 mip_level_count: 1,
421 array_layer_count: 1,
422 format,
423 format_desc: TextureFormatDesc {
424 internal: 0,
425 external: 0,
426 data_type: 0,
427 },
428 copy_size: CopyExtent {
429 width: 0,
430 height: 0,
431 depth: 0,
432 },
433 }
434 }
435
436 fn get_info_from_desc(desc: &TextureDescriptor) -> u32 {
438 match desc.dimension {
439 wgt::TextureDimension::D1 => glow::TEXTURE_2D,
442 wgt::TextureDimension::D2 => {
443 match (desc.is_cube_compatible(), desc.size.depth_or_array_layers) {
445 (false, 1) => glow::TEXTURE_2D,
446 (false, _) => glow::TEXTURE_2D_ARRAY,
447 (true, 6) => glow::TEXTURE_CUBE_MAP,
448 (true, _) => glow::TEXTURE_CUBE_MAP_ARRAY,
449 }
450 }
451 wgt::TextureDimension::D3 => glow::TEXTURE_3D,
452 }
453 }
454
455 fn log_failing_target_heuristics(view_dimension: wgt::TextureViewDimension, target: u32) {
457 let expected_target = match view_dimension {
458 wgt::TextureViewDimension::D1 => glow::TEXTURE_2D,
459 wgt::TextureViewDimension::D2 => glow::TEXTURE_2D,
460 wgt::TextureViewDimension::D2Array => glow::TEXTURE_2D_ARRAY,
461 wgt::TextureViewDimension::Cube => glow::TEXTURE_CUBE_MAP,
462 wgt::TextureViewDimension::CubeArray => glow::TEXTURE_CUBE_MAP_ARRAY,
463 wgt::TextureViewDimension::D3 => glow::TEXTURE_3D,
464 };
465
466 if expected_target == target {
467 return;
468 }
469
470 let buffer;
471 let got = match target {
472 glow::TEXTURE_2D => "D2",
473 glow::TEXTURE_2D_ARRAY => "D2Array",
474 glow::TEXTURE_CUBE_MAP => "Cube",
475 glow::TEXTURE_CUBE_MAP_ARRAY => "CubeArray",
476 glow::TEXTURE_3D => "D3",
477 target => {
478 buffer = target.to_string();
479 &buffer
480 }
481 };
482
483 log::error!(
484 concat!(
485 "wgpu-hal heuristics assumed that ",
486 "the view dimension will be equal to `{}` rather than `{:?}`.\n",
487 "`D2` textures with ",
488 "`depth_or_array_layers == 1` ",
489 "are assumed to have view dimension `D2`\n",
490 "`D2` textures with ",
491 "`depth_or_array_layers > 1` ",
492 "are assumed to have view dimension `D2Array`\n",
493 "`D2` textures with ",
494 "`depth_or_array_layers == 6` ",
495 "are assumed to have view dimension `Cube`\n",
496 "`D2` textures with ",
497 "`depth_or_array_layers > 6 && depth_or_array_layers % 6 == 0` ",
498 "are assumed to have view dimension `CubeArray`\n",
499 ),
500 got,
501 view_dimension,
502 );
503 }
504}
505
506#[derive(Clone, Debug)]
507pub struct TextureView {
508 inner: TextureInner,
509 aspects: crate::FormatAspects,
510 mip_levels: Range<u32>,
511 array_layers: Range<u32>,
512 format: wgt::TextureFormat,
513}
514
515impl crate::DynTextureView for TextureView {}
516
517#[derive(Debug)]
518pub struct Sampler {
519 raw: glow::Sampler,
520}
521
522impl crate::DynSampler for Sampler {}
523
524#[derive(Debug)]
525pub struct BindGroupLayout {
526 entries: Arc<[wgt::BindGroupLayoutEntry]>,
527}
528
529impl crate::DynBindGroupLayout for BindGroupLayout {}
530
531#[derive(Debug)]
532struct BindGroupLayoutInfo {
533 entries: Arc<[wgt::BindGroupLayoutEntry]>,
534 binding_to_slot: Box<[u8]>,
540}
541
542#[derive(Debug)]
543pub struct PipelineLayout {
544 group_infos: Box<[BindGroupLayoutInfo]>,
545 naga_options: naga::back::glsl::Options,
546}
547
548impl crate::DynPipelineLayout for PipelineLayout {}
549
550impl PipelineLayout {
551 fn get_slot(&self, br: &naga::ResourceBinding) -> u8 {
552 let group_info = &self.group_infos[br.group as usize];
553 group_info.binding_to_slot[br.binding as usize]
554 }
555}
556
557#[derive(Debug)]
558enum BindingRegister {
559 UniformBuffers,
560 StorageBuffers,
561 Textures,
562 Images,
563}
564
565#[derive(Debug)]
566enum RawBinding {
567 Buffer {
568 raw: glow::Buffer,
569 offset: i32,
570 size: i32,
571 },
572 Texture {
573 raw: glow::Texture,
574 target: BindTarget,
575 aspects: crate::FormatAspects,
576 mip_levels: Range<u32>,
577 },
579 Image(ImageBinding),
580 Sampler(glow::Sampler),
581}
582
583#[derive(Debug)]
584pub struct BindGroup {
585 contents: Box<[RawBinding]>,
586}
587
588impl crate::DynBindGroup for BindGroup {}
589
590type ShaderId = u32;
591
592#[derive(Debug)]
593pub struct ShaderModule {
594 naga: crate::NagaShader,
595 label: Option<String>,
596 id: ShaderId,
597}
598
599impl crate::DynShaderModule for ShaderModule {}
600
601#[derive(Clone, Debug, Default)]
602struct VertexFormatDesc {
603 element_count: i32,
604 element_format: u32,
605 attrib_kind: VertexAttribKind,
606}
607
608#[derive(Clone, Debug, Default)]
609struct AttributeDesc {
610 location: u32,
611 offset: u32,
612 buffer_index: u32,
613 format_desc: VertexFormatDesc,
614}
615
616#[derive(Clone, Debug)]
617struct BufferBinding {
618 raw: glow::Buffer,
619 offset: wgt::BufferAddress,
620}
621
622#[derive(Clone, Debug)]
623struct ImageBinding {
624 raw: glow::Texture,
625 mip_level: u32,
626 array_layer: Option<u32>,
627 access: u32,
628 format: u32,
629}
630
631#[derive(Clone, Debug, Default, PartialEq)]
632struct VertexBufferDesc {
633 step: wgt::VertexStepMode,
634 stride: u32,
635}
636
637#[derive(Clone, Debug)]
638struct PushConstantDesc {
639 location: glow::UniformLocation,
640 ty: naga::TypeInner,
641 offset: u32,
642 size_bytes: u32,
643}
644
645#[cfg(send_sync)]
646unsafe impl Sync for PushConstantDesc {}
647#[cfg(send_sync)]
648unsafe impl Send for PushConstantDesc {}
649
650type SamplerBindMap = [Option<u8>; MAX_TEXTURE_SLOTS];
653
654#[derive(Debug)]
655struct PipelineInner {
656 program: glow::Program,
657 sampler_map: SamplerBindMap,
658 first_instance_location: Option<glow::UniformLocation>,
659 push_constant_descs: ArrayVec<PushConstantDesc, MAX_PUSH_CONSTANT_COMMANDS>,
660}
661
662#[derive(Clone, Debug)]
663struct DepthState {
664 function: u32,
665 mask: bool,
666}
667
668#[derive(Clone, Debug, PartialEq)]
669struct BlendComponent {
670 src: u32,
671 dst: u32,
672 equation: u32,
673}
674
675#[derive(Clone, Debug, PartialEq)]
676struct BlendDesc {
677 alpha: BlendComponent,
678 color: BlendComponent,
679}
680
681#[derive(Clone, Debug, Default, PartialEq)]
682struct ColorTargetDesc {
683 mask: wgt::ColorWrites,
684 blend: Option<BlendDesc>,
685}
686
687#[derive(PartialEq, Eq, Hash)]
688struct ProgramStage {
689 naga_stage: naga::ShaderStage,
690 shader_id: ShaderId,
691 entry_point: String,
692 zero_initialize_workgroup_memory: bool,
693}
694
695#[derive(PartialEq, Eq, Hash)]
696struct ProgramCacheKey {
697 stages: ArrayVec<ProgramStage, 3>,
698 group_to_binding_to_slot: Box<[Box<[u8]>]>,
699}
700
701type ProgramCache = FastHashMap<ProgramCacheKey, Result<Arc<PipelineInner>, crate::PipelineError>>;
702
703#[derive(Debug)]
704pub struct RenderPipeline {
705 inner: Arc<PipelineInner>,
706 primitive: wgt::PrimitiveState,
707 vertex_buffers: Box<[VertexBufferDesc]>,
708 vertex_attributes: Box<[AttributeDesc]>,
709 color_targets: Box<[ColorTargetDesc]>,
710 depth: Option<DepthState>,
711 depth_bias: wgt::DepthBiasState,
712 stencil: Option<StencilState>,
713 alpha_to_coverage_enabled: bool,
714}
715
716impl crate::DynRenderPipeline for RenderPipeline {}
717
718#[cfg(send_sync)]
719unsafe impl Sync for RenderPipeline {}
720#[cfg(send_sync)]
721unsafe impl Send for RenderPipeline {}
722
723#[derive(Debug)]
724pub struct ComputePipeline {
725 inner: Arc<PipelineInner>,
726}
727
728impl crate::DynComputePipeline for ComputePipeline {}
729
730#[cfg(send_sync)]
731unsafe impl Sync for ComputePipeline {}
732#[cfg(send_sync)]
733unsafe impl Send for ComputePipeline {}
734
735#[derive(Debug)]
736pub struct QuerySet {
737 queries: Box<[glow::Query]>,
738 target: BindTarget,
739}
740
741impl crate::DynQuerySet for QuerySet {}
742
743#[derive(Debug)]
744pub struct AccelerationStructure;
745
746impl crate::DynAccelerationStructure for AccelerationStructure {}
747
748#[derive(Debug)]
749pub struct PipelineCache;
750
751impl crate::DynPipelineCache for PipelineCache {}
752
753#[derive(Clone, Debug, PartialEq)]
754struct StencilOps {
755 pass: u32,
756 fail: u32,
757 depth_fail: u32,
758}
759
760impl Default for StencilOps {
761 fn default() -> Self {
762 Self {
763 pass: glow::KEEP,
764 fail: glow::KEEP,
765 depth_fail: glow::KEEP,
766 }
767 }
768}
769
770#[derive(Clone, Debug, PartialEq)]
771struct StencilSide {
772 function: u32,
773 mask_read: u32,
774 mask_write: u32,
775 reference: u32,
776 ops: StencilOps,
777}
778
779impl Default for StencilSide {
780 fn default() -> Self {
781 Self {
782 function: glow::ALWAYS,
783 mask_read: 0xFF,
784 mask_write: 0xFF,
785 reference: 0,
786 ops: StencilOps::default(),
787 }
788 }
789}
790
791#[derive(Debug, Clone, Default)]
792struct StencilState {
793 front: StencilSide,
794 back: StencilSide,
795}
796
797#[derive(Clone, Debug, Default, PartialEq)]
798struct PrimitiveState {
799 front_face: u32,
800 cull_face: u32,
801 unclipped_depth: bool,
802 polygon_mode: u32,
803}
804
805type InvalidatedAttachments = ArrayVec<u32, { crate::MAX_COLOR_ATTACHMENTS + 2 }>;
806
807#[derive(Debug)]
808enum Command {
809 Draw {
810 topology: u32,
811 first_vertex: u32,
812 vertex_count: u32,
813 first_instance: u32,
814 instance_count: u32,
815 first_instance_location: Option<glow::UniformLocation>,
816 },
817 DrawIndexed {
818 topology: u32,
819 index_type: u32,
820 index_count: u32,
821 index_offset: wgt::BufferAddress,
822 base_vertex: i32,
823 first_instance: u32,
824 instance_count: u32,
825 first_instance_location: Option<glow::UniformLocation>,
826 },
827 DrawIndirect {
828 topology: u32,
829 indirect_buf: glow::Buffer,
830 indirect_offset: wgt::BufferAddress,
831 first_instance_location: Option<glow::UniformLocation>,
832 },
833 DrawIndexedIndirect {
834 topology: u32,
835 index_type: u32,
836 indirect_buf: glow::Buffer,
837 indirect_offset: wgt::BufferAddress,
838 first_instance_location: Option<glow::UniformLocation>,
839 },
840 Dispatch([u32; 3]),
841 DispatchIndirect {
842 indirect_buf: glow::Buffer,
843 indirect_offset: wgt::BufferAddress,
844 },
845 ClearBuffer {
846 dst: Buffer,
847 dst_target: BindTarget,
848 range: crate::MemoryRange,
849 },
850 CopyBufferToBuffer {
851 src: Buffer,
852 src_target: BindTarget,
853 dst: Buffer,
854 dst_target: BindTarget,
855 copy: crate::BufferCopy,
856 },
857 #[cfg(webgl)]
858 CopyExternalImageToTexture {
859 src: wgt::CopyExternalImageSourceInfo,
860 dst: glow::Texture,
861 dst_target: BindTarget,
862 dst_format: wgt::TextureFormat,
863 dst_premultiplication: bool,
864 copy: crate::TextureCopy,
865 },
866 CopyTextureToTexture {
867 src: glow::Texture,
868 src_target: BindTarget,
869 dst: glow::Texture,
870 dst_target: BindTarget,
871 copy: crate::TextureCopy,
872 },
873 CopyBufferToTexture {
874 src: Buffer,
875 #[allow(unused)]
876 src_target: BindTarget,
877 dst: glow::Texture,
878 dst_target: BindTarget,
879 dst_format: wgt::TextureFormat,
880 copy: crate::BufferTextureCopy,
881 },
882 CopyTextureToBuffer {
883 src: glow::Texture,
884 src_target: BindTarget,
885 src_format: wgt::TextureFormat,
886 dst: Buffer,
887 #[allow(unused)]
888 dst_target: BindTarget,
889 copy: crate::BufferTextureCopy,
890 },
891 SetIndexBuffer(glow::Buffer),
892 BeginQuery(glow::Query, BindTarget),
893 EndQuery(BindTarget),
894 TimestampQuery(glow::Query),
895 CopyQueryResults {
896 query_range: Range<u32>,
897 dst: Buffer,
898 dst_target: BindTarget,
899 dst_offset: wgt::BufferAddress,
900 },
901 ResetFramebuffer {
902 is_default: bool,
903 },
904 BindAttachment {
905 attachment: u32,
906 view: TextureView,
907 },
908 ResolveAttachment {
909 attachment: u32,
910 dst: TextureView,
911 size: wgt::Extent3d,
912 },
913 InvalidateAttachments(InvalidatedAttachments),
914 SetDrawColorBuffers(u8),
915 ClearColorF {
916 draw_buffer: u32,
917 color: [f32; 4],
918 is_srgb: bool,
919 },
920 ClearColorU(u32, [u32; 4]),
921 ClearColorI(u32, [i32; 4]),
922 ClearDepth(f32),
923 ClearStencil(u32),
924 ClearDepthAndStencil(f32, u32),
929 BufferBarrier(glow::Buffer, wgt::BufferUses),
930 TextureBarrier(wgt::TextureUses),
931 SetViewport {
932 rect: crate::Rect<i32>,
933 depth: Range<f32>,
934 },
935 SetScissor(crate::Rect<i32>),
936 SetStencilFunc {
937 face: u32,
938 function: u32,
939 reference: u32,
940 read_mask: u32,
941 },
942 SetStencilOps {
943 face: u32,
944 write_mask: u32,
945 ops: StencilOps,
946 },
947 SetDepth(DepthState),
948 SetDepthBias(wgt::DepthBiasState),
949 ConfigureDepthStencil(crate::FormatAspects),
950 SetAlphaToCoverage(bool),
951 SetVertexAttribute {
952 buffer: Option<glow::Buffer>,
953 buffer_desc: VertexBufferDesc,
954 attribute_desc: AttributeDesc,
955 },
956 UnsetVertexAttribute(u32),
957 SetVertexBuffer {
958 index: u32,
959 buffer: BufferBinding,
960 buffer_desc: VertexBufferDesc,
961 },
962 SetProgram(glow::Program),
963 SetPrimitive(PrimitiveState),
964 SetBlendConstant([f32; 4]),
965 SetColorTarget {
966 draw_buffer_index: Option<u32>,
967 desc: ColorTargetDesc,
968 },
969 BindBuffer {
970 target: BindTarget,
971 slot: u32,
972 buffer: glow::Buffer,
973 offset: i32,
974 size: i32,
975 },
976 BindSampler(u32, Option<glow::Sampler>),
977 BindTexture {
978 slot: u32,
979 texture: glow::Texture,
980 target: BindTarget,
981 aspects: crate::FormatAspects,
982 mip_levels: Range<u32>,
983 },
984 BindImage {
985 slot: u32,
986 binding: ImageBinding,
987 },
988 InsertDebugMarker(Range<u32>),
989 PushDebugGroup(Range<u32>),
990 PopDebugGroup,
991 SetPushConstants {
992 uniform: PushConstantDesc,
993 offset: u32,
995 },
996}
997
998#[derive(Default)]
999pub struct CommandBuffer {
1000 label: Option<String>,
1001 commands: Vec<Command>,
1002 data_bytes: Vec<u8>,
1003 queries: Vec<glow::Query>,
1004}
1005
1006impl crate::DynCommandBuffer for CommandBuffer {}
1007
1008impl fmt::Debug for CommandBuffer {
1009 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1010 let mut builder = f.debug_struct("CommandBuffer");
1011 if let Some(ref label) = self.label {
1012 builder.field("label", label);
1013 }
1014 builder.finish()
1015 }
1016}
1017
1018#[cfg(send_sync)]
1019unsafe impl Sync for CommandBuffer {}
1020#[cfg(send_sync)]
1021unsafe impl Send for CommandBuffer {}
1022
1023pub struct CommandEncoder {
1028 cmd_buffer: CommandBuffer,
1029 state: command::State,
1030 private_caps: PrivateCapabilities,
1031 counters: Arc<wgt::HalCounters>,
1032}
1033
1034impl fmt::Debug for CommandEncoder {
1035 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1036 f.debug_struct("CommandEncoder")
1037 .field("cmd_buffer", &self.cmd_buffer)
1038 .finish()
1039 }
1040}
1041
1042#[cfg(send_sync)]
1043unsafe impl Sync for CommandEncoder {}
1044#[cfg(send_sync)]
1045unsafe impl Send for CommandEncoder {}
1046
1047#[cfg(not(webgl))]
1048fn gl_debug_message_callback(source: u32, gltype: u32, id: u32, severity: u32, message: &str) {
1049 let source_str = match source {
1050 glow::DEBUG_SOURCE_API => "API",
1051 glow::DEBUG_SOURCE_WINDOW_SYSTEM => "Window System",
1052 glow::DEBUG_SOURCE_SHADER_COMPILER => "ShaderCompiler",
1053 glow::DEBUG_SOURCE_THIRD_PARTY => "Third Party",
1054 glow::DEBUG_SOURCE_APPLICATION => "Application",
1055 glow::DEBUG_SOURCE_OTHER => "Other",
1056 _ => unreachable!(),
1057 };
1058
1059 let log_severity = match severity {
1060 glow::DEBUG_SEVERITY_HIGH => log::Level::Error,
1061 glow::DEBUG_SEVERITY_MEDIUM => log::Level::Warn,
1062 glow::DEBUG_SEVERITY_LOW => log::Level::Info,
1063 glow::DEBUG_SEVERITY_NOTIFICATION => log::Level::Trace,
1064 _ => unreachable!(),
1065 };
1066
1067 let type_str = match gltype {
1068 glow::DEBUG_TYPE_DEPRECATED_BEHAVIOR => "Deprecated Behavior",
1069 glow::DEBUG_TYPE_ERROR => "Error",
1070 glow::DEBUG_TYPE_MARKER => "Marker",
1071 glow::DEBUG_TYPE_OTHER => "Other",
1072 glow::DEBUG_TYPE_PERFORMANCE => "Performance",
1073 glow::DEBUG_TYPE_POP_GROUP => "Pop Group",
1074 glow::DEBUG_TYPE_PORTABILITY => "Portability",
1075 glow::DEBUG_TYPE_PUSH_GROUP => "Push Group",
1076 glow::DEBUG_TYPE_UNDEFINED_BEHAVIOR => "Undefined Behavior",
1077 _ => unreachable!(),
1078 };
1079
1080 let _ = std::panic::catch_unwind(|| {
1081 log::log!(
1082 log_severity,
1083 "GLES: [{}/{}] ID {} : {}",
1084 source_str,
1085 type_str,
1086 id,
1087 message
1088 );
1089 });
1090
1091 if cfg!(debug_assertions) && log_severity == log::Level::Error {
1092 crate::VALIDATION_CANARY.add(message.to_string());
1094 }
1095}
1096
1097cfg_if::cfg_if! {
1099 if #[cfg(gles_with_std)] {
1100 type MaybeMutex<T> = std::sync::Mutex<T>;
1101
1102 fn lock<T>(mutex: &MaybeMutex<T>) -> std::sync::MutexGuard<'_, T> {
1103 mutex.lock().unwrap()
1104 }
1105 } else {
1106 #[cfg(all(send_sync, not(feature = "fragile-send-sync-non-atomic-wasm")))]
1110 compile_error!("cannot provide non-fragile Send+Sync without std");
1111
1112 type MaybeMutex<T> = core::cell::RefCell<T>;
1113
1114 fn lock<T>(mutex: &MaybeMutex<T>) -> core::cell::RefMut<'_, T> {
1115 mutex.borrow_mut()
1116 }
1117 }
1118}