Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2018-05-16 13:47:15 +0300
committerClément Foucault <foucault.clem@gmail.com>2018-05-16 17:58:32 +0300
commita25856f2a802dae4e2c4c01e9b74d8c8a1769933 (patch)
tree1ae725b9d04c36f4847c5bc08fb55f4a0f7a8aab /source/blender/gpu
parenta3f4c72ec9d431f65bf9f50b7849e22e2f213ad0 (diff)
GPUShader/DRW: Add Transform Feedback support.
This is a usefull feature that can be used to do a lot of precomputation on the GPU instead of the CPU. Implementation is simple and only covers the most usefull case. How to use: - Create shader with transform feedback. - Create a pass with DRW_STATE_TRANS_FEEDBACK. - Create a target Gwn_VertBuf (make sure it's big enough). - Create a shading group with DRW_shgroup_transform_feedback_create(). - Add your draw calls to the shading group. - Render your pass normaly. Current limitation: - Only one output buffer. - Cannot pause/resume tfb rendering to interleave with normal drawcalls. - Cannot get the number of verts drawn.
Diffstat (limited to 'source/blender/gpu')
-rw-r--r--source/blender/gpu/GPU_shader.h16
-rw-r--r--source/blender/gpu/intern/gpu_shader.c38
-rw-r--r--source/blender/gpu/intern/gpu_shader_private.h2
3 files changed, 53 insertions, 3 deletions
diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h
index 2a672873d86..baaa23c2398 100644
--- a/source/blender/gpu/GPU_shader.h
+++ b/source/blender/gpu/GPU_shader.h
@@ -50,6 +50,13 @@ enum {
GPU_SHADER_FLAGS_NEW_SHADING = (1 << 1),
};
+typedef enum GPUShaderTFBType {
+ GPU_SHADER_TFB_NONE = 0, /* Transform feedback unsupported. */
+ GPU_SHADER_TFB_POINTS = 1,
+ GPU_SHADER_TFB_LINES = 2,
+ GPU_SHADER_TFB_TRIANGLES = 3,
+} GPUShaderTFBType;
+
GPUShader *GPU_shader_create(
const char *vertexcode,
const char *fragcode,
@@ -62,12 +69,19 @@ GPUShader *GPU_shader_create_ex(
const char *geocode,
const char *libcode,
const char *defines,
- const int flags);
+ const int flags,
+ const GPUShaderTFBType tf_type,
+ const char **tf_names,
+ const int tf_count);
void GPU_shader_free(GPUShader *shader);
void GPU_shader_bind(GPUShader *shader);
void GPU_shader_unbind(void);
+/* Returns true if transform feedback was succesfully enabled. */
+bool GPU_shader_transform_feedback_enable(GPUShader *shader, unsigned int vbo_id);
+void GPU_shader_transform_feedback_disable(GPUShader *shader);
+
int GPU_shader_get_program(GPUShader *shader);
void *GPU_shader_get_interface(GPUShader *shader);
diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c
index 02baa2e58cb..2068c5a6a75 100644
--- a/source/blender/gpu/intern/gpu_shader.c
+++ b/source/blender/gpu/intern/gpu_shader.c
@@ -268,7 +268,10 @@ GPUShader *GPU_shader_create(const char *vertexcode,
geocode,
libcode,
defines,
- GPU_SHADER_FLAGS_NONE);
+ GPU_SHADER_FLAGS_NONE,
+ GPU_SHADER_TFB_NONE,
+ NULL,
+ 0);
}
#define DEBUG_SHADER_NONE ""
@@ -323,7 +326,10 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode,
const char *geocode,
const char *libcode,
const char *defines,
- const int flags)
+ const int flags,
+ const GPUShaderTFBType tf_type,
+ const char **tf_names,
+ const int tf_count)
{
#ifdef WITH_OPENSUBDIV
bool use_opensubdiv = (flags & GPU_SHADER_FLAGS_SPECIAL_OPENSUBDIV) != 0;
@@ -469,6 +475,13 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode,
}
#endif
+ if (tf_names != NULL) {
+ glTransformFeedbackVaryings(shader->program, tf_count, tf_names, GL_INTERLEAVED_ATTRIBS);
+ /* Primitive type must be setup */
+ BLI_assert(tf_type != GPU_SHADER_TFB_NONE);
+ shader->feedback_transform_type = tf_type;
+ }
+
glLinkProgram(shader->program);
glGetProgramiv(shader->program, GL_LINK_STATUS, &status);
if (!status) {
@@ -527,6 +540,27 @@ void GPU_shader_unbind(void)
glUseProgram(0);
}
+bool GPU_shader_transform_feedback_enable(GPUShader *shader, unsigned int vbo_id)
+{
+ if (shader->feedback_transform_type == GPU_SHADER_TFB_NONE) {
+ return false;
+ }
+
+ glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, vbo_id);
+
+ switch (shader->feedback_transform_type) {
+ case GPU_SHADER_TFB_POINTS: glBeginTransformFeedback(GL_POINTS); return true;
+ case GPU_SHADER_TFB_LINES: glBeginTransformFeedback(GL_LINES); return true;
+ case GPU_SHADER_TFB_TRIANGLES: glBeginTransformFeedback(GL_TRIANGLES); return true;
+ default: return false;
+ }
+}
+
+void GPU_shader_transform_feedback_disable(GPUShader *UNUSED(shader))
+{
+ glEndTransformFeedback();
+}
+
void GPU_shader_free(GPUShader *shader)
{
BLI_assert(shader);
diff --git a/source/blender/gpu/intern/gpu_shader_private.h b/source/blender/gpu/intern/gpu_shader_private.h
index 67d8c6e6213..d8ec6b5d6d1 100644
--- a/source/blender/gpu/intern/gpu_shader_private.h
+++ b/source/blender/gpu/intern/gpu_shader_private.h
@@ -36,6 +36,8 @@ struct GPUShader {
GLuint fragment; /* handle for fragment shader */
Gwn_ShaderInterface *interface; /* cached uniform & attrib interface for shader */
+
+ int feedback_transform_type;
};
#endif /* __GPU_SHADER_PRIVATE_H__ */