首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >OpenGL片段着色器不写入SSBO

OpenGL片段着色器不写入SSBO
EN

Stack Overflow用户
提问于 2016-11-05 03:05:10
回答 2查看 1.1K关注 0票数 0

我已经写了一个小的OpenGL引擎,我想使用SSBO来允许着色器写调试日志,我可以写出来。我的日志类如下所示:

代码语言:javascript
复制
#define SHADER_LOG_LINE_LENGTH 128
#define SHADER_LOG_MAX_LINES 512
#define SHADER_LOG_DATA_OFFSET sizeof(int32_t) * 3
#define SHADER_LOG_DATA_SIZE SHADER_LOG_LINE_LENGTH * SHADER_LOG_MAX_LINES * sizeof(int32_t)
#define SHADER_LOG_TOTAL_SIZE SHADER_LOG_DATA_OFFSET + SHADER_LOG_DATA_SIZE

class ShaderLog
  {
    protected:
      GLuint ssbo;
      GLuint binding_point;

      int32_t number_of_lines;
      int32_t max_lines;
      int32_t line_length;
      int32_t data[SHADER_LOG_DATA_SIZE];

    public:
      ShaderLog()
        {
          glGenBuffers(1,&(this->ssbo));

          this->number_of_lines = 0;
          this->max_lines = SHADER_LOG_MAX_LINES;
          this->line_length = SHADER_LOG_LINE_LENGTH;
          this->binding_point = 0;

          glBindBuffer(GL_SHADER_STORAGE_BUFFER,this->ssbo);
          glBufferData(GL_SHADER_STORAGE_BUFFER,SHADER_LOG_TOTAL_SIZE,&(this->number_of_lines),GL_DYNAMIC_COPY);
          glBindBufferBase(GL_SHADER_STORAGE_BUFFER,this->binding_point,this->ssbo);
          glBindBuffer(GL_SHADER_STORAGE_BUFFER,0);
        };

      void connect_to_shader(Shader *shader, string shader_variable_name)
        {
          GLuint block_index = 0;
          block_index = glGetProgramResourceIndex(shader->get_shader_program_number(),GL_SHADER_STORAGE_BLOCK,shader_variable_name.c_str());

          if (block_index == GL_INVALID_INDEX)
            ErrorWriter::write_error("Shader log could not be connected to the shader.");

          glBindBufferBase(GL_SHADER_STORAGE_BUFFER,block_index,this->binding_point);
          glShaderStorageBlockBinding(shader->get_shader_program_number(),block_index,this->binding_point);
        }

      virtual void load_from_gpu()
        {
          glBindBuffer(GL_SHADER_STORAGE_BUFFER,this->ssbo);
          GLvoid* mapped_ssbo = glMapBuffer(GL_SHADER_STORAGE_BUFFER,GL_READ_ONLY);

          if (mapped_ssbo == NULL)
            ErrorWriter::write_error("Could not map shader log into client's memory space for reading.");
          else
            memcpy(&(this->number_of_lines),mapped_ssbo,SHADER_LOG_DATA_SIZE);

          glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
        }

      int get_number_of_lines()
        {
          return this->number_of_lines;
        }

     ...
  };

在我的片段着色器中,我这样做:

代码语言:javascript
复制
#version 430

layout (std430, binding=0) buffer shader_log_data
  {
    int number_of_lines;
    int max_lines;
    int line_length;
    int data[];
  } shader_log;

...

void main()
  {
    shader_log.number_of_lines = 20;  // just to test
    shader_log.data[0] = 10000;

    ...
  }

主程序看起来像这样:

代码语言:javascript
复制
void render()
  {        
    ... // rendering

    shader_log->load_from_gpu();
    cout << "lines: " << shader_log->get_number_of_lines() << endl;

    glutSwapBuffers();
  }

...

int main(int argc, char** argv)
  { 
    ...
    shader_log = new ShaderLog();
    ...
    shader_log->connect_to_shader(shader,"shader_log_data");
    shader_log->update_gpu();
    ...
    // rendering loop
    ...
  }

现在,写出的行数保持为0,即使着色器应将其设置为20。我尝试在glBufferData(...)之后从图形处理器加载数据。它们在那里,问题似乎出在缓冲区和着色器之间的连接上。我还尝试读取着色器中的数据并将其输出到屏幕,它们始终为0,这支持我的假设。基本上,我似乎能够从CPU写入/读取SSBO,但不能从着色器读取。有人能帮我找出问题所在吗?

EN

回答 2

Stack Overflow用户

发布于 2016-11-05 16:17:14

为什么要将binding_point ( 0)传递给memcpy函数?通过这种方式,您可以复制0字节的数据。

代码语言:javascript
复制
memcpy(&(this->number_of_lines),mapped_ssbo,this->binding_point);
票数 2
EN

Stack Overflow用户

发布于 2016-11-06 15:00:06

我假设其中至少有一个...线条是你忽视的记忆障碍吗?

您需要跨并行调用的某种形式的同步来确保一致性,当使用SSBO、映像加载/存储等时,这不是自动的。您可能会在没有屏障的情况下读取未定义的值,因为每个执行单元都有相同内存的不同(隔离)视图。

确保对SSBO所做的更改对其他着色器调用可见,在执行读取之前需要在GLSL代码中设置障碍。其他类型的非相干操作可能需要GL命令流中的屏障,但前提是相同的;对命令和读/写内存进行排序,以便后续操作使用前一个操作的结果。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40430105

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档