floem icon indicating copy to clipboard operation
floem copied to clipboard

Add initial wasm support

Open timsueberkrueb opened this issue 1 year ago • 1 comments

Add initial support to run floem applications on the web using WASM and WebGPU. This only works on browsers that support WebGPU. WebGL2 via wgpu does not work because vger-rs uses storage buffers in its shaders which is not supported on WebGL2. Haven't looked into whether tinyskia can be made to work on the web.

Before this PR can be merged, the following changes need to land in winit and cosmic-text first:

  • https://github.com/lapce/winit/pull/7
  • https://github.com/lapce/cosmic-text/pull/7

timsueberkrueb avatar Aug 03 '24 09:08 timsueberkrueb

cosmic-text is now changed to the upstream version which doesn't have stretto

dzhou121 avatar Aug 06 '24 22:08 dzhou121

Looks good to me now!

Although I tried to run webgpu example but my Chrome complains about the wgsl. Does it run properly for you?

dzhou121 avatar Aug 24 '24 19:08 dzhou121

Thanks for noticing, I can reproduce it. I had other problems with Chrome before, so I mostly tested on Firefox nightly (on Linux). I'll look into these.

Error while parsing WGSL: :506:18 error: integral user-defined vertex outputs must have a '@interpolate(flat)' attribute
    @location(0) prim_index: u32,
                 ^^^^^^^^^^

:528:1 note: while analyzing entry point 'vs_main'
fn vs_main(
^^^^^^^^^^^
    @builtin(vertex_index) vid: u32,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    @builtin(instance_index) instance: u32
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
) -> VertexOutput {
^^^^^^^^^^^^^^^^^^^
    var out: VertexOutput;
^^^^^^^^^^^^^^^^^^^^^^^^^^
    out.prim_index = instance;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


    let prim = prims.prims[instance];
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


    var q: vec2<f32>;
^^^^^^^^^^^^^^^^^^^^^
    switch(vid) {
^^^^^^^^^^^^^^^^^
        case 0u: {
^^^^^^^^^^^^^^^^^^
            q = prim.quad_bounds_min;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            //q = vec3<f32>(80.0, 80.0, 1.0); 
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            out.t = prim.tex_bounds_min;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        }
^^^^^^^^^
        case 1u: {
^^^^^^^^^^^^^^^^^^
            q = vec2<f32>(prim.quad_bounds_min.x, prim.quad_bounds_max.y);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            //q = vec3<f32>(80.0,120.0, 1.0); 
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            out.t = vec2<f32>(prim.tex_bounds_min.x, prim.tex_bounds_max.y);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        }
^^^^^^^^^
        case 2u: {
^^^^^^^^^^^^^^^^^^
            q = vec2<f32>(prim.quad_bounds_max.x, prim.quad_bounds_min.y);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            //q = vec3<f32>(120.0,80.0, 1.0); 
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            out.t = vec2<f32>(prim.tex_bounds_max.x, prim.tex_bounds_min.y);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        }
^^^^^^^^^
        case 3u: {
^^^^^^^^^^^^^^^^^^
            q = prim.quad_bounds_max;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            //q = vec3<f32>(120.0,120.0, 1.0); 
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            out.t = prim.tex_bounds_max;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        }
^^^^^^^^^
        default: { }
^^^^^^^^^^^^^^^^^^^^
    }
^^^^^


    out.p = (xforms.xforms[prim.xform] * vec4<f32>(q, 0.0, 1.0)).xy;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    out.position = vec4<f32>((2.0 * out.p / uniforms.size - 1.0) * vec2<f32>(1.0, -1.0), 0.0, 1.0);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    out.size = uniforms.atlas_size;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


    return out;
^^^^^^^^^^^^^^^
}
^


 - While validating [ShaderModuleDescriptor]
 - While calling [Device].CreateShaderModule([ShaderModuleDescriptor]).

127.0.0.1/:1 Compilation log for [Invalid ShaderModule (unlabeled)]:
1 error(s) generated while compiling the shader:
:506:18 error: integral user-defined vertex outputs must have a '@interpolate(flat)' attribute
    @location(0) prim_index: u32,
                 ^^^^^^^^^^

:528:1 note: while analyzing entry point 'vs_main'
fn vs_main(
^^^^^^^^^^^
    @builtin(vertex_index) vid: u32,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    @builtin(instance_index) instance: u32
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
) -> VertexOutput {
^^^^^^^^^^^^^^^^^^^
    var out: VertexOutput;
^^^^^^^^^^^^^^^^^^^^^^^^^^
    out.prim_index = instance;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


    let prim = prims.prims[instance];
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


    var q: vec2<f32>;
^^^^^^^^^^^^^^^^^^^^^
    switch(vid) {
^^^^^^^^^^^^^^^^^
        case 0u: {
^^^^^^^^^^^^^^^^^^
            q = prim.quad_bounds_min;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            //q = vec3<f32>(80.0, 80.0, 1.0); 
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            out.t = prim.tex_bounds_min;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        }
^^^^^^^^^
        case 1u: {
^^^^^^^^^^^^^^^^^^
            q = vec2<f32>(prim.quad_bounds_min.x, prim.quad_bounds_max.y);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            //q = vec3<f32>(80.0,120.0, 1.0); 
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            out.t = vec2<f32>(prim.tex_bounds_min.x, prim.tex_bounds_max.y);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        }
^^^^^^^^^
        case 2u: {
^^^^^^^^^^^^^^^^^^
            q = vec2<f32>(prim.quad_bounds_max.x, prim.quad_bounds_min.y);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            //q = vec3<f32>(120.0,80.0, 1.0); 
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            out.t = vec2<f32>(prim.tex_bounds_max.x, prim.tex_bounds_min.y);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        }
^^^^^^^^^
        case 3u: {
^^^^^^^^^^^^^^^^^^
            q = prim.quad_bounds_max;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            //q = vec3<f32>(120.0,120.0, 1.0); 
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            out.t = prim.tex_bounds_max;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        }
^^^^^^^^^
        default: { }
^^^^^^^^^^^^^^^^^^^^
    }
^^^^^


    out.p = (xforms.xforms[prim.xform] * vec4<f32>(q, 0.0, 1.0)).xy;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    out.position = vec4<f32>((2.0 * out.p / uniforms.size - 1.0) * vec2<f32>(1.0, -1.0), 0.0, 1.0);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    out.size = uniforms.atlas_size;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


    return out;
^^^^^^^^^^^^^^^
}
^

127.0.0.1/:1 [Invalid ShaderModule (unlabeled)] is invalid.
 - While validating vertex stage ([Invalid ShaderModule (unlabeled)], entryPoint: vs_main).
 - While validating vertex state.
 - While calling [Device].CreateRenderPipeline([RenderPipelineDescriptor]).

148[Invalid RenderPipeline (unlabeled)] is invalid.
 - While encoding [RenderPassEncoder (unlabeled)].SetPipeline([Invalid RenderPipeline (unlabeled)]).

148[Invalid CommandBuffer "vger encoder" from CommandEncoder "vger encoder"] is invalid.
 - While calling [Queue].Submit([[Invalid CommandBuffer "vger encoder" from CommandEncoder "vger encoder"]])

timsueberkrueb avatar Aug 24 '24 20:08 timsueberkrueb

https://github.com/lapce/vger-rs/pull/16 fixes this problem for me.

timsueberkrueb avatar Aug 25 '24 11:08 timsueberkrueb

Few things I would like to point out:

  • [ ] Requires new floem-vger-rs release
  • [ ] Requires new floem-winit release
  • [ ] Example adds font files to the repository. Is this okay? Otherwise we can try to find another means to load these fonts (e.g. from some CDN).

timsueberkrueb avatar Aug 25 '24 11:08 timsueberkrueb