diff --git a/wgpu-hal/src/gles/command.rs b/wgpu-hal/src/gles/command.rs index 8d7423b94a..d23845e381 100644 --- a/wgpu-hal/src/gles/command.rs +++ b/wgpu-hal/src/gles/command.rs @@ -9,6 +9,12 @@ bitflags::bitflags! { } } +#[derive(Clone, Copy, Debug, Default)] +struct TextureSlotDesc { + tex_target: super::BindTarget, + sampler_index: Option, +} + #[derive(Default)] pub(super) struct State { topology: u32, @@ -19,6 +25,8 @@ pub(super) struct State { color_targets: ArrayVec<[super::ColorTargetDesc; crate::MAX_COLOR_TARGETS]>, stencil: super::StencilState, depth_bias: wgt::DepthBiasState, + samplers: [Option; super::MAX_SAMPLERS], + texture_slots: [TextureSlotDesc; super::MAX_TEXTURE_SLOTS], has_pass_label: bool, dirty: Dirty, } @@ -81,6 +89,22 @@ impl super::CommandEncoder { } } + fn rebind_sampler_states(&mut self, dirty_textures: u32, dirty_samplers: u32) { + for (texture_index, slot) in self.state.texture_slots.iter().enumerate() { + if let Some(sampler_index) = slot.sampler_index { + if dirty_textures & (1 << texture_index) != 0 + || dirty_samplers & (1 << sampler_index) != 0 + { + if let Some(sampler) = self.state.samplers[sampler_index as usize] { + self.cmd_buffer + .commands + .push(C::BindSampler(texture_index as u32, sampler)); + } + } + } + } + } + fn prepare_draw(&mut self, first_instance: u32) { if first_instance != 0 { self.rebind_vertex_attributes(first_instance); @@ -90,6 +114,31 @@ impl super::CommandEncoder { self.state.dirty.set(Dirty::VERTEX_BUFFERS, false); } } + + fn set_pipeline_inner(&mut self, inner: &super::PipelineInner) { + self.cmd_buffer.commands.push(C::SetProgram(inner.program)); + + //TODO: push constants + let _ = &inner.uniforms; + + // rebind textures, if needed + let mut dirty_textures = 0u32; + for (texture_index, (slot, &sampler_index)) in self + .state + .texture_slots + .iter_mut() + .zip(inner.sampler_map.iter()) + .enumerate() + { + if slot.sampler_index != sampler_index { + slot.sampler_index = sampler_index; + dirty_textures |= 1 << texture_index; + } + } + if dirty_textures != 0 { + self.rebind_sampler_states(dirty_textures, 0); + } + } } impl crate::CommandEncoder for super::CommandEncoder { @@ -405,14 +454,74 @@ impl crate::CommandEncoder for super::CommandEncoder { group: &super::BindGroup, dynamic_offsets: &[wgt::DynamicOffset], ) { + let mut do_index = 0; + let mut dirty_textures = 0u32; + let mut dirty_samplers = 0u32; + let group_info = &layout.group_infos[index as usize]; + + for (binding_layout, raw_binding) in group_info.entries.iter().zip(group.contents.iter()) { + let slot = group_info.binding_to_slot[binding_layout.binding as usize] as u32; + match *raw_binding { + super::RawBinding::Buffer { + raw, + offset: base_offset, + size, + } => { + let mut offset = base_offset; + let target = match binding_layout.ty { + wgt::BindingType::Buffer { + ty, + has_dynamic_offset, + min_binding_size: _, + } => { + if has_dynamic_offset { + offset += dynamic_offsets[do_index] as i32; + do_index += 1; + } + match ty { + wgt::BufferBindingType::Uniform => glow::UNIFORM_BUFFER, + wgt::BufferBindingType::Storage { .. } => { + glow::SHADER_STORAGE_BUFFER + } + } + } + _ => unreachable!(), + }; + self.cmd_buffer.commands.push(C::BindBuffer { + target, + slot, + buffer: raw, + offset, + size, + }); + } + super::RawBinding::Texture { raw, target } => { + dirty_textures |= 1 << slot; + self.state.texture_slots[slot as usize].tex_target = target; + self.cmd_buffer.commands.push(C::BindTexture { + slot, + texture: raw, + target, + }); + } + super::RawBinding::Sampler(sampler) => { + dirty_samplers |= 1 << slot; + self.state.samplers[slot as usize] = Some(sampler); + } + } + } + + self.rebind_sampler_states(dirty_textures, dirty_samplers); } + unsafe fn set_push_constants( &mut self, - layout: &super::PipelineLayout, - stages: wgt::ShaderStage, - offset: u32, - data: &[u32], + _layout: &super::PipelineLayout, + _stages: wgt::ShaderStage, + _offset: u32, + _data: &[u32], ) { + unimplemented!() } unsafe fn insert_debug_marker(&mut self, label: &str) { @@ -431,10 +540,9 @@ impl crate::CommandEncoder for super::CommandEncoder { self.state.topology = conv::map_primitive_topology(pipeline.primitive.topology); self.state.dirty |= Dirty::VERTEX_BUFFERS; - self.cmd_buffer - .commands - .push(C::SetProgram(pipeline.inner.program)); + self.set_pipeline_inner(&pipeline.inner); + // set vertex state self.state.vertex_attributes.clear(); for vat in pipeline.vertex_attributes.iter() { self.state.vertex_attributes.push(vat.clone()); @@ -449,6 +557,7 @@ impl crate::CommandEncoder for super::CommandEncoder { state_desc.stride = pipe_desc.stride; } + // set depth/stencil states let mut aspects = crate::FormatAspect::empty(); if pipeline.depth_bias != self.state.depth_bias { self.state.depth_bias = pipeline.depth_bias; @@ -489,6 +598,7 @@ impl crate::CommandEncoder for super::CommandEncoder { .commands .push(C::ConfigureDepthStencil(aspects)); + // set blend states if self.state.color_targets[..] != pipeline.color_targets[..] { if pipeline .color_targets @@ -686,9 +796,7 @@ impl crate::CommandEncoder for super::CommandEncoder { } unsafe fn set_compute_pipeline(&mut self, pipeline: &super::ComputePipeline) { - self.cmd_buffer - .commands - .push(C::SetProgram(pipeline.inner.program)); + self.set_pipeline_inner(&pipeline.inner); } unsafe fn dispatch(&mut self, count: [u32; 3]) { diff --git a/wgpu-hal/src/gles/device.rs b/wgpu-hal/src/gles/device.rs index 8da560e492..eae77c8879 100644 --- a/wgpu-hal/src/gles/device.rs +++ b/wgpu-hal/src/gles/device.rs @@ -595,16 +595,9 @@ impl crate::Device for super::Device { for (entry, layout) in desc.entries.iter().zip(desc.layout.entries.iter()) { let binding = match layout.ty { - wgt::BindingType::Buffer { ty, .. } => { + wgt::BindingType::Buffer { .. } => { let bb = &desc.buffers[entry.resource_index as usize]; - let register = match ty { - wgt::BufferBindingType::Uniform => super::BindingRegister::UniformBuffers, - wgt::BufferBindingType::Storage { .. } => { - super::BindingRegister::StorageBuffers - } - }; super::RawBinding::Buffer { - register, raw: bb.buffer.raw, offset: bb.offset as i32, size: match bb.size { @@ -632,7 +625,6 @@ impl crate::Device for super::Device { } Ok(super::BindGroup { - layout_entries: Arc::clone(&desc.layout.entries), contents: contents.into_boxed_slice(), }) } diff --git a/wgpu-hal/src/gles/egl.rs b/wgpu-hal/src/gles/egl.rs index f35693ea9e..35aad685d0 100644 --- a/wgpu-hal/src/gles/egl.rs +++ b/wgpu-hal/src/gles/egl.rs @@ -541,7 +541,8 @@ pub struct Swapchain { renderbuffer: glow::Renderbuffer, /// Extent because the window lies extent: wgt::Extent3d, - format: super::TextureFormat, + format: wgt::TextureFormat, + format_desc: super::TextureFormatDesc, sample_type: wgt::TextureSampleType, } @@ -657,7 +658,8 @@ impl crate::Surface for Surface { renderbuffer, framebuffer, extent: config.extent, - format: format_desc.internal, + format: config.format, + format_desc, sample_type: wgt::TextureSampleType::Float { filterable: false }, }); @@ -674,12 +676,20 @@ impl crate::Surface for Surface { unsafe fn acquire_texture( &mut self, - timeout_ms: u32, + _timeout_ms: u32, //TODO ) -> Result>, crate::SurfaceError> { let sc = self.swapchain.as_ref().unwrap(); - //let sc_image = - // native::SwapchainImage::new(sc.renderbuffer, sc.format, sc.extent, sc.channel); - Ok(None) + let texture = super::Texture { + inner: super::TextureInner::Renderbuffer { + raw: sc.renderbuffer, + }, + format: sc.format, + format_desc: sc.format_desc.clone(), + }; + Ok(Some(crate::AcquiredSurfaceTexture { + texture, + suboptimal: false, + })) } unsafe fn discard_texture(&mut self, _texture: super::Texture) {} } diff --git a/wgpu-hal/src/gles/mod.rs b/wgpu-hal/src/gles/mod.rs index 53dd24e8a1..88fc439477 100644 --- a/wgpu-hal/src/gles/mod.rs +++ b/wgpu-hal/src/gles/mod.rs @@ -20,6 +20,7 @@ pub struct Api; //Note: we can support more samplers if not every one of them is used at a time, // but it probably doesn't worth it. const MAX_TEXTURE_SLOTS: usize = 16; +const MAX_SAMPLERS: usize = 16; const MAX_VERTEX_ATTRIBUTES: usize = 16; impl crate::Api for Api { @@ -60,7 +61,6 @@ bitflags::bitflags! { } type BindTarget = u32; -type TextureFormat = u32; trait Sampled { unsafe fn set_param_float(&self, gl: &glow::Context, key: u32, value: f32); @@ -164,7 +164,7 @@ impl Default for VertexAttribKind { } } -#[derive(Debug)] +#[derive(Clone, Debug)] struct TextureFormatDesc { internal: u32, external: u32, @@ -278,7 +278,6 @@ enum BindingRegister { #[derive(Debug)] enum RawBinding { Buffer { - register: BindingRegister, raw: glow::Buffer, offset: i32, size: i32, @@ -292,7 +291,6 @@ enum RawBinding { #[derive(Debug)] pub struct BindGroup { - layout_entries: Arc<[wgt::BindGroupLayoutEntry]>, contents: Box<[RawBinding]>, } @@ -596,6 +594,19 @@ enum Command { draw_buffer_index: Option, desc: ColorTargetDesc, }, + BindBuffer { + target: BindTarget, + slot: u32, + buffer: glow::Buffer, + offset: i32, + size: i32, + }, + BindSampler(u32, glow::Sampler), + BindTexture { + slot: u32, + texture: glow::Texture, + target: BindTarget, + }, InsertDebugMarker(Range), PushDebugGroup(Range), PopDebugGroup, diff --git a/wgpu-hal/src/gles/queue.rs b/wgpu-hal/src/gles/queue.rs index 9f51204c53..58d13bd418 100644 --- a/wgpu-hal/src/gles/queue.rs +++ b/wgpu-hal/src/gles/queue.rs @@ -582,6 +582,26 @@ impl super::Queue { } } } + C::BindBuffer { + target, + slot, + buffer, + offset, + size, + } => { + gl.bind_buffer_range(target, slot, Some(buffer), offset, size); + } + C::BindSampler(texture_index, sampler) => { + gl.bind_sampler(texture_index, Some(sampler)); + } + C::BindTexture { + slot, + texture, + target, + } => { + gl.active_texture(glow::TEXTURE0 + slot); + gl.bind_texture(target, Some(texture)); + } C::InsertDebugMarker(ref range) => { let marker = extract_marker(data_bytes, range); gl.debug_message_insert(