mirror of
https://github.com/emilk/egui.git
synced 2026-09-01 22:30:03 -04:00
eframe support for wgpu on the web (#2107)
* basic working wgpu @ webgl on websys * fix glow compile error * introduced WebPainter trait, provide wgpu renderstate * WebPainterWgpu destroy implemented * make custom3d demo work on wgpu backend * changelog entry for wgpu support eframe wasm * remove temporary logging hack * stop using pollster for web we're actually not allowed to block - this only worked because wgpu on webgl doesn't actually cause anything blocking. However, when trying webgpu this became an issue * revert cargo update * compile error if neither glow nor wgpu features are enabled * code cleanup * Error handling * Update changelog with link * Make sure --all-features work * Select best framebuffer format from the available ones * update to wasm-bindgen 0.2.83 * Fix typo * Clean up Cargo.toml * Log about using the wgpu painter * fixup wgpu labels * fix custom3d_wgpu_shader ub padding * remove duplicated uniforms struct in wgsl shader for custom3d * Update docs: add async/await to the web 'start' function Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
use std::sync::Arc;
|
||||
use std::{num::NonZeroU64, sync::Arc};
|
||||
|
||||
use eframe::{
|
||||
egui_wgpu::{self, wgpu},
|
||||
@@ -18,32 +18,32 @@ impl Custom3d {
|
||||
let device = &wgpu_render_state.device;
|
||||
|
||||
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
|
||||
label: None,
|
||||
label: Some("custom3d"),
|
||||
source: wgpu::ShaderSource::Wgsl(include_str!("./custom3d_wgpu_shader.wgsl").into()),
|
||||
});
|
||||
|
||||
let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
label: None,
|
||||
label: Some("custom3d"),
|
||||
entries: &[wgpu::BindGroupLayoutEntry {
|
||||
binding: 0,
|
||||
visibility: wgpu::ShaderStages::VERTEX,
|
||||
ty: wgpu::BindingType::Buffer {
|
||||
ty: wgpu::BufferBindingType::Uniform,
|
||||
has_dynamic_offset: false,
|
||||
min_binding_size: None,
|
||||
min_binding_size: NonZeroU64::new(16),
|
||||
},
|
||||
count: None,
|
||||
}],
|
||||
});
|
||||
|
||||
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
label: None,
|
||||
label: Some("custom3d"),
|
||||
bind_group_layouts: &[&bind_group_layout],
|
||||
push_constant_ranges: &[],
|
||||
});
|
||||
|
||||
let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||
label: None,
|
||||
label: Some("custom3d"),
|
||||
layout: Some(&pipeline_layout),
|
||||
vertex: wgpu::VertexState {
|
||||
module: &shader,
|
||||
@@ -62,15 +62,15 @@ impl Custom3d {
|
||||
});
|
||||
|
||||
let uniform_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||
label: None,
|
||||
contents: bytemuck::cast_slice(&[0.0]),
|
||||
usage: wgpu::BufferUsages::COPY_DST
|
||||
| wgpu::BufferUsages::MAP_WRITE
|
||||
| wgpu::BufferUsages::UNIFORM,
|
||||
label: Some("custom3d"),
|
||||
contents: bytemuck::cast_slice(&[0.0_f32; 4]), // 16 bytes aligned!
|
||||
// Mapping at creation (as done by the create_buffer_init utility) doesn't require us to to add the MAP_WRITE usage
|
||||
// (this *happens* to workaround this bug )
|
||||
usage: wgpu::BufferUsages::COPY_DST | wgpu::BufferUsages::UNIFORM,
|
||||
});
|
||||
|
||||
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
label: None,
|
||||
label: Some("custom3d"),
|
||||
layout: &bind_group_layout,
|
||||
entries: &[wgpu::BindGroupEntry {
|
||||
binding: 0,
|
||||
@@ -165,7 +165,11 @@ struct TriangleRenderResources {
|
||||
impl TriangleRenderResources {
|
||||
fn prepare(&self, _device: &wgpu::Device, queue: &wgpu::Queue, angle: f32) {
|
||||
// Update our uniform buffer with the angle from the UI
|
||||
queue.write_buffer(&self.uniform_buffer, 0, bytemuck::cast_slice(&[angle]));
|
||||
queue.write_buffer(
|
||||
&self.uniform_buffer,
|
||||
0,
|
||||
bytemuck::cast_slice(&[angle, 0.0, 0.0, 0.0]),
|
||||
);
|
||||
}
|
||||
|
||||
fn paint<'rp>(&'rp self, render_pass: &mut wgpu::RenderPass<'rp>) {
|
||||
|
||||
@@ -4,7 +4,7 @@ struct VertexOut {
|
||||
};
|
||||
|
||||
struct Uniforms {
|
||||
angle: f32,
|
||||
@size(16) angle: f32, // pad to 16 bytes
|
||||
};
|
||||
|
||||
@group(0) @binding(0)
|
||||
|
||||
@@ -62,13 +62,14 @@ pub fn init_wasm_hooks() {
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[wasm_bindgen]
|
||||
pub fn start_separate(canvas_id: &str) -> Result<WebHandle, wasm_bindgen::JsValue> {
|
||||
pub async fn start_separate(canvas_id: &str) -> Result<WebHandle, wasm_bindgen::JsValue> {
|
||||
let web_options = eframe::WebOptions::default();
|
||||
let handle = eframe::start_web(
|
||||
canvas_id,
|
||||
web_options,
|
||||
Box::new(|cc| Box::new(WrapApp::new(cc))),
|
||||
)
|
||||
.await
|
||||
.map(|handle| WebHandle { handle });
|
||||
|
||||
handle
|
||||
@@ -80,7 +81,7 @@ pub fn start_separate(canvas_id: &str) -> Result<WebHandle, wasm_bindgen::JsValu
|
||||
/// You can add more callbacks like this if you want to call in to your code.
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[wasm_bindgen]
|
||||
pub fn start(canvas_id: &str) -> Result<WebHandle, wasm_bindgen::JsValue> {
|
||||
pub async fn start(canvas_id: &str) -> Result<WebHandle, wasm_bindgen::JsValue> {
|
||||
init_wasm_hooks();
|
||||
start_separate(canvas_id)
|
||||
start_separate(canvas_id).await
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user