Skip to content

Commit

Permalink
hal/gles: support externally initialized contexts
Browse files Browse the repository at this point in the history
kvark committed Jan 4, 2022

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent 43f09fd commit 75b885b
Showing 9 changed files with 502 additions and 178 deletions.
134 changes: 134 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 9 additions & 1 deletion wgpu-hal/Cargo.toml
Original file line number Diff line number Diff line change
@@ -19,6 +19,13 @@ gles = ["naga/glsl-out", "glow", "egl", "libloading"]
dx12 = ["naga/hlsl-out", "native", "bit-set", "range-alloc", "winapi/d3d12", "winapi/d3d12shader", "winapi/d3d12sdklayers", "winapi/dxgi1_6"]
renderdoc = ["libloading", "renderdoc-sys"]

[[example]]
name = "halmark"

[[example]]
name = "raw-gles"
required-features = ["gles"]

[dependencies]
bitflags = "1.0"
parking_lot = "0.11"
@@ -86,4 +93,5 @@ features = ["wgsl-in"]

[dev-dependencies]
env_logger = "0.8"
winit = "0.26"
winit = "0.26" # for "halmark" example
glutin = "0.28" # for "gles" example
2 changes: 2 additions & 0 deletions wgpu-hal/examples/halmark/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//! This example shows basic usage of wgpu-hal by rendering
//! a ton of moving sprites, each with a separate texture and draw call.
extern crate wgpu_hal as hal;

use hal::{
118 changes: 118 additions & 0 deletions wgpu-hal/examples/raw-gles.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
//! This example shows interop with raw GLES contexts -
//! the ability to hook up wgpu-hal to an existing context and draw into it.
extern crate wgpu_hal as hal;
use hal::{Adapter as _, CommandEncoder as _, Device as _, Queue as _};

fn main() {
env_logger::init();
println!("Initializing external GL context");

let event_loop = glutin::event_loop::EventLoop::new();
let window_builder = glutin::window::WindowBuilder::new();
let gl_context = unsafe {
glutin::ContextBuilder::new()
.with_gl(glutin::GlRequest::Specific(glutin::Api::OpenGlEs, (3, 0)))
.build_windowed(window_builder, &event_loop)
.unwrap()
.make_current()
.unwrap()
};
let inner_size = gl_context.window().inner_size();

println!("Hooking up to wgpu-hal");
let exposed = unsafe {
<hal::api::Gles as hal::Api>::Adapter::new_external(|name| {
gl_context.get_proc_address(name)
})
}
.expect("GL adapter can't be initialized");
let mut od = unsafe {
exposed
.adapter
.open(wgt::Features::empty(), &wgt::Limits::downlevel_defaults())
}
.unwrap();

let format = wgt::TextureFormat::Rgba8UnormSrgb;
let texture = <hal::api::Gles as hal::Api>::Texture::default_framebuffer(format);
let view = unsafe {
od.device
.create_texture_view(
&texture,
&hal::TextureViewDescriptor {
label: None,
format,
dimension: wgt::TextureViewDimension::D2,
usage: hal::TextureUses::COLOR_TARGET,
range: wgt::ImageSubresourceRange::default(),
},
)
.unwrap()
};

println!("Filling the screen");
let mut encoder = unsafe {
od.device
.create_command_encoder(&hal::CommandEncoderDescriptor {
label: None,
queue: &od.queue,
})
.unwrap()
};
let rp_desc = hal::RenderPassDescriptor {
label: None,
extent: wgt::Extent3d {
width: inner_size.width,
height: inner_size.height,
depth_or_array_layers: 1,
},
sample_count: 1,
color_attachments: &[hal::ColorAttachment {
target: hal::Attachment {
view: &view,
usage: hal::TextureUses::COLOR_TARGET,
},
resolve_target: None,
ops: hal::AttachmentOps::STORE,
clear_value: wgt::Color::BLUE,
}],
depth_stencil_attachment: None,
multiview: None,
};
unsafe {
encoder.begin_encoding(None).unwrap();
encoder.begin_render_pass(&rp_desc);
encoder.end_render_pass();
let cmd_buf = encoder.end_encoding().unwrap();
od.queue.submit(&[&cmd_buf], None).unwrap();
}

println!("Showing the window");
gl_context.swap_buffers().unwrap();

event_loop.run(move |event, _, control_flow| {
use glutin::{
event::{Event, KeyboardInput, VirtualKeyCode, WindowEvent},
event_loop::ControlFlow,
};
*control_flow = ControlFlow::Wait;

match event {
Event::LoopDestroyed => return,
Event::WindowEvent { event, .. } => match event {
WindowEvent::CloseRequested
| WindowEvent::KeyboardInput {
input:
KeyboardInput {
virtual_keycode: Some(VirtualKeyCode::Escape),
..
},
..
} => *control_flow = ControlFlow::Exit,
_ => (),
},
_ => (),
}
});
}
106 changes: 62 additions & 44 deletions wgpu-hal/src/gles/command.rs
Original file line number Diff line number Diff line change
@@ -386,54 +386,72 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
self.state.has_pass_label = true;
}

// set the framebuffer
self.cmd_buffer.commands.push(C::ResetFramebuffer);
for (i, cat) in desc.color_attachments.iter().enumerate() {
let attachment = glow::COLOR_ATTACHMENT0 + i as u32;
self.cmd_buffer.commands.push(C::BindAttachment {
attachment,
view: cat.target.view.clone(),
});
if let Some(ref rat) = cat.resolve_target {
self.state
.resolve_attachments
.push((attachment, rat.view.clone()));
}
if !cat.ops.contains(crate::AttachmentOps::STORE) {
self.state.invalidate_attachments.push(attachment);
}
}
if let Some(ref dsat) = desc.depth_stencil_attachment {
let aspects = dsat.target.view.aspects;
let attachment = match aspects {
crate::FormatAspects::DEPTH => glow::DEPTH_ATTACHMENT,
crate::FormatAspects::STENCIL => glow::STENCIL_ATTACHMENT,
_ => glow::DEPTH_STENCIL_ATTACHMENT,
};
self.cmd_buffer.commands.push(C::BindAttachment {
attachment,
view: dsat.target.view.clone(),
});
if aspects.contains(crate::FormatAspects::DEPTH)
&& !dsat.depth_ops.contains(crate::AttachmentOps::STORE)
{
self.state
.invalidate_attachments
.push(glow::DEPTH_ATTACHMENT);
match desc
.color_attachments
.first()
.map(|at| &at.target.view.inner)
{
// default framebuffer (provided externally)
Some(&super::TextureInner::DefaultRenderbuffer) => {
self.cmd_buffer
.commands
.push(C::ResetFramebuffer { is_default: true });
}
if aspects.contains(crate::FormatAspects::STENCIL)
&& !dsat.stencil_ops.contains(crate::AttachmentOps::STORE)
{
self.state
.invalidate_attachments
.push(glow::STENCIL_ATTACHMENT);
_ => {
// set the framebuffer
self.cmd_buffer
.commands
.push(C::ResetFramebuffer { is_default: false });

for (i, cat) in desc.color_attachments.iter().enumerate() {
let attachment = glow::COLOR_ATTACHMENT0 + i as u32;
self.cmd_buffer.commands.push(C::BindAttachment {
attachment,
view: cat.target.view.clone(),
});
if let Some(ref rat) = cat.resolve_target {
self.state
.resolve_attachments
.push((attachment, rat.view.clone()));
}
if !cat.ops.contains(crate::AttachmentOps::STORE) {
self.state.invalidate_attachments.push(attachment);
}
}
if let Some(ref dsat) = desc.depth_stencil_attachment {
let aspects = dsat.target.view.aspects;
let attachment = match aspects {
crate::FormatAspects::DEPTH => glow::DEPTH_ATTACHMENT,
crate::FormatAspects::STENCIL => glow::STENCIL_ATTACHMENT,
_ => glow::DEPTH_STENCIL_ATTACHMENT,
};
self.cmd_buffer.commands.push(C::BindAttachment {
attachment,
view: dsat.target.view.clone(),
});
if aspects.contains(crate::FormatAspects::DEPTH)
&& !dsat.depth_ops.contains(crate::AttachmentOps::STORE)
{
self.state
.invalidate_attachments
.push(glow::DEPTH_ATTACHMENT);
}
if aspects.contains(crate::FormatAspects::STENCIL)
&& !dsat.stencil_ops.contains(crate::AttachmentOps::STORE)
{
self.state
.invalidate_attachments
.push(glow::STENCIL_ATTACHMENT);
}
}

// set the draw buffers and states
self.cmd_buffer
.commands
.push(C::SetDrawColorBuffers(desc.color_attachments.len() as u8));
}
}

// set the draw buffers and states
self.cmd_buffer
.commands
.push(C::SetDrawColorBuffers(desc.color_attachments.len() as u8));
let rect = crate::Rect {
x: 0,
y: 0,
50 changes: 19 additions & 31 deletions wgpu-hal/src/gles/device.rs
Original file line number Diff line number Diff line change
@@ -656,6 +656,7 @@ impl crate::Device<super::Api> for super::Device {
super::TextureInner::Renderbuffer { raw, .. } => {
gl.delete_renderbuffer(raw);
}
super::TextureInner::DefaultRenderbuffer => {}
super::TextureInner::Texture { raw, .. } => {
gl.delete_texture(raw);
}
@@ -889,14 +890,8 @@ impl crate::Device<super::Api> for super::Device {
log::error!("Unable to create a sampled texture binding for non-zero mipmap level or array layer.\n{}",
"This is an implementation problem of wgpu-hal/gles backend.")
}
match view.inner {
super::TextureInner::Renderbuffer { .. } => {
panic!("Unable to use a renderbuffer in a group")
}
super::TextureInner::Texture { raw, target } => {
super::RawBinding::Texture { raw, target }
}
}
let (raw, target) = view.inner.as_native();
super::RawBinding::Texture { raw, target }
}
wgt::BindingType::StorageTexture {
access,
@@ -905,24 +900,18 @@ impl crate::Device<super::Api> for super::Device {
} => {
let view = desc.textures[entry.resource_index as usize].view;
let format_desc = self.shared.describe_texture_format(format);
match view.inner {
super::TextureInner::Renderbuffer { .. } => {
panic!("Unable to use a renderbuffer in a group")
}
super::TextureInner::Texture { raw, .. } => {
super::RawBinding::Image(super::ImageBinding {
raw,
mip_level: view.mip_levels.start,
array_layer: match view_dimension {
wgt::TextureViewDimension::D2Array
| wgt::TextureViewDimension::CubeArray => None,
_ => Some(view.array_layers.start),
},
access: conv::map_storage_access(access),
format: format_desc.internal,
})
}
}
let (raw, _target) = view.inner.as_native();
super::RawBinding::Image(super::ImageBinding {
raw,
mip_level: view.mip_levels.start,
array_layer: match view_dimension {
wgt::TextureViewDimension::D2Array
| wgt::TextureViewDimension::CubeArray => None,
_ => Some(view.array_layers.start),
},
access: conv::map_storage_access(access),
format: format_desc.internal,
})
}
};
contents.push(binding);
@@ -1133,11 +1122,10 @@ impl crate::Device<super::Api> for super::Device {

unsafe fn start_capture(&self) -> bool {
#[cfg(feature = "renderdoc")]
{
self.render_doc
.start_frame_capture(self.shared.context.egl_context.as_ptr(), ptr::null_mut())
}
#[cfg(not(feature = "renderdoc"))]
return self
.render_doc
.start_frame_capture(self.shared.context.raw_context(), ptr::null_mut());
#[allow(unreachable_code)]
false
}
unsafe fn stop_capture(&self) {
203 changes: 115 additions & 88 deletions wgpu-hal/src/gles/egl.rs

Large diffs are not rendered by default.

28 changes: 26 additions & 2 deletions wgpu-hal/src/gles/mod.rs
Original file line number Diff line number Diff line change
@@ -230,6 +230,7 @@ enum TextureInner {
Renderbuffer {
raw: glow::Renderbuffer,
},
DefaultRenderbuffer,
Texture {
raw: glow::Texture,
target: BindTarget,
@@ -239,7 +240,7 @@ enum TextureInner {
impl TextureInner {
fn as_native(&self) -> (glow::Texture, BindTarget) {
match *self {
Self::Renderbuffer { .. } => {
Self::Renderbuffer { .. } | Self::DefaultRenderbuffer => {
panic!("Unexpected renderbuffer");
}
Self::Texture { raw, target } => (raw, target),
@@ -258,6 +259,27 @@ pub struct Texture {
copy_size: crate::CopyExtent,
}

impl Texture {
pub fn default_framebuffer(format: wgt::TextureFormat) -> Self {
Self {
inner: TextureInner::DefaultRenderbuffer,
mip_level_count: 1,
array_layer_count: 1,
format,
format_desc: TextureFormatDesc {
internal: 0,
external: 0,
data_type: 0,
},
copy_size: crate::CopyExtent {
width: 0,
height: 0,
depth: 0,
},
}
}
}

#[derive(Clone, Debug)]
pub struct TextureView {
inner: TextureInner,
@@ -612,7 +634,9 @@ enum Command {
dst_target: BindTarget,
dst_offset: wgt::BufferAddress,
},
ResetFramebuffer,
ResetFramebuffer {
is_default: bool,
},
BindAttachment {
attachment: u32,
view: TextureView,
29 changes: 17 additions & 12 deletions wgpu-hal/src/gles/queue.rs
Original file line number Diff line number Diff line change
@@ -82,6 +82,7 @@ impl super::Queue {
super::TextureInner::Renderbuffer { raw } => {
gl.framebuffer_renderbuffer(fbo_target, attachment, glow::RENDERBUFFER, Some(raw));
}
super::TextureInner::DefaultRenderbuffer => panic!("Unexpected default RBO"),
super::TextureInner::Texture { raw, target } => {
if is_layered_target(target) {
gl.framebuffer_texture_layer(
@@ -636,24 +637,28 @@ impl super::Queue {
}
}
}
C::ResetFramebuffer => {
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;
C::ResetFramebuffer { is_default } => {
if is_default {
gl.bind_framebuffer(glow::DRAW_FRAMEBUFFER, None);
} else {
gl.bind_framebuffer(glow::DRAW_FRAMEBUFFER, Some(self.draw_fbo));
gl.framebuffer_texture_2d(
glow::DRAW_FRAMEBUFFER,
target,
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);

0 comments on commit 75b885b

Please sign in to comment.