[Bf-blender-cvs] [bb73a86977a] temp-gpu-compute-shaders: Add GPU api to read vertex/index buffers.

Jeroen Bakker noreply at git.blender.org
Tue May 11 10:55:48 CEST 2021


Commit: bb73a86977aff4bd83d5945cb45ca7ade43b3e5b
Author: Jeroen Bakker
Date:   Tue May 11 10:54:54 2021 +0200
Branches: temp-gpu-compute-shaders
https://developer.blender.org/rBbb73a86977aff4bd83d5945cb45ca7ade43b3e5b

Add GPU api to read vertex/index buffers.

===================================================================

M	source/blender/gpu/GPU_index_buffer.h
M	source/blender/gpu/GPU_vertex_buffer.h
M	source/blender/gpu/intern/gpu_index_buffer.cc
M	source/blender/gpu/intern/gpu_index_buffer_private.hh
M	source/blender/gpu/intern/gpu_vertex_buffer.cc
M	source/blender/gpu/intern/gpu_vertex_buffer_private.hh
M	source/blender/gpu/opengl/gl_index_buffer.cc
M	source/blender/gpu/opengl/gl_index_buffer.hh
M	source/blender/gpu/opengl/gl_vertex_buffer.cc
M	source/blender/gpu/opengl/gl_vertex_buffer.hh
M	source/blender/gpu/tests/gpu_shader_test.cc

===================================================================

diff --git a/source/blender/gpu/GPU_index_buffer.h b/source/blender/gpu/GPU_index_buffer.h
index 4fabf1eb0de..5ab0299c35d 100644
--- a/source/blender/gpu/GPU_index_buffer.h
+++ b/source/blender/gpu/GPU_index_buffer.h
@@ -80,6 +80,8 @@ void GPU_indexbuf_create_subrange_in_place(GPUIndexBuf *elem,
                                            uint start,
                                            uint length);
 
+uint32_t *GPU_indexbuf_read(GPUIndexBuf *elem);
+
 void GPU_indexbuf_discard(GPUIndexBuf *elem);
 
 bool GPU_indexbuf_is_init(GPUIndexBuf *elem);
diff --git a/source/blender/gpu/GPU_vertex_buffer.h b/source/blender/gpu/GPU_vertex_buffer.h
index 139b11557ec..b528c024e01 100644
--- a/source/blender/gpu/GPU_vertex_buffer.h
+++ b/source/blender/gpu/GPU_vertex_buffer.h
@@ -71,6 +71,7 @@ GPUVertBuf *GPU_vertbuf_create_with_format_ex(const GPUVertFormat *, GPUUsageTyp
 #define GPU_vertbuf_create_with_format(format) \
   GPU_vertbuf_create_with_format_ex(format, GPU_USAGE_STATIC)
 
+void *GPU_vertbuf_read(GPUVertBuf *verts);
 void GPU_vertbuf_clear(GPUVertBuf *verts);
 void GPU_vertbuf_discard(GPUVertBuf *);
 
diff --git a/source/blender/gpu/intern/gpu_index_buffer.cc b/source/blender/gpu/intern/gpu_index_buffer.cc
index 4d3894ce7d4..b9d1514c7c4 100644
--- a/source/blender/gpu/intern/gpu_index_buffer.cc
+++ b/source/blender/gpu/intern/gpu_index_buffer.cc
@@ -368,6 +368,11 @@ void GPU_indexbuf_create_subrange_in_place(GPUIndexBuf *elem,
   unwrap(elem)->init_subrange(unwrap(elem_src), start, length);
 }
 
+uint32_t *GPU_indexbuf_read(GPUIndexBuf *elem)
+{
+  return unwrap(elem)->read();
+}
+
 void GPU_indexbuf_discard(GPUIndexBuf *elem)
 {
   delete unwrap(elem);
diff --git a/source/blender/gpu/intern/gpu_index_buffer_private.hh b/source/blender/gpu/intern/gpu_index_buffer_private.hh
index 7acbf6f1194..113b054953f 100644
--- a/source/blender/gpu/intern/gpu_index_buffer_private.hh
+++ b/source/blender/gpu/intern/gpu_index_buffer_private.hh
@@ -82,7 +82,7 @@ class IndexBuf {
     return index_len_;
   }
   /* Return size in byte of the drawable data buffer range. Actual buffer size might be bigger. */
-  size_t size_get(void)
+  size_t size_get(void) const
   {
     return index_len_ * to_bytesize(index_type_);
   };
@@ -94,6 +94,8 @@ class IndexBuf {
 
   virtual void bind_as_ssbo(uint binding) = 0;
 
+  virtual uint32_t *read() const = 0;
+
  private:
   inline void squeeze_indices_short(uint min_idx, uint max_idx);
   inline uint index_range(uint *r_min, uint *r_max);
diff --git a/source/blender/gpu/intern/gpu_vertex_buffer.cc b/source/blender/gpu/intern/gpu_vertex_buffer.cc
index 3abd7e489f7..fa27ccfbed8 100644
--- a/source/blender/gpu/intern/gpu_vertex_buffer.cc
+++ b/source/blender/gpu/intern/gpu_vertex_buffer.cc
@@ -149,6 +149,11 @@ GPUVertBuf *GPU_vertbuf_duplicate(GPUVertBuf *verts_)
   return wrap(unwrap(verts_)->duplicate());
 }
 
+void *GPU_vertbuf_read(GPUVertBuf *verts)
+{
+  return unwrap(verts)->read();
+}
+
 /** Same as discard but does not free. */
 void GPU_vertbuf_clear(GPUVertBuf *verts)
 {
diff --git a/source/blender/gpu/intern/gpu_vertex_buffer_private.hh b/source/blender/gpu/intern/gpu_vertex_buffer_private.hh
index 03c60745f99..27e36ae3915 100644
--- a/source/blender/gpu/intern/gpu_vertex_buffer_private.hh
+++ b/source/blender/gpu/intern/gpu_vertex_buffer_private.hh
@@ -97,6 +97,7 @@ class VertBuf {
   }
 
   virtual void update_sub(uint start, uint len, void *data) = 0;
+  virtual void *read() = 0;
 
  protected:
   virtual void acquire_data(void) = 0;
diff --git a/source/blender/gpu/opengl/gl_index_buffer.cc b/source/blender/gpu/opengl/gl_index_buffer.cc
index 308fec40038..11822176bce 100644
--- a/source/blender/gpu/opengl/gl_index_buffer.cc
+++ b/source/blender/gpu/opengl/gl_index_buffer.cc
@@ -63,4 +63,24 @@ void GLIndexBuf::bind_as_ssbo(uint binding)
   glBindBufferBase(GL_SHADER_STORAGE_BUFFER, binding, ibo_id_);
 }
 
+uint32_t *GLIndexBuf::read() const
+{
+  BLI_assert(is_active());
+  size_t size = size_get();
+  uint32_t *result = static_cast<uint32_t *>(MEM_mallocN(size, __func__));
+  void *data = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
+  memcpy(result, data, size);
+  return result;
+}
+
+bool GLIndexBuf::is_active() const
+{
+  if (!ibo_id_) {
+    return false;
+  }
+  int active_ibo_id = 0;
+  glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &active_ibo_id);
+  return ibo_id_ == active_ibo_id;
+}
+
 }  // namespace blender::gpu
diff --git a/source/blender/gpu/opengl/gl_index_buffer.hh b/source/blender/gpu/opengl/gl_index_buffer.hh
index 2b0411d03f8..9a1f5c5d4e5 100644
--- a/source/blender/gpu/opengl/gl_index_buffer.hh
+++ b/source/blender/gpu/opengl/gl_index_buffer.hh
@@ -45,6 +45,8 @@ class GLIndexBuf : public IndexBuf {
   void bind(void);
   void bind_as_ssbo(uint binding) override;
 
+  uint32_t *read() const override;
+
   void *offset_ptr(uint additional_vertex_offset) const
   {
     additional_vertex_offset += index_start_;
@@ -59,6 +61,9 @@ class GLIndexBuf : public IndexBuf {
     return (index_type_ == GPU_INDEX_U16) ? 0xFFFFu : 0xFFFFFFFFu;
   }
 
+ private:
+  bool is_active() const;
+
   MEM_CXX_CLASS_ALLOC_FUNCS("GLIndexBuf")
 };
 
diff --git a/source/blender/gpu/opengl/gl_vertex_buffer.cc b/source/blender/gpu/opengl/gl_vertex_buffer.cc
index 9242ca090e5..477af8342f8 100644
--- a/source/blender/gpu/opengl/gl_vertex_buffer.cc
+++ b/source/blender/gpu/opengl/gl_vertex_buffer.cc
@@ -123,6 +123,25 @@ void GLVertBuf::bind_as_ssbo(uint binding)
   glBindBufferBase(GL_SHADER_STORAGE_BUFFER, binding, vbo_id_);
 }
 
+void *GLVertBuf::read()
+{
+  BLI_assert(is_active());
+  void *result = MEM_mallocN(vbo_size_, __func__);
+  void *data = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
+  memcpy(result, data, vbo_size_);
+  return result;
+}
+
+bool GLVertBuf::is_active() const
+{
+  if (!vbo_id_) {
+    return false;
+  }
+  int active_vbo_id = 0;
+  glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &active_vbo_id);
+  return vbo_id_ == active_vbo_id;
+}
+
 void GLVertBuf::update_sub(uint start, uint len, void *data)
 {
   glBufferSubData(GL_ARRAY_BUFFER, start, len, data);
diff --git a/source/blender/gpu/opengl/gl_vertex_buffer.hh b/source/blender/gpu/opengl/gl_vertex_buffer.hh
index 77e68908e61..fd7a63db519 100644
--- a/source/blender/gpu/opengl/gl_vertex_buffer.hh
+++ b/source/blender/gpu/opengl/gl_vertex_buffer.hh
@@ -47,6 +47,8 @@ class GLVertBuf : public VertBuf {
 
   void update_sub(uint start, uint len, void *data) override;
 
+  void *read() override;
+
  protected:
   void acquire_data(void) override;
   void resize_data(void) override;
@@ -55,6 +57,9 @@ class GLVertBuf : public VertBuf {
   void duplicate_data(VertBuf *dst) override;
   void bind_as_ssbo(uint binding) override;
 
+ private:
+  bool is_active() const;
+
   MEM_CXX_CLASS_ALLOC_FUNCS("GLVertBuf");
 };
 
diff --git a/source/blender/gpu/tests/gpu_shader_test.cc b/source/blender/gpu/tests/gpu_shader_test.cc
index ef06307a9ae..daa9c112060 100644
--- a/source/blender/gpu/tests/gpu_shader_test.cc
+++ b/source/blender/gpu/tests/gpu_shader_test.cc
@@ -185,9 +185,8 @@ void main() {
   /* Check if compute has been done. */
   GPU_memory_barrier(GPU_BARRIER_SHADER_STORAGE);
 
-  /* Use opengl function to download the vertex buffer. */
-  /* TODO(jbakker): Add function to copy it back to the VertexBuffer data. */
-  float *data = static_cast<float *>(glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY));
+  /* Download the vertex buffer. */
+  float *data = static_cast<float *>(GPU_vertbuf_read(vbo));
   ASSERT_NE(data, nullptr);
   for (int index = 0; index < SIZE; index++) {
     float expected_value = index;
@@ -196,6 +195,7 @@ void main() {
     EXPECT_FLOAT_EQ(data[index * 4 + 2], expected_value);
     EXPECT_FLOAT_EQ(data[index * 4 + 3], expected_value);
   }
+  MEM_freeN(data);
 
   /* Cleanup. */
   GPU_shader_unbind();
@@ -246,15 +246,14 @@ void main() {
   /* Check if compute has been done. */
   GPU_memory_barrier(GPU_BARRIER_SHADER_STORAGE);
 
-  /* Use opengl function to download the index buffer. */
-  /* TODO(jbakker): Add function to copy it back to the IndexBuffer data and accessors to read
-   * data. */
-  uint32_t *data = static_cast<uint32_t *>(glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_READ_ONLY));
+  /* Download the index buffer. */
+  uint32_t *data = GPU_indexbuf_read(ibo);
   ASSERT_NE(data, nullptr);
   for (int index = 0; index < SIZE; index++) {
     uint32_t expected = index;
     EXPECT_EQ(data[index], expected);
   }
+  MEM_freeN(data);
 
   /* Cleanup. */
   GPU_shader_unbind();
@@ -264,7 +263,6 @@ void main() {
 
 TEST_F(GPUTest, gpu_shader_ssbo_binding)
 {
-
   if (!GPU_compute_shader_support()) {
     /* We can't test as a the platform does not support compute shaders. */
     std::cout << "Skipping compute shader test: platform not supported";



More information about the Bf-blender-cvs mailing list