diff --git a/source/blender/gpu/GPU_storage_buffer.h b/source/blender/gpu/GPU_storage_buffer.h index 1478d490e23..739b0784317 100644 --- a/source/blender/gpu/GPU_storage_buffer.h +++ b/source/blender/gpu/GPU_storage_buffer.h @@ -47,6 +47,17 @@ void GPU_storagebuf_clear(GPUStorageBuf *ssbo, void *data); void GPU_storagebuf_clear_to_zero(GPUStorageBuf *ssbo); +/** + * @brief Copy a part of a vertex buffer to a storage buffer. + * \a ssbo: destination storage buffer + * \a src: source vertex buffer + * \a dst_offset: where to start copying to (in bytes). + * \a src_offset: where to start copying from (in bytes). + * \a copy_size: byte size of the segment to copy. + */ +void GPU_storagebuf_copy_sub_from_vertbuf( + GPUStorageBuf *ssbo, GPUVertBuf *src, uint dst_offset, uint src_offset, uint copy_size); + #ifdef __cplusplus } #endif diff --git a/source/blender/gpu/intern/gpu_storage_buffer.cc b/source/blender/gpu/intern/gpu_storage_buffer.cc index 806acad90fe..68020ec66f4 100644 --- a/source/blender/gpu/intern/gpu_storage_buffer.cc +++ b/source/blender/gpu/intern/gpu_storage_buffer.cc @@ -19,6 +19,7 @@ #include "GPU_storage_buffer.h" #include "gpu_storage_buffer_private.hh" +#include "gpu_vertex_buffer_private.hh" /* -------------------------------------------------------------------- */ /** \name Creation & Deletion @@ -103,4 +104,10 @@ void GPU_storagebuf_clear_to_zero(GPUStorageBuf *ssbo) GPU_storagebuf_clear(ssbo, GPU_R32UI, GPU_DATA_UINT, &data); } +void GPU_storagebuf_copy_sub_from_vertbuf( + GPUStorageBuf *ssbo, GPUVertBuf *src, uint dst_offset, uint src_offset, uint copy_size) +{ + unwrap(ssbo)->copy_sub(unwrap(src), dst_offset, src_offset, copy_size); +} + /** \} */ diff --git a/source/blender/gpu/intern/gpu_storage_buffer_private.hh b/source/blender/gpu/intern/gpu_storage_buffer_private.hh index 06e7c2c0e9d..091e6c2d386 100644 --- a/source/blender/gpu/intern/gpu_storage_buffer_private.hh +++ b/source/blender/gpu/intern/gpu_storage_buffer_private.hh @@ -43,6 +43,7 @@ class StorageBuf { virtual void clear(eGPUTextureFormat internal_format, eGPUDataFormat data_format, void *data) = 0; + virtual void copy_sub(VertBuf *src, uint dst_offset, uint src_offset, uint copy_size) = 0; }; /* Syntactic sugar. */ diff --git a/source/blender/gpu/opengl/gl_storage_buffer.cc b/source/blender/gpu/opengl/gl_storage_buffer.cc index 109bb65fcb7..b30674fe5fa 100644 --- a/source/blender/gpu/opengl/gl_storage_buffer.cc +++ b/source/blender/gpu/opengl/gl_storage_buffer.cc @@ -144,6 +144,30 @@ void GLStorageBuf::clear(eGPUTextureFormat internal_format, eGPUDataFormat data_ } } +void GLStorageBuf::copy_sub(VertBuf *src_, uint dst_offset, uint src_offset, uint copy_size) +{ + GLVertBuf *src = static_cast(src_); + GLStorageBuf *dst = this; + + if (dst->ssbo_id_ == 0) { + dst->init(); + } + if (src->vbo_id_ == 0) { + src->bind(); + } + + if (GLContext::direct_state_access_support) { + glCopyNamedBufferSubData(src->vbo_id_, dst->ssbo_id_, src_offset, dst_offset, copy_size); + } + else { + /* This binds the buffer to GL_ARRAY_BUFFER and upload the data if any. */ + src->bind(); + glBindBuffer(GL_COPY_WRITE_BUFFER, dst->ssbo_id_); + glCopyBufferSubData(GL_ARRAY_BUFFER, GL_COPY_WRITE_BUFFER, src_offset, dst_offset, copy_size); + glBindBuffer(GL_COPY_WRITE_BUFFER, 0); + } +} + /** \} */ } // namespace blender::gpu diff --git a/source/blender/gpu/opengl/gl_storage_buffer.hh b/source/blender/gpu/opengl/gl_storage_buffer.hh index c808a0bdda1..96052fe0065 100644 --- a/source/blender/gpu/opengl/gl_storage_buffer.hh +++ b/source/blender/gpu/opengl/gl_storage_buffer.hh @@ -36,6 +36,7 @@ class GLStorageBuf : public StorageBuf { void bind(int slot) override; void unbind() override; void clear(eGPUTextureFormat internal_format, eGPUDataFormat data_format, void *data) override; + void copy_sub(VertBuf *src, uint dst_offset, uint src_offset, uint copy_size) override; /* Special internal function to bind SSBOs to indirect argument targets. */ void bind_as(GLenum target); diff --git a/source/blender/gpu/opengl/gl_vertex_buffer.hh b/source/blender/gpu/opengl/gl_vertex_buffer.hh index 88d2a455778..e0a21587b60 100644 --- a/source/blender/gpu/opengl/gl_vertex_buffer.hh +++ b/source/blender/gpu/opengl/gl_vertex_buffer.hh @@ -19,8 +19,9 @@ namespace blender { namespace gpu { class GLVertBuf : public VertBuf { - friend class GLTexture; /* For buffer texture. */ - friend class GLShader; /* For transform feedback. */ + friend class GLTexture; /* For buffer texture. */ + friend class GLShader; /* For transform feedback. */ + friend class GLStorageBuf; /* For sub copy. */ private: /** OpenGL buffer handle. Init on first upload. Immutable after that. */