2016-07-13 12 views
0

Я написал простой тестовый пример, чтобы получить высоту изображения в вычислительном шейдере и записать его в SSBO. Я использовал код SSBO before, и я знаю, что эта часть работает нормально. Я использовал apitrace для проверки состояния во время вызова glDispatchCompute, и я могу видеть как исходную текстуру, так и изображение, привязанную к правильному блоку изображения. Однако imageSize всегда возвращает ноль (вывод - все нули, за исключением некоторых оставшихся -1s в конце, потому что разделение с размером рабочей группы округляется). Ошибок OpenGL не выбрасывается.OpenGL imageSize всегда равен нулю

Я основал этот тестовый пример на одном из моих предыдущих вопросов, который включал код для привязки SSBO к вычислительному шейдеру (я использую его здесь для получения отладочного вывода из вычислительного шейдера).

class ComputeShaderWindow : public QOpenGLWindow { 
    public: 
    void initializeGL() { 
     // Create the opengl functions object 
     gl = context()->versionFunctions<QOpenGLFunctions_4_3_Core>(); 
     m_compute_program = new QOpenGLShaderProgram(this); 
     auto compute_shader_s = fs::readFile(
            "test_assets/example_compute_shader.comp"); 
     QImage img("test_assets/input/out.png"); 
     // Adds the compute shader, then links and binds it 
     m_compute_program->addShaderFromSourceCode(QOpenGLShader::Compute, 
       compute_shader_s); 
     m_compute_program->link(); 
     m_compute_program->bind(); 

     GLuint frame; 

     // Create the texture 
     gl->glGenTextures(1, &frame); 

     // Bind the texture 
     gl->glBindTexture(GL_TEXTURE_2D, frame); 

     // Fill the texture with the image 
     gl->glTexImage2D(GL_TEXTURE_2D, 
         0, 
         GL_RGB8, 
         img.width(), 
         img.height(), 
         0, 
         GL_BGRA, 
         GL_UNSIGNED_BYTE, 
         img.bits()); 
     GLuint image_unit = 1; 
     // Get the location of the image uniform 
     GLuint uniform_location = gl->glGetUniformLocation(
             m_compute_program->programId(), 
             "video_frame"); 
     // Set location to 0 (a unique value that we choose) 
     gl->glUniform1i(uniform_location, image_unit); 
     // Bind layer of texture to image unit 
     gl->glBindImageTexture(image_unit, 
           frame, 
           0, 
           GL_FALSE, 
           0, 
           GL_READ_ONLY, 
           GL_RGBA8UI); 
     // We should only need the bit for shader image access, 
     // but for the purpose of this example, I set all the bits 
     // just to be safe 
     gl->glMemoryBarrier(GL_ALL_BARRIER_BITS); 

     // SSBO stuff to get output from the shader 
     GLfloat* default_values = new GLfloat[NUM_INVOCATIONS]; 
     std::fill(default_values, default_values + NUM_INVOCATIONS, -1.0); 
     GLuint ssbo; 
     gl->glGenBuffers(1, &ssbo); 
     gl->glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo); 
     gl->glBufferData(GL_SHADER_STORAGE_BUFFER, 
         NUM_INVOCATIONS * sizeof(float), 
         &default_values[0], 
         GL_STATIC_DRAW); 
     gl->glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo); 
     gl->glDispatchCompute(NUM_INVOCATIONS/WORKGROUP_SIZE, 1, 1); 
     gl->glMemoryBarrier(GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT); 
     gl->glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo); 

     // Now read from the buffer so that we can check its values 
     GLfloat* read_data = (GLfloat*) gl->glMapBuffer(GL_SHADER_STORAGE_BUFFER, 
          GL_READ_ONLY); 
     std::vector<GLfloat> buffer_data(NUM_INVOCATIONS); 

     // Read from buffer 
     for (int i = 0; i < NUM_INVOCATIONS; i++) { 
      DEBUG(read_data[i]); 
     } 
     DEBUG("Done!"); 

     gl->glUnmapBuffer(GL_SHADER_STORAGE_BUFFER); 
     assert(gl->glGetError() == GL_NO_ERROR); 
    } 

    void resizeGL(int width, int height) { 

    } 

    void paintGL() { 

    } 

    void teardownGL() { 

    } 

    private: 
    QOpenGLFunctions_4_3_Core* gl; 
    QOpenGLShaderProgram* m_compute_program; 
    static constexpr int NUM_INVOCATIONS = 9000; 
    static constexpr int WORKGROUP_SIZE = 128; 
}; 

Что касается Compute Shader:

#version 430 core 

layout(local_size_x = 128) in; 

layout(rgba8ui, binding = 1) readonly uniform uimage2D video_frame; 

layout(std430, binding = 0) writeonly buffer SSBO { 
    float data[]; 
}; 

void main() { 
    uint ident = int(gl_GlobalInvocationID); 
    uint num_workgroups = int(gl_WorkGroupID); 
    // Write the height of the image into the buffer 
    data[ident] = float(imageSize(video_frame).y); 
} 

ответ

0

Оказывается, я забыл параметры текстуры:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 

Нет разгадка, почему это ломает imageSize() звонки, хотя.