diff --git a/panda/src/gles2gsg/gles2gsg.h b/panda/src/gles2gsg/gles2gsg.h index 967f341703..c43beded29 100644 --- a/panda/src/gles2gsg/gles2gsg.h +++ b/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 diff --git a/panda/src/glstuff/glBufferContext_src.h b/panda/src/glstuff/glBufferContext_src.h index b67a9d214e..dcc31c09ab 100644 --- a/panda/src/glstuff/glBufferContext_src.h +++ b/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; diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 21383cc825..c8aa716366 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/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(); diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index 1abbc1d2a4..759ddcff68 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/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 &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; diff --git a/panda/src/glstuff/glShaderContext_src.cxx b/panda/src/glstuff/glShaderContext_src.cxx index f411bb9fcc..dde88cc554 100644 --- a/panda/src/glstuff/glShaderContext_src.cxx +++ b/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 } diff --git a/panda/src/glstuff/glShaderContext_src.h b/panda/src/glstuff/glShaderContext_src.h index 5da63ed21a..f196c1b6ba 100644 --- a/panda/src/glstuff/glShaderContext_src.h +++ b/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; };