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

call glDisableVertexAttribArray when delete buffer #522

Merged
merged 1 commit into from
Feb 2, 2025

Conversation

birhburh
Copy link
Contributor

@birhburh birhburh commented Feb 2, 2025

I have this minimal example:

Cargo.toml:

[package]
name = "miniquad_bug"
version = "0.1.0"
edition = "2021"

[dependencies]
miniquad = { git = "https://github.com/not-fl3/miniquad", rev = "ce657cf6a0c47dba11b712b2d5a127f9731a6e45"}

main.rs

use miniquad::*;

static QUAD_VERTEX_POSITIONS: [f32; 8] = [0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0];
static QUAD_VERTEX_INDICES: [u16; 6] = [0, 1, 3, 1, 2, 3];

struct Stage {
    ctx: Box<dyn RenderingBackend>,
    fill_pipeline: Pipeline,
    fill_bindings: Bindings,
    tile_pipeline: Pipeline,
    tile_bindings: Bindings,
}

impl Stage {
    pub fn new() -> Stage {
        let mut ctx: Box<dyn RenderingBackend> = window::new_rendering_backend();

        let quad_vertex_positions_buffer = ctx.new_buffer(
            BufferType::VertexBuffer,
            BufferUsage::Immutable,
            BufferSource::slice(&QUAD_VERTEX_POSITIONS),
        );
        let quad_vertex_indices_buffer = ctx.new_buffer(
            BufferType::IndexBuffer,
            BufferUsage::Immutable,
            BufferSource::slice(&QUAD_VERTEX_INDICES),
        );

        let fill_buffer = ctx.new_buffer(
            BufferType::VertexBuffer,
            BufferUsage::Immutable,
            BufferSource::empty::<f32>(0),
        );

        let fill_shader = ctx
            .new_shader(
                ShaderSource::Glsl {
                    vertex: "
                            #version 100

                            attribute vec2 aTessCoord;
                            attribute vec4 aLineSegment;

                            void main() {
                                gl_Position = vec4(aTessCoord - vec2(1.0, 0.0), 0.0, 1.0);
                                aLineSegment.xy; // comment this and everything works again
                            }
                        ",
                    fragment: "
                            #version 100

                            void main() {
                                gl_FragColor = vec4(1.52, 0.0, 0.152, 1.0052);
                            }
                        ",
                },
                ShaderMeta {
                    images: vec![],
                    uniforms: UniformBlockLayout {
                        uniforms: vec![
                            UniformDesc::new("uFramebufferSize", UniformType::Float2),
                            UniformDesc::new("uTileSize", UniformType::Float2),
                        ],
                    },
                },
            )
            .unwrap();

        let fill_bindings = Bindings {
            vertex_buffers: vec![quad_vertex_positions_buffer, fill_buffer],
            index_buffer: quad_vertex_indices_buffer,
            images: vec![],
        };

        let fill_pipeline = ctx.new_pipeline(
            &[
                BufferLayout::default(),
                BufferLayout {
                    step_func: VertexStep::PerInstance,
                    stride: size_of::<f32>() as i32,
                    ..Default::default()
                },
            ],
            &[
                VertexAttribute::with_buffer("aTessCoord", VertexFormat::Float2, 0),
                VertexAttribute::with_buffer("aLineSegment", VertexFormat::Float4, 1),
                VertexAttribute::with_buffer("aTileIndex", VertexFormat::Float1, 1),
            ],
            fill_shader,
            PipelineParams::default(),
        );

        let tile_shader = ctx
            .new_shader(
                ShaderSource::Glsl {
                    vertex: "
                            #version 100

                            attribute vec2 aTileOffset;

                            void main() {
                                gl_Position = vec4(aTileOffset, 0.0, 1.0);
                            }
                        ",
                    fragment: "
                            #version 100

                            void main() {
                                gl_FragColor = vec4(1.0, 0.52, 0.0, 1.0);
                            }
                        ",
                },
                ShaderMeta {
                    images: vec![],
                    uniforms: UniformBlockLayout {
                        uniforms: vec![],
                    },
                },
            )
            .unwrap();

        let tile_bindings = Bindings {
            vertex_buffers: vec![quad_vertex_positions_buffer],
            index_buffer: quad_vertex_indices_buffer,
            images: vec![],
        };

        let tile_pipeline = ctx.new_pipeline(
            &[BufferLayout::default()],
            &[VertexAttribute::with_buffer(
                "aTileOffset",
                VertexFormat::Float2,
                0,
            )],
            tile_shader,
            PipelineParams::default(),
        );

        Stage {
            ctx,

            fill_pipeline,
            fill_bindings,

            tile_pipeline,
            tile_bindings,
        }
    }
}

impl EventHandler for Stage {
    fn update(&mut self) {}

    fn draw(&mut self) {
        let old_fill_buffer = self.fill_bindings.vertex_buffers[1];
        self.fill_bindings.vertex_buffers[1] = self.ctx.new_buffer(
            BufferType::VertexBuffer,
            BufferUsage::Immutable,
            BufferSource::slice(&[486.0, 1832.0]),
        );

        self.ctx
            .begin_default_pass(PassAction::clear_color(0.0, 0.0, 0.0, 1.0));
        self.ctx.apply_pipeline(&self.fill_pipeline);
        self.ctx.apply_bindings(&self.fill_bindings);
        self.ctx.draw(0, 6, 1 as i32);
        self.ctx.end_render_pass();

        self.ctx.delete_buffer(self.fill_bindings.vertex_buffers[1]);
        self.fill_bindings.vertex_buffers[1] = old_fill_buffer;

        self.ctx.begin_default_pass(PassAction::Nothing);
        self.ctx.apply_pipeline(&self.tile_pipeline);
        self.ctx.apply_bindings(&self.tile_bindings);

        self.ctx.draw(0, 6, 1);
        self.ctx.end_render_pass();
    }
}

fn main() {
    let mut conf = conf::Conf::default();
    conf.window_title = "gl(Enable/Disable)VertexAttribArray bug".to_owned();
    conf.platform.blocking_event_loop = true;
    miniquad::start(conf, move || Box::new(Stage::new()));
}

Without this patch:
osx:
Screenshot 2025-02-02 at 04 19 12
Web:
image

With this patch:
osx:
Screenshot 2025-02-02 at 04 22 26
Web:
image

@not-fl3
Copy link
Owner

not-fl3 commented Feb 2, 2025

Good catch and a great repro, thanks for PR!

@not-fl3 not-fl3 merged commit 1802160 into not-fl3:master Feb 2, 2025
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants