hal/gles: render passes

This commit is contained in:
Dzmitry Malyshau 2021-06-24 01:22:38 -04:00 committed by Dzmitry Malyshau
parent 24ff58c6c1
commit 51dd90b1ab
13 changed files with 273 additions and 98 deletions

View File

@ -745,6 +745,8 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> {
let hal_desc = hal::RenderPassDescriptor {
label,
extent,
sample_count,
color_attachments: &colors,
depth_stencil_attachment: depth_stencil,
};

View File

@ -597,6 +597,12 @@ impl<A: hal::Api> Example<A> {
};
let pass_desc = hal::RenderPassDescriptor {
label: None,
extent: wgt::Extent3d {
width: self.extent[0],
height: self.extent[1],
depth_or_array_layers: 1,
},
sample_count: 1,
color_attachments: &[hal::ColorAttachment {
target: hal::Attachment {
view: &surface_tex_view,

View File

@ -284,7 +284,9 @@ impl crate::Adapter<super::Api> for super::Adapter {
let gl = &self.shared.context;
gl.pixel_store_i32(glow::UNPACK_ALIGNMENT, 1);
gl.pixel_store_i32(glow::PACK_ALIGNMENT, 1);
let main_vao = gl.create_vertex_array().unwrap();
let main_vao = gl
.create_vertex_array()
.map_err(|_| crate::DeviceError::OutOfMemory)?;
gl.bind_vertex_array(Some(main_vao));
Ok(crate::OpenDevice {
@ -294,7 +296,12 @@ impl crate::Adapter<super::Api> for super::Adapter {
},
queue: super::Queue {
shared: Arc::clone(&self.shared),
copy_fbo: gl.create_framebuffer().unwrap(),
draw_fbo: gl
.create_framebuffer()
.map_err(|_| crate::DeviceError::OutOfMemory)?,
copy_fbo: gl
.create_framebuffer()
.map_err(|_| crate::DeviceError::OutOfMemory)?,
temp_query_results: Vec::new(),
},
})

View File

@ -18,6 +18,7 @@ impl super::CommandBuffer {
impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
unsafe fn begin_encoding(&mut self, label: crate::Label) -> Result<(), crate::DeviceError> {
self.state = super::CommandState::default();
self.cmd_buffer.label = label.map(str::to_string);
Ok(())
}
@ -100,8 +101,9 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
) where
T: Iterator<Item = crate::BufferTextureCopy>,
{
let format_info = dst.format.describe();
assert_eq!(
dst.format_info.block_dimensions,
format_info.block_dimensions,
(1, 1),
"Compressed texture copies are TODO"
);
@ -115,7 +117,7 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
dst_info: super::TextureCopyInfo {
external_format: dst.format_desc.external,
data_type: dst.format_desc.data_type,
texel_size: dst.format_info.block_size,
texel_size: format_info.block_size,
},
copy,
})
@ -131,8 +133,9 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
) where
T: Iterator<Item = crate::BufferTextureCopy>,
{
let format_info = src.format.describe();
assert_eq!(
src.format_info.block_dimensions,
format_info.block_dimensions,
(1, 1),
"Compressed texture copies are TODO"
);
@ -144,7 +147,7 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
src_info: super::TextureCopyInfo {
external_format: src.format_desc.external,
data_type: src.format_desc.data_type,
texel_size: src.format_info.block_size,
texel_size: format_info.block_size,
},
dst: dst.raw,
dst_target: dst.target,
@ -190,8 +193,82 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
// render
unsafe fn begin_render_pass(&mut self, desc: &crate::RenderPassDescriptor<super::Api>) {}
unsafe fn end_render_pass(&mut self) {}
unsafe fn begin_render_pass(&mut self, desc: &crate::RenderPassDescriptor<super::Api>) {
if let Some(label) = desc.label {
let range = self.cmd_buffer.add_marker(label);
self.cmd_buffer.commands.push(C::PushDebugGroup(range));
self.state.has_pass_label = true;
}
// set the framebuffer
self.cmd_buffer
.commands
.push(C::ResetFramebuffer(desc.extent));
for (i, cat) in desc.color_attachments.iter().enumerate() {
let attachment = glow::COLOR_ATTACHMENT0 + i as u32;
self.cmd_buffer.commands.push(C::SetFramebufferAttachment {
attachment,
view: cat.target.view.clone(),
});
}
if let Some(ref dsat) = desc.depth_stencil_attachment {
let attachment = match dsat.target.view.aspects {
crate::FormatAspect::DEPTH => glow::DEPTH_ATTACHMENT,
crate::FormatAspect::STENCIL => glow::STENCIL_ATTACHMENT,
_ => glow::DEPTH_STENCIL_ATTACHMENT,
};
self.cmd_buffer.commands.push(C::SetFramebufferAttachment {
attachment,
view: dsat.target.view.clone(),
});
}
self.cmd_buffer
.commands
.push(C::SetDrawColorBuffers(desc.color_attachments.len() as u8));
// issue the clears
for (i, cat) in desc.color_attachments.iter().enumerate() {
if !cat.ops.contains(crate::AttachmentOp::LOAD) {
let draw_buffer = glow::DRAW_BUFFER0 + i as u32;
let c = &cat.clear_value;
self.cmd_buffer
.commands
.push(match cat.target.view.sample_type {
wgt::TextureSampleType::Float { .. } => C::ClearColorF(
draw_buffer,
[c.r as f32, c.g as f32, c.r as f32, c.a as f32],
),
wgt::TextureSampleType::Depth => unimplemented!(),
wgt::TextureSampleType::Uint => C::ClearColorU(
draw_buffer,
[c.r as u32, c.g as u32, c.r as u32, c.a as u32],
),
wgt::TextureSampleType::Sint => C::ClearColorI(
draw_buffer,
[c.r as i32, c.g as i32, c.r as i32, c.a as i32],
),
});
}
}
if let Some(ref dsat) = desc.depth_stencil_attachment {
if !dsat.depth_ops.contains(crate::AttachmentOp::LOAD) {
self.cmd_buffer
.commands
.push(C::ClearDepth(dsat.clear_value.0));
}
if !dsat.stencil_ops.contains(crate::AttachmentOp::LOAD) {
self.cmd_buffer
.commands
.push(C::ClearStencil(dsat.clear_value.1));
}
}
}
unsafe fn end_render_pass(&mut self) {
if self.state.has_pass_label {
self.cmd_buffer.commands.push(C::PopDebugGroup);
self.state.has_pass_label = false;
}
}
unsafe fn set_bind_group(
&mut self,
@ -346,8 +423,19 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
// compute
unsafe fn begin_compute_pass(&mut self, desc: &crate::ComputePassDescriptor) {}
unsafe fn end_compute_pass(&mut self) {}
unsafe fn begin_compute_pass(&mut self, desc: &crate::ComputePassDescriptor) {
if let Some(label) = desc.label {
let range = self.cmd_buffer.add_marker(label);
self.cmd_buffer.commands.push(C::PushDebugGroup(range));
self.state.has_pass_label = true;
}
}
unsafe fn end_compute_pass(&mut self) {
if self.state.has_pass_label {
self.cmd_buffer.commands.push(C::PopDebugGroup);
self.state.has_pass_label = false;
}
}
unsafe fn set_compute_pipeline(&mut self, pipeline: &super::ComputePipeline) {}

View File

@ -221,3 +221,14 @@ pub fn map_primitive_topology(topology: wgt::PrimitiveTopology) -> u32 {
Pt::TriangleStrip => glow::TRIANGLE_STRIP,
}
}
pub fn map_view_dimension(dim: wgt::TextureViewDimension) -> u32 {
use wgt::TextureViewDimension as Tvd;
match dim {
Tvd::D1 | Tvd::D2 => glow::TEXTURE_2D,
Tvd::D2Array => glow::TEXTURE_2D_ARRAY,
Tvd::Cube => glow::TEXTURE_CUBE_MAP,
Tvd::CubeArray => glow::TEXTURE_CUBE_MAP_ARRAY,
Tvd::D3 => glow::TEXTURE_3D,
}
}

View File

@ -113,8 +113,10 @@ impl super::Device {
};
let shader = &stage.module.naga;
let entry_point_index = (&shader.module.entry_points)
.into_iter()
let entry_point_index = shader
.module
.entry_points
.iter()
.position(|ep| ep.name.as_str() == stage.entry_point)
.ok_or(crate::PipelineError::EntryPoint(naga_stage))?;
@ -397,10 +399,7 @@ impl crate::Device<super::Api> for super::Device {
desc.size.height as i32,
);
}
super::TextureInner::Renderbuffer {
raw,
aspects: desc.format.into(),
}
super::TextureInner::Renderbuffer { raw }
} else {
let raw = gl.create_texture().unwrap();
let target = match desc.dimension {
@ -456,8 +455,8 @@ impl crate::Device<super::Api> for super::Device {
Ok(super::Texture {
inner,
format: desc.format,
format_desc,
format_info: desc.format.describe(),
})
}
unsafe fn destroy_texture(&self, texture: super::Texture) {
@ -477,18 +476,21 @@ impl crate::Device<super::Api> for super::Device {
texture: &super::Texture,
desc: &crate::TextureViewDescriptor,
) -> Result<super::TextureView, crate::DeviceError> {
Ok(match texture.inner {
super::TextureInner::Renderbuffer { raw, aspects } => {
super::TextureView::Renderbuffer {
raw,
aspects: aspects & crate::FormatAspect::from(desc.range.aspect),
Ok(super::TextureView {
inner: match texture.inner {
super::TextureInner::Renderbuffer { raw } => {
super::TextureInner::Renderbuffer { raw }
}
}
super::TextureInner::Texture { raw, target } => super::TextureView::Texture {
raw,
target,
range: desc.range.clone(),
super::TextureInner::Texture { raw, target: _ } => super::TextureInner::Texture {
raw,
target: conv::map_view_dimension(desc.dimension),
},
},
sample_type: texture.format.describe().sample_type,
aspects: crate::FormatAspect::from(texture.format)
& crate::FormatAspect::from(desc.range.aspect),
base_mip_level: desc.range.base_mip_level,
base_array_layer: desc.range.base_array_layer,
})
}
unsafe fn destroy_texture_view(&self, _view: super::TextureView) {}
@ -615,19 +617,13 @@ impl crate::Device<super::Api> for super::Device {
super::RawBinding::Sampler(sampler.raw)
}
wgt::BindingType::Texture { .. } | wgt::BindingType::StorageTexture { .. } => {
match *desc.textures[entry.resource_index as usize].view {
super::TextureView::Renderbuffer { .. } => {
match desc.textures[entry.resource_index as usize].view.inner {
super::TextureInner::Renderbuffer { .. } => {
panic!("Unable to use a renderbuffer in a group")
}
super::TextureView::Texture {
raw,
target,
ref range,
} => super::RawBinding::Texture {
raw,
target,
range: range.clone(),
},
super::TextureInner::Texture { raw, target } => {
super::RawBinding::Texture { raw, target }
}
}
}
};
@ -687,7 +683,7 @@ impl crate::Device<super::Api> for super::Device {
Ok(super::RenderPipeline {
inner,
primitive: desc.primitive.clone(),
primitive: desc.primitive,
attributes,
depth: desc.depth_stencil.clone(),
})

View File

@ -181,6 +181,7 @@ pub struct Device {
pub struct Queue {
shared: Arc<AdapterShared>,
draw_fbo: glow::Framebuffer,
copy_fbo: glow::Framebuffer,
temp_query_results: Vec<u64>,
}
@ -193,11 +194,10 @@ pub struct Buffer {
map_flags: u32,
}
#[derive(Debug)]
#[derive(Clone, Debug)]
enum TextureInner {
Renderbuffer {
raw: glow::Renderbuffer,
aspects: crate::FormatAspect,
},
Texture {
raw: glow::Texture,
@ -217,21 +217,17 @@ impl TextureInner {
#[derive(Debug)]
pub struct Texture {
inner: TextureInner,
format: wgt::TextureFormat,
format_desc: TextureFormatDesc,
format_info: wgt::TextureFormatInfo,
}
#[derive(Debug)]
pub enum TextureView {
Renderbuffer {
raw: glow::Renderbuffer,
aspects: crate::FormatAspect,
},
Texture {
raw: glow::Texture,
target: BindTarget,
range: wgt::ImageSubresourceRange,
},
#[derive(Clone, Debug)]
pub struct TextureView {
inner: TextureInner,
sample_type: wgt::TextureSampleType,
aspects: crate::FormatAspect,
base_mip_level: u32,
base_array_layer: u32,
}
#[derive(Debug)]
@ -283,7 +279,6 @@ enum RawBinding {
Texture {
raw: glow::Texture,
target: BindTarget,
range: wgt::ImageSubresourceRange,
},
Sampler(glow::Sampler),
}
@ -466,6 +461,17 @@ enum Command {
dst_target: BindTarget,
dst_offset: wgt::BufferAddress,
},
ResetFramebuffer(wgt::Extent3d),
SetFramebufferAttachment {
attachment: u32,
view: TextureView,
},
SetDrawColorBuffers(u8),
ClearColorF(u32, [f32; 4]),
ClearColorU(u32, [u32; 4]),
ClearColorI(u32, [i32; 4]),
ClearDepth(f32),
ClearStencil(u32),
InsertDebugMarker(Range<u32>),
PushDebugGroup(Range<u32>),
PopDebugGroup,
@ -484,6 +490,7 @@ struct CommandState {
topology: u32,
index_format: wgt::IndexFormat,
index_offset: wgt::BufferAddress,
has_pass_label: bool,
}
//TODO: we would have something like `Arc<typed_arena::Arena>`

View File

@ -1,4 +1,5 @@
use super::Command as C;
use arrayvec::ArrayVec;
use glow::HasContext;
use std::{mem, ops::Range, slice};
@ -291,6 +292,87 @@ impl super::Queue {
gl.bind_buffer(dst_target, Some(dst));
gl.buffer_sub_data_u8_slice(dst_target, dst_offset as i32, query_data);
}
C::ResetFramebuffer(extent) => {
gl.bind_framebuffer(glow::DRAW_FRAMEBUFFER, Some(self.draw_fbo));
gl.framebuffer_texture_2d(
glow::DRAW_FRAMEBUFFER,
glow::DEPTH_STENCIL_ATTACHMENT,
glow::TEXTURE_2D,
None,
0,
);
for i in 0..crate::MAX_COLOR_TARGETS {
let target = glow::COLOR_ATTACHMENT0 + i as u32;
gl.framebuffer_texture_2d(
glow::DRAW_FRAMEBUFFER,
target,
glow::TEXTURE_2D,
None,
0,
);
}
gl.color_mask(true, true, true, true);
gl.depth_mask(true);
gl.stencil_mask(!0);
gl.disable(glow::DEPTH_TEST);
gl.disable(glow::STENCIL_TEST);
gl.disable(glow::SCISSOR_TEST);
gl.scissor(0, 0, extent.width as i32, extent.height as i32);
gl.viewport(0, 0, extent.width as i32, extent.height as i32);
}
C::SetFramebufferAttachment {
attachment,
ref view,
} => match view.inner {
super::TextureInner::Renderbuffer { raw } => {
gl.framebuffer_renderbuffer(
glow::DRAW_FRAMEBUFFER,
attachment,
glow::RENDERBUFFER,
Some(raw),
);
}
super::TextureInner::Texture { raw, target } => {
if is_3d_target(target) {
gl.framebuffer_texture_layer(
glow::DRAW_FRAMEBUFFER,
attachment,
Some(raw),
view.base_mip_level as i32,
view.base_array_layer as i32,
);
} else {
gl.framebuffer_texture_2d(
glow::DRAW_FRAMEBUFFER,
attachment,
target,
Some(raw),
view.base_mip_level as i32,
);
}
}
},
C::SetDrawColorBuffers(count) => {
let indices = (0..count as u32)
.map(|i| glow::COLOR_ATTACHMENT0 + i)
.collect::<ArrayVec<[_; crate::MAX_COLOR_TARGETS]>>();
gl.draw_buffers(&indices);
}
C::ClearColorF(draw_buffer, mut color) => {
gl.clear_buffer_f32_slice(glow::COLOR, draw_buffer, &mut color);
}
C::ClearColorU(draw_buffer, mut color) => {
gl.clear_buffer_u32_slice(glow::COLOR, draw_buffer, &mut color);
}
C::ClearColorI(draw_buffer, mut color) => {
gl.clear_buffer_i32_slice(glow::COLOR, draw_buffer, &mut color);
}
C::ClearDepth(depth) => {
gl.clear_buffer_depth_stencil(glow::DEPTH, 0, depth, 0);
}
C::ClearStencil(value) => {
gl.clear_buffer_depth_stencil(glow::STENCIL, 0, 0.0, value as i32);
}
C::InsertDebugMarker(ref range) => {
let marker = extract_marker(data_bytes, range);
gl.debug_message_insert(

View File

@ -557,6 +557,8 @@ bitflags!(
}
);
//TODO: it's not intuitive for the backends to consider `LOAD` being optional.
bitflags!(
pub struct AttachmentOp: u8 {
const LOAD = 1;
@ -1067,6 +1069,8 @@ pub struct DepthStencilAttachment<'a, A: Api> {
#[derive(Clone, Debug)]
pub struct RenderPassDescriptor<'a, A: Api> {
pub label: Label<'a>,
pub extent: wgt::Extent3d,
pub sample_count: u32,
pub color_attachments: &'a [ColorAttachment<'a, A>],
pub depth_stencil_attachment: Option<DepthStencilAttachment<'a, A>>,
}

View File

@ -351,7 +351,11 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
let mut vk_clear_values = ArrayVec::<[vk::ClearValue; super::MAX_TOTAL_ATTACHMENTS]>::new();
let mut vk_image_views = ArrayVec::<[vk::ImageView; super::MAX_TOTAL_ATTACHMENTS]>::new();
let mut rp_key = super::RenderPassKey::default();
let mut fb_key = super::FramebufferKey::default();
let mut fb_key = super::FramebufferKey {
attachments: ArrayVec::default(),
extent: desc.extent,
sample_count: desc.sample_count,
};
let caps = &self.device.private_caps;
for cat in desc.color_attachments {
@ -366,11 +370,11 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
.as_ref()
.map(|target| target.make_attachment_key(crate::AttachmentOp::STORE, caps)),
});
fb_key.add(cat.target.view);
fb_key.attachments.push(cat.target.view.attachment.clone());
if let Some(ref at) = cat.resolve_target {
vk_clear_values.push(mem::zeroed());
vk_image_views.push(at.view.raw);
fb_key.add(at.view);
fb_key.attachments.push(at.view.attachment.clone());
}
}
if let Some(ref ds) = desc.depth_stencil_attachment {
@ -385,26 +389,26 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
base: ds.target.make_attachment_key(ds.depth_ops, caps),
stencil_ops: ds.stencil_ops,
});
fb_key.add(ds.target.view);
fb_key.attachments.push(ds.target.view.attachment.clone());
}
rp_key.sample_count = fb_key.sample_count;
let render_area = vk::Rect2D {
offset: vk::Offset2D { x: 0, y: 0 },
extent: vk::Extent2D {
width: fb_key.extent.width,
height: fb_key.extent.height,
width: desc.extent.width,
height: desc.extent.height,
},
};
let vk_viewports = [vk::Viewport {
x: 0.0,
y: if self.device.private_caps.flip_y_requires_shift {
fb_key.extent.height as f32
desc.extent.height as f32
} else {
0.0
},
width: fb_key.extent.width as f32,
height: -(fb_key.extent.height as f32),
width: desc.extent.width as f32,
height: -(desc.extent.height as f32),
min_depth: 0.0,
max_depth: 1.0,
}];

View File

@ -5,7 +5,7 @@ use ash::{extensions::khr, version::DeviceV1_0, vk};
use inplace_it::inplace_or_alloc_from_iter;
use parking_lot::Mutex;
use std::{borrow::Cow, cmp, collections::hash_map::Entry, ffi::CString, ptr, sync::Arc};
use std::{borrow::Cow, collections::hash_map::Entry, ffi::CString, ptr, sync::Arc};
impl super::DeviceShared {
pub(super) unsafe fn set_object_name(
@ -697,8 +697,6 @@ impl crate::Device<super::Api> for super::Device {
dim: desc.dimension,
aspects: crate::FormatAspect::from(desc.format),
format_info: desc.format.describe(),
sample_count: desc.sample_count,
size: desc.size,
raw_flags,
})
}
@ -746,19 +744,8 @@ impl crate::Device<super::Api> for super::Device {
raw_image_flags: texture.raw_flags,
view_format: desc.format,
};
let sample_count = texture.sample_count;
let render_size = wgt::Extent3d {
width: cmp::max(1, texture.size.width >> desc.range.base_mip_level),
height: cmp::max(1, texture.size.height >> desc.range.base_mip_level),
depth_or_array_layers: 1,
};
Ok(super::TextureView {
raw,
attachment,
sample_count,
render_size,
})
Ok(super::TextureView { raw, attachment })
}
unsafe fn destroy_texture_view(&self, view: super::TextureView) {
if !self.shared.private_caps.imageless_framebuffers {

View File

@ -638,8 +638,6 @@ impl crate::Surface<super::Api> for super::Surface {
dim: wgt::TextureDimension::D2,
aspects: crate::FormatAspect::COLOR,
format_info: sc.config.format.describe(),
sample_count: 1,
size: sc.config.extent,
raw_flags: vk::ImageCreateFlags::empty(),
},
};

View File

@ -181,26 +181,13 @@ struct FramebufferAttachment {
view_format: wgt::TextureFormat,
}
#[derive(Clone, Eq, Default, Hash, PartialEq)]
#[derive(Clone, Eq, Hash, PartialEq)]
struct FramebufferKey {
attachments: ArrayVec<[FramebufferAttachment; MAX_TOTAL_ATTACHMENTS]>,
extent: wgt::Extent3d,
sample_count: u32,
}
impl FramebufferKey {
fn add(&mut self, view: &TextureView) {
self.extent.width = self.extent.width.max(view.render_size.width);
self.extent.height = self.extent.height.max(view.render_size.height);
self.extent.depth_or_array_layers = self
.extent
.depth_or_array_layers
.max(view.render_size.depth_or_array_layers);
self.sample_count = self.sample_count.max(view.sample_count);
self.attachments.push(view.attachment.clone());
}
}
struct DeviceShared {
raw: ash::Device,
instance: Arc<InstanceShared>,
@ -243,8 +230,6 @@ pub struct Texture {
dim: wgt::TextureDimension,
aspects: crate::FormatAspect,
format_info: wgt::TextureFormatInfo,
sample_count: u32,
size: wgt::Extent3d,
raw_flags: vk::ImageCreateFlags,
}
@ -252,8 +237,6 @@ pub struct Texture {
pub struct TextureView {
raw: vk::ImageView,
attachment: FramebufferAttachment,
sample_count: u32,
render_size: wgt::Extent3d,
}
impl TextureView {