[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