hal/gles: resource binding

This commit is contained in:
Dzmitry Malyshau
2021-06-25 01:36:21 -04:00
committed by Dzmitry Malyshau
parent 91df157462
commit 673ec60396
5 changed files with 170 additions and 29 deletions

View File

@@ -9,6 +9,12 @@ bitflags::bitflags! {
}
}
#[derive(Clone, Copy, Debug, Default)]
struct TextureSlotDesc {
tex_target: super::BindTarget,
sampler_index: Option<u8>,
}
#[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<glow::Sampler>; 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<super::Api> for super::CommandEncoder {
@@ -405,14 +454,74 @@ impl crate::CommandEncoder<super::Api> 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<super::Api> 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<super::Api> 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<super::Api> 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<super::Api> 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]) {

View File

@@ -595,16 +595,9 @@ impl crate::Device<super::Api> 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<super::Api> for super::Device {
}
Ok(super::BindGroup {
layout_entries: Arc::clone(&desc.layout.entries),
contents: contents.into_boxed_slice(),
})
}

View File

@@ -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<super::Api> 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<super::Api> for Surface {
unsafe fn acquire_texture(
&mut self,
timeout_ms: u32,
_timeout_ms: u32, //TODO
) -> Result<Option<crate::AcquiredSurfaceTexture<super::Api>>, 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) {}
}

View File

@@ -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<u32>,
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<u32>),
PushDebugGroup(Range<u32>),
PopDebugGroup,

View File

@@ -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(