0

I can't get instanced geometry to work with a compute shader (I got both things work in isolation but don't know how to combine them). Below is an example that renders instances of a colored quad with different offsets. I'd like to be able to update those offsets via a compute shader.

#define COMPUTE_UPDATE

#include <glad/glad.h>
#include <GLFW/glfw3.h>

#include "Shader.h"

#include <iostream>

void framebuffer_size_callback(GLFWwindow* window, int width, int height);

const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;

int main()
{
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

#ifdef __APPLE__
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif

    // glfw window creation
    // --------------------
    GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
    if (window == NULL)
    {
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);

    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        std::cout << "Failed to initialize GLAD" << std::endl;
        return -1;
    }

    glEnable(GL_DEPTH_TEST);

    Shader shader("res/shaders/instanced.vs", "res/shaders/instanced.fs");
    Shader compute("res/shaders/instanced.glsl");

    float translations[200];
    int index = 0;
    float offset = 0.1f;
    for (int y = -10; y < 10; y += 2)
    {
        for (int x = -10; x < 10; x += 2)
        {
            float translation[2];
            translation[0] = (float)x / 10.0f + offset;
            translation[1] = (float)y / 10.0f + offset;
            translations[index++] = translation[0];
            translations[index++] = translation[1];
        }
    }

    unsigned int instanceVBO;
    glGenBuffers(1, &instanceVBO);
    glBindBuffer(GL_ARRAY_BUFFER, instanceVBO);
    glBufferData(GL_ARRAY_BUFFER, 2 * sizeof(float) * 100, &translations[0], GL_DYNAMIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    float quadVertices[] = {
        // positions     // colors
        -0.05f,  0.05f,  1.0f, 0.0f, 0.0f,
         0.05f, -0.05f,  0.0f, 1.0f, 0.0f,
        -0.05f, -0.05f,  0.0f, 0.0f, 1.0f,

        -0.05f,  0.05f,  1.0f, 0.0f, 0.0f,
         0.05f, -0.05f,  0.0f, 1.0f, 0.0f,
         0.05f,  0.05f,  0.0f, 1.0f, 1.0f
    };
    unsigned int quadVAO, quadVBO;
    glGenVertexArrays(1, &quadVAO);
    glGenBuffers(1, &quadVBO);
    glBindVertexArray(quadVAO);
    glBindBuffer(GL_ARRAY_BUFFER, quadVBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), quadVertices, GL_DYNAMIC_DRAW);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(2 * sizeof(float)));
    glEnableVertexAttribArray(2);
    glBindBuffer(GL_ARRAY_BUFFER, instanceVBO);
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glVertexAttribDivisor(2, 1); 


    while (!glfwWindowShouldClose(window))
    {
        
#ifdef COMPUTE_UPDATE
        // update instanced buffer
        compute.Use();
        glBindVertexArray(quadVAO);
        glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, instanceVBO);
        glDispatchCompute(1, 1, 1);

        glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT);
#endif
        // render
        glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // draw 100 instanced quads
        shader.Use();
        glBindVertexArray(quadVAO);
        glDrawArraysInstanced(GL_TRIANGLES, 0, 6, 100); // 100 triangles of 6 vertices each
        glBindVertexArray(0);

        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    glDeleteVertexArrays(1, &quadVAO);
    glDeleteBuffers(1, &quadVBO);

    glfwTerminate();
    return 0;
}

void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
    glViewport(0, 0, width, height);
}

Compute shader:

#version 460 core

struct Particle {
    vec2 pos;
};

layout(std430, binding = 1) buffer particleBuffer
{
    Particle particles[];
};

layout(local_size_x = 100, local_size_y = 1, local_size_z = 1) in;

void main() {
    uint i = gl_GlobalInvocationID.x;

    particles[i].pos += vec2(0.01, 0.0);
}

Vertex shader:

#version 460 core
layout (location = 0) in vec2 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aOffset;

out vec3 fColor;

void main()
{
    fColor = aColor;
    gl_Position = vec4(aPos + aOffset, 0.0, 1.0);
}
Yakov Galka
  • 70,775
  • 16
  • 139
  • 220
  • Try putting `glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_SHADER_STORAGE_BARRIER_BIT)` right after `glBindVertexArray(quadVAO);`. – Yakov Galka Nov 07 '21 at 04:49
  • @YakovGalka I tried it, but unfortunately I still get "Access violation executing location 0x0000000000000000" on the line with glBindBufferBase – Xenophilius Mildrententus Nov 07 '21 at 11:52
  • What's your driver and graphics card? That looks like your implementation couldn't find `glBindBufferBase`. – Yakov Galka Nov 07 '21 at 13:53
  • @YakovGalka I'm currently on a laptop with both integrated (Intel(R) UHD Graphics 620) and dedicated (VIDIA GeForce 940MX) gpu. To be completely honest I'm not entirely sure which one is being used by my application, I'll try to look into that. Oh, and driver version for Intel is 27.20.100.8681 and for Nvidia 27.21.14.5167 – Xenophilius Mildrententus Nov 07 '21 at 14:10
  • 1
    How were you able to get each of those working separately when `glBindBufferBase` is not available? Why do you request a 3.3 context when you use 4.3 features and 4.6 GLSL? – derhass Nov 07 '21 at 16:57
  • @derhass I got compute to work in a separate project where I don't have geometry buffer bound. Ahhh the context is wrong because of my sloppiness when creating this example, using code from learnopengl/instancing a base. Thank you for pointing this out. – Xenophilius Mildrententus Nov 07 '21 at 21:15

0 Answers0