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:
parent
a702ff4c03
commit
2abc21ace5
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue