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.
This commit is contained in:
2018-05-16 12:47:15 +02:00
parent a3f4c72ec9
commit a25856f2a8
8 changed files with 113 additions and 5 deletions

View File

@@ -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();
}