hecrj / wgpu_glyph

A fast text renderer for wgpu (https://github.com/gfx-rs/wgpu)
https://docs.rs/wgpu_glyph
MIT License
441 stars 77 forks source link

Glyph rendering issues with GL backend #61

Closed Anton-4 closed 3 years ago

Anton-4 commented 3 years ago

I have modified the hello.rs example to display a decreasing counter that is updated every frame. Where the numbers are different compared to the first frame I get the following artifacts: Selection_010

The numbers are rendered as expected when using the vulkan backend for wgpu. I can also run the opengl example in glyph_brush without artifacts.

I would greatly appreciate any advice that can help me narrow down the cause of this problem.

Here is source code of my modified hello.rs:

use std::error::Error;
use wgpu_glyph::{ab_glyph, GlyphBrushBuilder, Section, Text};

fn main() -> Result<(), Box<dyn Error>> {
    env_logger::init();

    // Open window and create a surface
    let event_loop = winit::event_loop::EventLoop::new();

    let window = winit::window::WindowBuilder::new()
        .with_resizable(false)
        .build(&event_loop)
        .unwrap();

    let instance = wgpu::Instance::new(wgpu::BackendBit::GL);
    let surface = unsafe { instance.create_surface(&window) };

    // Initialize GPU
    let (device, queue) = futures::executor::block_on(async {
        let adapter = instance
            .request_adapter(&wgpu::RequestAdapterOptions {
                power_preference: wgpu::PowerPreference::HighPerformance,
                compatible_surface: Some(&surface),
            })
            .await
            .expect("Request adapter");

        adapter
            .request_device(&wgpu::DeviceDescriptor::default(), None)
            .await
            .expect("Request device")
    });

    // Create staging belt and a local pool
    let mut staging_belt = wgpu::util::StagingBelt::new(1024);
    let mut local_pool = futures::executor::LocalPool::new();
    let local_spawner = local_pool.spawner();

    // Prepare swap chain
    let render_format = wgpu::TextureFormat::Bgra8UnormSrgb;
    let mut size = window.inner_size();

    let mut swap_chain = device.create_swap_chain(
        &surface,
        &wgpu::SwapChainDescriptor {
            usage: wgpu::TextureUsage::RENDER_ATTACHMENT,
            format: render_format,
            width: size.width,
            height: size.height,
            present_mode: wgpu::PresentMode::Mailbox,
        },
    );

    // Prepare glyph_brush
    let inconsolata = ab_glyph::FontArc::try_from_slice(include_bytes!(
        "Inconsolata-Regular.ttf"
    ))?;

    let mut counter: usize = 9876543210;

    let mut glyph_brush = GlyphBrushBuilder::using_font(inconsolata)
        .build(&device, render_format);

    // Render loop
    window.request_redraw();

    event_loop.run(move |event, _, control_flow| {

        *control_flow = winit::event_loop::ControlFlow::Poll;

        match event {
            winit::event::Event::WindowEvent {
                event: winit::event::WindowEvent::CloseRequested,
                ..
            } => *control_flow = winit::event_loop::ControlFlow::Exit,
            winit::event::Event::WindowEvent {
                event: winit::event::WindowEvent::Resized(new_size),
                ..
            } => {
                size = new_size;

                swap_chain = device.create_swap_chain(
                    &surface,
                    &wgpu::SwapChainDescriptor {
                        usage: wgpu::TextureUsage::RENDER_ATTACHMENT,
                        format: render_format,
                        width: size.width,
                        height: size.height,
                        present_mode: wgpu::PresentMode::Mailbox,
                    },
                );
            }
            winit::event::Event::RedrawRequested { .. } => {
                counter -= 1;
                // Get a command encoder for the current frame
                let mut encoder = device.create_command_encoder(
                    &wgpu::CommandEncoderDescriptor {
                        label: Some("Redraw"),
                    },
                );

                // Get the next frame
                let frame = swap_chain
                    .get_current_frame()
                    .expect("Get next frame")
                    .output;

                // Clear frame
                {
                    let _ = encoder.begin_render_pass(
                        &wgpu::RenderPassDescriptor {
                            label: Some("Render pass"),
                            color_attachments: &[
                                wgpu::RenderPassColorAttachmentDescriptor {
                                    attachment: &frame.view,
                                    resolve_target: None,
                                    ops: wgpu::Operations {
                                        load: wgpu::LoadOp::Clear(
                                            wgpu::Color {
                                                r: 0.4,
                                                g: 0.4,
                                                b: 0.4,
                                                a: 1.0,
                                            },
                                        ),
                                        store: true,
                                    },
                                },
                            ],
                            depth_stencil_attachment: None,
                        },
                    );
                }

                glyph_brush.queue(Section {
                    screen_position: (30.0, 30.0),
                    bounds: (size.width as f32, size.height as f32),
                    text: vec![Text::new(&counter.to_string())
                        .with_color([0.0, 0.0, 0.0, 1.0])
                        .with_scale(40.0)],
                    ..Section::default()
                });

                glyph_brush.queue(Section {
                    screen_position: (30.0, 90.0),
                    bounds: (size.width as f32, size.height as f32),
                    text: vec![Text::new("Hello wgpu_glyph!")
                        .with_color([1.0, 1.0, 1.0, 1.0])
                        .with_scale(40.0)],
                    ..Section::default()
                });

                // Draw the text!
                glyph_brush
                    .draw_queued(
                        &device,
                        &mut staging_belt,
                        &mut encoder,
                        &frame.view,
                        size.width,
                        size.height,
                    )
                    .expect("Draw queued");

                // Submit the work!
                staging_belt.finish();
                queue.submit(Some(encoder.finish()));

                // Recall unused staging buffers
                use futures::task::SpawnExt;

                local_spawner
                    .spawn(staging_belt.recall())
                    .expect("Recall staging belt");

                local_pool.run_until_stalled();
            }
            winit::event::Event::MainEventsCleared => window.request_redraw(),
            _ => {
            }
        }
    })
}

Here is the log at the info level:

    Finished dev [unoptimized + debuginfo] target(s) in 0.04s
     Running `target/debug/examples/hello`
[2021-04-06T15:16:29Z INFO  winit::platform_impl::platform::x11::window] Guessed window scale factor: 1.25
[2021-04-06T15:16:29Z INFO  gfx_backend_gl::window::egl] Client extensions: "EGL_EXT_platform_base EGL_EXT_device_base EGL_EXT_device_enumeration EGL_EXT_device_query EGL_KHR_client_get_all_proc_addresses EGL_EXT_client_extensions EGL_KHR_debug EGL_KHR_platform_x11 EGL_EXT_platform_x11 EGL_EXT_platform_device EGL_EXT_platform_wayland EGL_KHR_platform_wayland EGL_MESA_platform_gbm EGL_KHR_platform_gbm EGL_MESA_platform_surfaceless"
[2021-04-06T15:16:29Z INFO  gfx_backend_gl::window::egl] Loading Wayland library to get the current display
[2021-04-06T15:16:29Z INFO  gfx_backend_gl::window::egl] Loading X11 library to get the current display
[2021-04-06T15:16:29Z INFO  gfx_backend_gl::window::egl] Using X11 platform
[2021-04-06T15:16:29Z INFO  gfx_backend_gl::window::egl] Display vendor "NVIDIA", version (1, 5), extensions: "EGL_EXT_buffer_age EGL_EXT_client_sync EGL_EXT_create_context_robustness EGL_EXT_image_dma_buf_import EGL_EXT_image_dma_buf_import_modifiers EGL_MESA_image_dma_buf_export EGL_EXT_output_base EGL_EXT_stream_acquire_mode EGL_EXT_sync_reuse EGL_IMG_context_priority EGL_KHR_config_attribs EGL_KHR_create_context_no_error EGL_KHR_context_flush_control EGL_KHR_create_context EGL_KHR_fence_sync EGL_KHR_get_all_proc_addresses EGL_KHR_partial_update EGL_KHR_swap_buffers_with_damage EGL_KHR_no_config_context EGL_KHR_gl_colorspace EGL_KHR_gl_renderbuffer_image EGL_KHR_gl_texture_2D_image EGL_KHR_gl_texture_3D_image EGL_KHR_gl_texture_cubemap_image EGL_KHR_image EGL_KHR_image_base EGL_KHR_image_pixmap EGL_KHR_reusable_sync EGL_KHR_stream EGL_KHR_stream_attrib EGL_KHR_stream_consumer_gltexture EGL_KHR_stream_cross_process_fd EGL_KHR_stream_fifo EGL_KHR_stream_producer_eglsurface EGL_KHR_surfaceless_context EGL_KHR_wait_sync EGL_NV_nvrm_fence_sync EGL_NV_post_sub_buffer EGL_NV_quadruple_buffer EGL_NV_stream_consumer_eglimage EGL_NV_stream_cross_display EGL_NV_stream_cross_object EGL_NV_stream_cross_process EGL_NV_stream_cross_system EGL_NV_stream_dma EGL_NV_stream_flush EGL_NV_stream_metadata EGL_NV_stream_remote EGL_NV_stream_reset EGL_NV_stream_socket EGL_NV_stream_socket_inet EGL_NV_stream_socket_unix EGL_NV_stream_sync EGL_NV_stream_fifo_next EGL_NV_stream_fifo_synchronous EGL_NV_stream_consumer_gltexture_yuv EGL_NV_stream_attrib EGL_NV_stream_origin EGL_NV_system_time EGL_NV_output_drm_flip_event EGL_NV_triple_buffer"
[2021-04-06T15:16:29Z INFO  gfx_backend_gl::window::egl] Trying native-render
[2021-04-06T15:16:29Z WARN  gfx_backend_gl::window::egl] No config found!
[2021-04-06T15:16:29Z INFO  gfx_backend_gl::window::egl] Trying presentation
[2021-04-06T15:16:29Z INFO  gfx_backend_gl] Vendor: "NVIDIA Corporation"
[2021-04-06T15:16:29Z INFO  gfx_backend_gl] Renderer: "GeForce RTX 2070/PCIe/SSE2"
[2021-04-06T15:16:29Z INFO  gfx_backend_gl] Version: 3.2, NVIDIA 460.39
[2021-04-06T15:16:29Z INFO  gfx_backend_gl] Shading Language: 3.2
[2021-04-06T15:16:29Z INFO  gfx_backend_gl] Supported Features: INDEPENDENT_BLENDING | SAMPLER_ANISOTROPY | INSTANCE_RATE | MUTABLE_COMPARISON_SAMPLER | NDC_Y_UP
[2021-04-06T15:16:29Z INFO  gfx_backend_gl] Legacy Features: DRAW_INSTANCED | DRAW_INDEXED_INSTANCED | VERTEX_BASE | CONSTANT_BUFFER | COPY_BUFFER | SAMPLER_OBJECTS | EXPLICIT_LAYOUTS_IN_SHADER | INSTANCED_ATTRIBUTE_BINDING
[2021-04-06T15:16:29Z INFO  gfx_backend_gl] Memory types: [
        (
            MemoryType {
                properties: CPU_VISIBLE | COHERENT | CPU_CACHED,
                heap_index: 1,
            },
            Buffer(
                TRANSFER_SRC | TRANSFER_DST | UNIFORM_TEXEL | STORAGE_TEXEL | UNIFORM | STORAGE | INDEX | VERTEX | INDIRECT,
            ),
        ),
        (
            MemoryType {
                properties: CPU_VISIBLE | COHERENT,
                heap_index: 1,
            },
            Buffer(
                TRANSFER_SRC | TRANSFER_DST | UNIFORM_TEXEL | STORAGE_TEXEL | UNIFORM | STORAGE | INDEX | VERTEX | INDIRECT,
            ),
        ),
        (
            MemoryType {
                properties: DEVICE_LOCAL,
                heap_index: 0,
            },
            Buffer(
                TRANSFER_SRC | TRANSFER_DST | UNIFORM_TEXEL | STORAGE_TEXEL | UNIFORM | STORAGE | INDEX | VERTEX | INDIRECT,
            ),
        ),
        (
            MemoryType {
                properties: DEVICE_LOCAL,
                heap_index: 0,
            },
            Image,
        ),
    ]
[2021-04-06T15:16:29Z INFO  gfx_backend_gl] Debug output is enabled
[2021-04-06T15:16:29Z INFO  gfx_backend_gl::device]     Created frame buffer 1
[2021-04-06T15:16:29Z WARN  gfx_backend_gl::device] View format 33321 is different from base 6403
[2021-04-06T15:16:29Z WARN  naga::front::spv] Unknown decoration ColMajor
[2021-04-06T15:16:29Z WARN  naga::front::spv] Unknown decoration MatrixStride
[2021-04-06T15:16:29Z WARN  naga::front::spv] Treating VertexIndex as unsigned
[2021-04-06T15:16:29Z INFO  gfx_backend_gl::device]     Compiled shader 2
[2021-04-06T15:16:29Z INFO  gfx_backend_gl::device]     Compiled shader 3
[2021-04-06T15:16:29Z INFO  gfx_backend_gl::device]     Linked program 1
Anton-4 commented 3 years ago

I have talked with the good folks behind wgpu-rs, they think the issue is at their end.