diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2018-03-06 04:19:28 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2018-03-06 18:45:23 +0300 |
commit | f8b63b564de7e9d46a2fcb0fd485d0cea1a98aae (patch) | |
tree | c9df587defdb32505af3010bdf289ad8c99bea2a | |
parent | 2faa809ea6bf9aa7558b582858f5e539c9b60c88 (diff) |
Eevee: Update to support shader deferred compilation.
World probe is tagged to refresh when it it's shader is updated.
Probes are recomputed only after all meshes shaders have been compiled.
5 files changed, 148 insertions, 89 deletions
diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c index 2a866ee2b86..ecded9bb929 100644 --- a/source/blender/draw/engines/eevee/eevee_engine.c +++ b/source/blender/draw/engines/eevee/eevee_engine.c @@ -100,7 +100,7 @@ static void eevee_cache_init(void *vedata) EEVEE_effects_cache_init(sldata, vedata); EEVEE_lightprobes_cache_init(sldata, vedata); EEVEE_lights_cache_init(sldata, vedata); - EEVEE_materials_cache_init(vedata); + EEVEE_materials_cache_init(sldata, vedata); EEVEE_motion_blur_cache_init(sldata, vedata); EEVEE_occlusion_cache_init(sldata, vedata); EEVEE_screen_raytrace_cache_init(sldata, vedata); diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c index dd4dc590b10..9705ba7d645 100644 --- a/source/blender/draw/engines/eevee/eevee_lightprobes.c +++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c @@ -85,8 +85,6 @@ static struct { struct Gwn_VertFormat *format_probe_display_cube; struct Gwn_VertFormat *format_probe_display_planar; - - int update_world; } e_data = {NULL}; /* Engine data */ extern char datatoc_background_vert_glsl[]; @@ -304,6 +302,9 @@ void EEVEE_lightprobes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *UNUSED(veda sldata->planar_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_PlanarReflection) * MAX_PLANAR, NULL); } + /* Only start doing probes if all materials have finished compiling. */ + sldata->probes->all_materials_updated = true; + common_data->spec_toggle = true; common_data->ssr_toggle = true; common_data->sss_toggle = true; @@ -334,7 +335,7 @@ void EEVEE_lightprobes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *UNUSED(veda } if (update_all) { - e_data.update_world |= PROBE_UPDATE_ALL; + sldata->probes->update_world |= PROBE_UPDATE_ALL; sldata->probes->updated_bounce = 0; sldata->probes->grid_initialized = false; } @@ -395,34 +396,50 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat float *col = ts.colorBackground; if (wo) { col = &wo->horr; - if (wo->update_flag != 0 || pinfo->prev_world != wo) { - e_data.update_world |= PROBE_UPDATE_ALL; - pinfo->updated_bounce = 0; - pinfo->grid_initialized = false; - } - wo->update_flag = 0; + bool wo_sh_compiled = true; if (wo->use_nodes && wo->nodetree) { + static float error_col[3] = {1.0f, 0.0f, 1.0f}; + static float compile_col[3] = {0.5f, 0.5f, 0.5f}; struct GPUMaterial *gpumat = EEVEE_material_world_lightprobe_get(scene, wo); - grp = DRW_shgroup_material_create(gpumat, psl->probe_background); - - if (grp) { - DRW_shgroup_uniform_float(grp, "backgroundAlpha", &stl->g_data->background_alpha, 1); - DRW_shgroup_call_add(grp, geom, NULL); - } - else { - /* Shader failed : pink background */ - static float pink[3] = {1.0f, 0.0f, 1.0f}; - col = pink; + GPUMaterialStatus status = GPU_material_status(gpumat); + + switch (status) { + case GPU_MAT_SUCCESS: + grp = DRW_shgroup_material_create(gpumat, psl->probe_background); + DRW_shgroup_uniform_float(grp, "backgroundAlpha", &stl->g_data->background_alpha, 1); + DRW_shgroup_call_add(grp, geom, NULL); + wo_sh_compiled = true; + break; + case GPU_MAT_QUEUED: + pinfo->all_materials_updated = false; + wo_sh_compiled = false; + /* TODO Bypass probe compilation. */ + col = compile_col; + break; + case GPU_MAT_FAILED: + default: + wo_sh_compiled = true; + col = error_col; + break; } } - pinfo->prev_world = wo; + if (wo->update_flag != 0 || pinfo->prev_world != wo || pinfo->prev_wo_sh_compiled != wo_sh_compiled) { + pinfo->update_world |= PROBE_UPDATE_ALL; + pinfo->updated_bounce = 0; + pinfo->grid_initialized = false; + + pinfo->prev_wo_sh_compiled = wo_sh_compiled; + pinfo->prev_world = wo; + } + wo->update_flag = 0; } else if (pinfo->prev_world) { + pinfo->prev_wo_sh_compiled = false; pinfo->prev_world = NULL; - e_data.update_world |= PROBE_UPDATE_ALL; + pinfo->update_world |= PROBE_UPDATE_ALL; pinfo->updated_bounce = 0; pinfo->grid_initialized = false; } @@ -584,7 +601,7 @@ void EEVEE_lightprobes_cache_add(EEVEE_ViewLayerData *sldata, Object *ob) } } - if (e_data.update_world) { + if (pinfo->update_world) { ped->need_update = true; ped->updated_cells = 0; ped->updated_lvl = 0; @@ -899,7 +916,7 @@ void EEVEE_lightprobes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved } /* Tag probes to refresh */ - e_data.update_world |= PROBE_UPDATE_CUBE; + pinfo->update_world |= PROBE_UPDATE_CUBE; common_data->prb_num_render_cube = 0; pinfo->cache_num_cube = pinfo->num_cube; @@ -935,7 +952,7 @@ void EEVEE_lightprobes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved common_data->prb_num_render_grid = 0; pinfo->updated_bounce = 0; pinfo->grid_initialized = false; - e_data.update_world |= PROBE_UPDATE_GRID; + pinfo->update_world |= PROBE_UPDATE_GRID; for (int i = 1; (ob = pinfo->probes_grid_ref[i]) && (i < MAX_PROBE); i++) { EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_ensure(ob); @@ -1372,14 +1389,15 @@ static void lightprobe_cell_world_location_get(EEVEE_LightGrid *egrid, float loc static void lightprobes_refresh_world(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) { EEVEE_CommonUniformBuffer *common_data = &sldata->common_data; + EEVEE_LightProbesInfo *pinfo = sldata->probes; EEVEE_PassList *psl = vedata->psl; render_world_to_probe(sldata, psl); - if (e_data.update_world & PROBE_UPDATE_CUBE) { + if (pinfo->update_world & PROBE_UPDATE_CUBE) { glossy_filter_probe(sldata, vedata, psl, 0, 1.0); common_data->prb_num_render_cube = 1; } - if (e_data.update_world & PROBE_UPDATE_GRID) { + if (pinfo->update_world & PROBE_UPDATE_GRID) { diffuse_filter_probe(sldata, vedata, psl, 0, 0.0, 0.0, 0.0, 0.0, 1.0); SWAP(GPUTexture *, sldata->irradiance_pool, sldata->irradiance_rt); DRW_framebuffer_texture_detach(sldata->probe_pool); @@ -1389,7 +1407,7 @@ static void lightprobes_refresh_world(EEVEE_ViewLayerData *sldata, EEVEE_Data *v DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->probe_pool, 0, 0); common_data->prb_num_render_grid = 1; } - e_data.update_world = 0; + pinfo->update_world = 0; DRW_viewport_request_redraw(); } @@ -1664,6 +1682,7 @@ bool EEVEE_lightprobes_all_probes_ready(EEVEE_ViewLayerData *sldata, EEVEE_Data void EEVEE_lightprobes_refresh(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) { EEVEE_CommonUniformBuffer *common_data = &sldata->common_data; + EEVEE_LightProbesInfo *pinfo = sldata->probes; /* Disable specular lighting when rendering probes to avoid feedback loops (looks bad). */ common_data->spec_toggle = false; @@ -1677,10 +1696,10 @@ void EEVEE_lightprobes_refresh(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) common_data->ao_dist = 0.0f; /* Render world in priority */ - if (e_data.update_world) { + if (pinfo->update_world) { lightprobes_refresh_world(sldata, vedata); } - else if (EEVEE_lightprobes_all_probes_ready(sldata, vedata) == false) { + else if (EEVEE_lightprobes_all_probes_ready(sldata, vedata) == false && pinfo->all_materials_updated) { lightprobes_refresh_all_no_world(sldata, vedata); } diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c index 314cbc5033a..a72bf85cbe9 100644 --- a/source/blender/draw/engines/eevee/eevee_materials.c +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -856,7 +856,7 @@ static struct DRWShadingGroup *EEVEE_default_shading_group_get( return DRW_shgroup_create(e_data.default_lit[options], vedata->psl->default_pass[options]); } -void EEVEE_materials_cache_init(EEVEE_Data *vedata) +void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) { EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl; EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl; @@ -894,6 +894,7 @@ void EEVEE_materials_cache_init(EEVEE_Data *vedata) DRW_shgroup_call_add(grp, geom, NULL); break; case GPU_MAT_QUEUED: + sldata->probes->all_materials_updated = false; /* TODO Bypass probe compilation. */ col = compile_col; break; @@ -1042,60 +1043,29 @@ static void material_opaque( } if (use_gpumat) { + static float error_col[3] = {1.0f, 0.0f, 1.0f}; + static float compile_col[3] = {0.5f, 0.5f, 0.5f}; + static float half = 0.5f; + /* Shading */ *gpumat = EEVEE_material_mesh_get(scene, ma, vedata, false, false, use_refract, use_sss, use_translucency, linfo->shadow_method); - *shgrp = DRW_shgroup_material_create(*gpumat, - (use_refract) ? psl->refract_pass : - (use_sss) ? psl->sss_pass : psl->material_pass); - if (*shgrp) { - static int no_ssr = -1; - static int first_ssr = 1; - int *ssr_id = (((effects->enabled_effects & EFFECT_SSR) != 0) && !use_refract) ? &first_ssr : &no_ssr; - add_standard_uniforms(*shgrp, sldata, vedata, ssr_id, &ma->refract_depth, use_refract, false); - - if (use_sss) { - struct GPUTexture *sss_tex_profile = NULL; - struct GPUUniformBuffer *sss_profile = GPU_material_sss_profile_get(*gpumat, - stl->effects->sss_sample_count, - &sss_tex_profile); - - if (sss_profile) { - if (use_translucency) { - DRW_shgroup_uniform_block(*shgrp, "sssProfile", sss_profile); - DRW_shgroup_uniform_texture(*shgrp, "sssTexProfile", sss_tex_profile); - } - - /* Limit of 8 bit stencil buffer. ID 255 is refraction. */ - if (e_data.sss_count < 254) { - DRW_shgroup_stencil_mask(*shgrp, e_data.sss_count + 1); - EEVEE_subsurface_add_pass(sldata, vedata, e_data.sss_count + 1, sss_profile); - e_data.sss_count++; - } - else { - /* TODO : display message. */ - printf("Error: Too many different Subsurface shader in the scene.\n"); - } - } - } - } - else { - /* Shader failed : pink color */ - static float col[3] = {1.0f, 0.0f, 1.0f}; - static float half = 0.5f; - - color_p = col; - metal_p = spec_p = rough_p = ½ - } + GPUMaterialStatus status_mat_surface = GPU_material_status(*gpumat); /* Alpha CLipped : Discard pixel from depth pass, then * fail the depth test for shading. */ if (ELEM(ma->blend_method, MA_BM_CLIP, MA_BM_HASHED)) { *gpumat_depth = EEVEE_material_mesh_depth_get(scene, ma, - (ma->blend_method == MA_BM_HASHED), false); + (ma->blend_method == MA_BM_HASHED), false); - if (use_refract) { + GPUMaterialStatus status_mat_depth = GPU_material_status(*gpumat_depth); + if (status_mat_depth != GPU_MAT_SUCCESS) { + /* Mixing both flags. If depth shader fails, show it to the user by not using + * the surface shader. */ + status_mat_surface = status_mat_depth; + } + else if (use_refract) { *shgrp_depth = DRW_shgroup_material_create(*gpumat_depth, (do_cull) ? psl->refract_depth_pass_cull : psl->refract_depth_pass); *shgrp_depth_clip = DRW_shgroup_material_create(*gpumat_depth, (do_cull) ? psl->refract_depth_pass_clip_cull : psl->refract_depth_pass_clip); } @@ -1117,6 +1087,59 @@ static void material_opaque( } } } + + switch (status_mat_surface) { + case GPU_MAT_SUCCESS: + { + static int no_ssr = -1; + static int first_ssr = 1; + int *ssr_id = (((effects->enabled_effects & EFFECT_SSR) != 0) && !use_refract) ? &first_ssr : &no_ssr; + + *shgrp = DRW_shgroup_material_create(*gpumat, + (use_refract) ? psl->refract_pass : + (use_sss) ? psl->sss_pass : psl->material_pass); + add_standard_uniforms(*shgrp, sldata, vedata, ssr_id, &ma->refract_depth, use_refract, false); + + if (use_sss) { + struct GPUTexture *sss_tex_profile = NULL; + struct GPUUniformBuffer *sss_profile = GPU_material_sss_profile_get(*gpumat, + stl->effects->sss_sample_count, + &sss_tex_profile); + + if (sss_profile) { + if (use_translucency) { + DRW_shgroup_uniform_block(*shgrp, "sssProfile", sss_profile); + DRW_shgroup_uniform_texture(*shgrp, "sssTexProfile", sss_tex_profile); + } + + /* Limit of 8 bit stencil buffer. ID 255 is refraction. */ + if (e_data.sss_count < 254) { + DRW_shgroup_stencil_mask(*shgrp, e_data.sss_count + 1); + EEVEE_subsurface_add_pass(sldata, vedata, e_data.sss_count + 1, sss_profile); + e_data.sss_count++; + } + else { + /* TODO : display message. */ + printf("Error: Too many different Subsurface shader in the scene.\n"); + } + } + } + break; + } + case GPU_MAT_QUEUED: + { + sldata->probes->all_materials_updated = false; + /* TODO Bypass probe compilation. */ + color_p = compile_col; + metal_p = spec_p = rough_p = ½ + break; + } + case GPU_MAT_FAILED: + default: + color_p = error_col; + metal_p = spec_p = rough_p = ½ + break; + } } /* Fallback to default shader */ @@ -1166,23 +1189,37 @@ static void material_transparent( float *rough_p = &ma->gloss_mir; if (ma->use_nodes && ma->nodetree) { + static float error_col[3] = {1.0f, 0.0f, 1.0f}; + static float compile_col[3] = {0.5f, 0.5f, 0.5f}; + static float half = 0.5f; + /* Shading */ *gpumat = EEVEE_material_mesh_get(scene, ma, vedata, true, (ma->blend_method == MA_BM_MULTIPLY), use_refract, false, false, linfo->shadow_method); - *shgrp = DRW_shgroup_material_create(*gpumat, psl->transparent_pass); - if (*shgrp) { - static int ssr_id = -1; /* TODO transparent SSR */ - bool use_blend = (ma->blend_method & MA_BM_BLEND) != 0; - add_standard_uniforms(*shgrp, sldata, vedata, &ssr_id, &ma->refract_depth, use_refract, use_blend); - } - else { - /* Shader failed : pink color */ - static float col[3] = {1.0f, 0.0f, 1.0f}; - static float half = 0.5f; + switch (GPU_material_status(*gpumat)) { + case GPU_MAT_SUCCESS: + { + static int ssr_id = -1; /* TODO transparent SSR */ + bool use_blend = (ma->blend_method & MA_BM_BLEND) != 0; - color_p = col; - metal_p = spec_p = rough_p = ½ + *shgrp = DRW_shgroup_material_create(*gpumat, psl->transparent_pass); + add_standard_uniforms(*shgrp, sldata, vedata, &ssr_id, &ma->refract_depth, use_refract, use_blend); + break; + } + case GPU_MAT_QUEUED: + { + sldata->probes->all_materials_updated = false; + /* TODO Bypass probe compilation. */ + color_p = compile_col; + metal_p = spec_p = rough_p = ½ + break; + } + case GPU_MAT_FAILED: + default: + color_p = error_col; + metal_p = spec_p = rough_p = ½ + break; } } diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index 8b035e97bf4..70e8d56d546 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -441,7 +441,10 @@ typedef struct EEVEE_LightProbesInfo { int target_size; int grid_initialized; struct World *prev_world; + int update_world; + bool prev_wo_sh_compiled; bool do_cube_update; + bool all_materials_updated; /* For rendering probes */ float probemat[6][4][4]; int layer; @@ -766,7 +769,7 @@ EEVEE_LampEngineData *EEVEE_lamp_data_ensure(Object *ob); /* eevee_materials.c */ struct GPUTexture *EEVEE_materials_get_util_tex(void); /* XXX */ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata, EEVEE_StorageList *stl, EEVEE_FramebufferList *fbl); -void EEVEE_materials_cache_init(EEVEE_Data *vedata); +void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *sldata, Object *ob); void EEVEE_materials_cache_finish(EEVEE_Data *vedata); struct GPUMaterial *EEVEE_material_world_lightprobe_get(struct Scene *scene, struct World *wo); diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c index bc55624c7b7..b54640e64df 100644 --- a/source/blender/draw/engines/eevee/eevee_render.c +++ b/source/blender/draw/engines/eevee/eevee_render.c @@ -115,7 +115,7 @@ void EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph * EEVEE_effects_cache_init(sldata, vedata); EEVEE_lightprobes_cache_init(sldata, vedata); EEVEE_lights_cache_init(sldata, vedata); - EEVEE_materials_cache_init(vedata); + EEVEE_materials_cache_init(sldata, vedata); EEVEE_motion_blur_cache_init(sldata, vedata); EEVEE_occlusion_cache_init(sldata, vedata); EEVEE_screen_raytrace_cache_init(sldata, vedata); |