Explorar el Código

glgsg: Issue memory barriers for SSBOs

At the moment, it assumes that all SSBO accesses are writes, once shaderpipeline lands we can sort out readonly accesses based on the qualifiers in the shader
rdb hace 11 meses
padre
commit
db692edfa9

+ 2 - 0
panda/src/gles2gsg/gles2gsg.h

@@ -147,6 +147,7 @@ typedef char GLchar;
 #define GL_FRAMEBUFFER_BARRIER_BIT 0x400
 #define GL_TRANSFORM_FEEDBACK_BARRIER_BIT 0x800
 #define GL_ATOMIC_COUNTER_BARRIER_BIT 0x1000
+#define GL_SHADER_STORAGE_BARRIER_BIT 0x2000
 #define GL_HALF_FLOAT 0x140B
 #define GL_COLOR 0x1800
 #define GL_DEPTH 0x1801
@@ -181,6 +182,7 @@ typedef char GLchar;
 #define GL_WRITE_ONLY 0x88B9
 #define GL_READ_WRITE 0x88BA
 #define GL_PIXEL_PACK_BUFFER 0x88EB
+#define GL_PIXEL_UNPACK_BUFFER 0x88EC
 #define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF
 #define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35
 #define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36

+ 4 - 0
panda/src/glstuff/glBufferContext_src.h

@@ -32,6 +32,10 @@ public:
   // This is the GL "name" of the data object.
   GLuint _index;
 
+  // This is set to glgsg->_shader_storage_barrier_counter if a write was
+  // performed, in which case a barrier is issued before the next use.
+  int _shader_storage_barrier_counter = -1;
+
 public:
   static TypeHandle get_class_type() {
     return _type_handle;

+ 18 - 2
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -6274,6 +6274,11 @@ issue_memory_barrier(GLbitfield barriers) {
     GLCAT.spam(false) << " framebuffer";
   }
 
+  if (barriers & GL_SHADER_STORAGE_BARRIER_BIT) {
+    ++_shader_storage_barrier_counter;
+    GLCAT.spam(false) << " shader_storage";
+  }
+
   GLCAT.spam(false) << "\n";
 
   report_my_gl_errors();
@@ -7367,6 +7372,9 @@ prepare_shader_buffer(ShaderBuffer *data) {
       _glBufferData(GL_SHADER_STORAGE_BUFFER, num_bytes, data->get_initial_data(), get_usage(data->get_usage_hint()));
     }
 
+    // Barrier not needed.
+    gbc->_shader_storage_barrier_counter = _shader_storage_barrier_counter - 1;
+
     gbc->enqueue_lru(&_prepared_objects->_graphics_memory_lru);
 
     report_my_gl_errors();
@@ -7379,13 +7387,15 @@ prepare_shader_buffer(ShaderBuffer *data) {
 /**
  * Binds the given shader buffer to the given binding slot.
  */
-void CLP(GraphicsStateGuardian)::
+CLP(BufferContext) *CLP(GraphicsStateGuardian)::
 apply_shader_buffer(GLuint base, ShaderBuffer *buffer) {
+  CLP(BufferContext) *gbc = nullptr;
+
   GLuint index = 0;
   if (buffer != nullptr) {
     BufferContext *bc = buffer->prepare_now(get_prepared_objects(), this);
     if (bc != nullptr) {
-      CLP(BufferContext) *gbc = DCAST(CLP(BufferContext), bc);
+      gbc = DCAST(CLP(BufferContext), bc);
       index = gbc->_index;
       gbc->set_active(true);
     }
@@ -7407,6 +7417,8 @@ apply_shader_buffer(GLuint base, ShaderBuffer *buffer) {
 
     report_my_gl_errors();
   }
+
+  return gbc;
 }
 
 /**
@@ -7636,6 +7648,10 @@ dispatch_compute(int num_groups_x, int num_groups_y, int num_groups_z) {
   PStatGPUTimer timer(this, _compute_dispatch_pcollector);
   nassertv(_supports_compute_shaders);
   nassertv(_current_shader_context != nullptr);
+  CLP(ShaderContext) *gsc;
+  DCAST_INTO_V(gsc, _current_shader_context);
+  gsc->issue_memory_barriers();
+
   _glDispatchCompute(num_groups_x, num_groups_y, num_groups_z);
 
   maybe_gl_finish();

+ 2 - 1
panda/src/glstuff/glGraphicsStateGuardian_src.h

@@ -391,7 +391,7 @@ public:
 
 #ifndef OPENGLES
   virtual BufferContext *prepare_shader_buffer(ShaderBuffer *data);
-  void apply_shader_buffer(GLuint base, ShaderBuffer *buffer);
+  CLP(BufferContext) *apply_shader_buffer(GLuint base, ShaderBuffer *buffer);
   virtual void release_shader_buffer(BufferContext *bc);
   virtual void release_shader_buffers(const pvector<BufferContext *> &contexts);
 #endif
@@ -1167,6 +1167,7 @@ public:
   TextureSet _textures_needing_image_access_barrier;
   TextureSet _textures_needing_update_barrier;
   TextureSet _textures_needing_framebuffer_barrier;
+  int _shader_storage_barrier_counter = 0;
 #endif
 
   // RenderState::SlotMask _inv_state_mask;

+ 33 - 1
panda/src/glstuff/glShaderContext_src.cxx

@@ -2672,6 +2672,10 @@ update_shader_vertex_arrays(ShaderContext *prev, bool force) {
     update_slider_table(table);
   }
 
+  // This ought to be moved elsewhere, but it's convenient to do this here for
+  // now since it's called before every Geom is drawn.
+  issue_memory_barriers();
+
   _glgsg->report_my_gl_errors();
 
   return true;
@@ -3039,7 +3043,35 @@ update_shader_buffer_bindings(ShaderContext *prev) {
            " (expected at least " << block._min_size << " bytes)\n";
     }
 #endif
-    _glgsg->apply_shader_buffer(block._binding_index, buffer);
+    block._gbc = _glgsg->apply_shader_buffer(block._binding_index, buffer);
+  }
+#endif
+}
+
+/**
+ * Issues memory barriers for shader buffers, should be called before a draw.
+ */
+void CLP(ShaderContext)::
+issue_memory_barriers() {
+#ifndef OPENGLES
+  bool barrier_needed = false;
+  for (StorageBlock &block : _storage_blocks) {
+    if (block._gbc != nullptr &&
+        block._gbc->_shader_storage_barrier_counter == _glgsg->_shader_storage_barrier_counter) {
+      barrier_needed = true;
+      break;
+    }
+  }
+
+  if (barrier_needed) {
+    _glgsg->issue_memory_barrier(GL_SHADER_STORAGE_BARRIER_BIT);
+  }
+
+  // We assume that all SSBOs will be written to, for now.
+  for (StorageBlock &block : _storage_blocks) {
+    if (block._gbc != nullptr) {
+      block._gbc->_shader_storage_barrier_counter = _glgsg->_shader_storage_barrier_counter;
+    }
   }
 #endif
 }

+ 2 - 0
panda/src/glstuff/glShaderContext_src.h

@@ -58,6 +58,7 @@ public:
   void disable_shader_texture_bindings() override;
   void update_shader_texture_bindings(ShaderContext *prev) override;
   void update_shader_buffer_bindings(ShaderContext *prev) override;
+  void issue_memory_barriers();
 
   bool uses_standard_vertex_arrays(void) override {
     return _uses_standard_vertex_arrays;
@@ -96,6 +97,7 @@ private:
 #ifndef OPENGLES
   struct StorageBlock {
     CPT(InternalName) _name;
+    CLP(BufferContext) *_gbc = nullptr;
     GLuint _binding_index;
     GLuint _min_size;
   };