diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2017-08-18 23:31:06 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2017-08-19 02:20:09 +0300 |
commit | 2abc21ace5a046ee4043a6b9c8a317defb05a035 (patch) | |
tree | 23c1c7f032f15a38395af6f5a5ab7ccbaa757627 /source/blender/draw | |
parent | a702ff4c03860e0cc80a15f5efe9ba7d9f02b3ed (diff) |
Eevee: Fix problem with GPU_texture_generate_mipmap
This function was called to recreate the lower mip level of the probe texture. But this is not it's usage and it introduced a stall.
This patch add cubemap mipmap level regeneration in eevee_effects.c
Diffstat (limited to 'source/blender/draw')
6 files changed, 98 insertions, 22 deletions
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 2a22715baf3..63f466d3792 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -141,6 +141,7 @@ data_to_c_simple(engines/eevee/shaders/effect_dof_vert.glsl SRC) data_to_c_simple(engines/eevee/shaders/effect_dof_geom.glsl SRC) data_to_c_simple(engines/eevee/shaders/effect_dof_frag.glsl SRC) data_to_c_simple(engines/eevee/shaders/effect_downsample_frag.glsl SRC) +data_to_c_simple(engines/eevee/shaders/effect_downsample_cube_frag.glsl SRC) data_to_c_simple(engines/eevee/shaders/effect_gtao_frag.glsl SRC) data_to_c_simple(engines/eevee/shaders/effect_motion_blur_frag.glsl SRC) data_to_c_simple(engines/eevee/shaders/effect_ssr_frag.glsl SRC) diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c index f16393eb35a..45b0d16b2e1 100644 --- a/source/blender/draw/engines/eevee/eevee_effects.c +++ b/source/blender/draw/engines/eevee/eevee_effects.c @@ -98,6 +98,7 @@ static struct { /* Simple Downsample */ struct GPUShader *downsample_sh; + struct GPUShader *downsample_cube_sh; /* Ground Truth Ambient Occlusion */ struct GPUShader *gtao_sh; @@ -106,6 +107,7 @@ static struct { struct GPUTexture *depth_src; struct GPUTexture *color_src; int depth_src_layer; + float cube_texel_size; } e_data = {NULL}; /* Engine data */ extern char datatoc_ambient_occlusion_lib_glsl[]; @@ -120,8 +122,11 @@ extern char datatoc_effect_dof_vert_glsl[]; extern char datatoc_effect_dof_geom_glsl[]; extern char datatoc_effect_dof_frag_glsl[]; extern char datatoc_effect_downsample_frag_glsl[]; +extern char datatoc_effect_downsample_cube_frag_glsl[]; extern char datatoc_effect_gtao_frag_glsl[]; extern char datatoc_lightprobe_lib_glsl[]; +extern char datatoc_lightprobe_vert_glsl[]; +extern char datatoc_lightprobe_geom_glsl[]; extern char datatoc_raytrace_lib_glsl[]; extern char datatoc_tonemap_frag_glsl[]; extern char datatoc_volumetric_frag_glsl[]; @@ -248,6 +253,9 @@ void EEVEE_effects_init(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata) MEM_freeN(frag_str); e_data.downsample_sh = DRW_shader_create_fullscreen(datatoc_effect_downsample_frag_glsl, NULL); + e_data.downsample_cube_sh = DRW_shader_create(datatoc_lightprobe_vert_glsl, + datatoc_lightprobe_geom_glsl, + datatoc_effect_downsample_cube_frag_glsl, NULL); e_data.volumetric_upsample_sh = DRW_shader_create_fullscreen(datatoc_volumetric_frag_glsl, "#define STEP_UPSAMPLE\n"); @@ -906,6 +914,17 @@ void EEVEE_effects_cache_init(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata) } { + static int zero = 0; + psl->color_downsample_cube_ps = DRW_pass_create("Downsample Cube", DRW_STATE_WRITE_COLOR); + DRWShadingGroup *grp = DRW_shgroup_instance_create(e_data.downsample_cube_sh, psl->color_downsample_cube_ps, quad); + DRW_shgroup_uniform_buffer(grp, "source", &e_data.color_src); + DRW_shgroup_uniform_float(grp, "texelSize", &e_data.cube_texel_size, 1); + DRW_shgroup_uniform_int(grp, "Layer", &zero, 1); + for (int i = 0; i < 6; ++i) + DRW_shgroup_call_dynamic_add_empty(grp); + } + + { /* Perform min/max downsample */ psl->minz_downlevel_ps = DRW_pass_create("HiZ Min Down Level", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS); DRWShadingGroup *grp = DRW_shgroup_create(e_data.minz_downlevel_sh, psl->minz_downlevel_ps); @@ -1097,6 +1116,13 @@ static void simple_downsample_cb(void *vedata, int UNUSED(level)) DRW_draw_pass(psl->color_downsample_ps); } +static void simple_downsample_cube_cb(void *vedata, int level) +{ + EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl; + e_data.cube_texel_size = (float)(1 << level) / (float)GPU_texture_width(e_data.color_src); + DRW_draw_pass(psl->color_downsample_cube_ps); +} + void EEVEE_create_minmax_buffer(EEVEE_Data *vedata, GPUTexture *depth_src, int layer) { EEVEE_PassList *psl = vedata->psl; @@ -1153,6 +1179,19 @@ void EEVEE_downsample_buffer(EEVEE_Data *vedata, struct GPUFrameBuffer *fb_src, DRW_stats_group_end(); } +/** + * Simple downsampling algorithm for cubemap. Reconstruct mip chain up to mip level. + **/ +void EEVEE_downsample_cube_buffer(EEVEE_Data *vedata, struct GPUFrameBuffer *fb_src, GPUTexture *texture_src, int level) +{ + e_data.color_src = texture_src; + + DRW_stats_group_start("Downsample Cube buffer"); + /* Create lower levels */ + DRW_framebuffer_recursive_downsample(fb_src, texture_src, level, &simple_downsample_cube_cb, vedata); + DRW_stats_group_end(); +} + void EEVEE_effects_do_volumetrics(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata) { EEVEE_PassList *psl = vedata->psl; @@ -1493,6 +1532,7 @@ void EEVEE_effects_free(void) DRW_SHADER_FREE_SAFE(e_data.ssr_sh[i]); } DRW_SHADER_FREE_SAFE(e_data.downsample_sh); + DRW_SHADER_FREE_SAFE(e_data.downsample_cube_sh); DRW_SHADER_FREE_SAFE(e_data.gtao_sh); DRW_SHADER_FREE_SAFE(e_data.gtao_debug_sh); diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c index f77637edac0..a20b373d3b1 100644 --- a/source/blender/draw/engines/eevee/eevee_lightprobes.c +++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c @@ -827,14 +827,17 @@ static void downsample_planar(void *vedata, int level) } /* Glossy filter probe_rt to probe_pool at index probe_idx */ -static void glossy_filter_probe(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl, int probe_idx) +static void glossy_filter_probe(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata, EEVEE_PassList *psl, int probe_idx) { EEVEE_LightProbesInfo *pinfo = sldata->probes; + /* Max lod used from the render target probe */ + pinfo->lod_rt_max = floorf(log2f(PROBE_RT_SIZE)) - 2.0f; + /* 2 - Let gpu create Mipmaps for Filtered Importance Sampling. */ /* Bind next framebuffer to be able to gen. mips for probe_rt. */ DRW_framebuffer_bind(sldata->probe_filter_fb); - DRW_texture_generate_mipmaps(sldata->probe_rt); + EEVEE_downsample_cube_buffer(vedata, sldata->probe_filter_fb, sldata->probe_rt, (int)(pinfo->lod_rt_max)); /* 3 - Render to probe array to the specified layer, do prefiltering. */ /* Detach to rebind the right mipmap. */ @@ -843,7 +846,7 @@ static void glossy_filter_probe(EEVEE_SceneLayerData *sldata, EEVEE_PassList *ps const int maxlevel = (int)floorf(log2f(PROBE_OCTAHEDRON_SIZE)); const int min_lod_level = 3; for (int i = 0; i < maxlevel - min_lod_level; i++) { - float bias = (i == 0) ? 0.0f : 1.0f; + float bias = (i == 0) ? -1.0f : 1.0f; pinfo->texel_size = 1.0f / mipsize; pinfo->padding_size = powf(2.0f, (float)(maxlevel - min_lod_level - 1 - i)); /* XXX : WHY THE HECK DO WE NEED THIS ??? */ @@ -880,7 +883,6 @@ static void glossy_filter_probe(EEVEE_SceneLayerData *sldata, EEVEE_PassList *ps pinfo->invsamples_ct = 1.0f / pinfo->samples_ct; pinfo->lodfactor = bias + 0.5f * log((float)(PROBE_RT_SIZE * PROBE_RT_SIZE) * pinfo->invsamples_ct) / log(2); - pinfo->lod_rt_max = floorf(log2f(PROBE_RT_SIZE)) - 2.0f; DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->probe_pool, 0, i); DRW_framebuffer_viewport_size(sldata->probe_filter_fb, 0, 0, mipsize, mipsize); @@ -898,19 +900,10 @@ static void glossy_filter_probe(EEVEE_SceneLayerData *sldata, EEVEE_PassList *ps } /* Diffuse filter probe_rt to irradiance_pool at index probe_idx */ -static void diffuse_filter_probe(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl, int offset) +static void diffuse_filter_probe(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata, EEVEE_PassList *psl, int offset) { EEVEE_LightProbesInfo *pinfo = sldata->probes; - /* 4 - Compute spherical harmonics */ - /* Tweaking parameters to balance perf. vs precision */ - DRW_framebuffer_bind(sldata->probe_filter_fb); - DRW_texture_generate_mipmaps(sldata->probe_rt); - - /* Bind the right texture layer (one layer per irradiance grid) */ - DRW_framebuffer_texture_detach(sldata->probe_pool); - DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->irradiance_rt, 0, 0); - /* find cell position on the virtual 3D texture */ /* NOTE : Keep in sync with load_irradiance_cell() */ #if defined(IRRADIANCE_SH_L2) @@ -928,6 +921,7 @@ static void diffuse_filter_probe(EEVEE_SceneLayerData *sldata, EEVEE_PassList *p int y = size[1] * (offset / cell_per_row); #ifndef IRRADIANCE_SH_L2 + /* Tweaking parameters to balance perf. vs precision */ const float bias = 0.0f; pinfo->invsamples_ct = 1.0f / pinfo->samples_ct; pinfo->lodfactor = bias + 0.5f * log((float)(PROBE_RT_SIZE * PROBE_RT_SIZE) * pinfo->invsamples_ct) / log(2); @@ -937,6 +931,14 @@ static void diffuse_filter_probe(EEVEE_SceneLayerData *sldata, EEVEE_PassList *p pinfo->lod_rt_max = 2.0f; /* Improve cache reuse */ #endif + /* 4 - Compute spherical harmonics */ + DRW_framebuffer_bind(sldata->probe_filter_fb); + EEVEE_downsample_cube_buffer(vedata, sldata->probe_filter_fb, sldata->probe_rt, (int)(pinfo->lod_rt_max)); + + /* Bind the right texture layer (one layer per irradiance grid) */ + DRW_framebuffer_texture_detach(sldata->probe_pool); + DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->irradiance_rt, 0, 0); + DRW_framebuffer_viewport_size(sldata->probe_filter_fb, x, y, size[0], size[1]); DRW_draw_pass(psl->probe_diffuse_compute); @@ -1199,13 +1201,13 @@ void EEVEE_lightprobes_refresh(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata) /* Render world in priority */ if (e_data.update_world) { render_world_to_probe(sldata, psl); - glossy_filter_probe(sldata, psl, 0); - diffuse_filter_probe(sldata, psl, 0); + glossy_filter_probe(sldata, vedata, psl, 0); + diffuse_filter_probe(sldata, vedata, psl, 0); /* Swap and redo prefiltering for other rendertarget. * This way we have world lighting waiting for irradiance grids to catch up. */ SWAP(GPUTexture *, sldata->irradiance_pool, sldata->irradiance_rt); - diffuse_filter_probe(sldata, psl, 0); + diffuse_filter_probe(sldata, vedata, psl, 0); e_data.update_world = false; @@ -1258,7 +1260,7 @@ void EEVEE_lightprobes_refresh(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata) lightprobe_cell_location_get(egrid, cell_id, pos); render_scene_to_probe(sldata, vedata, pos, prb->clipsta, prb->clipend); - diffuse_filter_probe(sldata, psl, egrid->offset + cell_id); + diffuse_filter_probe(sldata, vedata, psl, egrid->offset + cell_id); /* Restore */ pinfo->num_render_grid = tmp_num_render_grid; @@ -1303,7 +1305,7 @@ void EEVEE_lightprobes_refresh(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata) LightProbe *prb = (LightProbe *)ob->data; render_scene_to_probe(sldata, vedata, ob->obmat[3], prb->clipsta, prb->clipend); - glossy_filter_probe(sldata, psl, i); + glossy_filter_probe(sldata, vedata, psl, i); ped->need_update = false; ped->probe_id = i; diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index 3fe07e8e653..280ebcbb1aa 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -110,6 +110,7 @@ typedef struct EEVEE_PassList { struct DRWPass *ssr_raytrace; struct DRWPass *ssr_resolve; struct DRWPass *color_downsample_ps; + struct DRWPass *color_downsample_cube_ps; /* HiZ */ struct DRWPass *minz_downlevel_ps; @@ -547,6 +548,7 @@ void EEVEE_effects_init(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata); void EEVEE_effects_cache_init(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata); void EEVEE_create_minmax_buffer(EEVEE_Data *vedata, struct GPUTexture *depth_src, int layer); void EEVEE_downsample_buffer(EEVEE_Data *vedata, struct GPUFrameBuffer *fb_src, struct GPUTexture *texture_src, int level); +void EEVEE_downsample_cube_buffer(EEVEE_Data *vedata, struct GPUFrameBuffer *fb_src, struct GPUTexture *texture_src, int level); void EEVEE_effects_do_volumetrics(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata); void EEVEE_effects_do_ssr(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata); void EEVEE_effects_do_refraction(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata); diff --git a/source/blender/draw/engines/eevee/shaders/effect_downsample_cube_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_downsample_cube_frag.glsl new file mode 100644 index 00000000000..eb463d51146 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/effect_downsample_cube_frag.glsl @@ -0,0 +1,30 @@ +/** + * Simple downsample shader. Takes the average of the 4 texels of lower mip. + **/ + +uniform samplerCube source; +uniform float texelSize; + +flat in int fFace; + +out vec4 FragColor; + +const vec3 maj_axes[6] = vec3[6](vec3(1.0, 0.0, 0.0), vec3(-1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(0.0, -1.0, 0.0), vec3( 0.0, 0.0, 1.0), vec3( 0.0, 0.0, -1.0)); +const vec3 x_axis[6] = vec3[6](vec3(0.0, 0.0, -1.0), vec3( 0.0, 0.0, 1.0), vec3(1.0, 0.0, 0.0), vec3(1.0, 0.0, 0.0), vec3( 1.0, 0.0, 0.0), vec3(-1.0, 0.0, 0.0)); +const vec3 y_axis[6] = vec3[6](vec3(0.0, -1.0, 0.0), vec3( 0.0, -1.0, 0.0), vec3(0.0, 0.0, 1.0), vec3(0.0, 0.0, -1.0), vec3( 0.0, -1.0, 0.0), vec3( 0.0, -1.0, 0.0)); + +float brightness(vec3 c) +{ + return max(max(c.r, c.g), c.b); +} + +void main() +{ + vec2 uvs = gl_FragCoord.xy * texelSize; + + uvs = 2.0 * uvs - 1.0; + + vec3 cubevec = x_axis[fFace] * uvs.x + y_axis[fFace] * uvs.y + maj_axes[fFace]; + + FragColor = textureLod(source, cubevec, 0.0); +}
\ No newline at end of file diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_geom.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_geom.glsl index 222d272da72..7e63f4cdaf7 100644 --- a/source/blender/draw/engines/eevee/shaders/lightprobe_geom.glsl +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_geom.glsl @@ -6,6 +6,7 @@ uniform int Layer; in vec4 vPos[]; flat in int face[]; +flat out int fFace; out vec3 worldPosition; out vec3 viewPosition; /* Required. otherwise generate linking error. */ @@ -17,12 +18,12 @@ const vec3 x_axis[6] = vec3[6](vec3(0.0, 0.0, -1.0), vec3( 0.0, 0.0, 1.0), v const vec3 y_axis[6] = vec3[6](vec3(0.0, -1.0, 0.0), vec3( 0.0, -1.0, 0.0), vec3(0.0, 0.0, 1.0), vec3(0.0, 0.0, -1.0), vec3( 0.0, -1.0, 0.0), vec3( 0.0, -1.0, 0.0)); void main() { - int f = face[0]; - gl_Layer = Layer + f; + fFace = face[0]; + gl_Layer = Layer + fFace; for (int v = 0; v < 3; ++v) { gl_Position = vPos[v]; - worldPosition = x_axis[f] * vPos[v].x + y_axis[f] * vPos[v].y + maj_axes[f]; + worldPosition = x_axis[fFace] * vPos[v].x + y_axis[fFace] * vPos[v].y + maj_axes[fFace]; #ifdef ATTRIB pass_attrib(v); #endif |