mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
hal/gles: resource binding
This commit is contained in:
committed by
Dzmitry Malyshau
parent
91df157462
commit
673ec60396
@@ -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]) {
|
||||
|
||||
@@ -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(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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) {}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user