glUseProgram выдает ошибку Invalid Operation при попытке использовать вычислительный шейдер

Я пытаюсь использовать OpenGL в Python для игры с Compute Shaders, но я очень мало представляю, что я делаю. Я хотел бы иметь возможность отправить некоторые данные, чтобы шейдер изменил их и считал эти данные обратно. Это код, который я написал до сих пор:

import OpenGL
from OpenGL.GL import *
from OpenGL.GL import shaders
from OpenGL.GLU import *
import pygame
from pygame.locals import *

import numpy as np

buffer_data = np.array([0, 0, 0, 0])

compute_shader_code = """
#version 430 core

layout(std430, binding=9) buffer data{
    vec4 Data[];
};

void main() 
{
    Data[0].x = 1;
    Data[0].y = 2;
    Data[0].z = 3;
    Data[0].w = 4;
}
"""

def setup():
    pygame.init()
    window_width = 1000
    window_height = 800
    display = (window_width, window_height)
    pygame.display.set_mode(display, DOUBLEBUF|OPENGL)

    test()

    pygame.quit()
    quit()

def test():
    print("Creating shader program")
    compute_shader_program = -1
    shader_program = -1

    compute_shader_program = glCreateShader(GL_COMPUTE_SHADER)
    glShaderSource(compute_shader_program, compute_shader_code)
    glCompileShader(compute_shader_program)
    if glGetShaderiv(compute_shader_program, GL_COMPILE_STATUS) != GL_TRUE:
        raise RuntimeError(glGetShaderInfoLog(compute_shader_program))
    shader_program = glCreateProgram()
    glAttachShader(shader_program, compute_shader_program)
    glLinkProgram(shader_program)

    if shader_program != -1:
        ssbo = -1
        print("Binding buffers")
        glUseProgram(shader_program)
        glGenBuffers(1, ssbo)
        glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 9, ssbo)
        glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo)

        print("Calling compute")
        glDispatchCompute(1, 1, 1)
        glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT)

        block_index = glGetProgramResourceIndex(shader_program, GL_SHADER_STORAGE_BLOCK, "data", 9)
        if block_index != GL_INVALID_INDEX:
            print("I think I found the data")
        #   How do I access the data here

        glUnmapBuffer(GL_SHADER_STORAGE_BUFFER)


setup()

Когда я запускаю эту программу, я получаю эту ошибку:

  File "some location/Compute Shader Test.py", line 56, in test
    glUseProgram(shader_program)
  File "some location\Anaconda3\envs\Regression\lib\site-packages\OpenGL\platform\baseplatform.py", line 402, in __call__
    return self( *args, **named )
  File "errorchecker.pyx", line 53, in OpenGL_accelerate.errorchecker._ErrorChecker.glCheckError (src\errorchecker.c:1218)
OpenGL.error.GLError: GLError(
    err = 1282,
    description = b'invalid operation',
    baseOperation = glUseProgram,
    cArguments = (2,)
)

Итак, я думаю, у меня есть 2 вопроса. Во-первых, почему я получаю эту ошибку? Кажется, что программа шейдера прекрасно компилируется, и на моем компьютере ей присваивается целое значение 2. Я неправильно ее создаю? Разве это не то, как вы используете вычислительные шейдеры?

Во-вторых, как я могу прочитать данные обратно после запуска шейдера?

Большое спасибо!

***************Обновить***************

После некоторых предложений из комментариев он работает без сбоев. Теперь проблема в том, что значение, которое возвращается с карты, странно.

Обновленный код:

import OpenGL
from OpenGL.GL import *
from OpenGL.GL import shaders
from OpenGL.GLU import *
import pygame
from pygame.locals import *

import numpy as np

buffer_data = np.array([0, 0, 0, 0])

compute_shader_code = """
#version 430 core
layout(local_size_x = 1, local_size_y = 1) in;

layout(std430, binding=9) buffer data{
    vec4 Data[];
};

void main() 
{
    Data[0].x = 1;
    Data[0].y = 2;
    Data[0].z = 3;
    Data[0].w = 4;
}
"""

def setup():
    pygame.init()
    window_width = 1000
    window_height = 800
    display = (window_width, window_height)
    pygame.display.set_mode(display, DOUBLEBUF|OPENGL)
    print(glGetString(GL_VERSION))
    test()

    pygame.quit()
    quit()

def test():
    print("Creating shader program")
    compute_shader_program = -1
    shader_program = -1

    compute_shader_program = glCreateShader(GL_COMPUTE_SHADER)
    glShaderSource(compute_shader_program, compute_shader_code)
    glCompileShader(compute_shader_program)
    if glGetShaderiv(compute_shader_program, GL_COMPILE_STATUS) != GL_TRUE:
        raise RuntimeError(glGetShaderInfoLog(compute_shader_program))
    shader_program = glCreateProgram()
    glAttachShader(shader_program, compute_shader_program)
    glLinkProgram(shader_program)
    print(glGetProgramInfoLog(shader_program))

    if shader_program != -1:
        ssbo = -1
        print("Binding buffers")
        glUseProgram(shader_program)
        glGenBuffers(1, ssbo)
        glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 9, ssbo)
        glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo)
        glBufferData(GL_SHADER_STORAGE_BUFFER, np.ascontiguousarray(buffer_data, dtype=np.float32), GL_DYNAMIC_READ)

        print("Calling compute")
        glDispatchCompute(1, 1, 1)
        glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT)

        block_index = glGetProgramResourceIndex(shader_program, GL_SHADER_STORAGE_BLOCK, "data", 9)
        if block_index != GL_INVALID_INDEX:
            print("I think I found the data")
        #   How do I access the data here
            result = glMapBuffer(GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY)
            print(result)
            print(buffer_data)
            glUnmapBuffer(GL_SHADER_STORAGE_BUFFER)


setup()

Когда я печатаю результат, я получаю 2109824291840, что явно не то, что я ожидал. Буду признателен за любую помощь о том, как правильно читать данные обратно из буфера. Еще раз спасибо!

0 ответов

Другие вопросы по тегам