2016-11-04 9 views
0

小さなOpenGLエンジンが書かれていて、SSBOを使用してシェーダが書き込み可能なデバッグログを書き込めるようにしたい。私のフラグメントシェーダでOpenGLフラグメントシェーダがSSBOに書き込まない

#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; 
     } 

    ... 
    }; 

私は:私のログクラスは次のようになります

#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; 

    ... 
    } 

そして、メインプログラムは次のようになります。

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 
    ... 
    } 

今書き出された行数シェイダーによって20に設定されていても、0のままです。私はglBufferData(...)の後にGPUからデータをロードしようとしましたが、そこには問題がバッファとシェーダ間の接続にあるようです。私はまた、シェーダのデータを読み込み、それらをスクリーンに出力しようとしました、そして、私は常に私の仮説を支持する0です。基本的に私はCPUからのSSBOへの書き込み/読み出しが可能だが、シェーダからの読み込みはできないようだ。問題を見つけるのに誰も助けてくれますか?

答えて

2

memcpy関数にbinding_point(0)を渡すのはなぜですか?この方法では、0バイトのデータがコピーされます。

memcpy(&(this->number_of_lines),mapped_ssbo,this->binding_point); 
+0

ありがとう、それは1つのバグです、私はそれをSHADER_LOG_TOTAL_SIZEに置き換えました。しかし、まだ動作しません:/ –

0

私は、これらの行のうちの少なくとも1つが、あなたが見捨てるメモリの壁であると仮定していますか?

SSBO、イメージロード/ストアなどを使用するときは、コヒーレンシを確保するために、並行呼び出しの間に何らかの形式の同期が必要です。SSBO、イメージロード/ストアなどを使用するときは自動ではありません。同じメモリの異なる(隔離された)ビュー。

SSBOの変更を他のシェーダ呼び出しで確認できるようにするには、読み取りを実行する前にGLSLコードに障壁が必要です。インコヒーレントなオペレーションの他のタイプは、GLコマンドストリーム内にバリアを必要とすることがあるが、前提は同じである。次の操作が前の操作の結果を使用するように、順序コマンドと読み取り/書き込みメモリを使用します。

+0

私の計画は、ShaderのatomicAdd(...)関数を使用して、バッファの一部(ログ内の単一の "行")を、シェーダの呼び出しごとに "割り当てる"ことですログに書き込みます。このコードでは、シェーダ内のバッファに値を書き込んだ後、その値をCPUから取り出すことができるかどうかだけを確認する必要があります。私は後で同期を使用する必要があることを知っていますが、すべてのシェーダが書き込みを行うだけなので、コードはOKになるはずです。 –

関連する問題