[Bf-blender-cvs] [c41c15d62c9] temp-gpu-compute-shaders: Use IBO buffer as a target for a compute shader.

Jeroen Bakker noreply at git.blender.org
Wed Apr 28 11:55:15 CEST 2021


Commit: c41c15d62c95743fe55fbeca069ce3b064cd59d3
Author: Jeroen Bakker
Date:   Wed Apr 28 11:34:36 2021 +0200
Branches: temp-gpu-compute-shaders
https://developer.blender.org/rBc41c15d62c95743fe55fbeca069ce3b064cd59d3

Use IBO buffer as a target for a compute shader.

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

M	source/blender/gpu/GPU_shader.h
M	source/blender/gpu/intern/gpu_shader.cc
M	source/blender/gpu/intern/gpu_shader_private.hh
M	source/blender/gpu/opengl/gl_index_buffer.hh
M	source/blender/gpu/opengl/gl_shader.cc
M	source/blender/gpu/opengl/gl_shader.hh
M	source/blender/gpu/tests/gpu_shader_test.cc

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

diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h
index bb84aaa0645..6eea690627f 100644
--- a/source/blender/gpu/GPU_shader.h
+++ b/source/blender/gpu/GPU_shader.h
@@ -27,6 +27,7 @@
 extern "C" {
 #endif
 
+struct GPUIndexBuf;
 struct GPUVertBuf;
 
 /** Opaque type hiding #blender::gpu::Shader */
@@ -89,6 +90,7 @@ bool GPU_shader_transform_feedback_enable(GPUShader *shader, struct GPUVertBuf *
 void GPU_shader_transform_feedback_disable(GPUShader *shader);
 
 void GPU_shader_attach_vertex_buffer(GPUShader *shader, struct GPUVertBuf *vertbuf, int location);
+void GPU_shader_attach_index_buffer(GPUShader *shader, struct GPUIndexBuf *indexbuf, int location);
 
 int GPU_shader_get_program(GPUShader *shader);
 
diff --git a/source/blender/gpu/intern/gpu_shader.cc b/source/blender/gpu/intern/gpu_shader.cc
index b5c3b2c3f58..304d5d4a296 100644
--- a/source/blender/gpu/intern/gpu_shader.cc
+++ b/source/blender/gpu/intern/gpu_shader.cc
@@ -591,6 +591,11 @@ void GPU_shader_attach_vertex_buffer(GPUShader *shader, struct GPUVertBuf *vertb
   unwrap(shader)->attach_buffer(vertbuf, position);
 }
 
+void GPU_shader_attach_index_buffer(GPUShader *shader, struct GPUIndexBuf *indexbuf, int position)
+{
+  unwrap(shader)->attach_buffer(indexbuf, position);
+}
+
 /** \} */
 
 /* -------------------------------------------------------------------- */
diff --git a/source/blender/gpu/intern/gpu_shader_private.hh b/source/blender/gpu/intern/gpu_shader_private.hh
index a6f2e617777..1e2e2e0da64 100644
--- a/source/blender/gpu/intern/gpu_shader_private.hh
+++ b/source/blender/gpu/intern/gpu_shader_private.hh
@@ -58,6 +58,7 @@ class Shader {
   virtual void transform_feedback_disable(void) = 0;
 
   virtual void attach_buffer(GPUVertBuf *vertex_buffer, uint location) = 0;
+  virtual void attach_buffer(GPUIndexBuf *index_buffer, uint location) = 0;
 
   virtual void bind(void) = 0;
   virtual void unbind(void) = 0;
diff --git a/source/blender/gpu/opengl/gl_index_buffer.hh b/source/blender/gpu/opengl/gl_index_buffer.hh
index b84934bb77f..9c89b8ae87d 100644
--- a/source/blender/gpu/opengl/gl_index_buffer.hh
+++ b/source/blender/gpu/opengl/gl_index_buffer.hh
@@ -34,6 +34,7 @@ namespace blender::gpu {
 class GLIndexBuf : public IndexBuf {
   friend class GLBatch;
   friend class GLDrawList;
+  friend class GLShader; /* For compute shaders. */
 
  private:
   GLuint ibo_id_ = 0;
diff --git a/source/blender/gpu/opengl/gl_shader.cc b/source/blender/gpu/opengl/gl_shader.cc
index c0809a0387e..e8c89f87a8a 100644
--- a/source/blender/gpu/opengl/gl_shader.cc
+++ b/source/blender/gpu/opengl/gl_shader.cc
@@ -313,6 +313,15 @@ void GLShader::attach_buffer(GPUVertBuf *vertex_buffer_, unsigned int location)
   glBindBufferBase(GL_SHADER_STORAGE_BUFFER, location, vertex_buffer->vbo_id_);
 }
 
+void GLShader::attach_buffer(GPUIndexBuf *index_buffer_, unsigned int location)
+{
+  BLI_assert(GPU_compute_shader_support());
+  GLIndexBuf *index_buffer = static_cast<GLIndexBuf *>(unwrap(index_buffer_));
+  index_buffer->bind();
+  BLI_assert(index_buffer->ibo_id_ != 0);
+  glBindBufferBase(GL_SHADER_STORAGE_BUFFER, location, index_buffer->ibo_id_);
+}
+
 /** \} */
 
 /* -------------------------------------------------------------------- */
diff --git a/source/blender/gpu/opengl/gl_shader.hh b/source/blender/gpu/opengl/gl_shader.hh
index 3993944b974..88748f08c54 100644
--- a/source/blender/gpu/opengl/gl_shader.hh
+++ b/source/blender/gpu/opengl/gl_shader.hh
@@ -66,6 +66,7 @@ class GLShader : public Shader {
   void transform_feedback_disable(void) override;
 
   void attach_buffer(GPUVertBuf *vertex_buffer, uint location) override;
+  void attach_buffer(GPUIndexBuf *index_buffer, uint location) override;
 
   void bind(void) override;
   void unbind(void) override;
diff --git a/source/blender/gpu/tests/gpu_shader_test.cc b/source/blender/gpu/tests/gpu_shader_test.cc
index a864c70c826..937e13cd4a6 100644
--- a/source/blender/gpu/tests/gpu_shader_test.cc
+++ b/source/blender/gpu/tests/gpu_shader_test.cc
@@ -4,6 +4,7 @@
 
 #include "GPU_capabilities.h"
 #include "GPU_compute.h"
+#include "GPU_index_buffer.h"
 #include "GPU_shader.h"
 #include "GPU_texture.h"
 #include "GPU_vertex_buffer.h"
@@ -185,7 +186,6 @@ void main() {
   for (int i = 0; i < SIZE; i++) {
     GPU_vertbuf_vert_set(vbo, i, dummy);
   }
-  GPU_vertbuf_use(vbo);
 
   GPU_shader_attach_vertex_buffer(shader, vbo, 0);
 
@@ -214,4 +214,139 @@ void main() {
   GPU_shader_free(shader);
 }
 
+TEST_F(GPUTest, gpu_shader_compute_ibo_short)
+{
+
+  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";
+    return;
+  }
+
+  static constexpr uint SIZE = 128;
+
+  /* Build compute shader. */
+  const char *compute_glsl = R"(
+
+layout(local_size_x = 1) in;
+
+layout(std430, binding = 0) buffer outputIboData
+{
+  int Indexes[];
+};
+
+void main() {
+  int store_index = int(gl_GlobalInvocationID.x);
+  int index1 = store_index * 2;
+  int index2 = store_index *2 + 1;
+  int store = ((index2 & 0xFFFF) << 16) | (index1 & 0xFFFF);
+  Indexes[store_index] = store;
+}
+
+)";
+
+  GPUShader *shader = GPU_shader_create_compute(
+      compute_glsl, nullptr, nullptr, "gpu_shader_compute_vbo");
+  EXPECT_NE(shader, nullptr);
+  GPU_shader_bind(shader);
+
+  /* Construct IBO. */
+  GPUIndexBufBuilder ibo_builder;
+  const int max_vertex_index = 65536;
+  GPU_indexbuf_init(&ibo_builder, GPU_PRIM_POINTS, SIZE, max_vertex_index);
+  for (int index = 0; index < SIZE; index++) {
+    GPU_indexbuf_set_point_vert(&ibo_builder, index, 57005);
+  }
+  GPUIndexBuf *ibo = GPU_indexbuf_build(&ibo_builder);
+
+  GPU_shader_attach_index_buffer(shader, ibo, 0);
+
+  /* Dispatch compute task. */
+  GPU_compute_dispatch(shader, SIZE / 2, 1, 1);
+
+  /* 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 IndexBuffer data. */
+  uint16_t *data = static_cast<uint16_t *>(glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_READ_ONLY));
+  ASSERT_NE(data, nullptr);
+  /* Create texture to load back result. */
+  for (int index = 0; index < SIZE; index++) {
+    EXPECT_EQ(data[index], index);
+  }
+
+  /* Cleanup. */
+  GPU_shader_unbind();
+  GPU_indexbuf_discard(ibo);
+  GPU_shader_free(shader);
+}
+
+TEST_F(GPUTest, gpu_shader_compute_ibo_int)
+{
+
+  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";
+    return;
+  }
+
+  static constexpr uint SIZE = 128;
+
+  /* Build compute shader. */
+  const char *compute_glsl = R"(
+
+layout(local_size_x = 1) in;
+
+layout(std430, binding = 0) buffer outputIboData
+{
+  int Indexes[];
+};
+
+void main() {
+  int store_index = int(gl_GlobalInvocationID.x);
+  int store = store_index;
+  Indexes[store_index] = store;
+}
+
+)";
+
+  GPUShader *shader = GPU_shader_create_compute(
+      compute_glsl, nullptr, nullptr, "gpu_shader_compute_vbo");
+  EXPECT_NE(shader, nullptr);
+  GPU_shader_bind(shader);
+
+  /* Construct IBO. */
+  GPUIndexBufBuilder ibo_builder;
+  GPU_indexbuf_init(&ibo_builder, GPU_PRIM_POINTS, SIZE, 0);
+  for (int index = 0; index < SIZE; index++) {
+    GPU_indexbuf_set_point_vert(&ibo_builder, index, 65536 * index);
+  }
+  GPUIndexBuf *ibo = GPU_indexbuf_build(&ibo_builder);
+
+  GPU_shader_attach_index_buffer(shader, ibo, 0);
+
+  /* Dispatch compute task. */
+  GPU_compute_dispatch(shader, SIZE, 1, 1);
+
+  /* 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 IndexBuffer data and accessors to read
+   * data. */
+  uint32_t *data = static_cast<uint32_t *>(glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_READ_ONLY));
+  ASSERT_NE(data, nullptr);
+  /* Create texture to load back result. */
+  for (int index = 0; index < SIZE; index++) {
+    uint32_t expected = index;
+    EXPECT_EQ(data[index], expected);
+  }
+
+  /* Cleanup. */
+  GPU_shader_unbind();
+  GPU_indexbuf_discard(ibo);
+  GPU_shader_free(shader);
+}
+
 }  // namespace blender::gpu::tests



More information about the Bf-blender-cvs mailing list