[Bf-blender-cvs] [2abc21ace5a] blender2.8: Eevee: Fix problem with GPU_texture_generate_mipmap

Clément Foucault noreply at git.blender.org
Sat Aug 19 02:40:30 CEST 2017


Commit: 2abc21ace5a046ee4043a6b9c8a317defb05a035
Author: Clément Foucault
Date:   Fri Aug 18 22:31:06 2017 +0200
Branches: blender2.8
https://developer.blender.org/rB2abc21ace5a046ee4043a6b9c8a317defb05a035

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

===================================================================

M	source/blender/draw/CMakeLists.txt
M	source/blender/draw/engines/eevee/eevee_effects.c
M	source/blender/draw/engines/eevee/eevee_lightprobes.c
M	source/blender/draw/engines/eevee/eevee_private.h
A	source/blender/draw/engines/eevee/shaders/effect_downsample_cube_frag.glsl
M	source/blender/draw/engines/eevee/shaders/lightprobe_geom.glsl

===================================================================

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");
 
@@ -905,6 +913,17 @@ void EEVEE_effects_cache_init(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata)
 		DRW_shgroup_call_add(grp, quad, NULL);
 	}
 
+	{
+		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);
@@ -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

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list