Commit: 72a2f4ec6d5111d572b8029d11fb512049787a37 Author: Jeroen Bakker Date: Fri Apr 23 14:11:17 2021 +0200 Branches: temp-gpu-compute-shader-hair https://developer.blender.org/rB72a2f4ec6d5111d572b8029d11fb512049787a37
DrawManager: Use Compute Shader to Update Hair. Differential Revision: https://developer.blender.org/D11057 =================================================================== M source/blender/draw/intern/DRW_render.h M source/blender/draw/intern/draw_hair.c M source/blender/draw/intern/draw_manager.h M source/blender/draw/intern/draw_manager_data.c M source/blender/draw/intern/draw_manager_exec.c M source/blender/draw/intern/shaders/common_hair_lib.glsl M source/blender/draw/intern/shaders/common_hair_refine_vert.glsl M source/blender/gpu/intern/gpu_shader.cc =================================================================== diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h index 2545cfa65dc..949a2225aa6 100644 --- a/source/blender/draw/intern/DRW_render.h +++ b/source/blender/draw/intern/DRW_render.h @@ -438,6 +438,10 @@ void DRW_shgroup_call_range( void DRW_shgroup_call_instance_range( DRWShadingGroup *shgroup, Object *ob, struct GPUBatch *geom, uint i_sta, uint i_ct); +void DRW_shgroup_call_compute(DRWShadingGroup *shgroup, + int groups_x_len, + int groups_y_len, + int groups_z_len); void DRW_shgroup_call_procedural_points(DRWShadingGroup *sh, Object *ob, uint point_count); void DRW_shgroup_call_procedural_lines(DRWShadingGroup *sh, Object *ob, uint line_count); void DRW_shgroup_call_procedural_triangles(DRWShadingGroup *sh, Object *ob, uint tri_count); diff --git a/source/blender/draw/intern/draw_hair.c b/source/blender/draw/intern/draw_hair.c index bca227a24e2..70768273e1b 100644 --- a/source/blender/draw/intern/draw_hair.c +++ b/source/blender/draw/intern/draw_hair.c @@ -36,15 +36,27 @@ #include "BKE_duplilist.h" #include "GPU_batch.h" +#include "GPU_capabilities.h" #include "GPU_shader.h" #include "GPU_vertex_buffer.h" #include "draw_hair_private.h" +#include "PIL_time_utildefines.h" + #ifndef __APPLE__ # define USE_TRANSFORM_FEEDBACK #endif +BLI_INLINE bool drw_hair_use_compute_shaders(void) +{ +#ifdef USE_TRANSFORM_FEEDBACK + return false; // GPU_compute_shader_support(); +#else + return false; +#endif +} + typedef enum ParticleRefineShader { PART_REFINE_CATMULL_ROM = 0, PART_REFINE_MAX_SHADER, @@ -79,15 +91,24 @@ static GPUShader *hair_refine_shader_get(ParticleRefineShader sh) return g_refine_shaders[sh]; } - char *vert_with_lib = BLI_string_joinN(datatoc_common_hair_lib_glsl, - datatoc_common_hair_refine_vert_glsl); - #ifdef USE_TRANSFORM_FEEDBACK + const bool do_compute = drw_hair_use_compute_shaders(); + if (do_compute) { + g_refine_shaders[sh] = GPU_shader_create_compute(datatoc_common_hair_refine_vert_glsl, + datatoc_common_hair_lib_glsl, + "#define HAIR_PHASE_SUBDIV\n", + __func__); + return g_refine_shaders[sh]; + } + + char *shader_src = BLI_string_joinN(datatoc_common_hair_lib_glsl, + datatoc_common_hair_refine_vert_glsl); const char *var_names[1] = {"finalColor"}; g_refine_shaders[sh] = DRW_shader_create_with_transform_feedback( - vert_with_lib, NULL, "#define HAIR_PHASE_SUBDIV\n", GPU_SHADER_TFB_POINTS, var_names, 1); + shader_src, NULL, "#define HAIR_PHASE_SUBDIV\n", GPU_SHADER_TFB_POINTS, var_names, 1); + #else - g_refine_shaders[sh] = DRW_shader_create(vert_with_lib, + g_refine_shaders[sh] = DRW_shader_create(shader_src, NULL, datatoc_gpu_shader_3D_smooth_color_frag_glsl, "#define blender_srgb_to_framebuffer_space(a) a\n" @@ -95,7 +116,7 @@ static GPUShader *hair_refine_shader_get(ParticleRefineShader sh) "#define TF_WORKAROUND\n"); #endif - MEM_freeN(vert_with_lib); + MEM_freeN(shader_src); return g_refine_shaders[sh]; } @@ -125,6 +146,59 @@ void DRW_hair_init(void) } } +static void drw_hair_particle_cache_shgrp_attach_resources(DRWShadingGroup *shgrp, + ParticleHairCache *cache, + const int subdiv) +{ + DRW_shgroup_uniform_texture(shgrp, "hairPointBuffer", cache->point_tex); + DRW_shgroup_uniform_texture(shgrp, "hairStrandBuffer", cache->strand_tex); + DRW_shgroup_uniform_texture(shgrp, "hairStrandSegBuffer", cache->strand_seg_tex); + DRW_shgroup_uniform_int(shgrp, "hairStrandsRes", &cache->final[subdiv].strands_res, 1); +} + +static void drw_hair_particle_cache_update_compute(ParticleHairCache *cache, const int subdiv) +{ + const int final_points_len = cache->final[subdiv].strands_res * cache->strands_len; + if (final_points_len > 0) { + GPUShader *shader = hair_refine_shader_get(PART_REFINE_CATMULL_ROM); + + DRWShadingGroup *shgrp = DRW_shgroup_create(shader, g_tf_pass); + + drw_hair_particle_cache_shgrp_attach_resources(shgrp, cache, subdiv); + DRW_shgroup_uniform_image(shgrp, "hairPointOutputBuffer", cache->point_tex); + DRW_shgroup_call_compute(shgrp, cache->strands_len, cache->final[subdiv].strands_res, 1); + } +} + +static void drw_hair_particle_cache_update_transform_feedback(ParticleHairCache *cache, + const int subdiv) +{ + const int final_points_len = cache->final[subdiv].strands_res * cache->strands_len; + if (final_points_len > 0) { + GPUShader *tf_shader = hair_refine_shader_get(PART_REFINE_CATMULL_ROM); + +#ifdef USE_TRANSFORM_FEEDBACK + DRWShadingGroup *tf_shgrp = DRW_shgroup_transform_feedback_create( + tf_shader, g_tf_pass, cache->final[subdiv].proc_buf); +#else + DRWShadingGroup *tf_shgrp = DRW_shgroup_create(tf_shader, g_tf_pass); + + ParticleRefineCall *pr_call = MEM_mallocN(sizeof(*pr_call), __func__); + pr_call->next = g_tf_calls; + pr_call->vbo = cache->final[subdiv].proc_buf; + pr_call->shgrp = tf_shgrp; + pr_call->vert_len = final_points_len; + g_tf_calls = pr_call; + DRW_shgroup_uniform_int(tf_shgrp, "targetHeight", &g_tf_target_height, 1); + DRW_shgroup_uniform_int(tf_shgrp, "targetWidth", &g_tf_target_width, 1); + DRW_shgroup_uniform_int(tf_shgrp, "idOffset", &g_tf_id_offset, 1); +#endif + + drw_hair_particle_cache_shgrp_attach_resources(tf_shgrp, cache, subdiv); + DRW_shgroup_call_procedural_points(tf_shgrp, NULL, final_points_len); + } +} + static ParticleHairCache *drw_hair_particle_cache_get( Object *object, ParticleSystem *psys, ModifierData *md, int subdiv, int thickness_res) { @@ -140,32 +214,12 @@ static ParticleHairCache *drw_hair_particle_cache_get( } if (update) { - int final_points_len = cache->final[subdiv].strands_res * cache->strands_len; - if (final_points_len > 0) { - GPUShader *tf_shader = hair_refine_shader_get(PART_REFINE_CATMULL_ROM); - -#ifdef USE_TRANSFORM_FEEDBACK - DRWShadingGroup *tf_shgrp = DRW_shgroup_transform_feedback_create( - tf_shader, g_tf_pass, cache->final[subdiv].proc_buf); -#else - DRWShadingGroup *tf_shgrp = DRW_shgroup_create(tf_shader, g_tf_pass); - - ParticleRefineCall *pr_call = MEM_mallocN(sizeof(*pr_call), __func__); - pr_call->next = g_tf_calls; - pr_call->vbo = cache->final[subdiv].proc_buf; - pr_call->shgrp = tf_shgrp; - pr_call->vert_len = final_points_len; - g_tf_calls = pr_call; - DRW_shgroup_uniform_int(tf_shgrp, "targetHeight", &g_tf_target_height, 1); - DRW_shgroup_uniform_int(tf_shgrp, "targetWidth", &g_tf_target_width, 1); - DRW_shgroup_uniform_int(tf_shgrp, "idOffset", &g_tf_id_offset, 1); -#endif + if (drw_hair_use_compute_shaders()) { + drw_hair_particle_cache_update_compute(cache, subdiv); + } + else { - DRW_shgroup_uniform_texture(tf_shgrp, "hairPointBuffer", cache->point_tex); - DRW_shgroup_uniform_texture(tf_shgrp, "hairStrandBuffer", cache->strand_tex); - DRW_shgroup_uniform_texture(tf_shgrp, "hairStrandSegBuffer", cache->strand_seg_tex); - DRW_shgroup_uniform_int(tf_shgrp, "hairStrandsRes", &cache->final[subdiv].strands_res, 1); - DRW_shgroup_call_procedural_points(tf_shgrp, NULL, final_points_len); + drw_hair_particle_cache_update_transform_feedback(cache, subdiv); } } return cache; @@ -299,6 +353,7 @@ DRWShadingGroup *DRW_shgroup_hair_create_sub(Object *object, void DRW_hair_update(void) { + TIMEIT_START(DRW_hair_update); #ifndef USE_TRANSFORM_FEEDBACK /** * Workaround to transform feedback not working on mac. @@ -367,10 +422,10 @@ void DRW_hair_update(void) MEM_freeN(data); GPU_framebuffer_free(fb); #else - /* TODO(fclem): replace by compute shader. */ - /* Just render using transform feedback. */ + /* Just render the pass when using compute shaders or transform feedback. */ DRW_draw_pass(g_tf_pass); #endif + TIMEIT_END(DRW_hair_update); } void DRW_hair_free(void) diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h index 84bc0327aa2..f2af1bcdcf2 100644 --- a/source/blender/draw/intern/draw_manager.h +++ b/source/blender/draw/intern/draw_manager.h @@ -187,6 +187,10 @@ typedef enum { DRW_CMD_DRAW_INSTANCE = 2, DRW_CMD_DRAW_INSTANCE_RANGE = 3, DRW_CMD_DRAW_PROCEDURAL = 4, + + /* Compute Commands. */ + DRW_CMD_COMPUTE = 8, + /* Other Commands */ DRW_CMD_CLEAR = 12, DRW_CMD_DRWSTATE = 13, @@ -224,6 +228,12 @@ typedef struct DRWCommandDrawInstanceRange { uint inst_count; } DRWCommandDrawInstanceRange; +typedef struct DRWCommandCompute { + int groups_x_len; + int groups_y_len; + int groups_z_len; +} DRWCommandCompute; + typedef struct DRWCommandDrawProcedural { GPUBatch *batch; DRWResourceHandle handle; @@ -260,6 +270,7 @@ typedef union DRWCommand { DRWCommandDrawInstance instance; DRWCommandDrawInstanceRange instance_range; DRWCommandDrawProcedural procedural; + DRWCommandCompute compute; DRWCommandSetMutableState state; DRWCommandSetStencil stencil; DRWCommandSetSelectID select_id; diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c index 6bdc5305fed..d19c3bc7db1 100644 --- a/source/blender/draw/intern/draw_manager_data.c +++ b/source/blender/draw/intern/draw_manager_data.c @@ -47,6 +47,7 @@ #endif #include "GPU_buffers.h" +#include "GPU_capabilities.h" #include "GPU_material.h" #include "GPU_uniform_buffer.h" @@ -700,6 +701,17 @@ static void drw_command_draw_intance_range( cmd->inst_count = count; } +static void drw_command_compute @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list [email protected] https://lists.blender.org/mailman/listinfo/bf-blender-cvs
