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/draw
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/draw')
-rw-r--r--source/blender/draw/intern/DRW_render.h6
-rw-r--r--source/blender/draw/intern/draw_manager.h5
-rw-r--r--source/blender/draw/intern/draw_manager_data.c14
-rw-r--r--source/blender/draw/intern/draw_manager_exec.c29
-rw-r--r--source/blender/draw/intern/draw_manager_shader.c8
5 files changed, 60 insertions, 2 deletions
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
index 901f009e7ed..827ac4701e5 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -47,6 +47,7 @@
#include "GPU_framebuffer.h"
#include "GPU_texture.h"
+#include "GPU_shader.h"
#include "draw_common.h"
#include "draw_cache.h"
@@ -229,6 +230,9 @@ struct GPUShader *DRW_shader_create(
const char *vert, const char *geom, const char *frag, const char *defines);
struct GPUShader *DRW_shader_create_with_lib(
const char *vert, const char *geom, const char *frag, const char *lib, const char *defines);
+struct GPUShader *DRW_shader_create_with_transform_feedback(
+ const char *vert, const char *geom, const char *defines,
+ const GPUShaderTFBType prim_type, const char **varying_names, const int varying_count);
struct GPUShader *DRW_shader_create_2D(const char *frag, const char *defines);
struct GPUShader *DRW_shader_create_3D(const char *frag, const char *defines);
struct GPUShader *DRW_shader_create_fullscreen(const char *frag, const char *defines);
@@ -274,6 +278,7 @@ typedef enum {
DRW_STATE_ADDITIVE_FULL = (1 << 19), /* Same as DRW_STATE_ADDITIVE but let alpha accumulate without premult. */
DRW_STATE_BLEND_PREMUL = (1 << 20), /* Use that if color is already premult by alpha. */
DRW_STATE_WIRE_SMOOTH = (1 << 21),
+ DRW_STATE_TRANS_FEEDBACK = (1 << 22),
DRW_STATE_WRITE_STENCIL = (1 << 27),
DRW_STATE_WRITE_STENCIL_SHADOW = (1 << 28),
@@ -312,6 +317,7 @@ DRWShadingGroup *DRW_shgroup_instance_create(
DRWShadingGroup *DRW_shgroup_point_batch_create(struct GPUShader *shader, DRWPass *pass);
DRWShadingGroup *DRW_shgroup_line_batch_create(struct GPUShader *shader, DRWPass *pass);
DRWShadingGroup *DRW_shgroup_empty_tri_batch_create(struct GPUShader *shader, DRWPass *pass, int size);
+DRWShadingGroup *DRW_shgroup_transform_feedback_create(struct GPUShader *shader, DRWPass *pass, struct Gwn_VertBuf *tf_target);
typedef void (DRWCallGenerateFn)(
DRWShadingGroup *shgroup,
diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h
index e71da41f118..0f9a68552fe 100644
--- a/source/blender/draw/intern/draw_manager.h
+++ b/source/blender/draw/intern/draw_manager.h
@@ -193,6 +193,7 @@ typedef enum {
DRW_SHG_TRIANGLE_BATCH,
DRW_SHG_INSTANCE,
DRW_SHG_INSTANCE_EXTERNAL,
+ DRW_SHG_FEEDBACK_TRANSFORM,
} DRWShadingGroupType;
struct DRWShadingGroup {
@@ -206,6 +207,10 @@ struct DRWShadingGroup {
struct { /* DRW_SHG_NORMAL */
DRWCall *first, *last; /* Linked list of DRWCall or DRWCallDynamic depending of type */
} calls;
+ struct { /* DRW_SHG_FEEDBACK_TRANSFORM */
+ DRWCall *first, *last; /* Linked list of DRWCall or DRWCallDynamic depending of type */
+ struct Gwn_VertBuf *tfeedback_target; /* Transform Feedback target. */
+ };
struct { /* DRW_SHG_***_BATCH */
struct Gwn_Batch *batch_geom; /* Result of call batching */
struct Gwn_VertBuf *batch_vbo;
diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c
index 306ca0c6a3c..6f4de3bb02b 100644
--- a/source/blender/draw/intern/draw_manager_data.c
+++ b/source/blender/draw/intern/draw_manager_data.c
@@ -353,7 +353,7 @@ static DRWCallState *drw_call_state_object(DRWShadingGroup *shgroup, float (*obm
void DRW_shgroup_call_add(DRWShadingGroup *shgroup, Gwn_Batch *geom, float (*obmat)[4])
{
BLI_assert(geom != NULL);
- BLI_assert(shgroup->type == DRW_SHG_NORMAL);
+ BLI_assert(ELEM(shgroup->type, DRW_SHG_NORMAL, DRW_SHG_FEEDBACK_TRANSFORM));
DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls);
call->state = drw_call_state_create(shgroup, obmat, NULL);
@@ -828,6 +828,18 @@ DRWShadingGroup *DRW_shgroup_empty_tri_batch_create(struct GPUShader *shader, DR
return shgroup;
}
+DRWShadingGroup *DRW_shgroup_transform_feedback_create(struct GPUShader *shader, DRWPass *pass, Gwn_VertBuf *tf_target)
+{
+ DRWShadingGroup *shgroup = drw_shgroup_create_ex(shader, pass);
+ shgroup->type = DRW_SHG_FEEDBACK_TRANSFORM;
+
+ drw_shgroup_init(shgroup, shader);
+
+ shgroup->tfeedback_target = tf_target;
+
+ return shgroup;
+}
+
/* Specify an external batch instead of adding each attrib one by one. */
void DRW_shgroup_instance_batch(DRWShadingGroup *shgroup, struct Gwn_Batch *batch)
{
diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c
index 033168680b8..78ac96e41b2 100644
--- a/source/blender/draw/intern/draw_manager_exec.c
+++ b/source/blender/draw/intern/draw_manager_exec.c
@@ -102,6 +102,21 @@ void drw_state_set(DRWState state)
}
}
+ /* Raster Discard */
+ {
+ if (CHANGED_ANY(DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR |
+ DRW_STATE_WRITE_STENCIL | DRW_STATE_WRITE_STENCIL_SHADOW))
+ {
+ if ((state & (DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR |
+ DRW_STATE_WRITE_STENCIL | DRW_STATE_WRITE_STENCIL_SHADOW)) != 0) {
+ glDisable(GL_RASTERIZER_DISCARD);
+ }
+ else {
+ glEnable(GL_RASTERIZER_DISCARD);
+ }
+ }
+ }
+
/* Cull */
{
DRWState test;
@@ -900,6 +915,7 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
int val;
float fval;
const bool shader_changed = (DST.shader != shgroup->shader);
+ bool use_tfeedback = false;
if (shader_changed) {
if (DST.shader) GPU_shader_unbind();
@@ -907,6 +923,13 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
DST.shader = shgroup->shader;
}
+ if ((pass_state & DRW_STATE_TRANS_FEEDBACK) != 0 &&
+ (shgroup->type == DRW_SHG_FEEDBACK_TRANSFORM))
+ {
+ use_tfeedback = GPU_shader_transform_feedback_enable(shgroup->shader,
+ shgroup->tfeedback_target->vbo_id);
+ }
+
release_ubo_slots(shader_changed);
release_texture_slots(shader_changed);
@@ -1023,7 +1046,7 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
#endif
/* Rendering Calls */
- if (!ELEM(shgroup->type, DRW_SHG_NORMAL)) {
+ if (!ELEM(shgroup->type, DRW_SHG_NORMAL, DRW_SHG_FEEDBACK_TRANSFORM)) {
/* Replacing multiple calls with only one */
if (ELEM(shgroup->type, DRW_SHG_INSTANCE, DRW_SHG_INSTANCE_EXTERNAL)) {
if (shgroup->type == DRW_SHG_INSTANCE_EXTERNAL) {
@@ -1104,6 +1127,10 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
glFrontFace(DST.frontface);
}
+ if (use_tfeedback) {
+ GPU_shader_transform_feedback_disable(shgroup->shader);
+ }
+
/* TODO: remove, (currently causes alpha issue with sculpt, need to investigate) */
DRW_state_reset();
}
diff --git a/source/blender/draw/intern/draw_manager_shader.c b/source/blender/draw/intern/draw_manager_shader.c
index 06a579c2208..77fcb766743 100644
--- a/source/blender/draw/intern/draw_manager_shader.c
+++ b/source/blender/draw/intern/draw_manager_shader.c
@@ -295,6 +295,14 @@ GPUShader *DRW_shader_create_with_lib(
return sh;
}
+GPUShader *DRW_shader_create_with_transform_feedback(
+ const char *vert, const char *geom, const char *defines,
+ const GPUShaderTFBType prim_type, const char **varying_names, const int varying_count)
+{
+ return GPU_shader_create_ex(vert, NULL, geom, NULL, defines, GPU_SHADER_FLAGS_NONE,
+ prim_type, varying_names, varying_count);
+}
+
GPUShader *DRW_shader_create_2D(const char *frag, const char *defines)
{
return GPU_shader_create(datatoc_gpu_shader_2D_vert_glsl, frag, NULL, NULL, defines);