Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update egui to 0.30 and wgpu to 23.0.1 #159

Merged
merged 3 commits into from
Dec 21, 2024
Merged

Update egui to 0.30 and wgpu to 23.0.1 #159

merged 3 commits into from
Dec 21, 2024

Conversation

abey79
Copy link
Owner

@abey79 abey79 commented Dec 20, 2024

Includes a workaround for

This migration highlighted a major non-compliance in my use of webgpu, fixed in #160. See below for the associated saga.

@abey79
Copy link
Owner Author

abey79 commented Dec 20, 2024

Currently struggling with wgpu update: the line preview rendering doesn't display anything anymore. The other, simpler shaders still work correctly.

First finding: by slashing most of the logic of the vertex shader, I'm able to get some output (so presumably the shader itself is being executed and it's not a general setup issue).

Second finding: I'm getting a warning from Xcode on the metal translated shader after the update:
image

There was no such warning with wgpu 22.1.0.

This is the wgsl shader in repo: https://github.com/abey79/vsvg/blob/master/crates/vsvg-viewer/src/shaders/line.wgsl

Here is the shader translated by 22.1.0
Here is the shader translated by 23.0.1

Here is the diff:

--- /Users/hhip/Library/Application Support/JetBrains/RustRover2024.3/scratches/metal_shader_22.1.0.txt	2024-12-20 17:12:48
+++ /Users/hhip/Library/Application Support/JetBrains/RustRover2024.3/scratches/metal_shader_23.0.1.txt	2024-12-20 17:17:21
@@ -3,12 +3,6 @@
 #include <simd/simd.h>

 using metal::uint;
-struct DefaultConstructible {
-    template<typename T>
-    operator T() && {
-        return T {};
-    }
-};

 struct _mslBufferSizes {
     uint buffer_size15;
@@ -39,6 +33,15 @@
     metal::float2 m2_;
     float width;
 };
+metal::float2 unpackFloat32x2_(uint b0, uint b1, uint b2, uint b3, uint b4, uint b5, uint b6, uint b7) {
+    return metal::float2(as_type<float>(b3 << 24 | b2 << 16 | b1 << 8 | b0), as_type<float>(b7 << 24 | b6 << 16 | b5 << 8 | b4));
+}
+uint unpackUint32_(uint b0, uint b1, uint b2, uint b3) {
+    return (b3 << 24 | b2 << 16 | b1 << 8 | b0);
+}
+float unpackFloat32_(uint b0, uint b1, uint b2, uint b3) {
+    return as_type<float>(b3 << 24 | b2 << 16 | b1 << 8 | b0);
+}

 metal::float2 compute_miter(
     metal::float2 p0_,
@@ -69,14 +72,6 @@
     return metal::float4(static_cast<float>(color & 255u), static_cast<float>((color >> 8u) & 255u), static_cast<float>((color >> 16u) & 255u), static_cast<float>((color >> 24u) & 255u)) / metal::float4(255.0);
 }

-struct vs_mainInput {
-    metal::float2 p0_ [[attribute(0)]];
-    metal::float2 p1_ [[attribute(1)]];
-    metal::float2 p2_ [[attribute(2)]];
-    metal::float2 p3_ [[attribute(3)]];
-    uint color [[attribute(4)]];
-    float width [[attribute(5)]];
-};
 struct vs_mainOutput {
     metal::float4 position [[position]];
     metal::float2 tex_coords [[user(loc0), center_perspective]];
@@ -86,13 +81,35 @@
     metal::float2 m2_ [[user(loc4), flat]];
     float width [[user(loc5), flat]];
 };
+struct vb_15_type { metal::uchar data[8]; };
+struct vb_14_type { metal::uchar data[8]; };
 vertex vs_mainOutput vs_main(
-  vs_mainInput varyings [[stage_in]]
-, uint in_vertex_index [[vertex_id]]
+  uint in_vertex_index [[vertex_id]]
 , uint in_instance_index [[instance_id]]
 , constant CameraUniform& camera [[buffer(0)]]
+, const device vb_15_type* vb_15_in [[buffer(15)]]
+, const device vb_14_type* vb_14_in [[buffer(14)]]
+, constant _mslBufferSizes& _buffer_sizes [[buffer(1)]]
 ) {
-    const InstanceInput instance = { varyings.p0_, varyings.p1_, varyings.p2_, varyings.p3_, varyings.color, varyings.width };
+    metal::float2 p0_1 = {};
+    metal::float2 p1_1 = {};
+    metal::float2 p2_ = {};
+    metal::float2 p3_ = {};
+    if (in_instance_index < (_buffer_sizes.buffer_size15 / 8)) {
+        const vb_15_type vb_15_elem = vb_15_in[in_instance_index];
+        p0_1 = unpackFloat32x2_(vb_15_elem.data[0], vb_15_elem.data[1], vb_15_elem.data[2], vb_15_elem.data[3], vb_15_elem.data[4], vb_15_elem.data[5], vb_15_elem.data[6], vb_15_elem.data[7]);
+        p1_1 = unpackFloat32x2_(vb_15_elem.data[8], vb_15_elem.data[9], vb_15_elem.data[10], vb_15_elem.data[11], vb_15_elem.data[12], vb_15_elem.data[13], vb_15_elem.data[14], vb_15_elem.data[15]);
+        p2_ = unpackFloat32x2_(vb_15_elem.data[16], vb_15_elem.data[17], vb_15_elem.data[18], vb_15_elem.data[19], vb_15_elem.data[20], vb_15_elem.data[21], vb_15_elem.data[22], vb_15_elem.data[23]);
+        p3_ = unpackFloat32x2_(vb_15_elem.data[24], vb_15_elem.data[25], vb_15_elem.data[26], vb_15_elem.data[27], vb_15_elem.data[28], vb_15_elem.data[29], vb_15_elem.data[30], vb_15_elem.data[31]);
+    }
+    uint color_1 = {};
+    float width = {};
+    if (in_instance_index < (_buffer_sizes.buffer_size14 / 8)) {
+        const vb_14_type vb_14_elem = vb_14_in[in_instance_index];
+        color_1 = unpackUint32_(vb_14_elem.data[0], vb_14_elem.data[1], vb_14_elem.data[2], vb_14_elem.data[3]);
+        width = unpackFloat32_(vb_14_elem.data[4], vb_14_elem.data[5], vb_14_elem.data[6], vb_14_elem.data[7]);
+    }
+    const InstanceInput instance = { p0_1, p1_1, p2_, p3_, color_1, width };
     VertexOutput out = VertexOutput {};
     metal::float2 vertex_ = {};
     metal::float2 tex_coords = {};

Hypothesis: could my "overlapping" stride setup confuse wgpu? (Note the points_buffer_layout having a stride of a vertex, aka two f32, but attributes with 8xf32).

// key insight: the stride is one point, but we expose 4 points at once!
let points_buffer_layout = wgpu::VertexBufferLayout {
array_stride: mem::size_of::<Vertex>() as wgpu::BufferAddress,
step_mode: wgpu::VertexStepMode::Instance,
attributes: &vertex_attr_array![
0 => Float32x2,
1 => Float32x2,
2 => Float32x2,
3 => Float32x2,
],
};
let attributes_buffer_layout = wgpu::VertexBufferLayout {
array_stride: mem::size_of::<Attribute>() as wgpu::BufferAddress,
step_mode: wgpu::VertexStepMode::Instance,
attributes: &vertex_attr_array![
4 => Uint32,
5 => Float32,
],
};
let shader = render_objects
.device
.create_shader_module(include_wgsl!("../shaders/line.wgsl"));
let pipeline_layout =
render_objects
.device
.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: None,
bind_group_layouts: &[&render_objects.camera_bind_group_layout],
push_constant_ranges: &[],
});
// enable alpha blending
let target = ColorTargetState {
format: render_objects.target_format,
blend: Some(wgpu::BlendState {
color: wgpu::BlendComponent {
src_factor: wgpu::BlendFactor::SrcAlpha,
dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha,
operation: wgpu::BlendOperation::Add,
},
alpha: wgpu::BlendComponent {
src_factor: wgpu::BlendFactor::SrcAlpha,
dst_factor: wgpu::BlendFactor::DstAlpha,
operation: wgpu::BlendOperation::Add,
},
}),
write_mask: wgpu::ColorWrites::ALL,
};
let render_pipeline =
render_objects
.device
.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: Some("line pipeline"),
layout: Some(&pipeline_layout),
vertex: wgpu::VertexState {
module: &shader,
entry_point: "vs_main",
compilation_options: Default::default(),
buffers: &[points_buffer_layout, attributes_buffer_layout],
},
fragment: Some(wgpu::FragmentState {
module: &shader,
entry_point: "fs_main",
compilation_options: Default::default(),
targets: &[Some(target)],
}),
primitive: wgpu::PrimitiveState {
topology: PrimitiveTopology::TriangleStrip,
..Default::default()
},
depth_stencil: None,
multisample: wgpu::MultisampleState::default(),
multiview: None,
cache: None,
});

@cwfitzgerald
Copy link

Hypothesis: could my "overlapping" stride setup confuse wgpu?

Yes, absolutely - we switched metal over to vertex pull on metal, so something could be wrong with that.

@abey79
Copy link
Owner Author

abey79 commented Dec 20, 2024

Unclear if this is related, but a recent versions of chrome (131.0.6778.205) is extremely unhappy with my wgsl shader, regardless of the wgpu version. This can be observed directly with https://whisk.rs.

image

I'm 95% sure that this shader worked on WebGPU Chrome at least at some point.

@cwfitzgerald
Copy link

Nah I expect that to be different - our webgpu backend is mainly just passing through, unless you are using spirv/glsl shaders.

@abey79
Copy link
Owner Author

abey79 commented Dec 20, 2024

After fixing the easy errors as per above, I'm now getting this last error from Chrome:

image

Now this seems more relevant. It appears that the way I'm setting up my "sliding window" into the buffer is not compliant with (Chrome's view of) the spec.

edit: I mean "relevant" as "the same bit of shader code is seemingly troublesome in two wildly different code paths"

@abey79
Copy link
Owner Author

abey79 commented Dec 20, 2024

I'm very tempted to brute force this by quadrupling the buffer size, so I can use a "civilised" stride. This would at least be an interesting debugging experiment. I'll sleep on it.

@abey79
Copy link
Owner Author

abey79 commented Dec 21, 2024

The spec says my sliding window is not valid:

image

@abey79
Copy link
Owner Author

abey79 commented Dec 21, 2024

This is now solved by #160, which no longer use the weird stride (but instead binds the same buffer 4 times with offsets).

@abey79 abey79 added common Relates to multiple crates dependencies Change/update dependencies labels Dec 21, 2024
@abey79 abey79 merged commit cc44dbb into master Dec 21, 2024
10 checks passed
@abey79 abey79 deleted the egui-0.30.0 branch December 21, 2024 16:23
abey79 added a commit that referenced this pull request Dec 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
common Relates to multiple crates dependencies Change/update dependencies
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants