首页 > 解决方案 > 带计算着色器的环形缓冲 SSBO

问题描述

我正在计算着色器中的 GPU 上执行视锥体剔除和生成绘制命令,并且我想在 SSBO 中传递边界体积。目前我只使用一个大型统一阵列,但我想做得更大,因此需要转移到 SSBO。

我想要完成的事情类似于使用三重缓冲的 AZDO 方法,以便在更新 SSBO 时避免同步问题,只更新三分之一的缓冲区,而用栅栏保护其余部分。

这是否可以与计算着色器调度结合使用,或者我应该只创建三个不同的 SSBO,然后相应地绑定它们中的每一个?

我目前看到的解决方案是以某种方式告诉以下drawcall仅从某个偏移量(0 * buffer_size,1 * buffer_size等)获取SSBO中的数据。这甚至可能吗?

渲染循环

  /* Fence creation omitted for clarity */

  // Cycle round updating different parts of the buffer
  const uint32_t buffer_idx = (frame % gl_state.bvb_num_partitions);
  uint8_t* ptr = (uint8_t*)gl_state.bvbp + buffer_idx * gl_state.bvb_buffer_size;
  std::memcpy(ptr, bounding_volumes.data(), gl_state.bvb_buffer_size);
  const uint32_t gl_bv_binding_point = 3; // Shader hard coded
  const uint32_t offset = buffer_idx * gl_state.bvb_buffer_size;
  glBindBufferRange(GL_SHADER_STORAGE_BUFFER, gl_bv_binding_point, gl_state.bvb, offset, gl_state.bvb_buffer_size);

  // OLD WAY: glUniform4fv(glGetUniformLocation(gl_state.cull_shader.gl_program, "spheres"), NUM_OBJECTS, &bounding_volumes[0].pos.x);

  glUniform4fv(glGetUniformLocation(gl_state.cull_shader.gl_program, "frustum_planes"), 6, glm::value_ptr(frustum[0]));

  glDispatchCompute(NUM_OBJECTS, 1, 1);

  glMemoryBarrier(GL_COMMAND_BARRIER_BIT | GL_SHADER_STORAGE_BARRIER_BIT); // Buffer objects affected by this bit are derived from the GL_DRAW_INDIRECT_BUFFER binding. 

包围体 SSBO 创建

// Bounding volume buffer
glGenBuffers(1, &gl_state.bvb);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, gl_state.bvb);
gl_state.bvb_buffer_size = NUM_OBJECTS * sizeof(BoundingVolume);
gl_state.bvb_num_partitions = 3; // 1 for application, 1 for OpenGL driver, 1 for GPU
GLbitfield flags = GL_MAP_COHERENT_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT;
glBufferStorage(GL_SHADER_STORAGE_BUFFER, gl_state.bvb_num_partitions * gl_state.bvb_buffer_size, nullptr, flags);
gl_state.bvbp = glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, gl_state.bvb_buffer_size * gl_state.bvb_num_partitions, flags);

标签: openglgraphicscompute-shader

解决方案


推荐阅读