egui-miniquad
egui-miniquad copied to clipboard
SegFault when there are lines with too many points
use egui::*;
use {egui_miniquad as egui_mq, miniquad as mq};
struct Stage {
egui_mq: egui_mq::EguiMq,
}
impl Stage {
fn new(ctx: &mut mq::Context) -> Self {
Self {
egui_mq: egui_mq::EguiMq::new(ctx),
}
}
}
impl mq::EventHandler for Stage {
fn update(&mut self, _ctx: &mut mq::Context) {}
fn draw(&mut self, mq_ctx: &mut mq::Context) {
mq_ctx.clear(Some((0., 0., 0., 1.)), None, None);
self.egui_mq.run(mq_ctx, |egui_ctx| {
const SAMPLE_GRAPH_SIZE: usize = 331;
egui::Window::new("tapes").show(egui_ctx, |ui| {
egui_ctx.request_repaint();
for _ in 0..8 {
ui.group(|ui| {
let desired_size = ui.available_width() * vec2(1.0, 0.02);
let (_id, rect) = ui.allocate_space(desired_size);
let to_screen = emath::RectTransform::from_to(
Rect::from_x_y_ranges(0.0..=1.0, -1.0..=1.0),
rect,
);
let mut shapes = vec![];
let points: Vec<Pos2> = (0..SAMPLE_GRAPH_SIZE)
.enumerate()
.map(|(index, _)| {
to_screen * pos2(index as f32 / SAMPLE_GRAPH_SIZE as f32, 0.)
})
.collect();
shapes.push(epaint::Shape::line(
points,
Stroke::new(1.0, Color32::WHITE),
));
ui.painter().extend(shapes);
});
}
});
});
self.egui_mq.draw(mq_ctx);
mq_ctx.commit_frame();
}
}
fn main() {
mq::start(Default::default(), |mut ctx| {
mq::UserData::owning(Stage::new(&mut ctx), ctx)
});
}
The code above crashes on my 2015 MacBook Pro when SAMPLE_GRAPH_SIZE is 331. It works if if it is less than 331 for this example. I'm using miniquad 0.3.0-alpha.46
, egui-miniquad 0.11.0
and egui 0.18.0
Here is the stack trace, hope it helps.
_platform_memmove$VARIANT$Haswell (@_platform_memmove$VARIANT$Haswell:75)
glrIntelRenderVertexArray (@glrIntelRenderVertexArray:414)
glDrawElementsInstanced_ACC_GL3Exec (@glDrawElementsInstanced_ACC_GL3Exec:96)
miniquad::graphics::Context::draw (/Users/zehreken/.cargo/registry/src/github.com-1ecc6299db9ec823/miniquad-0.3.0-alpha.46/src/graphics.rs:1113)
egui_miniquad::painter::Painter::paint_job (/Users/zehreken/.cargo/registry/src/github.com-1ecc6299db9ec823/egui-miniquad-0.11.0/src/painter.rs:277)
egui_miniquad::painter::Painter::paint (/Users/zehreken/.cargo/registry/src/github.com-1ecc6299db9ec823/egui-miniquad-0.11.0/src/painter.rs:188)
egui_miniquad::painter::Painter::paint_and_update_textures (/Users/zehreken/.cargo/registry/src/github.com-1ecc6299db9ec823/egui-miniquad-0.11.0/src/painter.rs:161)
egui_miniquad::EguiMq::draw (/Users/zehreken/.cargo/registry/src/github.com-1ecc6299db9ec823/egui-miniquad-0.11.0/src/lib.rs:195)
<modul::Stage as miniquad::event::EventHandler>::draw (/Users/zehreken/Development/modul/src/main.rs:51)
miniquad::frame (/Users/zehreken/.cargo/registry/src/github.com-1ecc6299db9ec823/miniquad-0.3.0-alpha.46/src/lib.rs:309)
_sapp_call_frame (/Users/zehreken/.cargo/registry/src/github.com-1ecc6299db9ec823/sapp-darwin-0.1.8/external/sokol/sokol_app.h:987)
_sapp_frame (/Users/zehreken/.cargo/registry/src/github.com-1ecc6299db9ec823/sapp-darwin-0.1.8/external/sokol/sokol_app.h:1083)
_sapp_macos_frame (/Users/zehreken/.cargo/registry/src/github.com-1ecc6299db9ec823/sapp-darwin-0.1.8/external/sokol/sokol_app.h:1311)
-[_sapp_macos_view drawRect:] (/Users/zehreken/.cargo/registry/src/github.com-1ecc6299db9ec823/sapp-darwin-0.1.8/external/sokol/sokol_app.h:1548)
-[_NSOpenGLViewBackingLayer display] (@-[_NSOpenGLViewBackingLayer display]:196)
CA::Layer::display_if_needed(CA::Transaction*) (@CA::Layer::display_if_needed(CA::Transaction*):193)
CA::Context::commit_transaction(CA::Transaction*, double, double*) (@CA::Context::commit_transaction(CA::Transaction*, double, double*):128)
CA::Transaction::commit() (@CA::Transaction::commit():199)
__62+[CATransaction(NSCATransaction) NS_setFlushesWithDisplayLink]_block_invoke (@__62+[CATransaction(NSCATransaction) NS_setFlushesWithDisplayLink]_block_invoke:70)
___NSRunLoopObserverCreateWithHandler_block_invoke (@___NSRunLoopObserverCreateWithHandler_block_invoke:18)
I've been doing some experiments and noticed that values for y-axis actually matter. When I change
.map(|(index, _)| { to_screen * pos2(index as f32 / SAMPLE_GRAPH_SIZE as f32, 0.) })
to
.map(|(index, _)| { to_screen * pos2(index as f32 / SAMPLE_GRAPH_SIZE as f32, index as f32 % modulus) })
,
different modulus values crash at different SAMPLE_GRAPH_SIZE values. For example for SAMPLE_SIZE_GRAPH = 201, it runs fine when modulus = 1.0 and moduls > 25.0, it crashes in other cases.
The segfault happens in this function https://github.com/not-fl3/egui-miniquad/blob/master/src/painter.rs#L244 it seems to me that it only segfaults in case it goes in this branch(at least the example above): https://github.com/not-fl3/egui-miniquad/blob/master/src/painter.rs#L267
If one changes this function to apply
fn cut_mesh(mesh: &mut Mesh16) {
mesh.indices.truncate(65536 / std::mem::size_of::<u16>());
}
at the beginning of this loop https://github.com/not-fl3/egui-miniquad/blob/509dae209c337a31a7c03d4630e6718134600814/src/painter.rs#L256 it does not.
It makes me think that we can for example temporarily(not a proper fix) fix it by batching it further (if the index buffer is too big)
One idea why it might happen for big index buffers was that index buffer is not allowed to be bigger than u16::MAX
but it seems to work with the index_buffer_byts=65536 > u16::MAX
.
But it might be a good idea to reduce this example to be even smaller miniquad only example and draw something with a huge index buffer size and investigate further.