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, что явно не то, что я ожидал. Буду признателен за любую помощь о том, как правильно читать данные обратно из буфера. Еще раз спасибо!