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 /source | |
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.
Diffstat (limited to 'source')
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); |