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
This commit is contained in:
Clément Foucault 2017-08-18 22:31:06 +02:00
parent a702ff4c03
commit 2abc21ace5
6 changed files with 98 additions and 22 deletions

View File

@ -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)

View File

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

View File

@ -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;

View File

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

View File

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

View File

@ -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