Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/draw')
-rw-r--r--source/blender/draw/CMakeLists.txt5
-rw-r--r--source/blender/draw/engines/basic/basic_engine.c25
-rw-r--r--source/blender/draw/engines/basic/shaders/depth_frag.glsl (renamed from source/blender/draw/engines/basic/shaders/conservative_depth_frag.glsl)0
-rw-r--r--source/blender/draw/engines/basic/shaders/depth_vert.glsl (renamed from source/blender/draw/engines/basic/shaders/conservative_depth_vert.glsl)4
-rw-r--r--source/blender/draw/engines/eevee/eevee_data.c15
-rw-r--r--source/blender/draw/engines/eevee/eevee_depth_of_field.c12
-rw-r--r--source/blender/draw/engines/eevee/eevee_effects.c3
-rw-r--r--source/blender/draw/engines/eevee/eevee_engine.c16
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightcache.c8
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightprobes.c91
-rw-r--r--source/blender/draw/engines/eevee/eevee_lookdev.c44
-rw-r--r--source/blender/draw/engines/eevee/eevee_lut_gen.c198
-rw-r--r--source/blender/draw/engines/eevee/eevee_materials.c2352
-rw-r--r--source/blender/draw/engines/eevee/eevee_mist.c3
-rw-r--r--source/blender/draw/engines/eevee/eevee_occlusion.c12
-rw-r--r--source/blender/draw/engines/eevee/eevee_private.h170
-rw-r--r--source/blender/draw/engines/eevee/eevee_render.c16
-rw-r--r--source/blender/draw/engines/eevee/eevee_renderpasses.c44
-rw-r--r--source/blender/draw/engines/eevee/eevee_screen_raytrace.c6
-rw-r--r--source/blender/draw/engines/eevee/eevee_shaders.c488
-rw-r--r--source/blender/draw/engines/eevee/eevee_shadows.c44
-rw-r--r--source/blender/draw/engines/eevee/eevee_subsurface.c133
-rw-r--r--source/blender/draw/engines/eevee/eevee_temporal_sampling.c3
-rw-r--r--source/blender/draw/engines/eevee/eevee_volumes.c33
-rw-r--r--source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl10
-rw-r--r--source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl8
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_dof_frag.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl27
-rw-r--r--source/blender/draw/engines/eevee/shaders/prepass_frag.glsl21
-rw-r--r--source/blender/draw/engines/external/external_engine.c18
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_antialiasing.c5
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_cache_utils.c2
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_engine.c7
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_engine.h2
-rw-r--r--source/blender/draw/engines/overlay/overlay_armature.c24
-rw-r--r--source/blender/draw/engines/overlay/overlay_extra.c24
-rw-r--r--source/blender/draw/engines/overlay/overlay_facing.c2
-rw-r--r--source/blender/draw/engines/overlay/overlay_gpencil.c2
-rw-r--r--source/blender/draw/engines/overlay/overlay_motion_path.c4
-rw-r--r--source/blender/draw/engines/overlay/overlay_outline.c2
-rw-r--r--source/blender/draw/engines/overlay/overlay_particle.c8
-rw-r--r--source/blender/draw/engines/overlay/overlay_pointcloud.c2
-rw-r--r--source/blender/draw/engines/overlay/overlay_wireframe.c8
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_effect_dof_frag.glsl1
-rw-r--r--source/blender/draw/engines/workbench/workbench_effect_antialiasing.c5
-rw-r--r--source/blender/draw/engines/workbench/workbench_materials.c6
-rw-r--r--source/blender/draw/engines/workbench/workbench_opaque.c16
-rw-r--r--source/blender/draw/engines/workbench/workbench_shader.c33
-rw-r--r--source/blender/draw/engines/workbench/workbench_transparent.c12
-rw-r--r--source/blender/draw/intern/DRW_render.h28
-rw-r--r--source/blender/draw/intern/draw_cache.c6
-rw-r--r--source/blender/draw/intern/draw_cache_extract.h5
-rw-r--r--source/blender/draw/intern/draw_cache_extract_mesh.c501
-rw-r--r--source/blender/draw/intern/draw_cache_impl.h4
-rw-r--r--source/blender/draw/intern/draw_cache_impl_gpencil.c11
-rw-r--r--source/blender/draw/intern/draw_cache_impl_mesh.c25
-rw-r--r--source/blender/draw/intern/draw_common.h12
-rw-r--r--source/blender/draw/intern/draw_hair.c53
-rw-r--r--source/blender/draw/intern/draw_manager.c55
-rw-r--r--source/blender/draw/intern/draw_manager.h53
-rw-r--r--source/blender/draw/intern/draw_manager_data.c218
-rw-r--r--source/blender/draw/intern/draw_manager_exec.c244
-rw-r--r--source/blender/draw/intern/draw_manager_shader.c25
-rw-r--r--source/blender/draw/intern/draw_manager_texture.c4
65 files changed, 2287 insertions, 2935 deletions
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index d9f7a3acae0..aeecb452217 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -34,6 +34,7 @@ set(INC
../imbuf
../makesdna
../makesrna
+ ../nodes
../render/extern/include
../render/intern/include
../windowmanager
@@ -317,8 +318,8 @@ data_to_c_simple(engines/select/shaders/selection_id_3D_vert.glsl SRC)
data_to_c_simple(engines/select/shaders/selection_id_frag.glsl SRC)
data_to_c_simple(engines/basic/shaders/conservative_depth_geom.glsl SRC)
-data_to_c_simple(engines/basic/shaders/conservative_depth_vert.glsl SRC)
-data_to_c_simple(engines/basic/shaders/conservative_depth_frag.glsl SRC)
+data_to_c_simple(engines/basic/shaders/depth_vert.glsl SRC)
+data_to_c_simple(engines/basic/shaders/depth_frag.glsl SRC)
if(WITH_LANPR)
data_to_c_simple(engines/lanpr/shaders/lanpr_dpix_preview_geom.glsl SRC)
diff --git a/source/blender/draw/engines/basic/basic_engine.c b/source/blender/draw/engines/basic/basic_engine.c
index 6658fea7825..bbc3c407f14 100644
--- a/source/blender/draw/engines/basic/basic_engine.c
+++ b/source/blender/draw/engines/basic/basic_engine.c
@@ -37,8 +37,8 @@
#define BASIC_ENGINE "BLENDER_BASIC"
-extern char datatoc_conservative_depth_frag_glsl[];
-extern char datatoc_conservative_depth_vert_glsl[];
+extern char datatoc_depth_frag_glsl[];
+extern char datatoc_depth_vert_glsl[];
extern char datatoc_conservative_depth_geom_glsl[];
extern char datatoc_common_view_lib_glsl[];
@@ -91,22 +91,28 @@ static void basic_engine_init(void *UNUSED(vedata))
/* Depth prepass */
if (!sh_data->depth) {
- sh_data->depth = DRW_shader_create_3d_depth_only(draw_ctx->sh_cfg);
-
const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg];
+
+ sh_data->depth = GPU_shader_create_from_arrays({
+ .vert = (const char *[]){sh_cfg->lib,
+ datatoc_common_view_lib_glsl,
+ datatoc_depth_vert_glsl,
+ NULL},
+ .frag = (const char *[]){datatoc_depth_frag_glsl, NULL},
+ .defs = (const char *[]){sh_cfg->def, NULL},
+ });
+
sh_data->depth_conservative = GPU_shader_create_from_arrays({
.vert = (const char *[]){sh_cfg->lib,
datatoc_common_view_lib_glsl,
- datatoc_conservative_depth_vert_glsl,
+ datatoc_depth_vert_glsl,
NULL},
.geom = (const char *[]){sh_cfg->lib,
datatoc_common_view_lib_glsl,
datatoc_conservative_depth_geom_glsl,
NULL},
- .frag = (const char *[]){datatoc_common_view_lib_glsl,
- datatoc_conservative_depth_frag_glsl,
- NULL},
- .defs = (const char *[]){sh_cfg->def, NULL},
+ .frag = (const char *[]){datatoc_depth_frag_glsl, NULL},
+ .defs = (const char *[]){sh_cfg->def, "#define CONSERVATIVE_RASTER\n", NULL},
});
}
}
@@ -233,6 +239,7 @@ static void basic_engine_free(void)
{
for (int i = 0; i < GPU_SHADER_CFG_LEN; i++) {
BASIC_Shaders *sh_data = &e_data.sh_data[i];
+ DRW_SHADER_FREE_SAFE(sh_data->depth);
DRW_SHADER_FREE_SAFE(sh_data->depth_conservative);
}
}
diff --git a/source/blender/draw/engines/basic/shaders/conservative_depth_frag.glsl b/source/blender/draw/engines/basic/shaders/depth_frag.glsl
index ff4a015c335..ff4a015c335 100644
--- a/source/blender/draw/engines/basic/shaders/conservative_depth_frag.glsl
+++ b/source/blender/draw/engines/basic/shaders/depth_frag.glsl
diff --git a/source/blender/draw/engines/basic/shaders/conservative_depth_vert.glsl b/source/blender/draw/engines/basic/shaders/depth_vert.glsl
index c55a3211ff2..318d0acef6f 100644
--- a/source/blender/draw/engines/basic/shaders/conservative_depth_vert.glsl
+++ b/source/blender/draw/engines/basic/shaders/depth_vert.glsl
@@ -1,12 +1,16 @@
+#ifdef CONSERVATIVE_RASTER
RESOURCE_ID_VARYING
+#endif
in vec3 pos;
void main()
{
GPU_INTEL_VERTEX_SHADER_WORKAROUND
+#ifdef CONSERVATIVE_RASTER
PASS_RESOURCE_ID
+#endif
vec3 world_pos = point_object_to_world(pos);
gl_Position = point_world_to_ndc(world_pos);
diff --git a/source/blender/draw/engines/eevee/eevee_data.c b/source/blender/draw/engines/eevee/eevee_data.c
index 6874947de55..a19af77124f 100644
--- a/source/blender/draw/engines/eevee/eevee_data.c
+++ b/source/blender/draw/engines/eevee/eevee_data.c
@@ -24,6 +24,8 @@
#include "DRW_render.h"
+#include "BLI_memblock.h"
+
#include "eevee_lightcache.h"
#include "eevee_private.h"
@@ -54,8 +56,17 @@ void EEVEE_view_layer_data_free(void *storage)
DRW_UBO_FREE_SAFE(sldata->grid_ubo);
DRW_UBO_FREE_SAFE(sldata->planar_ubo);
DRW_UBO_FREE_SAFE(sldata->common_ubo);
- for (int i = 0; i < MAX_MATERIAL_RENDER_PASSES_UBO; i++) {
- DRW_UBO_FREE_SAFE(sldata->renderpass_ubo[i]);
+
+ DRW_UBO_FREE_SAFE(sldata->renderpass_ubo.combined);
+ DRW_UBO_FREE_SAFE(sldata->renderpass_ubo.diff_color);
+ DRW_UBO_FREE_SAFE(sldata->renderpass_ubo.diff_light);
+ DRW_UBO_FREE_SAFE(sldata->renderpass_ubo.spec_color);
+ DRW_UBO_FREE_SAFE(sldata->renderpass_ubo.spec_light);
+ DRW_UBO_FREE_SAFE(sldata->renderpass_ubo.emit);
+
+ if (sldata->material_cache) {
+ BLI_memblock_destroy(sldata->material_cache, NULL);
+ sldata->material_cache = NULL;
}
}
diff --git a/source/blender/draw/engines/eevee/eevee_depth_of_field.c b/source/blender/draw/engines/eevee/eevee_depth_of_field.c
index ec6770e4549..4a3cc36ddef 100644
--- a/source/blender/draw/engines/eevee/eevee_depth_of_field.c
+++ b/source/blender/draw/engines/eevee/eevee_depth_of_field.c
@@ -31,6 +31,8 @@
#include "BKE_camera.h"
+#include "BLI_string_utils.h"
+
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
@@ -48,24 +50,28 @@ static struct {
extern char datatoc_effect_dof_vert_glsl[];
extern char datatoc_effect_dof_frag_glsl[];
+extern char datatoc_common_view_lib_glsl[];
+
static void eevee_create_shader_depth_of_field(const bool use_alpha)
{
+ char *frag = BLI_string_joinN(datatoc_common_view_lib_glsl, datatoc_effect_dof_frag_glsl);
e_data.dof_downsample_sh[use_alpha] = DRW_shader_create_fullscreen(
- datatoc_effect_dof_frag_glsl,
+ frag,
use_alpha ? "#define USE_ALPHA_DOF\n"
"#define STEP_DOWNSAMPLE\n" :
"#define STEP_DOWNSAMPLE\n");
e_data.dof_scatter_sh[use_alpha] = DRW_shader_create(datatoc_effect_dof_vert_glsl,
NULL,
- datatoc_effect_dof_frag_glsl,
+ frag,
use_alpha ? "#define USE_ALPHA_DOF\n"
"#define STEP_SCATTER\n" :
"#define STEP_SCATTER\n");
- e_data.dof_resolve_sh[use_alpha] = DRW_shader_create_fullscreen(datatoc_effect_dof_frag_glsl,
+ e_data.dof_resolve_sh[use_alpha] = DRW_shader_create_fullscreen(frag,
use_alpha ?
"#define USE_ALPHA_DOF\n"
"#define STEP_RESOLVE\n" :
"#define STEP_RESOLVE\n");
+ MEM_freeN(frag);
}
int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata),
diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c
index 05b18da4374..ab846fe0f11 100644
--- a/source/blender/draw/engines/eevee/eevee_effects.c
+++ b/source/blender/draw/engines/eevee/eevee_effects.c
@@ -333,8 +333,7 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
grp = DRW_shgroup_create(EEVEE_shaders_velocity_resolve_sh_get(), psl->velocity_resolve);
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &e_data.depth_src);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_uniform_mat4(grp, "currPersinv", effects->velocity_curr_persinv);
DRW_shgroup_uniform_mat4(grp, "pastPersmat", effects->velocity_past_persmat);
DRW_shgroup_call(grp, quad, NULL);
diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c
index a1112eb92df..b698574f9d7 100644
--- a/source/blender/draw/engines/eevee/eevee_engine.c
+++ b/source/blender/draw/engines/eevee/eevee_engine.c
@@ -88,7 +88,7 @@ static void eevee_engine_init(void *ved)
* `EEVEE_effects_init` needs to go second for TAA. */
EEVEE_renderpasses_init(vedata);
EEVEE_effects_init(sldata, vedata, camera, false);
- EEVEE_materials_init(sldata, stl, fbl);
+ EEVEE_materials_init(sldata, vedata, stl, fbl);
EEVEE_shadows_init(sldata);
EEVEE_lightprobes_init(sldata, vedata);
}
@@ -230,7 +230,7 @@ static void eevee_draw_scene(void *vedata)
BLI_halton_3d(primes, offset, samp, r);
EEVEE_update_noise(psl, fbl, r);
EEVEE_volumes_set_jitter(sldata, samp - 1);
- EEVEE_materials_init(sldata, stl, fbl);
+ EEVEE_materials_init(sldata, vedata, stl, fbl);
}
/* Copy previous persmat to UBO data */
copy_m4_m4(sldata->common_data.prev_persmat, stl->effects->prev_persmat);
@@ -274,8 +274,7 @@ static void eevee_draw_scene(void *vedata)
/* Depth prepass */
DRW_stats_group_start("Prepass");
- DRW_draw_pass(psl->depth_pass);
- DRW_draw_pass(psl->depth_pass_cull);
+ DRW_draw_pass(psl->depth_ps);
DRW_stats_group_end();
/* Create minmax texture */
@@ -289,9 +288,9 @@ static void eevee_draw_scene(void *vedata)
/* Shading pass */
DRW_stats_group_start("Shading");
if (DRW_state_draw_background()) {
- DRW_draw_pass(psl->background_pass);
+ DRW_draw_pass(psl->background_ps);
}
- EEVEE_materials_draw_opaque(sldata, psl);
+ DRW_draw_pass(psl->material_ps);
EEVEE_subsurface_data_render(sldata, vedata);
DRW_stats_group_end();
@@ -306,9 +305,8 @@ static void eevee_draw_scene(void *vedata)
/* Opaque refraction */
DRW_stats_group_start("Opaque Refraction");
- DRW_draw_pass(psl->refract_depth_pass);
- DRW_draw_pass(psl->refract_depth_pass_cull);
- DRW_draw_pass(psl->refract_pass);
+ DRW_draw_pass(psl->depth_refract_ps);
+ DRW_draw_pass(psl->material_refract_ps);
DRW_stats_group_end();
/* Volumetrics Resolve Opaque */
diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.c b/source/blender/draw/engines/eevee/eevee_lightcache.c
index 614c749b9aa..4cdd166f09c 100644
--- a/source/blender/draw/engines/eevee/eevee_lightcache.c
+++ b/source/blender/draw/engines/eevee/eevee_lightcache.c
@@ -379,9 +379,7 @@ static bool eevee_lightcache_static_load(LightCache *lcache)
0,
false,
NULL);
- GPU_texture_bind(lcache->grid_tx.tex, 0);
GPU_texture_filter_mode(lcache->grid_tx.tex, true);
- GPU_texture_unbind(lcache->grid_tx.tex);
}
if (lcache->cube_tx.tex == NULL) {
@@ -406,13 +404,11 @@ static bool eevee_lightcache_static_load(LightCache *lcache)
NULL);
}
- GPU_texture_bind(lcache->cube_tx.tex, 0);
- GPU_texture_mipmap_mode(lcache->cube_tx.tex, true, true);
for (int mip = 0; mip < lcache->mips_len; mip++) {
GPU_texture_add_mipmap(
lcache->cube_tx.tex, GPU_DATA_10_11_11_REV, mip + 1, lcache->cube_mips[mip].data);
}
- GPU_texture_unbind(lcache->cube_tx.tex);
+ GPU_texture_mipmap_mode(lcache->cube_tx.tex, true, true);
}
return true;
}
@@ -822,7 +818,7 @@ static void eevee_lightbake_cache_create(EEVEE_Data *vedata, EEVEE_LightBake *lb
DRW_render_viewport_size_set(viewport_size);
EEVEE_effects_init(sldata, vedata, NULL, true);
- EEVEE_materials_init(sldata, stl, fbl);
+ EEVEE_materials_init(sldata, vedata, stl, fbl);
EEVEE_shadows_init(sldata);
EEVEE_lightprobes_init(sldata, vedata);
diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c
index 3350c512b17..83b2a9bb6d4 100644
--- a/source/blender/draw/engines/eevee/eevee_lightprobes.c
+++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c
@@ -248,8 +248,7 @@ void EEVEE_lightbake_cache_init(EEVEE_ViewLayerData *sldata,
// DRW_shgroup_uniform_texture(grp, "texJitter", e_data.jitter);
DRW_shgroup_uniform_texture(grp, "probeHdr", rt_color);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
DRW_shgroup_call_instances(grp, NULL, geom, 6);
@@ -271,8 +270,7 @@ void EEVEE_lightbake_cache_init(EEVEE_ViewLayerData *sldata,
DRW_shgroup_uniform_float(grp, "intensityFac", &pinfo->intensity_fac, 1);
DRW_shgroup_uniform_texture(grp, "probeHdr", rt_color);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
DRW_shgroup_call(grp, geom, NULL);
@@ -293,8 +291,7 @@ void EEVEE_lightbake_cache_init(EEVEE_ViewLayerData *sldata,
DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley);
DRW_shgroup_uniform_texture(grp, "probeDepth", rt_depth);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
DRW_shgroup_call(grp, geom, NULL);
@@ -337,51 +334,29 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
Scene *scene = draw_ctx->scene;
World *wo = scene->world;
- const float *col = G_draw.block.colorBackground;
-
/* LookDev */
EEVEE_lookdev_cache_init(vedata, sldata, &grp, psl->probe_background, wo, pinfo);
- /* END */
+
if (!grp && wo) {
- col = &wo->horr;
-
- if (wo->use_nodes && wo->nodetree) {
- static float error_col[3] = {1.0f, 0.0f, 1.0f};
- static float queue_col[3] = {0.5f, 0.5f, 0.5f};
- struct GPUMaterial *gpumat = EEVEE_material_world_lightprobe_get(scene, wo);
-
- eGPUMaterialStatus status = GPU_material_status(gpumat);
-
- switch (status) {
- case GPU_MAT_SUCCESS:
- grp = DRW_shgroup_material_create(gpumat, psl->probe_background);
- DRW_shgroup_uniform_float_copy(grp, "backgroundAlpha", 1.0f);
- /* TODO (fclem): remove those (need to clean the GLSL files). */
- DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
- DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
- DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
- DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
- DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
- DRW_shgroup_call(grp, geom, NULL);
- break;
- case GPU_MAT_QUEUED:
- stl->g_data->queued_shaders_count++;
- col = queue_col;
- break;
- default:
- col = error_col;
- break;
- }
- }
+ struct GPUMaterial *gpumat = EEVEE_material_get(vedata, scene, NULL, wo, VAR_WORLD_PROBE);
+
+ grp = DRW_shgroup_material_create(gpumat, psl->probe_background);
+ DRW_shgroup_uniform_float_copy(grp, "backgroundAlpha", 1.0f);
+ /* TODO (fclem): remove those (need to clean the GLSL files). */
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+ DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
+ DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
+ DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
+ DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
+ DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
+ DRW_shgroup_call(grp, geom, NULL);
}
/* Fallback if shader fails or if not using nodetree. */
if (grp == NULL) {
grp = DRW_shgroup_create(EEVEE_shaders_probe_default_sh_get(), psl->probe_background);
- DRW_shgroup_uniform_vec3(grp, "color", col, 1);
+ DRW_shgroup_uniform_vec3(grp, "color", G_draw.block.colorBackground, 1);
DRW_shgroup_uniform_float_copy(grp, "backgroundAlpha", 1.0f);
DRW_shgroup_call(grp, geom, NULL);
}
@@ -408,8 +383,7 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
/* TODO (fclem) get rid of those UBO. */
DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_call_procedural_triangles(grp, NULL, cube_len * 2);
}
@@ -436,8 +410,7 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
DRW_shgroup_uniform_block(shgrp, "planar_block", sldata->planar_ubo);
DRW_shgroup_uniform_block(shgrp, "grid_block", sldata->grid_ubo);
DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- shgrp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(shgrp, "renderpass_block", sldata->renderpass_ubo.combined);
int tri_count = egrid->resolution[0] * egrid->resolution[1] * egrid->resolution[2] * 2;
DRW_shgroup_call_procedural_triangles(shgrp, NULL, tri_count);
}
@@ -455,8 +428,7 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
DRWShadingGroup *grp = DRW_shgroup_create(EEVEE_shaders_probe_planar_display_sh_get(),
psl->probe_display);
DRW_shgroup_uniform_texture_ref(grp, "probePlanars", &txl->planar_pool);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
stl->g_data->planar_display_shgrp = DRW_shgroup_call_buffer_instance(
grp, e_data.format_probe_display_planar, DRW_cache_quad_get());
@@ -923,12 +895,10 @@ static void lightbake_render_scene_face(int face, EEVEE_BakeRenderData *user_dat
GPU_framebuffer_bind(face_fb[face]);
GPU_framebuffer_clear_depth(face_fb[face], 1.0f);
- DRW_draw_pass(psl->depth_pass);
- DRW_draw_pass(psl->depth_pass_cull);
+ DRW_draw_pass(psl->depth_ps);
DRW_draw_pass(psl->probe_background);
- EEVEE_materials_draw_opaque(sldata, psl);
- DRW_draw_pass(psl->sss_pass); /* Only output standard pass */
- DRW_draw_pass(psl->sss_pass_cull);
+ DRW_draw_pass(psl->material_ps);
+ DRW_draw_pass(psl->material_sss_ps); /* Only output standard pass */
DRW_draw_pass(psl->transparent_pass);
}
@@ -987,10 +957,8 @@ static void lightbake_render_scene_reflected(int layer, EEVEE_BakeRenderData *us
/* Slight modification: we handle refraction as normal
* shading and don't do SSRefraction. */
- DRW_draw_pass(psl->depth_pass_clip);
- DRW_draw_pass(psl->depth_pass_clip_cull);
- DRW_draw_pass(psl->refract_depth_pass_clip);
- DRW_draw_pass(psl->refract_depth_pass_clip_cull);
+ DRW_draw_pass(psl->depth_ps);
+ DRW_draw_pass(psl->depth_refract_ps);
DRW_draw_pass(psl->probe_background);
EEVEE_create_minmax_buffer(vedata, tmp_planar_depth, layer);
@@ -999,10 +967,9 @@ static void lightbake_render_scene_reflected(int layer, EEVEE_BakeRenderData *us
GPU_framebuffer_bind(fbl->planarref_fb);
/* Shading pass */
- EEVEE_materials_draw_opaque(sldata, psl);
- DRW_draw_pass(psl->sss_pass); /* Only output standard pass */
- DRW_draw_pass(psl->sss_pass_cull);
- DRW_draw_pass(psl->refract_pass);
+ DRW_draw_pass(psl->material_ps);
+ DRW_draw_pass(psl->material_sss_ps); /* Only output standard pass */
+ DRW_draw_pass(psl->material_refract_ps);
/* Transparent */
if (DRW_state_is_image_render()) {
diff --git a/source/blender/draw/engines/eevee/eevee_lookdev.c b/source/blender/draw/engines/eevee/eevee_lookdev.c
index b33be750d80..18365d69514 100644
--- a/source/blender/draw/engines/eevee/eevee_lookdev.c
+++ b/source/blender/draw/engines/eevee/eevee_lookdev.c
@@ -34,6 +34,8 @@
#include "ED_screen.h"
+#include "GPU_material.h"
+
#include "UI_resources.h"
#include "eevee_lightcache.h"
@@ -56,6 +58,43 @@ static void eevee_lookdev_lightcache_delete(EEVEE_Data *vedata)
g_data->studiolight_rot_z = 0.0f;
}
+static void eevee_lookdev_hdri_preview_init(EEVEE_Data *vedata, EEVEE_ViewLayerData *sldata)
+{
+ EEVEE_PassList *psl = vedata->psl;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Scene *scene = draw_ctx->scene;
+ DRWShadingGroup *grp;
+
+ struct GPUBatch *sphere = DRW_cache_sphere_get();
+ int mat_options = VAR_MAT_MESH | VAR_MAT_LOOKDEV;
+
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS |
+ DRW_STATE_CULL_BACK;
+
+ {
+ Material *ma = EEVEE_material_default_diffuse_get();
+ GPUMaterial *gpumat = EEVEE_material_get(vedata, scene, ma, NULL, mat_options);
+ struct GPUShader *sh = GPU_material_get_shader(gpumat);
+
+ DRW_PASS_CREATE(psl->lookdev_diffuse_pass, state);
+ grp = DRW_shgroup_create(sh, psl->lookdev_diffuse_pass);
+ EEVEE_material_bind_resources(grp, gpumat, sldata, vedata, NULL, NULL, false, false);
+ DRW_shgroup_add_material_resources(grp, gpumat);
+ DRW_shgroup_call(grp, sphere, NULL);
+ }
+ {
+ Material *ma = EEVEE_material_default_glossy_get();
+ GPUMaterial *gpumat = EEVEE_material_get(vedata, scene, ma, NULL, mat_options);
+ struct GPUShader *sh = GPU_material_get_shader(gpumat);
+
+ DRW_PASS_CREATE(psl->lookdev_glossy_pass, state);
+ grp = DRW_shgroup_create(sh, psl->lookdev_glossy_pass);
+ EEVEE_material_bind_resources(grp, gpumat, sldata, vedata, NULL, NULL, false, false);
+ DRW_shgroup_add_material_resources(grp, gpumat);
+ DRW_shgroup_call(grp, sphere, NULL);
+ }
+}
+
void EEVEE_lookdev_cache_init(EEVEE_Data *vedata,
EEVEE_ViewLayerData *sldata,
DRWShadingGroup **r_grp,
@@ -106,6 +145,8 @@ void EEVEE_lookdev_cache_init(EEVEE_Data *vedata,
effects->anchor[1] = rect->ymin;
EEVEE_temporal_sampling_reset(vedata);
}
+
+ eevee_lookdev_hdri_preview_init(vedata, sldata);
}
if (LOOK_DEV_STUDIO_LIGHT_ENABLED(v3d)) {
@@ -176,8 +217,7 @@ void EEVEE_lookdev_cache_init(EEVEE_Data *vedata,
DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
}
DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
diff --git a/source/blender/draw/engines/eevee/eevee_lut_gen.c b/source/blender/draw/engines/eevee/eevee_lut_gen.c
new file mode 100644
index 00000000000..5f20d6fbfb8
--- /dev/null
+++ b/source/blender/draw/engines/eevee/eevee_lut_gen.c
@@ -0,0 +1,198 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2020, Blender Foundation.
+ */
+
+/** \file
+ * \ingroup draw_engine
+ *
+ * EEVEE LUT generation:
+ *
+ * Routine to generate the LUT used by eevee stored in eevee_lut.h
+ * Theses functions are not to be used in the final executable.
+ */
+
+#include "DRW_render.h"
+
+#include "BLI_alloca.h"
+#include "BLI_rand.h"
+#include "BLI_string_utils.h"
+
+extern char datatoc_bsdf_lut_frag_glsl[];
+extern char datatoc_btdf_lut_frag_glsl[];
+extern char datatoc_bsdf_common_lib_glsl[];
+extern char datatoc_bsdf_sampling_lib_glsl[];
+extern char datatoc_lightprobe_geom_glsl[];
+extern char datatoc_lightprobe_vert_glsl[];
+
+static struct GPUTexture *create_ggx_lut_texture(int UNUSED(w), int UNUSED(h))
+{
+ struct GPUTexture *tex;
+ struct GPUFrameBuffer *fb = NULL;
+ static float samples_len = 8192.0f;
+ static float inv_samples_len = 1.0f / 8192.0f;
+
+ char *lib_str = BLI_string_joinN(datatoc_bsdf_common_lib_glsl, datatoc_bsdf_sampling_lib_glsl);
+
+ struct GPUShader *sh = DRW_shader_create_with_lib(datatoc_lightprobe_vert_glsl,
+ datatoc_lightprobe_geom_glsl,
+ datatoc_bsdf_lut_frag_glsl,
+ lib_str,
+ "#define HAMMERSLEY_SIZE 8192\n"
+ "#define BRDF_LUT_SIZE 64\n"
+ "#define NOISE_SIZE 64\n");
+
+ DRWPass *pass = DRW_pass_create("LightProbe Filtering", DRW_STATE_WRITE_COLOR);
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
+ DRW_shgroup_uniform_float(grp, "sampleCount", &samples_len, 1);
+ DRW_shgroup_uniform_float(grp, "invSampleCount", &inv_samples_len, 1);
+ DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley);
+ DRW_shgroup_uniform_texture(grp, "texJitter", e_data.jitter);
+
+ struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
+ DRW_shgroup_call(grp, geom, NULL);
+
+ float *texels = MEM_mallocN(sizeof(float[2]) * w * h, "lut");
+
+ tex = DRW_texture_create_2d(w, h, GPU_RG16F, DRW_TEX_FILTER, (float *)texels);
+
+ DRWFboTexture tex_filter = {&tex, GPU_RG16F, DRW_TEX_FILTER};
+ GPU_framebuffer_init(&fb, &draw_engine_eevee_type, w, h, &tex_filter, 1);
+
+ GPU_framebuffer_bind(fb);
+ DRW_draw_pass(pass);
+
+ float *data = MEM_mallocN(sizeof(float[3]) * w * h, "lut");
+ glReadBuffer(GL_COLOR_ATTACHMENT0);
+ glReadPixels(0, 0, w, h, GL_RGB, GL_FLOAT, data);
+
+ printf("{");
+ for (int i = 0; i < w * h * 3; i += 3) {
+ printf("%ff, %ff, ", data[i], data[i + 1]);
+ i += 3;
+ printf("%ff, %ff, ", data[i], data[i + 1]);
+ i += 3;
+ printf("%ff, %ff, ", data[i], data[i + 1]);
+ i += 3;
+ printf("%ff, %ff, \n", data[i], data[i + 1]);
+ }
+ printf("}");
+
+ MEM_freeN(texels);
+ MEM_freeN(data);
+
+ return tex;
+}
+
+static struct GPUTexture *create_ggx_refraction_lut_texture(int w, int h)
+{
+ struct GPUTexture *tex;
+ struct GPUTexture *hammersley = create_hammersley_sample_texture(8192);
+ struct GPUFrameBuffer *fb = NULL;
+ static float samples_len = 8192.0f;
+ static float a2 = 0.0f;
+ static float inv_samples_len = 1.0f / 8192.0f;
+
+ char *frag_str = BLI_string_joinN(
+ datatoc_bsdf_common_lib_glsl, datatoc_bsdf_sampling_lib_glsl, datatoc_btdf_lut_frag_glsl);
+
+ struct GPUShader *sh = DRW_shader_create_fullscreen(frag_str,
+ "#define HAMMERSLEY_SIZE 8192\n"
+ "#define BRDF_LUT_SIZE 64\n"
+ "#define NOISE_SIZE 64\n"
+ "#define LUT_SIZE 64\n");
+
+ MEM_freeN(frag_str);
+
+ DRWPass *pass = DRW_pass_create("LightProbe Filtering", DRW_STATE_WRITE_COLOR);
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
+ DRW_shgroup_uniform_float(grp, "a2", &a2, 1);
+ DRW_shgroup_uniform_float(grp, "sampleCount", &samples_len, 1);
+ DRW_shgroup_uniform_float(grp, "invSampleCount", &inv_samples_len, 1);
+ DRW_shgroup_uniform_texture(grp, "texHammersley", hammersley);
+ DRW_shgroup_uniform_texture(grp, "utilTex", e_data.util_tex);
+
+ struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
+ DRW_shgroup_call(grp, geom, NULL);
+
+ float *texels = MEM_mallocN(sizeof(float[2]) * w * h, "lut");
+
+ tex = DRW_texture_create_2d(w, h, GPU_R16F, DRW_TEX_FILTER, (float *)texels);
+
+ DRWFboTexture tex_filter = {&tex, GPU_R16F, DRW_TEX_FILTER};
+ GPU_framebuffer_init(&fb, &draw_engine_eevee_type, w, h, &tex_filter, 1);
+
+ GPU_framebuffer_bind(fb);
+
+ float *data = MEM_mallocN(sizeof(float[3]) * w * h, "lut");
+
+ float inc = 1.0f / 31.0f;
+ float roughness = 1e-8f - inc;
+ FILE *f = BLI_fopen("btdf_split_sum_ggx.h", "w");
+ fprintf(f, "static float btdf_split_sum_ggx[32][64 * 64] = {\n");
+ do {
+ roughness += inc;
+ CLAMP(roughness, 1e-4f, 1.0f);
+ a2 = powf(roughness, 4.0f);
+ DRW_draw_pass(pass);
+
+ GPU_framebuffer_read_data(0, 0, w, h, 3, 0, data);
+
+#if 1
+ fprintf(f, "\t{\n\t\t");
+ for (int i = 0; i < w * h * 3; i += 3) {
+ fprintf(f, "%ff,", data[i]);
+ if (((i / 3) + 1) % 12 == 0) {
+ fprintf(f, "\n\t\t");
+ }
+ else {
+ fprintf(f, " ");
+ }
+ }
+ fprintf(f, "\n\t},\n");
+#else
+ for (int i = 0; i < w * h * 3; i += 3) {
+ if (data[i] < 0.01) {
+ printf(" ");
+ }
+ else if (data[i] < 0.3) {
+ printf(".");
+ }
+ else if (data[i] < 0.6) {
+ printf("+");
+ }
+ else if (data[i] < 0.9) {
+ printf("%%");
+ }
+ else {
+ printf("#");
+ }
+ if ((i / 3 + 1) % 64 == 0) {
+ printf("\n");
+ }
+ }
+#endif
+
+ } while (roughness < 1.0f);
+ fprintf(f, "\n};\n");
+
+ fclose(f);
+
+ MEM_freeN(texels);
+ MEM_freeN(data);
+
+ return tex;
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c
index 03cdb02a48a..0f10fb0ef53 100644
--- a/source/blender/draw/engines/eevee/eevee_materials.c
+++ b/source/blender/draw/engines/eevee/eevee_materials.c
@@ -23,10 +23,10 @@
#include "DRW_render.h"
#include "BLI_alloca.h"
-#include "BLI_dynstr.h"
#include "BLI_ghash.h"
#include "BLI_listbase.h"
#include "BLI_math_bits.h"
+#include "BLI_memblock.h"
#include "BLI_rand.h"
#include "BLI_string_utils.h"
@@ -48,29 +48,11 @@
/* *********** STATIC *********** */
static struct {
- char *frag_shader_lib;
- char *vert_shader_str;
- char *vert_shadow_shader_str;
- char *vert_background_shader_str;
- char *vert_volume_shader_str;
- char *geom_volume_shader_str;
- char *volume_shader_lib;
-
- struct GPUShader *default_prepass_sh;
- struct GPUShader *default_prepass_clip_sh;
- struct GPUShader *default_hair_prepass_sh;
- struct GPUShader *default_hair_prepass_clip_sh;
- struct GPUShader *default_lit[VAR_MAT_MAX];
- struct GPUShader *default_background;
- struct GPUShader *update_noise_sh;
-
/* 64*64 array texture containing all LUTs and other utilitarian arrays.
* Packing enables us to same precious textures slots. */
struct GPUTexture *util_tex;
struct GPUTexture *noise_tex;
- uint sss_count;
-
float noise_offsets[3];
} e_data = {NULL}; /* Engine data */
@@ -82,8 +64,6 @@ extern char datatoc_prepass_vert_glsl[];
extern char datatoc_default_frag_glsl[];
extern char datatoc_default_world_frag_glsl[];
extern char datatoc_ltc_lib_glsl[];
-extern char datatoc_bsdf_lut_frag_glsl[];
-extern char datatoc_btdf_lut_frag_glsl[];
extern char datatoc_bsdf_common_lib_glsl[];
extern char datatoc_bsdf_sampling_lib_glsl[];
extern char datatoc_common_uniforms_lib_glsl[];
@@ -107,320 +87,45 @@ extern char datatoc_volumetric_frag_glsl[];
extern char datatoc_volumetric_lib_glsl[];
extern char datatoc_gpu_shader_uniform_color_frag_glsl[];
-#define DEFAULT_RENDER_PASS_FLAG 0xefffffff
-
-/* Iterator for render passes. This iteration will only do the material based render passes. it
- * will ignore `EEVEE_RENDER_PASS_ENVIRONMENT`.
- *
- * parameters:
- * - `render_passes_` is a bitflag for render_passes that needs to be iterated over.
- * - `render_pass_index_` is a parameter name where the index of the render_pass will be available
- * during iteration. This index can be used to select the right pass in the `psl`.
- * - `render_pass_` is the bitflag of the render_pass of the current iteration.
- *
- * The `render_pass_index_` parameter needs to be the same for the `RENDER_PASS_ITER_BEGIN` and
- * `RENDER_PASS_ITER_END`.
- */
-#define RENDER_PASS_ITER_BEGIN(render_passes_, render_pass_index_, render_pass_) \
- const eViewLayerEEVEEPassType __filtered_##render_pass_index_ = render_passes_ & \
- EEVEE_RENDERPASSES_MATERIAL & \
- ~EEVEE_RENDER_PASS_ENVIRONMENT; \
- if (__filtered_##render_pass_index_ != 0) { \
- int render_pass_index_ = 1; \
- for (int bit_##render_pass_ = 0; bit_##render_pass_ < EEVEE_RENDER_PASS_MAX_BIT; \
- bit_##render_pass_++) { \
- eViewLayerEEVEEPassType render_pass_ = (1 << bit_##render_pass_); \
- if ((__filtered_##render_pass_index_ & render_pass_) != 0) {
-#define RENDER_PASS_ITER_END(render_pass_index_) \
- render_pass_index_ += 1; \
- } \
- } \
- } \
- ((void)0)
+typedef struct EeveeMaterialCache {
+ struct DRWShadingGroup *depth_grp;
+ struct DRWShadingGroup *shading_grp;
+ struct DRWShadingGroup *shadow_grp;
+ struct GPUMaterial *shading_gpumat;
+ /* Meh, Used by hair to ensure draw order when calling DRW_shgroup_create_sub.
+ * Pointers to ghash values. */
+ struct DRWShadingGroup **depth_grp_p;
+ struct DRWShadingGroup **shading_grp_p;
+ struct DRWShadingGroup **shadow_grp_p;
+} EeveeMaterialCache;
/* *********** FUNCTIONS *********** */
-#if 0 /* Used only to generate the LUT values */
-static struct GPUTexture *create_ggx_lut_texture(int UNUSED(w), int UNUSED(h))
-{
- struct GPUTexture *tex;
- struct GPUFrameBuffer *fb = NULL;
- static float samples_len = 8192.0f;
- static float inv_samples_len = 1.0f / 8192.0f;
-
- char *lib_str = BLI_string_joinN(datatoc_bsdf_common_lib_glsl, datatoc_bsdf_sampling_lib_glsl);
-
- struct GPUShader *sh = DRW_shader_create_with_lib(datatoc_lightprobe_vert_glsl,
- datatoc_lightprobe_geom_glsl,
- datatoc_bsdf_lut_frag_glsl,
- lib_str,
- "#define HAMMERSLEY_SIZE 8192\n"
- "#define BRDF_LUT_SIZE 64\n"
- "#define NOISE_SIZE 64\n");
-
- DRWPass *pass = DRW_pass_create("LightProbe Filtering", DRW_STATE_WRITE_COLOR);
- DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
- DRW_shgroup_uniform_float(grp, "sampleCount", &samples_len, 1);
- DRW_shgroup_uniform_float(grp, "invSampleCount", &inv_samples_len, 1);
- DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley);
- DRW_shgroup_uniform_texture(grp, "texJitter", e_data.jitter);
-
- struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
- DRW_shgroup_call(grp, geom, NULL);
-
- float *texels = MEM_mallocN(sizeof(float[2]) * w * h, "lut");
-
- tex = DRW_texture_create_2d(w, h, GPU_RG16F, DRW_TEX_FILTER, (float *)texels);
-
- DRWFboTexture tex_filter = {&tex, GPU_RG16F, DRW_TEX_FILTER};
- GPU_framebuffer_init(&fb, &draw_engine_eevee_type, w, h, &tex_filter, 1);
-
- GPU_framebuffer_bind(fb);
- DRW_draw_pass(pass);
-
- float *data = MEM_mallocN(sizeof(float[3]) * w * h, "lut");
- glReadBuffer(GL_COLOR_ATTACHMENT0);
- glReadPixels(0, 0, w, h, GL_RGB, GL_FLOAT, data);
-
- printf("{");
- for (int i = 0; i < w * h * 3; i += 3) {
- printf("%ff, %ff, ", data[i], data[i + 1]);
- i += 3;
- printf("%ff, %ff, ", data[i], data[i + 1]);
- i += 3;
- printf("%ff, %ff, ", data[i], data[i + 1]);
- i += 3;
- printf("%ff, %ff, \n", data[i], data[i + 1]);
- }
- printf("}");
-
- MEM_freeN(texels);
- MEM_freeN(data);
-
- return tex;
-}
-
-static struct GPUTexture *create_ggx_refraction_lut_texture(int w, int h)
-{
- struct GPUTexture *tex;
- struct GPUTexture *hammersley = create_hammersley_sample_texture(8192);
- struct GPUFrameBuffer *fb = NULL;
- static float samples_len = 8192.0f;
- static float a2 = 0.0f;
- static float inv_samples_len = 1.0f / 8192.0f;
-
- char *frag_str = BLI_string_joinN(
- datatoc_bsdf_common_lib_glsl, datatoc_bsdf_sampling_lib_glsl, datatoc_btdf_lut_frag_glsl);
-
- struct GPUShader *sh = DRW_shader_create_fullscreen(frag_str,
- "#define HAMMERSLEY_SIZE 8192\n"
- "#define BRDF_LUT_SIZE 64\n"
- "#define NOISE_SIZE 64\n"
- "#define LUT_SIZE 64\n");
-
- MEM_freeN(frag_str);
-
- DRWPass *pass = DRW_pass_create("LightProbe Filtering", DRW_STATE_WRITE_COLOR);
- DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
- DRW_shgroup_uniform_float(grp, "a2", &a2, 1);
- DRW_shgroup_uniform_float(grp, "sampleCount", &samples_len, 1);
- DRW_shgroup_uniform_float(grp, "invSampleCount", &inv_samples_len, 1);
- DRW_shgroup_uniform_texture(grp, "texHammersley", hammersley);
- DRW_shgroup_uniform_texture(grp, "utilTex", e_data.util_tex);
-
- struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
- DRW_shgroup_call(grp, geom, NULL);
-
- float *texels = MEM_mallocN(sizeof(float[2]) * w * h, "lut");
-
- tex = DRW_texture_create_2d(w, h, GPU_R16F, DRW_TEX_FILTER, (float *)texels);
-
- DRWFboTexture tex_filter = {&tex, GPU_R16F, DRW_TEX_FILTER};
- GPU_framebuffer_init(&fb, &draw_engine_eevee_type, w, h, &tex_filter, 1);
-
- GPU_framebuffer_bind(fb);
-
- float *data = MEM_mallocN(sizeof(float[3]) * w * h, "lut");
-
- float inc = 1.0f / 31.0f;
- float roughness = 1e-8f - inc;
- FILE *f = BLI_fopen("btdf_split_sum_ggx.h", "w");
- fprintf(f, "static float btdf_split_sum_ggx[32][64 * 64] = {\n");
- do {
- roughness += inc;
- CLAMP(roughness, 1e-4f, 1.0f);
- a2 = powf(roughness, 4.0f);
- DRW_draw_pass(pass);
-
- GPU_framebuffer_read_data(0, 0, w, h, 3, 0, data);
-
-# if 1
- fprintf(f, "\t{\n\t\t");
- for (int i = 0; i < w * h * 3; i += 3) {
- fprintf(f, "%ff,", data[i]);
- if (((i / 3) + 1) % 12 == 0) {
- fprintf(f, "\n\t\t");
- }
- else {
- fprintf(f, " ");
- }
- }
- fprintf(f, "\n\t},\n");
-# else
- for (int i = 0; i < w * h * 3; i += 3) {
- if (data[i] < 0.01) {
- printf(" ");
- }
- else if (data[i] < 0.3) {
- printf(".");
- }
- else if (data[i] < 0.6) {
- printf("+");
- }
- else if (data[i] < 0.9) {
- printf("%%");
- }
- else {
- printf("#");
- }
- if ((i / 3 + 1) % 64 == 0) {
- printf("\n");
- }
- }
-# endif
-
- } while (roughness < 1.0f);
- fprintf(f, "\n};\n");
-
- fclose(f);
-
- MEM_freeN(texels);
- MEM_freeN(data);
-
- return tex;
-}
-#endif
/* XXX TODO define all shared resources in a shared place without duplication */
struct GPUTexture *EEVEE_materials_get_util_tex(void)
{
return e_data.util_tex;
}
-static char *eevee_get_defines(int options)
-{
- char *str = NULL;
-
- DynStr *ds = BLI_dynstr_new();
- BLI_dynstr_append(ds, SHADER_DEFINES);
-
- if ((options & VAR_MAT_MESH) != 0) {
- BLI_dynstr_append(ds, "#define MESH_SHADER\n");
- }
- if ((options & VAR_MAT_HAIR) != 0) {
- BLI_dynstr_append(ds, "#define HAIR_SHADER\n");
- }
- if ((options & VAR_MAT_PROBE) != 0) {
- BLI_dynstr_append(ds, "#define PROBE_CAPTURE\n");
- }
- if ((options & VAR_MAT_CLIP) != 0) {
- BLI_dynstr_append(ds, "#define USE_ALPHA_CLIP\n");
- }
- if ((options & VAR_MAT_SHADOW) != 0) {
- BLI_dynstr_append(ds, "#define SHADOW_SHADER\n");
- }
- if ((options & VAR_MAT_HASH) != 0) {
- BLI_dynstr_append(ds, "#define USE_ALPHA_HASH\n");
- }
- if ((options & VAR_MAT_BLEND) != 0) {
- BLI_dynstr_append(ds, "#define USE_ALPHA_BLEND\n");
- }
- if ((options & VAR_MAT_MULT) != 0) {
- BLI_dynstr_append(ds, "#define USE_MULTIPLY\n");
- }
- if ((options & VAR_MAT_REFRACT) != 0) {
- BLI_dynstr_append(ds, "#define USE_REFRACTION\n");
- }
- if ((options & VAR_MAT_LOOKDEV) != 0) {
- BLI_dynstr_append(ds, "#define LOOKDEV\n");
- }
- if ((options & VAR_MAT_HOLDOUT) != 0) {
- BLI_dynstr_append(ds, "#define HOLDOUT\n");
- }
-
- str = BLI_dynstr_get_cstring(ds);
- BLI_dynstr_free(ds);
-
- return str;
-}
-
-static char *eevee_get_volume_defines(int options)
-{
- char *str = NULL;
-
- DynStr *ds = BLI_dynstr_new();
- BLI_dynstr_append(ds, SHADER_DEFINES);
- BLI_dynstr_append(ds, "#define VOLUMETRICS\n");
-
- if ((options & VAR_MAT_VOLUME) != 0) {
- BLI_dynstr_append(ds, "#define MESH_SHADER\n");
- }
-
- str = BLI_dynstr_get_cstring(ds);
- BLI_dynstr_free(ds);
-
- return str;
-}
-
-/* Get the default render pass ubo. This is a ubo that enables all bsdf render passes. */
-struct GPUUniformBuffer *EEVEE_material_default_render_pass_ubo_get(EEVEE_ViewLayerData *sldata)
-{
- return sldata->renderpass_ubo[0];
-}
-
-/* Get the render pass ubo for rendering the given render_pass. */
-static struct GPUUniformBuffer *get_render_pass_ubo(EEVEE_ViewLayerData *sldata,
- eViewLayerEEVEEPassType render_pass)
-{
- int index;
- switch (render_pass) {
- case EEVEE_RENDER_PASS_DIFFUSE_COLOR:
- index = 1;
- break;
- case EEVEE_RENDER_PASS_DIFFUSE_LIGHT:
- index = 2;
- break;
- case EEVEE_RENDER_PASS_SPECULAR_COLOR:
- index = 3;
- break;
- case EEVEE_RENDER_PASS_SPECULAR_LIGHT:
- index = 4;
- break;
- case EEVEE_RENDER_PASS_EMIT:
- index = 5;
- break;
- default:
- index = 0;
- break;
- }
- return sldata->renderpass_ubo[index];
-}
/**
* ssr_id can be null to disable ssr contribution.
*/
-static void add_standard_uniforms(DRWShadingGroup *shgrp,
- EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- int *ssr_id,
- float *refract_depth,
- bool use_diffuse,
- bool use_glossy,
- bool use_refract,
- bool use_ssrefraction,
- bool use_alpha_blend,
- eViewLayerEEVEEPassType render_pass)
+void EEVEE_material_bind_resources(DRWShadingGroup *shgrp,
+ GPUMaterial *gpumat,
+ EEVEE_ViewLayerData *sldata,
+ EEVEE_Data *vedata,
+ int *ssr_id,
+ float *refract_depth,
+ bool use_ssrefraction,
+ bool use_alpha_blend)
{
+ bool use_diffuse = GPU_material_flag_get(gpumat, GPU_MATFLAG_DIFFUSE);
+ bool use_glossy = GPU_material_flag_get(gpumat, GPU_MATFLAG_GLOSSY);
+ bool use_refract = GPU_material_flag_get(gpumat, GPU_MATFLAG_REFRACT);
+
LightCache *lcache = vedata->stl->g_data->light_cache;
EEVEE_EffectsInfo *effects = vedata->stl->effects;
+ EEVEE_PrivateData *pd = vedata->stl->g_data;
DRW_shgroup_uniform_block(shgrp, "probe_block", sldata->probe_ubo);
DRW_shgroup_uniform_block(shgrp, "grid_block", sldata->grid_ubo);
@@ -428,11 +133,11 @@ static void add_standard_uniforms(DRWShadingGroup *shgrp,
DRW_shgroup_uniform_block(shgrp, "light_block", sldata->light_ubo);
DRW_shgroup_uniform_block(shgrp, "shadow_block", sldata->shadow_ubo);
DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(shgrp, "renderpass_block", get_render_pass_ubo(sldata, render_pass));
+ DRW_shgroup_uniform_block_ref(shgrp, "renderpass_block", &pd->renderpass_ubo);
DRW_shgroup_uniform_int_copy(shgrp, "outputSssId", 1);
+ DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex);
if (use_diffuse || use_glossy || use_refract) {
- DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex);
DRW_shgroup_uniform_texture_ref(shgrp, "shadowCubeTexture", &sldata->shadow_cube_pool);
DRW_shgroup_uniform_texture_ref(shgrp, "shadowCascadeTexture", &sldata->shadow_cascade_pool);
DRW_shgroup_uniform_texture_ref(shgrp, "maxzBuffer", &vedata->txl->maxzbuffer);
@@ -463,36 +168,6 @@ static void add_standard_uniforms(DRWShadingGroup *shgrp,
}
}
-/* Add the uniforms for the background shader to `shgrp`. */
-static void add_background_uniforms(DRWShadingGroup *shgrp,
- EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata)
-{
- EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
- DRW_shgroup_uniform_float(shgrp, "backgroundAlpha", &stl->g_data->background_alpha, 1);
- /* TODO (fclem): remove those (need to clean the GLSL files). */
- DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(shgrp, "grid_block", sldata->grid_ubo);
- DRW_shgroup_uniform_block(shgrp, "probe_block", sldata->probe_ubo);
- DRW_shgroup_uniform_block(shgrp, "planar_block", sldata->planar_ubo);
- DRW_shgroup_uniform_block(shgrp, "light_block", sldata->light_ubo);
- DRW_shgroup_uniform_block(shgrp, "shadow_block", sldata->shadow_ubo);
- DRW_shgroup_uniform_block(
- shgrp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
-}
-
-static void create_default_shader(int options)
-{
- char *frag_str = BLI_string_joinN(e_data.frag_shader_lib, datatoc_default_frag_glsl);
-
- char *defines = eevee_get_defines(options);
-
- e_data.default_lit[options] = DRW_shader_create(e_data.vert_shader_str, NULL, frag_str, defines);
-
- MEM_freeN(defines);
- MEM_freeN(frag_str);
-}
-
static void eevee_init_noise_texture(void)
{
e_data.noise_tex = DRW_texture_create_2d(64, 64, GPU_RGBA16F, 0, (float *)blue_noise);
@@ -559,8 +234,6 @@ void EEVEE_update_noise(EEVEE_PassList *psl, EEVEE_FramebufferList *fbl, const d
e_data.noise_offsets[1] = offsets[1];
e_data.noise_offsets[2] = offsets[2];
- /* Attach & detach because we don't currently support multiple FB per texture,
- * and this would be the case for multiple viewport. */
GPU_framebuffer_bind(fbl->update_noise_fb);
DRW_draw_pass(psl->update_noise_pass);
}
@@ -606,94 +279,15 @@ void EEVEE_update_viewvecs(float invproj[4][4], float winmat[4][4], float (*r_vi
}
void EEVEE_materials_init(EEVEE_ViewLayerData *sldata,
+ EEVEE_Data *vedata,
EEVEE_StorageList *stl,
EEVEE_FramebufferList *fbl)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
EEVEE_PrivateData *g_data = stl->g_data;
- if (!e_data.frag_shader_lib) {
- /* Shaders */
- e_data.frag_shader_lib = BLI_string_joinN(datatoc_common_view_lib_glsl,
- datatoc_common_uniforms_lib_glsl,
- datatoc_bsdf_common_lib_glsl,
- datatoc_bsdf_sampling_lib_glsl,
- datatoc_ambient_occlusion_lib_glsl,
- datatoc_raytrace_lib_glsl,
- datatoc_ssr_lib_glsl,
- datatoc_octahedron_lib_glsl,
- datatoc_cubemap_lib_glsl,
- datatoc_irradiance_lib_glsl,
- datatoc_lightprobe_lib_glsl,
- datatoc_ltc_lib_glsl,
- datatoc_lights_lib_glsl,
- /* Add one for each Closure */
- datatoc_lit_surface_frag_glsl,
- datatoc_lit_surface_frag_glsl,
- datatoc_lit_surface_frag_glsl,
- datatoc_lit_surface_frag_glsl,
- datatoc_lit_surface_frag_glsl,
- datatoc_lit_surface_frag_glsl,
- datatoc_lit_surface_frag_glsl,
- datatoc_lit_surface_frag_glsl,
- datatoc_lit_surface_frag_glsl,
- datatoc_lit_surface_frag_glsl,
- datatoc_lit_surface_frag_glsl,
- datatoc_volumetric_lib_glsl);
-
- e_data.volume_shader_lib = BLI_string_joinN(datatoc_common_view_lib_glsl,
- datatoc_common_uniforms_lib_glsl,
- datatoc_bsdf_common_lib_glsl,
- datatoc_ambient_occlusion_lib_glsl,
- datatoc_octahedron_lib_glsl,
- datatoc_cubemap_lib_glsl,
- datatoc_irradiance_lib_glsl,
- datatoc_lightprobe_lib_glsl,
- datatoc_ltc_lib_glsl,
- datatoc_lights_lib_glsl,
- datatoc_volumetric_lib_glsl,
- datatoc_volumetric_frag_glsl);
-
- e_data.vert_shader_str = BLI_string_joinN(
- datatoc_common_view_lib_glsl, datatoc_common_hair_lib_glsl, datatoc_lit_surface_vert_glsl);
-
- e_data.vert_shadow_shader_str = BLI_string_joinN(
- datatoc_common_view_lib_glsl, datatoc_common_hair_lib_glsl, datatoc_shadow_vert_glsl);
-
- e_data.vert_background_shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
- datatoc_background_vert_glsl);
-
- e_data.vert_volume_shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
- datatoc_volumetric_vert_glsl);
-
- e_data.geom_volume_shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
- datatoc_volumetric_geom_glsl);
-
- e_data.default_background = DRW_shader_create_with_lib(datatoc_background_vert_glsl,
- NULL,
- datatoc_default_world_frag_glsl,
- datatoc_common_view_lib_glsl,
- NULL);
-
- char *vert_str = BLI_string_joinN(
- datatoc_common_view_lib_glsl, datatoc_common_hair_lib_glsl, datatoc_prepass_vert_glsl);
-
- e_data.default_prepass_sh = DRW_shader_create(vert_str, NULL, datatoc_prepass_frag_glsl, NULL);
-
- e_data.default_prepass_clip_sh = DRW_shader_create(
- vert_str, NULL, datatoc_prepass_frag_glsl, "#define CLIP_PLANES\n");
-
- e_data.default_hair_prepass_sh = DRW_shader_create(
- vert_str, NULL, datatoc_prepass_frag_glsl, "#define HAIR_SHADER\n");
-
- e_data.default_hair_prepass_clip_sh = DRW_shader_create(vert_str,
- NULL,
- datatoc_prepass_frag_glsl,
- "#define HAIR_SHADER\n"
- "#define CLIP_PLANES\n");
- MEM_freeN(vert_str);
-
- e_data.update_noise_sh = DRW_shader_create_fullscreen(datatoc_update_noise_frag_glsl, NULL);
+ if (!e_data.util_tex) {
+ EEVEE_shaders_material_shaders_init();
eevee_init_util_texture();
eevee_init_noise_texture();
@@ -728,33 +322,36 @@ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata,
{
/* Create RenderPass UBO */
- if (sldata->renderpass_ubo[0] == NULL) {
- /* EEVEE_RENDER_PASS_COMBINED */
- sldata->renderpass_data[0] = (const EEVEE_RenderPassData){
- true, true, true, true, true, false};
- /* EEVEE_RENDER_PASS_DIFFUSE_COLOR */
- sldata->renderpass_data[1] = (const EEVEE_RenderPassData){
- true, false, false, false, false, true};
- /* EEVEE_RENDER_PASS_DIFFUSE_LIGHT */
- sldata->renderpass_data[2] = (const EEVEE_RenderPassData){
- true, true, false, false, false, false};
- /* EEVEE_RENDER_PASS_SPECULAR_COLOR */
- sldata->renderpass_data[3] = (const EEVEE_RenderPassData){
- false, false, true, false, false, false};
- /* EEVEE_RENDER_PASS_SPECULAR_LIGHT */
- sldata->renderpass_data[4] = (const EEVEE_RenderPassData){
- false, false, true, true, false, false};
- /* EEVEE_RENDER_PASS_EMIT */
- sldata->renderpass_data[5] = (const EEVEE_RenderPassData){
- false, false, false, false, true, false};
-
- for (int i = 0; i < MAX_MATERIAL_RENDER_PASSES_UBO; i++) {
- sldata->renderpass_ubo[i] = DRW_uniformbuffer_create(sizeof(EEVEE_RenderPassData),
- &sldata->renderpass_data[i]);
- }
+ if (sldata->renderpass_ubo.combined == NULL) {
+ sldata->renderpass_ubo.combined = DRW_uniformbuffer_create(
+ sizeof(EEVEE_RenderPassData),
+ &(const EEVEE_RenderPassData){true, true, true, true, true, false});
+
+ sldata->renderpass_ubo.diff_color = DRW_uniformbuffer_create(
+ sizeof(EEVEE_RenderPassData),
+ &(const EEVEE_RenderPassData){true, false, false, false, false, true});
+
+ sldata->renderpass_ubo.diff_light = DRW_uniformbuffer_create(
+ sizeof(EEVEE_RenderPassData),
+ &(const EEVEE_RenderPassData){true, true, false, false, false, false});
+
+ sldata->renderpass_ubo.spec_color = DRW_uniformbuffer_create(
+ sizeof(EEVEE_RenderPassData),
+ &(const EEVEE_RenderPassData){false, false, true, false, false, false});
+
+ sldata->renderpass_ubo.spec_light = DRW_uniformbuffer_create(
+ sizeof(EEVEE_RenderPassData),
+ &(const EEVEE_RenderPassData){false, false, true, true, false, false});
+
+ sldata->renderpass_ubo.emit = DRW_uniformbuffer_create(
+ sizeof(EEVEE_RenderPassData),
+ &(const EEVEE_RenderPassData){false, false, false, false, true, false});
}
- /* HACK: EEVEE_material_world_background_get can create a new context. This can only be
+ /* Used combined pass by default. */
+ g_data->renderpass_ubo = sldata->renderpass_ubo.combined;
+
+ /* HACK: EEVEE_material_get can create a new context. This can only be
* done when there is no active framebuffer. We do this here otherwise
* `EEVEE_renderpasses_output_init` will fail. It cannot be done in
* `EEVEE_renderpasses_init` as the `e_data.vertcode` can be uninitialized.
@@ -763,414 +360,12 @@ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata,
struct Scene *scene = draw_ctx->scene;
struct World *wo = scene->world;
if (wo && wo->use_nodes) {
- EEVEE_material_world_background_get(scene, wo);
+ EEVEE_material_get(vedata, scene, NULL, wo, VAR_WORLD_BACKGROUND);
}
}
}
}
-struct GPUMaterial *EEVEE_material_world_lightprobe_get(struct Scene *scene, World *wo)
-{
- const void *engine = &DRW_engine_viewport_eevee_type;
- const int options = VAR_WORLD_PROBE;
-
- GPUMaterial *mat = DRW_shader_find_from_world(wo, engine, options, false);
- if (mat != NULL) {
- return mat;
- }
- return DRW_shader_create_from_world(scene,
- wo,
- engine,
- options,
- false,
- e_data.vert_background_shader_str,
- NULL,
- e_data.frag_shader_lib,
- SHADER_DEFINES "#define PROBE_CAPTURE\n",
- false);
-}
-
-struct GPUMaterial *EEVEE_material_world_background_get(struct Scene *scene, World *wo)
-{
- const void *engine = &DRW_engine_viewport_eevee_type;
- int options = VAR_WORLD_BACKGROUND;
-
- GPUMaterial *mat = DRW_shader_find_from_world(wo, engine, options, true);
- if (mat != NULL) {
- return mat;
- }
- return DRW_shader_create_from_world(scene,
- wo,
- engine,
- options,
- false,
- e_data.vert_background_shader_str,
- NULL,
- e_data.frag_shader_lib,
- SHADER_DEFINES "#define WORLD_BACKGROUND\n",
- true);
-}
-
-struct GPUMaterial *EEVEE_material_world_volume_get(struct Scene *scene, World *wo)
-{
- const void *engine = &DRW_engine_viewport_eevee_type;
- int options = VAR_WORLD_VOLUME;
-
- GPUMaterial *mat = DRW_shader_find_from_world(wo, engine, options, true);
- if (mat != NULL) {
- return mat;
- }
-
- char *defines = eevee_get_volume_defines(options);
-
- mat = DRW_shader_create_from_world(scene,
- wo,
- engine,
- options,
- true,
- e_data.vert_volume_shader_str,
- e_data.geom_volume_shader_str,
- e_data.volume_shader_lib,
- defines,
- true);
-
- MEM_freeN(defines);
-
- return mat;
-}
-
-struct GPUMaterial *EEVEE_material_mesh_get(struct Scene *scene,
- Material *ma,
- EEVEE_Data *UNUSED(vedata),
- bool use_blend,
- bool use_refract)
-{
- const void *engine = &DRW_engine_viewport_eevee_type;
- int options = VAR_MAT_MESH;
-
- SET_FLAG_FROM_TEST(options, use_blend, VAR_MAT_BLEND);
- SET_FLAG_FROM_TEST(options, use_refract, VAR_MAT_REFRACT);
-
- GPUMaterial *mat = DRW_shader_find_from_material(ma, engine, options, true);
- if (mat) {
- return mat;
- }
-
- char *defines = eevee_get_defines(options);
-
- mat = DRW_shader_create_from_material(scene,
- ma,
- engine,
- options,
- false,
- e_data.vert_shader_str,
- NULL,
- e_data.frag_shader_lib,
- defines,
- true);
-
- MEM_freeN(defines);
-
- return mat;
-}
-
-struct GPUMaterial *EEVEE_material_mesh_volume_get(struct Scene *scene, Material *ma)
-{
- const void *engine = &DRW_engine_viewport_eevee_type;
- int options = VAR_MAT_VOLUME;
-
- GPUMaterial *mat = DRW_shader_find_from_material(ma, engine, options, true);
- if (mat != NULL) {
- return mat;
- }
-
- char *defines = eevee_get_volume_defines(options);
-
- mat = DRW_shader_create_from_material(scene,
- ma,
- engine,
- options,
- true,
- e_data.vert_volume_shader_str,
- e_data.geom_volume_shader_str,
- e_data.volume_shader_lib,
- defines,
- true);
-
- MEM_freeN(defines);
-
- return mat;
-}
-
-struct GPUMaterial *EEVEE_material_mesh_depth_get(struct Scene *scene,
- Material *ma,
- bool use_hashed_alpha,
- bool is_shadow)
-{
- const void *engine = &DRW_engine_viewport_eevee_type;
- int options = VAR_MAT_MESH;
-
- SET_FLAG_FROM_TEST(options, use_hashed_alpha, VAR_MAT_HASH);
- SET_FLAG_FROM_TEST(options, !use_hashed_alpha, VAR_MAT_CLIP);
- SET_FLAG_FROM_TEST(options, is_shadow, VAR_MAT_SHADOW);
-
- GPUMaterial *mat = DRW_shader_find_from_material(ma, engine, options, true);
- if (mat) {
- return mat;
- }
-
- char *defines = eevee_get_defines(options);
-
- char *frag_str = BLI_string_joinN(e_data.frag_shader_lib, datatoc_prepass_frag_glsl);
-
- mat = DRW_shader_create_from_material(scene,
- ma,
- engine,
- options,
- false,
- (is_shadow) ? e_data.vert_shadow_shader_str :
- e_data.vert_shader_str,
- NULL,
- frag_str,
- defines,
- true);
-
- MEM_freeN(frag_str);
- MEM_freeN(defines);
-
- return mat;
-}
-
-static struct GPUMaterial *EEVEE_material_hair_depth_get(struct Scene *scene,
- Material *ma,
- bool use_hashed_alpha,
- bool is_shadow)
-{
- const void *engine = &DRW_engine_viewport_eevee_type;
- int options = VAR_MAT_MESH | VAR_MAT_HAIR;
-
- SET_FLAG_FROM_TEST(options, use_hashed_alpha, VAR_MAT_HASH);
- SET_FLAG_FROM_TEST(options, !use_hashed_alpha, VAR_MAT_CLIP);
- SET_FLAG_FROM_TEST(options, is_shadow, VAR_MAT_SHADOW);
-
- GPUMaterial *mat = DRW_shader_find_from_material(ma, engine, options, true);
- if (mat) {
- return mat;
- }
-
- char *defines = eevee_get_defines(options);
-
- char *frag_str = BLI_string_joinN(e_data.frag_shader_lib, datatoc_prepass_frag_glsl);
-
- mat = DRW_shader_create_from_material(scene,
- ma,
- engine,
- options,
- false,
- (is_shadow) ? e_data.vert_shadow_shader_str :
- e_data.vert_shader_str,
- NULL,
- frag_str,
- defines,
- false);
-
- MEM_freeN(frag_str);
- MEM_freeN(defines);
-
- return mat;
-}
-
-struct GPUMaterial *EEVEE_material_hair_get(struct Scene *scene, Material *ma)
-{
- const void *engine = &DRW_engine_viewport_eevee_type;
- int options = VAR_MAT_MESH | VAR_MAT_HAIR;
-
- GPUMaterial *mat = DRW_shader_find_from_material(ma, engine, options, true);
- if (mat) {
- return mat;
- }
-
- char *defines = eevee_get_defines(options);
-
- mat = DRW_shader_create_from_material(scene,
- ma,
- engine,
- options,
- false,
- e_data.vert_shader_str,
- NULL,
- e_data.frag_shader_lib,
- defines,
- true);
-
- MEM_freeN(defines);
-
- return mat;
-}
-
-/**
- * Create a default shading group inside the given pass.
- */
-static struct DRWShadingGroup *EEVEE_default_shading_group_create(EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- DRWPass *pass,
- bool is_hair,
- bool use_blend,
- bool use_ssr)
-{
- static int ssr_id;
- ssr_id = (use_ssr) ? 1 : -1;
- int options = VAR_MAT_MESH;
-
- SET_FLAG_FROM_TEST(options, is_hair, VAR_MAT_HAIR);
- SET_FLAG_FROM_TEST(options, use_blend, VAR_MAT_BLEND);
-
- if (e_data.default_lit[options] == NULL) {
- create_default_shader(options);
- }
-
- DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.default_lit[options], pass);
- add_standard_uniforms(shgrp,
- sldata,
- vedata,
- &ssr_id,
- NULL,
- true,
- true,
- false,
- false,
- use_blend,
- DEFAULT_RENDER_PASS_FLAG);
-
- return shgrp;
-}
-
-/**
- * Create a default shading group inside the default pass without standard uniforms.
- */
-static struct DRWShadingGroup *EEVEE_default_shading_group_get(EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- Object *ob,
- ParticleSystem *psys,
- ModifierData *md,
- bool is_hair,
- bool holdout,
- bool use_ssr)
-{
- static int ssr_id;
- ssr_id = (use_ssr) ? 1 : -1;
- int options = VAR_MAT_MESH;
-
- EEVEE_PassList *psl = vedata->psl;
-
- BLI_assert(!is_hair || (ob && ((psys && md) || ob->type == OB_HAIR)));
-
- SET_FLAG_FROM_TEST(options, is_hair, VAR_MAT_HAIR);
- SET_FLAG_FROM_TEST(options, holdout, VAR_MAT_HOLDOUT);
-
- if (e_data.default_lit[options] == NULL) {
- create_default_shader(options);
- }
-
- if (psl->default_pass[options] == NULL) {
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES;
- DRW_PASS_CREATE(psl->default_pass[options], state);
-
- /* XXX / WATCH: This creates non persistent binds for the ubos and textures.
- * But it's currently OK because the following shgroups does not add any bind.
- * EDIT: THIS IS NOT THE CASE FOR HAIRS !!! DUMMY!!! */
- if (!is_hair) {
- DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.default_lit[options],
- psl->default_pass[options]);
- add_standard_uniforms(shgrp,
- sldata,
- vedata,
- &ssr_id,
- NULL,
- true,
- true,
- false,
- false,
- false,
- DEFAULT_RENDER_PASS_FLAG);
- }
- }
-
- if (is_hair) {
- DRWShadingGroup *shgrp = DRW_shgroup_hair_create(
- ob, psys, md, vedata->psl->default_pass[options], e_data.default_lit[options]);
- add_standard_uniforms(shgrp,
- sldata,
- vedata,
- &ssr_id,
- NULL,
- true,
- true,
- false,
- false,
- false,
- DEFAULT_RENDER_PASS_FLAG);
- return shgrp;
- }
- else {
- return DRW_shgroup_create(e_data.default_lit[options], vedata->psl->default_pass[options]);
- }
-}
-
-static struct DRWShadingGroup *EEVEE_default_render_pass_shading_group_get(
- EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- bool holdout,
- bool use_ssr,
- DRWPass *pass,
- eViewLayerEEVEEPassType render_pass_flag)
-{
- static int ssr_id;
- ssr_id = (use_ssr) ? 1 : -1;
- int options = VAR_MAT_MESH;
-
- SET_FLAG_FROM_TEST(options, holdout, VAR_MAT_HOLDOUT);
-
- if (e_data.default_lit[options] == NULL) {
- create_default_shader(options);
- }
-
- DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.default_lit[options], pass);
- add_standard_uniforms(
- shgrp, sldata, vedata, &ssr_id, NULL, true, true, false, false, false, render_pass_flag);
- return shgrp;
-}
-
-static struct DRWShadingGroup *EEVEE_default_hair_render_pass_shading_group_get(
- EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- Object *ob,
- ParticleSystem *psys,
- ModifierData *md,
- bool holdout,
- bool use_ssr,
- DRWPass *pass,
- eViewLayerEEVEEPassType render_pass_flag)
-{
- static int ssr_id;
- ssr_id = (use_ssr) ? 1 : -1;
- int options = VAR_MAT_MESH | VAR_MAT_HAIR;
-
- BLI_assert((ob && psys && md));
-
- SET_FLAG_FROM_TEST(options, holdout, VAR_MAT_HOLDOUT);
-
- if (e_data.default_lit[options] == NULL) {
- create_default_shader(options);
- }
-
- DRWShadingGroup *shgrp = DRW_shgroup_hair_create(
- ob, psys, md, pass, e_data.default_lit[options]);
- add_standard_uniforms(
- shgrp, sldata, vedata, &ssr_id, NULL, true, true, false, false, false, render_pass_flag);
- return shgrp;
-}
-
void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
@@ -1180,10 +375,17 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
/* Create Material Ghash */
{
stl->g_data->material_hash = BLI_ghash_ptr_new("Eevee_material ghash");
+
+ if (sldata->material_cache == NULL) {
+ sldata->material_cache = BLI_memblock_create(sizeof(EeveeMaterialCache));
+ }
+ else {
+ BLI_memblock_clear(sldata->material_cache, NULL);
+ }
}
{
- DRW_PASS_CREATE(psl->background_pass, DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL);
+ DRW_PASS_CREATE(psl->background_ps, DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL);
struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
DRWShadingGroup *grp = NULL;
@@ -1191,485 +393,297 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
Scene *scene = draw_ctx->scene;
World *wo = scene->world;
- const float *col = G_draw.block.colorBackground;
-
- EEVEE_lookdev_cache_init(vedata, sldata, &grp, psl->background_pass, wo, NULL);
+ EEVEE_lookdev_cache_init(vedata, sldata, &grp, psl->background_ps, wo, NULL);
if (!grp && wo) {
- col = &wo->horr;
-
- 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_background_get(scene, wo);
-
- switch (GPU_material_status(gpumat)) {
- case GPU_MAT_SUCCESS:
- grp = DRW_shgroup_material_create(gpumat, psl->background_pass);
- add_background_uniforms(grp, sldata, vedata);
- DRW_shgroup_call(grp, geom, NULL);
- break;
- case GPU_MAT_QUEUED:
- /* TODO Bypass probe compilation. */
- stl->g_data->queued_shaders_count++;
- col = compile_col;
- break;
- case GPU_MAT_FAILED:
- default:
- col = error_col;
- break;
- }
- }
+ struct GPUMaterial *gpumat = EEVEE_material_get(
+ vedata, scene, NULL, wo, VAR_WORLD_BACKGROUND);
+
+ grp = DRW_shgroup_material_create(gpumat, psl->background_ps);
+ DRW_shgroup_uniform_float(grp, "backgroundAlpha", &stl->g_data->background_alpha, 1);
+ /* TODO (fclem): remove those (need to clean the GLSL files). */
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+ DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
+ DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
+ DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
+ DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
+ DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
+ DRW_shgroup_call(grp, geom, NULL);
}
/* Fallback if shader fails or if not using nodetree. */
if (grp == NULL) {
- grp = DRW_shgroup_create(e_data.default_background, psl->background_pass);
- DRW_shgroup_uniform_vec3(grp, "color", col, 1);
+ GPUShader *sh = EEVEE_shaders_default_background_sh_get();
+ grp = DRW_shgroup_create(sh, psl->background_ps);
+ DRW_shgroup_uniform_vec3(grp, "color", G_draw.block.colorBackground, 1);
DRW_shgroup_uniform_float(grp, "backgroundAlpha", &stl->g_data->background_alpha, 1);
DRW_shgroup_call(grp, geom, NULL);
}
}
- {
- DRWState state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
- DRW_PASS_CREATE(psl->depth_pass, state);
- stl->g_data->depth_shgrp = DRW_shgroup_create(e_data.default_prepass_sh, psl->depth_pass);
-
- state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK;
- DRW_PASS_CREATE(psl->depth_pass_cull, state);
- stl->g_data->depth_shgrp_cull = DRW_shgroup_create(e_data.default_prepass_sh,
- psl->depth_pass_cull);
-
- state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CLIP_PLANES;
- DRW_PASS_CREATE(psl->depth_pass_clip, state);
- stl->g_data->depth_shgrp_clip = DRW_shgroup_create(e_data.default_prepass_clip_sh,
- psl->depth_pass_clip);
-
- state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CLIP_PLANES |
- DRW_STATE_CULL_BACK;
- DRW_PASS_CREATE(psl->depth_pass_clip_cull, state);
- stl->g_data->depth_shgrp_clip_cull = DRW_shgroup_create(e_data.default_prepass_clip_sh,
- psl->depth_pass_clip_cull);
- }
+#define EEVEE_PASS_CREATE(pass, state) \
+ do { \
+ DRW_PASS_CREATE(psl->pass##_ps, state); \
+ DRW_PASS_CREATE(psl->pass##_cull_ps, state | DRW_STATE_CULL_BACK); \
+ DRW_pass_link(psl->pass##_ps, psl->pass##_cull_ps); \
+ } while (0)
- {
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES;
- DRW_PASS_CREATE(psl->material_pass, state);
- DRW_PASS_CREATE(psl->material_pass_cull, state | DRW_STATE_CULL_BACK);
- }
+#define EEVEE_CLIP_PASS_CREATE(pass, state) \
+ do { \
+ DRWState st = state | DRW_STATE_CLIP_PLANES; \
+ DRW_PASS_INSTANCE_CREATE(psl->pass##_clip_ps, psl->pass##_ps, st); \
+ DRW_PASS_INSTANCE_CREATE( \
+ psl->pass##_clip_cull_ps, psl->pass##_cull_ps, st | DRW_STATE_CULL_BACK); \
+ DRW_pass_link(psl->pass##_clip_ps, psl->pass##_clip_cull_ps); \
+ } while (0)
{
- DRWState state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
- DRW_PASS_CREATE(psl->refract_depth_pass, state);
- stl->g_data->refract_depth_shgrp = DRW_shgroup_create(e_data.default_prepass_sh,
- psl->refract_depth_pass);
-
- state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK;
- DRW_PASS_CREATE(psl->refract_depth_pass_cull, state);
- stl->g_data->refract_depth_shgrp_cull = DRW_shgroup_create(e_data.default_prepass_sh,
- psl->refract_depth_pass_cull);
-
- state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CLIP_PLANES;
- DRW_PASS_CREATE(psl->refract_depth_pass_clip, state);
- stl->g_data->refract_depth_shgrp_clip = DRW_shgroup_create(e_data.default_prepass_clip_sh,
- psl->refract_depth_pass_clip);
-
- state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CLIP_PLANES |
- DRW_STATE_CULL_BACK;
- DRW_PASS_CREATE(psl->refract_depth_pass_clip_cull, state);
- stl->g_data->refract_depth_shgrp_clip_cull = DRW_shgroup_create(
- e_data.default_prepass_clip_sh, psl->refract_depth_pass_clip_cull);
- }
+ DRWState state_depth = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
+ DRWState state_shading = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES;
+ DRWState state_sss = DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_ALWAYS;
- {
- DRWState state = (DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES);
- DRW_PASS_CREATE(psl->refract_pass, state);
- }
+ EEVEE_PASS_CREATE(depth, state_depth);
+ EEVEE_CLIP_PASS_CREATE(depth, state_depth);
- {
- DRWState state = (DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES |
- DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_ALWAYS);
- DRW_PASS_CREATE(psl->sss_pass, state);
- DRW_PASS_CREATE(psl->sss_pass_cull, state | DRW_STATE_CULL_BACK);
- e_data.sss_count = 0;
+ EEVEE_PASS_CREATE(depth_refract, state_depth);
+ EEVEE_CLIP_PASS_CREATE(depth_refract, state_depth);
+
+ EEVEE_PASS_CREATE(material, state_shading);
+ EEVEE_PASS_CREATE(material_refract, state_shading);
+ EEVEE_PASS_CREATE(material_sss, state_shading | state_sss);
}
+ {
+ /* Renderpass accumulation. */
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND_ADD_FULL;
+ /* Create an instance of each of theses passes and link them together. */
+ DRWPass *passes[] = {
+ psl->material_ps,
+ psl->material_cull_ps,
+ psl->material_sss_ps,
+ psl->material_sss_cull_ps,
+ };
+ DRWPass *first = NULL, *last = NULL;
+ for (int i = 0; i < ARRAY_SIZE(passes); i++) {
+ DRWPass *pass = DRW_pass_create_instance("Renderpass Accumulation", passes[i], state);
+ if (first == NULL) {
+ first = last = pass;
+ }
+ else {
+ DRW_pass_link(last, pass);
+ last = pass;
+ }
+ }
+ psl->material_accum_ps = first;
+ /* Same for background */
+ DRW_PASS_INSTANCE_CREATE(psl->background_accum_ps, psl->background_ps, state);
+ }
{
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CLIP_PLANES;
DRW_PASS_CREATE(psl->transparent_pass, state);
}
-
{
DRW_PASS_CREATE(psl->update_noise_pass, DRW_STATE_WRITE_COLOR);
- DRWShadingGroup *grp = DRW_shgroup_create(e_data.update_noise_sh, psl->update_noise_pass);
+ GPUShader *sh = EEVEE_shaders_update_noise_sh_get();
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, psl->update_noise_pass);
DRW_shgroup_uniform_texture(grp, "blueNoise", e_data.noise_tex);
DRW_shgroup_uniform_vec3(grp, "offsets", e_data.noise_offsets, 1);
DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
}
+}
- if (eevee_hdri_preview_overlay_enabled(draw_ctx->v3d)) {
- DRWShadingGroup *shgrp;
-
- struct GPUBatch *sphere = DRW_cache_sphere_get();
- static float color_chrome[3] = {1.0f, 1.0f, 1.0f};
- static float color_diffuse[3] = {0.8f, 0.8f, 0.8f};
- int options = VAR_MAT_MESH | VAR_MAT_LOOKDEV;
+BLI_INLINE void material_shadow(EEVEE_Data *vedata,
+ EEVEE_ViewLayerData *sldata,
+ Material *ma,
+ bool is_hair,
+ EeveeMaterialCache *emc)
+{
+ EEVEE_PrivateData *pd = vedata->stl->g_data;
+ EEVEE_PassList *psl = vedata->psl;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Scene *scene = draw_ctx->scene;
- if (e_data.default_lit[options] == NULL) {
- create_default_shader(options);
+ if (ma->blend_shadow != MA_BS_NONE) {
+ /* Shadow Pass */
+ const bool use_shadow_shader = ma->use_nodes && ma->nodetree &&
+ ELEM(ma->blend_shadow, MA_BS_CLIP, MA_BS_HASHED);
+ int mat_options = VAR_MAT_MESH | VAR_MAT_DEPTH;
+ SET_FLAG_FROM_TEST(mat_options, use_shadow_shader, VAR_MAT_HASH);
+ SET_FLAG_FROM_TEST(mat_options, is_hair, VAR_MAT_HAIR);
+ GPUMaterial *gpumat = (use_shadow_shader) ?
+ EEVEE_material_get(vedata, scene, ma, NULL, mat_options) :
+ EEVEE_material_default_get(scene, ma, mat_options);
+
+ /* Avoid possible confusion with depth pre-pass options. */
+ int option = KEY_SHADOW;
+ SET_FLAG_FROM_TEST(option, is_hair, KEY_HAIR);
+
+ /* Search for the same shaders usage in the pass. */
+ struct GPUShader *sh = GPU_material_get_shader(gpumat);
+ void *cache_key = (char *)sh + option;
+ DRWShadingGroup *grp, **grp_p;
+
+ if (BLI_ghash_ensure_p(pd->material_hash, cache_key, (void ***)&grp_p)) {
+ /* This GPUShader has already been used by another material.
+ * Add new shading group just after to avoid shader switching cost. */
+ grp = DRW_shgroup_create_sub(*grp_p);
+ }
+ else {
+ *grp_p = grp = DRW_shgroup_create(sh, psl->shadow_pass);
+ EEVEE_material_bind_resources(grp, gpumat, sldata, vedata, NULL, NULL, false, false);
}
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS |
- DRW_STATE_CULL_BACK;
-
- DRW_PASS_CREATE(psl->lookdev_diffuse_pass, state);
- shgrp = DRW_shgroup_create(e_data.default_lit[options], psl->lookdev_diffuse_pass);
- add_standard_uniforms(shgrp,
- sldata,
- vedata,
- NULL,
- NULL,
- true,
- true,
- false,
- false,
- false,
- DEFAULT_RENDER_PASS_FLAG);
- DRW_shgroup_uniform_vec3(shgrp, "basecol", color_diffuse, 1);
- DRW_shgroup_uniform_float_copy(shgrp, "metallic", 0.0f);
- DRW_shgroup_uniform_float_copy(shgrp, "specular", 0.5f);
- DRW_shgroup_uniform_float_copy(shgrp, "roughness", 1.0f);
- DRW_shgroup_call(shgrp, sphere, NULL);
-
- DRW_PASS_CREATE(psl->lookdev_glossy_pass, state);
- shgrp = DRW_shgroup_create(e_data.default_lit[options], psl->lookdev_glossy_pass);
- add_standard_uniforms(shgrp,
- sldata,
- vedata,
- NULL,
- NULL,
- true,
- true,
- false,
- false,
- false,
- DEFAULT_RENDER_PASS_FLAG);
- DRW_shgroup_uniform_vec3(shgrp, "basecol", color_chrome, 1);
- DRW_shgroup_uniform_float_copy(shgrp, "metallic", 1.0f);
- DRW_shgroup_uniform_float_copy(shgrp, "roughness", 0.0f);
- DRW_shgroup_call(shgrp, sphere, NULL);
- }
+ DRW_shgroup_add_material_resources(grp, gpumat);
- {
- memset(psl->material_accum_pass, 0, sizeof(psl->material_accum_pass));
- for (int pass_index = 0; pass_index < stl->g_data->render_passes_material_count;
- pass_index++) {
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND_ADD_FULL;
- DRW_PASS_CREATE(psl->material_accum_pass[pass_index], state);
- }
+ emc->shadow_grp = grp;
+ emc->shadow_grp_p = grp_p;
+ }
+ else {
+ emc->shadow_grp = NULL;
+ emc->shadow_grp_p = NULL;
}
}
-#define ADD_SHGROUP_CALL(shgrp, ob, geom, oedata) \
- do { \
- if (oedata) { \
- DRW_shgroup_call_with_callback(shgrp, geom, ob, oedata); \
- } \
- else { \
- DRW_shgroup_call(shgrp, geom, ob); \
- } \
- } while (0)
-
-#define ADD_SHGROUP_CALL_SAFE(shgrp, ob, geom, oedata) \
- do { \
- if (shgrp) { \
- ADD_SHGROUP_CALL(shgrp, ob, geom, oedata); \
- } \
- } while (0)
-
-typedef struct EeveeMaterialShadingGroups {
- struct DRWShadingGroup *shading_grp;
- struct DRWShadingGroup *depth_grp;
- struct DRWShadingGroup *depth_clip_grp;
- struct DRWShadingGroup *material_accum_grp[MAX_MATERIAL_RENDER_PASSES];
-} EeveeMaterialShadingGroups;
-
-static void material_opaque(Material *ma,
- GHash *material_hash,
- EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- struct GPUMaterial **gpumat,
- struct GPUMaterial **gpumat_depth,
- struct EeveeMaterialShadingGroups *shgrps,
- bool holdout)
+static EeveeMaterialCache material_opaque(EEVEE_Data *vedata,
+ EEVEE_ViewLayerData *sldata,
+ Material *ma,
+ const bool is_hair)
{
EEVEE_EffectsInfo *effects = vedata->stl->effects;
+ EEVEE_PrivateData *pd = vedata->stl->g_data;
+ EEVEE_PassList *psl = vedata->psl;
const DRWContextState *draw_ctx = DRW_context_state_get();
Scene *scene = draw_ctx->scene;
- EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
- EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
- bool use_diffuse, use_glossy, use_refract;
- bool store_material = true;
- float *color_p = &ma->r;
- float *metal_p = &ma->metallic;
- float *spec_p = &ma->spec;
- float *rough_p = &ma->roughness;
- const bool do_cull = (ma->blend_flag & MA_BL_CULL_BACKFACE) != 0;
- const bool use_gpumat = (ma->use_nodes && ma->nodetree && !holdout);
+ const bool do_cull = !is_hair && (ma->blend_flag & MA_BL_CULL_BACKFACE) != 0;
+ const bool use_gpumat = (ma->use_nodes && ma->nodetree);
const bool use_ssrefract = use_gpumat && ((ma->blend_flag & MA_BL_SS_REFRACTION) != 0) &&
((effects->enabled_effects & EFFECT_REFRACT) != 0);
- const bool use_translucency = ((ma->blend_flag & MA_BL_TRANSLUCENCY) != 0);
+ const bool use_depth_shader = use_gpumat && ELEM(ma->blend_method, MA_BM_CLIP, MA_BM_HASHED);
- EeveeMaterialShadingGroups *emsg = BLI_ghash_lookup(material_hash, (const void *)ma);
-
- if (emsg) {
- memcpy(shgrps, emsg, sizeof(EeveeMaterialShadingGroups));
-
- /* This will have been created already, just perform a lookup. */
- *gpumat = (use_gpumat) ? EEVEE_material_mesh_get(scene, ma, vedata, false, use_ssrefract) :
- NULL;
- *gpumat_depth = (use_gpumat) ? EEVEE_material_mesh_depth_get(
- scene, ma, (ma->blend_method == MA_BM_HASHED), false) :
- NULL;
- return;
+ /* HACK: Assume the struct will never be smaller than our variations.
+ * This allow us to only keep one ghash and avoid bigger keys comparissons/hashing. */
+ void *key = (char *)ma + is_hair;
+ /* Search for other material instances (sharing the same Material datablock). */
+ EeveeMaterialCache **emc_p, *emc;
+ if (BLI_ghash_ensure_p(pd->material_hash, key, (void ***)&emc_p)) {
+ return **emc_p;
+ }
+ else {
+ *emc_p = emc = BLI_memblock_alloc(sldata->material_cache);
}
- emsg = MEM_callocN(sizeof(EeveeMaterialShadingGroups), "EeveeMaterialShadingGroups");
- 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, use_ssrefract);
-
- eGPUMaterialStatus 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);
+ material_shadow(vedata, sldata, ma, is_hair, emc);
- eGPUMaterialStatus 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_ssrefract) {
- emsg->depth_grp = DRW_shgroup_material_create(
- *gpumat_depth, (do_cull) ? psl->refract_depth_pass_cull : psl->refract_depth_pass);
- emsg->depth_clip_grp = DRW_shgroup_material_create(
- *gpumat_depth,
- (do_cull) ? psl->refract_depth_pass_clip_cull : psl->refract_depth_pass_clip);
- }
- else {
- emsg->depth_grp = DRW_shgroup_material_create(
- *gpumat_depth, (do_cull) ? psl->depth_pass_cull : psl->depth_pass);
- emsg->depth_clip_grp = DRW_shgroup_material_create(
- *gpumat_depth, (do_cull) ? psl->depth_pass_clip_cull : psl->depth_pass_clip);
- }
-
- if (emsg->depth_grp != NULL) {
- use_diffuse = GPU_material_flag_get(*gpumat_depth, GPU_MATFLAG_DIFFUSE);
- use_glossy = GPU_material_flag_get(*gpumat_depth, GPU_MATFLAG_GLOSSY);
- use_refract = GPU_material_flag_get(*gpumat_depth, GPU_MATFLAG_REFRACT);
-
- add_standard_uniforms(emsg->depth_grp,
- sldata,
- vedata,
- NULL,
- NULL,
- use_diffuse,
- use_glossy,
- use_refract,
- false,
- false,
- DEFAULT_RENDER_PASS_FLAG);
- add_standard_uniforms(emsg->depth_clip_grp,
- sldata,
- vedata,
- NULL,
- NULL,
- use_diffuse,
- use_glossy,
- use_refract,
- false,
- false,
- DEFAULT_RENDER_PASS_FLAG);
-
- if (ma->blend_method == MA_BM_CLIP) {
- DRW_shgroup_uniform_float(emsg->depth_grp, "alphaThreshold", &ma->alpha_threshold, 1);
- DRW_shgroup_uniform_float(
- emsg->depth_clip_grp, "alphaThreshold", &ma->alpha_threshold, 1);
- }
- }
+ {
+ /* Depth Pass */
+ int mat_options = VAR_MAT_MESH | VAR_MAT_DEPTH;
+ SET_FLAG_FROM_TEST(mat_options, use_ssrefract, VAR_MAT_REFRACT);
+ SET_FLAG_FROM_TEST(mat_options, use_depth_shader, VAR_MAT_HASH);
+ SET_FLAG_FROM_TEST(mat_options, is_hair, VAR_MAT_HAIR);
+ GPUMaterial *gpumat = (use_depth_shader) ?
+ EEVEE_material_get(vedata, scene, ma, NULL, mat_options) :
+ EEVEE_material_default_get(scene, ma, mat_options);
+
+ int option = 0;
+ SET_FLAG_FROM_TEST(option, do_cull, KEY_CULL);
+ SET_FLAG_FROM_TEST(option, use_ssrefract, KEY_REFRACT);
+ DRWPass *depth_ps = (DRWPass *[]){
+ psl->depth_ps,
+ psl->depth_cull_ps,
+ psl->depth_refract_ps,
+ psl->depth_refract_cull_ps,
+ }[option];
+ /* Hair are rendered inside the non-cull pass but needs to have a separate cache key. */
+ SET_FLAG_FROM_TEST(option, is_hair, KEY_HAIR);
+
+ /* Search for the same shaders usage in the pass. */
+ struct GPUShader *sh = GPU_material_get_shader(gpumat);
+ void *cache_key = (char *)sh + option;
+ DRWShadingGroup *grp, **grp_p;
+
+ if (BLI_ghash_ensure_p(pd->material_hash, cache_key, (void ***)&grp_p)) {
+ /* This GPUShader has already been used by another material.
+ * Add new shading group just after to avoid shader switching cost. */
+ grp = DRW_shgroup_create_sub(*grp_p);
}
-
- switch (status_mat_surface) {
- case GPU_MAT_SUCCESS: {
- static int no_ssr = 0;
- static int first_ssr = 1;
- int *ssr_id = (((effects->enabled_effects & EFFECT_SSR) != 0) && !use_ssrefract) ?
- &first_ssr :
- &no_ssr;
- const bool use_sss = GPU_material_flag_get(*gpumat, GPU_MATFLAG_SSS);
- use_diffuse = GPU_material_flag_get(*gpumat, GPU_MATFLAG_DIFFUSE);
- use_glossy = GPU_material_flag_get(*gpumat, GPU_MATFLAG_GLOSSY);
- use_refract = GPU_material_flag_get(*gpumat, GPU_MATFLAG_REFRACT);
-
- emsg->shading_grp = DRW_shgroup_material_create(
- *gpumat,
- (use_ssrefract) ?
- psl->refract_pass :
- (use_sss) ? ((do_cull) ? psl->sss_pass_cull : psl->sss_pass) :
- ((do_cull) ? psl->material_pass_cull : psl->material_pass));
-
- add_standard_uniforms(emsg->shading_grp,
- sldata,
- vedata,
- ssr_id,
- &ma->refract_depth,
- use_diffuse,
- use_glossy,
- use_refract,
- use_ssrefract,
- false,
- DEFAULT_RENDER_PASS_FLAG);
-
- 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) {
- /* Limit of 8 bit stencil buffer. ID 255 is refraction. */
- if (e_data.sss_count < 254) {
- int sss_id = e_data.sss_count + 1;
- DRW_shgroup_stencil_mask(emsg->shading_grp, sss_id);
- EEVEE_subsurface_add_pass(sldata, vedata, sss_id, sss_profile);
- if (use_translucency) {
- EEVEE_subsurface_translucency_add_pass(
- sldata, vedata, sss_id, sss_profile, sss_tex_profile);
- }
- e_data.sss_count++;
- }
- else {
- /* TODO : display message. */
- printf("Error: Too many different Subsurface shader in the scene.\n");
- }
- }
- }
-
- RENDER_PASS_ITER_BEGIN (stl->g_data->render_passes, render_pass_index, render_pass_flag) {
- emsg->material_accum_grp[render_pass_index] = DRW_shgroup_material_create(
- *gpumat, psl->material_accum_pass[render_pass_index]);
- add_standard_uniforms(emsg->material_accum_grp[render_pass_index],
- sldata,
- vedata,
- ssr_id,
- &ma->refract_depth,
- use_diffuse,
- use_glossy,
- use_refract,
- use_ssrefract,
- false,
- render_pass_flag);
- }
- RENDER_PASS_ITER_END(render_pass_index);
-
- break;
- }
- case GPU_MAT_QUEUED: {
- stl->g_data->queued_shaders_count++;
- color_p = compile_col;
- metal_p = spec_p = rough_p = &half;
- store_material = false;
- break;
- }
- case GPU_MAT_FAILED:
- default:
- color_p = error_col;
- metal_p = spec_p = rough_p = &half;
- break;
+ else {
+ *grp_p = grp = DRW_shgroup_create(sh, depth_ps);
+ EEVEE_material_bind_resources(grp, gpumat, sldata, vedata, NULL, NULL, false, false);
}
- }
- /* Fallback to default shader */
- if (emsg->shading_grp == NULL) {
- bool use_ssr = ((effects->enabled_effects & EFFECT_SSR) != 0);
- emsg->shading_grp = EEVEE_default_shading_group_get(
- sldata, vedata, NULL, NULL, NULL, false, holdout, use_ssr);
- DRW_shgroup_uniform_vec3(emsg->shading_grp, "basecol", color_p, 1);
- DRW_shgroup_uniform_float(emsg->shading_grp, "metallic", metal_p, 1);
- DRW_shgroup_uniform_float(emsg->shading_grp, "specular", spec_p, 1);
- DRW_shgroup_uniform_float(emsg->shading_grp, "roughness", rough_p, 1);
-
- RENDER_PASS_ITER_BEGIN (stl->g_data->render_passes, render_pass_index, render_pass_flag) {
- DRWShadingGroup *shgrp = EEVEE_default_render_pass_shading_group_get(
- sldata,
- vedata,
- holdout,
- use_ssr,
- psl->material_accum_pass[render_pass_index],
- render_pass_flag);
-
- DRW_shgroup_uniform_vec3(shgrp, "basecol", color_p, 1);
- DRW_shgroup_uniform_float(shgrp, "metallic", metal_p, 1);
- DRW_shgroup_uniform_float(shgrp, "specular", spec_p, 1);
- DRW_shgroup_uniform_float(shgrp, "roughness", rough_p, 1);
- emsg->material_accum_grp[render_pass_index] = shgrp;
- }
- RENDER_PASS_ITER_END(render_pass_index);
- }
+ DRW_shgroup_add_material_resources(grp, gpumat);
- /* Fallback default depth prepass */
- if (emsg->depth_grp == NULL) {
- if (use_ssrefract) {
- emsg->depth_grp = (do_cull) ? stl->g_data->refract_depth_shgrp_cull :
- stl->g_data->refract_depth_shgrp;
- emsg->depth_clip_grp = (do_cull) ? stl->g_data->refract_depth_shgrp_clip_cull :
- stl->g_data->refract_depth_shgrp_clip;
+ emc->depth_grp = grp;
+ emc->depth_grp_p = grp_p;
+ }
+ {
+ /* Shading Pass */
+ int mat_options = VAR_MAT_MESH;
+ SET_FLAG_FROM_TEST(mat_options, use_ssrefract, VAR_MAT_REFRACT);
+ SET_FLAG_FROM_TEST(mat_options, is_hair, VAR_MAT_HAIR);
+ GPUMaterial *gpumat = EEVEE_material_get(vedata, scene, ma, NULL, mat_options);
+ const bool use_sss = GPU_material_flag_get(gpumat, GPU_MATFLAG_SSS);
+
+ int ssr_id = (((effects->enabled_effects & EFFECT_SSR) != 0) && !use_ssrefract) ? 1 : 0;
+ int option = (use_ssrefract ? 0 : (use_sss ? 1 : 2)) * 2 + do_cull;
+ DRWPass *shading_pass = (DRWPass *[]){
+ psl->material_refract_ps,
+ psl->material_refract_cull_ps,
+ psl->material_sss_ps,
+ psl->material_sss_cull_ps,
+ psl->material_ps,
+ psl->material_cull_ps,
+ }[option];
+ /* Hair are rendered inside the non-cull pass but needs to have a separate cache key */
+ option = option * 2 + is_hair;
+
+ /* Search for the same shaders usage in the pass. */
+ /* HACK: Assume the struct will never be smaller than our variations.
+ * This allow us to only keep one ghash and avoid bigger keys comparissons/hashing. */
+ BLI_assert(option <= 16);
+ struct GPUShader *sh = GPU_material_get_shader(gpumat);
+ void *cache_key = (char *)sh + option;
+ DRWShadingGroup *grp, **grp_p;
+
+ if (BLI_ghash_ensure_p(pd->material_hash, cache_key, (void ***)&grp_p)) {
+ /* This GPUShader has already been used by another material.
+ * Add new shading group just after to avoid shader switching cost. */
+ grp = DRW_shgroup_create_sub(*grp_p);
}
else {
- emsg->depth_grp = (do_cull) ? stl->g_data->depth_shgrp_cull : stl->g_data->depth_shgrp;
- emsg->depth_clip_grp = (do_cull) ? stl->g_data->depth_shgrp_clip_cull :
- stl->g_data->depth_shgrp_clip;
+ *grp_p = grp = DRW_shgroup_create(sh, shading_pass);
+ EEVEE_material_bind_resources(
+ grp, gpumat, sldata, vedata, &ssr_id, &ma->refract_depth, use_ssrefract, false);
}
- }
+ DRW_shgroup_add_material_resources(grp, gpumat);
- memcpy(shgrps, emsg, sizeof(EeveeMaterialShadingGroups));
- if (store_material) {
- BLI_ghash_insert(material_hash, ma, emsg);
- }
- else {
- MEM_freeN(emsg);
+ if (use_sss) {
+ EEVEE_subsurface_add_pass(sldata, vedata, ma, grp, gpumat);
+ }
+
+ emc->shading_grp = grp;
+ emc->shading_grp_p = grp_p;
+ emc->shading_gpumat = gpumat;
}
+ return *emc;
}
-static void material_transparent(Material *ma,
- EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- struct GPUMaterial **gpumat,
- struct EeveeMaterialShadingGroups *shgrps)
+static EeveeMaterialCache material_transparent(EEVEE_Data *vedata,
+ EEVEE_ViewLayerData *sldata,
+ Material *ma)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
Scene *scene = draw_ctx->scene;
- EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
- EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_EffectsInfo *effects = vedata->stl->effects;
+ EeveeMaterialCache emc = {0};
const bool do_cull = (ma->blend_flag & MA_BL_CULL_BACKFACE) != 0;
const bool use_gpumat = ma->use_nodes && ma->nodetree;
const bool use_ssrefract = use_gpumat && ((ma->blend_flag & MA_BL_SS_REFRACTION) != 0) &&
- ((stl->effects->enabled_effects & EFFECT_REFRACT) != 0);
- const float *color_p = &ma->r;
- const float *metal_p = &ma->metallic;
- const float *spec_p = &ma->spec;
- const float *rough_p = &ma->roughness;
-
+ ((effects->enabled_effects & EFFECT_REFRACT) != 0);
const bool use_prepass = ((ma->blend_flag & MA_BL_HIDE_BACKFACE) != 0);
DRWState cur_state;
@@ -1677,81 +691,53 @@ static void material_transparent(Material *ma,
DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_DEPTH_EQUAL |
DRW_STATE_BLEND_CUSTOM);
- /* Depth prepass */
+ material_shadow(vedata, sldata, ma, false, &emc);
+
if (use_prepass) {
- shgrps->depth_grp = DRW_shgroup_create(e_data.default_prepass_clip_sh, psl->transparent_pass);
+ /* Depth prepass */
+ int mat_options = VAR_MAT_MESH | VAR_MAT_DEPTH;
+ GPUMaterial *gpumat = EEVEE_material_get(vedata, scene, ma, NULL, mat_options);
+ struct GPUShader *sh = GPU_material_get_shader(gpumat);
+
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, psl->transparent_pass);
+
+ EEVEE_material_bind_resources(grp, gpumat, sldata, vedata, NULL, NULL, false, true);
+ DRW_shgroup_add_material_resources(grp, gpumat);
cur_state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
cur_state |= (do_cull) ? DRW_STATE_CULL_BACK : 0;
- DRW_shgroup_state_disable(shgrps->depth_grp, all_state);
- DRW_shgroup_state_enable(shgrps->depth_grp, cur_state);
+ DRW_shgroup_state_disable(grp, all_state);
+ DRW_shgroup_state_enable(grp, cur_state);
+
+ emc.depth_grp = grp;
}
+ {
+ /* Shading */
+ int ssr_id = -1; /* TODO transparent SSR */
+ int mat_options = VAR_MAT_MESH | VAR_MAT_BLEND;
+ SET_FLAG_FROM_TEST(mat_options, use_ssrefract, VAR_MAT_REFRACT);
+ GPUMaterial *gpumat = EEVEE_material_get(vedata, scene, ma, NULL, mat_options);
- 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;
+ DRWShadingGroup *grp = DRW_shgroup_create(GPU_material_get_shader(gpumat),
+ psl->transparent_pass);
- /* Shading */
- *gpumat = EEVEE_material_mesh_get(scene, ma, vedata, true, use_ssrefract);
-
- switch (GPU_material_status(*gpumat)) {
- case GPU_MAT_SUCCESS: {
- static int ssr_id = -1; /* TODO transparent SSR */
-
- shgrps->shading_grp = DRW_shgroup_material_create(*gpumat, psl->transparent_pass);
-
- bool use_blend = true;
- bool use_diffuse = GPU_material_flag_get(*gpumat, GPU_MATFLAG_DIFFUSE);
- bool use_glossy = GPU_material_flag_get(*gpumat, GPU_MATFLAG_GLOSSY);
- bool use_refract = GPU_material_flag_get(*gpumat, GPU_MATFLAG_REFRACT);
-
- add_standard_uniforms(shgrps->shading_grp,
- sldata,
- vedata,
- &ssr_id,
- &ma->refract_depth,
- use_diffuse,
- use_glossy,
- use_refract,
- use_ssrefract,
- use_blend,
- DEFAULT_RENDER_PASS_FLAG);
- break;
- }
- case GPU_MAT_QUEUED: {
- /* TODO Bypass probe compilation. */
- stl->g_data->queued_shaders_count++;
- color_p = compile_col;
- metal_p = spec_p = rough_p = &half;
- break;
- }
- case GPU_MAT_FAILED:
- default:
- color_p = error_col;
- metal_p = spec_p = rough_p = &half;
- break;
- }
- }
+ EEVEE_material_bind_resources(
+ grp, gpumat, sldata, vedata, &ssr_id, &ma->refract_depth, use_ssrefract, true);
+ DRW_shgroup_add_material_resources(grp, gpumat);
- /* Fallback to default shader */
- if (shgrps->shading_grp == NULL) {
- shgrps->shading_grp = EEVEE_default_shading_group_create(
- sldata, vedata, psl->transparent_pass, false, true, false);
- DRW_shgroup_uniform_vec3(shgrps->shading_grp, "basecol", color_p, 1);
- DRW_shgroup_uniform_float(shgrps->shading_grp, "metallic", metal_p, 1);
- DRW_shgroup_uniform_float(shgrps->shading_grp, "specular", spec_p, 1);
- DRW_shgroup_uniform_float(shgrps->shading_grp, "roughness", rough_p, 1);
- }
+ cur_state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_CUSTOM;
+ cur_state |= (use_prepass) ? DRW_STATE_DEPTH_EQUAL : DRW_STATE_DEPTH_LESS_EQUAL;
+ cur_state |= (do_cull) ? DRW_STATE_CULL_BACK : 0;
- cur_state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_CUSTOM;
- cur_state |= (use_prepass) ? DRW_STATE_DEPTH_EQUAL : DRW_STATE_DEPTH_LESS_EQUAL;
- cur_state |= (do_cull) ? DRW_STATE_CULL_BACK : 0;
+ /* Disable other blend modes and use the one we want. */
+ DRW_shgroup_state_disable(grp, all_state);
+ DRW_shgroup_state_enable(grp, cur_state);
- /* Disable other blend modes and use the one we want. */
- DRW_shgroup_state_disable(shgrps->shading_grp, all_state);
- DRW_shgroup_state_enable(shgrps->shading_grp, cur_state);
+ emc.shading_grp = grp;
+ emc.shading_gpumat = gpumat;
+ }
+ return emc;
}
/* Return correct material or empty default material if slot is empty. */
@@ -1766,12 +752,35 @@ BLI_INLINE Material *eevee_object_material_get(Object *ob, int slot, bool holdou
ma = BKE_material_default_volume();
}
else {
- ma = BKE_material_default_empty();
+ ma = BKE_material_default_surface();
}
}
return ma;
}
+BLI_INLINE EeveeMaterialCache eevee_material_cache_get(
+ EEVEE_Data *vedata, EEVEE_ViewLayerData *sldata, Object *ob, int slot, bool is_hair)
+{
+ const bool holdout = (ob->base_flag & BASE_HOLDOUT) != 0;
+ EeveeMaterialCache matcache;
+ Material *ma = eevee_object_material_get(ob, slot, holdout);
+ switch (ma->blend_method) {
+ case MA_BM_BLEND:
+ if (!is_hair) {
+ matcache = material_transparent(vedata, sldata, ma);
+ break;
+ }
+ ATTR_FALLTHROUGH;
+ case MA_BM_SOLID:
+ case MA_BM_CLIP:
+ case MA_BM_HASHED:
+ default:
+ matcache = material_opaque(vedata, sldata, ma, is_hair);
+ break;
+ }
+ return matcache;
+}
+
static void eevee_hair_cache_populate(EEVEE_Data *vedata,
EEVEE_ViewLayerData *sldata,
Object *ob,
@@ -1780,240 +789,49 @@ static void eevee_hair_cache_populate(EEVEE_Data *vedata,
int matnr,
bool *cast_shadow)
{
- EEVEE_PassList *psl = vedata->psl;
- EEVEE_StorageList *stl = vedata->stl;
- const DRWContextState *draw_ctx = DRW_context_state_get();
- Scene *scene = draw_ctx->scene;
- const bool holdout = (ob->base_flag & BASE_HOLDOUT) != 0;
-
- DRWShadingGroup *shgrp = NULL;
- Material *ma = eevee_object_material_get(ob, matnr - 1, holdout);
- const bool use_gpumat = ma->use_nodes && ma->nodetree && !holdout;
- const bool use_alpha_hash = (ma->blend_method == MA_BM_HASHED);
- const bool use_alpha_clip = (ma->blend_method == MA_BM_CLIP);
- const bool use_ssr = ((stl->effects->enabled_effects & EFFECT_SSR) != 0);
+ EeveeMaterialCache matcache = eevee_material_cache_get(vedata, sldata, ob, matnr - 1, true);
- GPUMaterial *gpumat = use_gpumat ? EEVEE_material_hair_get(scene, ma) : NULL;
- eGPUMaterialStatus status_mat_surface = gpumat ? GPU_material_status(gpumat) : GPU_MAT_SUCCESS;
-
- float *color_p = &ma->r;
- float *metal_p = &ma->metallic;
- float *spec_p = &ma->spec;
- float *rough_p = &ma->roughness;
-
- /* Depth prepass. */
- if (use_gpumat && (use_alpha_clip || use_alpha_hash)) {
- GPUMaterial *gpumat_depth = EEVEE_material_hair_depth_get(scene, ma, use_alpha_hash, false);
-
- eGPUMaterialStatus 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 {
- const bool use_diffuse = GPU_material_flag_get(gpumat_depth, GPU_MATFLAG_DIFFUSE);
- const bool use_glossy = GPU_material_flag_get(gpumat_depth, GPU_MATFLAG_GLOSSY);
- const bool use_refract = GPU_material_flag_get(gpumat_depth, GPU_MATFLAG_REFRACT);
-
- for (int i = 0; i < 2; i++) {
- DRWPass *pass = (i == 0) ? psl->depth_pass : psl->depth_pass_clip;
-
- shgrp = DRW_shgroup_material_hair_create(ob, psys, md, pass, gpumat_depth);
-
- add_standard_uniforms(shgrp,
- sldata,
- vedata,
- NULL,
- NULL,
- use_diffuse,
- use_glossy,
- use_refract,
- false,
- false,
- DEFAULT_RENDER_PASS_FLAG);
-
- /* Unfortunately needed for correctness but not 99% of the time not needed.
- * TODO detect when needed? */
- DRW_shgroup_uniform_block(shgrp, "probe_block", sldata->probe_ubo);
- DRW_shgroup_uniform_block(shgrp, "grid_block", sldata->grid_ubo);
- DRW_shgroup_uniform_block(shgrp, "planar_block", sldata->planar_ubo);
- DRW_shgroup_uniform_block(shgrp, "light_block", sldata->light_ubo);
- DRW_shgroup_uniform_block(shgrp, "shadow_block", sldata->shadow_ubo);
- DRW_shgroup_uniform_block(
- shgrp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
- DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex);
-
- if (use_alpha_clip) {
- DRW_shgroup_uniform_float(shgrp, "alphaThreshold", &ma->alpha_threshold, 1);
- }
- }
- }
+ if (matcache.depth_grp) {
+ *matcache.depth_grp_p = DRW_shgroup_hair_create_sub(ob, psys, md, matcache.depth_grp);
}
-
- /* Fallback to default shader */
- if (shgrp == NULL) {
- for (int i = 0; i < 2; i++) {
- DRWPass *depth_pass = (i == 0) ? psl->depth_pass : psl->depth_pass_clip;
- struct GPUShader *depth_sh = (i == 0) ? e_data.default_hair_prepass_sh :
- e_data.default_hair_prepass_clip_sh;
- DRW_shgroup_hair_create(ob, psys, md, depth_pass, depth_sh);
- }
+ if (matcache.shading_grp) {
+ *matcache.shading_grp_p = DRW_shgroup_hair_create_sub(ob, psys, md, matcache.shading_grp);
}
-
- shgrp = NULL;
-
- if (gpumat) {
- static int ssr_id;
- ssr_id = (use_ssr) ? 1 : -1;
- static float half = 0.5f;
- static float error_col[3] = {1.0f, 0.0f, 1.0f};
- static float compile_col[3] = {0.5f, 0.5f, 0.5f};
-
- switch (status_mat_surface) {
- case GPU_MAT_SUCCESS: {
- bool use_diffuse = GPU_material_flag_get(gpumat, GPU_MATFLAG_DIFFUSE);
- bool use_glossy = GPU_material_flag_get(gpumat, GPU_MATFLAG_GLOSSY);
- bool use_refract = GPU_material_flag_get(gpumat, GPU_MATFLAG_REFRACT);
-
- shgrp = DRW_shgroup_material_hair_create(ob, psys, md, psl->material_pass, gpumat);
-
- if (!use_diffuse && !use_glossy && !use_refract) {
- /* HACK: Small hack to avoid issue when utilTex is needed for
- * world_normals_get and none of the bsdfs are present.
- * This binds utilTex even if not needed. */
- DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex);
- }
-
- add_standard_uniforms(shgrp,
- sldata,
- vedata,
- &ssr_id,
- NULL,
- use_diffuse,
- use_glossy,
- use_refract,
- false,
- false,
- DEFAULT_RENDER_PASS_FLAG);
-
- /* Add the hair to all the render_passes that are enabled */
- RENDER_PASS_ITER_BEGIN (stl->g_data->render_passes, render_pass_index, render_pass_flag) {
- shgrp = DRW_shgroup_material_hair_create(
- ob, psys, md, psl->material_accum_pass[render_pass_index], gpumat);
- if (!use_diffuse && !use_glossy && !use_refract) {
- /* Small hack to avoid issue when utilTex is needed for
- * world_normals_get and none of the bsdfs that need it are present.
- * This binds `utilTex` even if not needed. */
- DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex);
- }
-
- add_standard_uniforms(shgrp,
- sldata,
- vedata,
- &ssr_id,
- NULL,
- use_diffuse,
- use_glossy,
- use_refract,
- false,
- false,
- render_pass_flag);
- }
- RENDER_PASS_ITER_END(render_pass_index);
-
- break;
- }
- case GPU_MAT_QUEUED: {
- stl->g_data->queued_shaders_count++;
- color_p = compile_col;
- metal_p = spec_p = rough_p = &half;
- break;
- }
- case GPU_MAT_FAILED:
- default:
- color_p = error_col;
- metal_p = spec_p = rough_p = &half;
- break;
- }
+ if (matcache.shadow_grp) {
+ *matcache.shadow_grp_p = DRW_shgroup_hair_create_sub(ob, psys, md, matcache.shadow_grp);
+ *cast_shadow = true;
}
+}
- /* Fallback to default shader */
- if (shgrp == NULL) {
- shgrp = EEVEE_default_shading_group_get(sldata, vedata, ob, psys, md, true, holdout, use_ssr);
- DRW_shgroup_uniform_vec3(shgrp, "basecol", color_p, 1);
- DRW_shgroup_uniform_float(shgrp, "metallic", metal_p, 1);
- DRW_shgroup_uniform_float(shgrp, "specular", spec_p, 1);
- DRW_shgroup_uniform_float(shgrp, "roughness", rough_p, 1);
-
- RENDER_PASS_ITER_BEGIN (stl->g_data->render_passes, render_pass_index, render_pass_flag) {
- shgrp = EEVEE_default_hair_render_pass_shading_group_get(
- sldata,
- vedata,
- ob,
- psys,
- md,
- holdout,
- use_ssr,
- psl->material_accum_pass[render_pass_index],
- render_pass_flag);
-
- DRW_shgroup_uniform_vec3(shgrp, "basecol", color_p, 1);
- DRW_shgroup_uniform_float(shgrp, "metallic", metal_p, 1);
- DRW_shgroup_uniform_float(shgrp, "specular", spec_p, 1);
- DRW_shgroup_uniform_float(shgrp, "roughness", rough_p, 1);
- }
- RENDER_PASS_ITER_END(render_pass_index);
- }
+#define ADD_SHGROUP_CALL(shgrp, ob, geom, oedata) \
+ do { \
+ if (oedata) { \
+ DRW_shgroup_call_with_callback(shgrp, geom, ob, oedata); \
+ } \
+ else { \
+ DRW_shgroup_call(shgrp, geom, ob); \
+ } \
+ } while (0)
- /* Shadows */
- char blend_shadow = use_gpumat ? ma->blend_shadow : MA_BS_SOLID;
- const bool shadow_alpha_hash = (blend_shadow == MA_BS_HASHED);
- switch (blend_shadow) {
- case MA_BS_SOLID:
- DRW_shgroup_hair_create(ob, psys, md, psl->shadow_pass, e_data.default_hair_prepass_sh);
- *cast_shadow = true;
- break;
- case MA_BS_CLIP:
- case MA_BS_HASHED:
- gpumat = EEVEE_material_hair_depth_get(scene, ma, shadow_alpha_hash, true);
- shgrp = DRW_shgroup_material_hair_create(ob, psys, md, psl->shadow_pass, gpumat);
- /* Unfortunately needed for correctness but not 99% of the time not needed.
- * TODO detect when needed? */
- DRW_shgroup_uniform_block(shgrp, "probe_block", sldata->probe_ubo);
- DRW_shgroup_uniform_block(shgrp, "grid_block", sldata->grid_ubo);
- DRW_shgroup_uniform_block(shgrp, "planar_block", sldata->planar_ubo);
- DRW_shgroup_uniform_block(shgrp, "light_block", sldata->light_ubo);
- DRW_shgroup_uniform_block(shgrp, "shadow_block", sldata->shadow_ubo);
- DRW_shgroup_uniform_block(
- shgrp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
- DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex);
-
- if (!shadow_alpha_hash) {
- DRW_shgroup_uniform_float(shgrp, "alphaThreshold", &ma->alpha_threshold, 1);
- }
- *cast_shadow = true;
- break;
- case MA_BS_NONE:
- default:
- break;
+#define ADD_SHGROUP_CALL_SAFE(shgrp, ob, geom, oedata) \
+ do { \
+ if (shgrp) { \
+ ADD_SHGROUP_CALL(shgrp, ob, geom, oedata); \
+ } \
+ } while (0)
+
+#define MATCACHE_AS_ARRAY(matcache, member, materials_len, output_array) \
+ for (int i = 0; i < materials_len; i++) { \
+ output_array[i] = matcache[i].member; \
}
-}
void EEVEE_materials_cache_populate(EEVEE_Data *vedata,
EEVEE_ViewLayerData *sldata,
Object *ob,
bool *cast_shadow)
{
- EEVEE_PassList *psl = vedata->psl;
- EEVEE_StorageList *stl = vedata->stl;
const DRWContextState *draw_ctx = DRW_context_state_get();
Scene *scene = draw_ctx->scene;
- GHash *material_hash = stl->g_data->material_hash;
- const bool holdout = (ob->base_flag & BASE_HOLDOUT) != 0;
bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d) &&
!DRW_state_is_image_render();
@@ -2022,139 +840,64 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata,
if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) {
const int materials_len = DRW_cache_object_material_count_get(ob);
- struct EeveeMaterialShadingGroups *shgrps_array = BLI_array_alloca(shgrps_array,
- materials_len);
-
- struct GPUMaterial **gpumat_array = BLI_array_alloca(gpumat_array, materials_len);
- struct GPUMaterial **gpumat_depth_array = BLI_array_alloca(gpumat_array, materials_len);
- struct Material **ma_array = BLI_array_alloca(ma_array, materials_len);
-
+ EeveeMaterialCache *matcache = BLI_array_alloca(matcache, materials_len);
for (int i = 0; i < materials_len; i++) {
- ma_array[i] = eevee_object_material_get(ob, i, holdout);
- memset(&shgrps_array[i], 0, sizeof(EeveeMaterialShadingGroups));
- gpumat_array[i] = NULL;
- gpumat_depth_array[i] = NULL;
-
- switch (ma_array[i]->blend_method) {
- case MA_BM_SOLID:
- case MA_BM_CLIP:
- case MA_BM_HASHED:
- material_opaque(ma_array[i],
- material_hash,
- sldata,
- vedata,
- &gpumat_array[i],
- &gpumat_depth_array[i],
- &shgrps_array[i],
- holdout);
- break;
- case MA_BM_BLEND:
- material_transparent(ma_array[i], sldata, vedata, &gpumat_array[i], &shgrps_array[i]);
- break;
- default:
- BLI_assert(0);
- break;
- }
+ matcache[i] = eevee_material_cache_get(vedata, sldata, ob, i, false);
}
/* Only support single volume material for now. */
/* XXX We rely on the previously compiled surface shader
* to know if the material has a "volume nodetree".
*/
- bool use_volume_material = (gpumat_array[0] &&
- GPU_material_has_volume_output(gpumat_array[0]));
+ bool use_volume_material = (matcache[0].shading_gpumat &&
+ GPU_material_has_volume_output(matcache[0].shading_gpumat));
if ((ob->dt >= OB_SOLID) || DRW_state_is_image_render()) {
- /* Get per-material split surface */
- struct GPUBatch **mat_geom = NULL;
-
- if (!use_sculpt_pbvh) {
- mat_geom = DRW_cache_object_surface_material_get(ob, gpumat_array, materials_len);
- }
-
if (use_sculpt_pbvh) {
- struct DRWShadingGroup **sculpt_shgrps_array = BLI_array_alloca(sculpt_shgrps_array,
- materials_len);
- for (int i = 0; i < materials_len; i++) {
- sculpt_shgrps_array[i] = shgrps_array[i].shading_grp;
- }
- DRW_shgroup_call_sculpt_with_materials(sculpt_shgrps_array, materials_len, ob);
+ struct DRWShadingGroup **shgrps_array = BLI_array_alloca(shgrps_array, materials_len);
- for (int i = 0; i < materials_len; i++) {
- sculpt_shgrps_array[i] = shgrps_array[i].depth_grp;
- }
- DRW_shgroup_call_sculpt_with_materials(sculpt_shgrps_array, materials_len, ob);
- for (int i = 0; i < materials_len; i++) {
- sculpt_shgrps_array[i] = shgrps_array[i].depth_clip_grp;
- }
- DRW_shgroup_call_sculpt_with_materials(sculpt_shgrps_array, materials_len, ob);
+ MATCACHE_AS_ARRAY(matcache, shading_grp, materials_len, shgrps_array);
+ DRW_shgroup_call_sculpt_with_materials(shgrps_array, materials_len, ob);
- for (int renderpass_index = 0;
- renderpass_index < stl->g_data->render_passes_material_count;
- renderpass_index++) {
- for (int i = 0; i < materials_len; i++) {
- sculpt_shgrps_array[i] = shgrps_array[i].material_accum_grp[renderpass_index];
- }
- DRW_shgroup_call_sculpt_with_materials(sculpt_shgrps_array, materials_len, ob);
- }
+ MATCACHE_AS_ARRAY(matcache, depth_grp, materials_len, shgrps_array);
+ DRW_shgroup_call_sculpt_with_materials(shgrps_array, materials_len, ob);
- /* TODO(fclem): Support shadows in sculpt mode. */
+ MATCACHE_AS_ARRAY(matcache, shadow_grp, materials_len, shgrps_array);
+ DRW_shgroup_call_sculpt_with_materials(shgrps_array, materials_len, ob);
}
- else if (mat_geom) {
- for (int i = 0; i < materials_len; i++) {
- if (mat_geom[i] == NULL) {
- continue;
- }
+ else {
+ struct GPUMaterial **gpumat_array = BLI_array_alloca(gpumat_array, materials_len);
+ MATCACHE_AS_ARRAY(matcache, shading_gpumat, materials_len, gpumat_array);
+ /* Get per-material split surface */
+ struct GPUBatch **mat_geom = DRW_cache_object_surface_material_get(
+ ob, gpumat_array, materials_len);
- /* Do not render surface if we are rendering a volume object
- * and do not have a surface closure. */
- if (use_volume_material &&
- (gpumat_array[i] && !GPU_material_has_surface_output(gpumat_array[i]))) {
- continue;
- }
+ if (mat_geom) {
+ for (int i = 0; i < materials_len; i++) {
+ if (mat_geom[i] == NULL) {
+ continue;
+ }
- /* XXX TODO rewrite this to include the dupli objects.
- * This means we cannot exclude dupli objects from reflections!!! */
- EEVEE_ObjectEngineData *oedata = NULL;
- if ((ob->base_flag & BASE_FROM_DUPLI) == 0) {
- oedata = EEVEE_object_data_ensure(ob);
- oedata->ob = ob;
- oedata->test_data = &sldata->probes->vis_data;
- }
- EeveeMaterialShadingGroups *shgrps = &shgrps_array[i];
- ADD_SHGROUP_CALL(shgrps->shading_grp, ob, mat_geom[i], oedata);
- ADD_SHGROUP_CALL_SAFE(shgrps->depth_grp, ob, mat_geom[i], oedata);
- ADD_SHGROUP_CALL_SAFE(shgrps->depth_clip_grp, ob, mat_geom[i], oedata);
- for (int renderpass_index = 0;
- renderpass_index < stl->g_data->render_passes_material_count;
- renderpass_index++) {
- ADD_SHGROUP_CALL_SAFE(
- shgrps->material_accum_grp[renderpass_index], ob, mat_geom[i], oedata);
- }
+ /* Do not render surface if we are rendering a volume object
+ * and do not have a surface closure. */
+ if (use_volume_material &&
+ (gpumat_array[i] && !GPU_material_has_surface_output(gpumat_array[i]))) {
+ continue;
+ }
+
+ /* XXX TODO rewrite this to include the dupli objects.
+ * This means we cannot exclude dupli objects from reflections!!! */
+ EEVEE_ObjectEngineData *oedata = NULL;
+ if ((ob->base_flag & BASE_FROM_DUPLI) == 0) {
+ oedata = EEVEE_object_data_ensure(ob);
+ oedata->ob = ob;
+ oedata->test_data = &sldata->probes->vis_data;
+ }
- /* Shadow Pass */
- struct GPUMaterial *gpumat;
- const bool use_gpumat = (ma_array[i]->use_nodes && ma_array[i]->nodetree);
- char blend_shadow = use_gpumat ? ma_array[i]->blend_shadow : MA_BS_SOLID;
- switch (blend_shadow) {
- case MA_BS_SOLID:
- EEVEE_shadows_caster_add(sldata, stl, mat_geom[i], ob);
- *cast_shadow = true;
- break;
- case MA_BS_CLIP:
- gpumat = EEVEE_material_mesh_depth_get(scene, ma_array[i], false, true);
- EEVEE_shadows_caster_material_add(
- sldata, psl, gpumat, mat_geom[i], ob, &ma_array[i]->alpha_threshold);
- *cast_shadow = true;
- break;
- case MA_BS_HASHED:
- gpumat = EEVEE_material_mesh_depth_get(scene, ma_array[i], true, true);
- EEVEE_shadows_caster_material_add(sldata, psl, gpumat, mat_geom[i], ob, NULL);
- *cast_shadow = true;
- break;
- case MA_BS_NONE:
- default:
- break;
+ ADD_SHGROUP_CALL(matcache[i].shading_grp, ob, mat_geom[i], oedata);
+ ADD_SHGROUP_CALL_SAFE(matcache[i].depth_grp, ob, mat_geom[i], oedata);
+ ADD_SHGROUP_CALL_SAFE(matcache[i].shadow_grp, ob, mat_geom[i], oedata);
+ *cast_shadow = (matcache[i].shadow_grp != NULL);
}
}
}
@@ -2205,11 +948,12 @@ void EEVEE_object_hair_cache_populate(EEVEE_Data *vedata,
void EEVEE_materials_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
- EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
+ EEVEE_PrivateData *pd = vedata->stl->g_data;
+ EEVEE_EffectsInfo *effects = vedata->stl->effects;
- BLI_ghash_free(stl->g_data->material_hash, NULL, MEM_freeN);
+ BLI_ghash_free(pd->material_hash, NULL, NULL);
- SET_FLAG_FROM_TEST(stl->effects->enabled_effects, e_data.sss_count > 0, EFFECT_SSS);
+ SET_FLAG_FROM_TEST(effects->enabled_effects, effects->sss_surface_count > 0, EFFECT_SSS);
/* TODO(fclem) this is not really clean. Init should not be done in cache finish. */
EEVEE_subsurface_draw_init(sldata, vedata);
@@ -2217,38 +961,10 @@ void EEVEE_materials_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
void EEVEE_materials_free(void)
{
- for (int i = 0; i < VAR_MAT_MAX; i++) {
- DRW_SHADER_FREE_SAFE(e_data.default_lit[i]);
- }
- MEM_SAFE_FREE(e_data.frag_shader_lib);
- MEM_SAFE_FREE(e_data.vert_shader_str);
- MEM_SAFE_FREE(e_data.vert_shadow_shader_str);
- MEM_SAFE_FREE(e_data.vert_background_shader_str);
- MEM_SAFE_FREE(e_data.vert_volume_shader_str);
- MEM_SAFE_FREE(e_data.geom_volume_shader_str);
- MEM_SAFE_FREE(e_data.volume_shader_lib);
- DRW_SHADER_FREE_SAFE(e_data.default_hair_prepass_sh);
- DRW_SHADER_FREE_SAFE(e_data.default_hair_prepass_clip_sh);
- DRW_SHADER_FREE_SAFE(e_data.default_prepass_sh);
- DRW_SHADER_FREE_SAFE(e_data.default_prepass_clip_sh);
- DRW_SHADER_FREE_SAFE(e_data.default_background);
- DRW_SHADER_FREE_SAFE(e_data.update_noise_sh);
DRW_TEXTURE_FREE_SAFE(e_data.util_tex);
DRW_TEXTURE_FREE_SAFE(e_data.noise_tex);
}
-void EEVEE_materials_draw_opaque(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_PassList *psl)
-{
- for (int i = 0; i < VAR_MAT_MAX; i++) {
- if (psl->default_pass[i]) {
- DRW_draw_pass(psl->default_pass[i]);
- }
- }
-
- DRW_draw_pass(psl->material_pass);
- DRW_draw_pass(psl->material_pass_cull);
-}
-
/* -------------------------------------------------------------------- */
/** \name Render Passes
@@ -2256,172 +972,140 @@ void EEVEE_materials_draw_opaque(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Pass
void EEVEE_material_renderpasses_init(EEVEE_Data *vedata)
{
- EEVEE_StorageList *stl = vedata->stl;
- EEVEE_PrivateData *g_data = stl->g_data;
+ EEVEE_PrivateData *pd = vedata->stl->g_data;
/* For diffuse and glossy we calculate the final light + color buffer where we extract the
* light from by dividing by the color buffer. When one the light is requested we also tag
* the color buffer to do the extraction. */
- if (g_data->render_passes & EEVEE_RENDER_PASS_DIFFUSE_LIGHT) {
- g_data->render_passes |= EEVEE_RENDER_PASS_DIFFUSE_COLOR;
+ if (pd->render_passes & EEVEE_RENDER_PASS_DIFFUSE_LIGHT) {
+ pd->render_passes |= EEVEE_RENDER_PASS_DIFFUSE_COLOR;
}
- if (g_data->render_passes & EEVEE_RENDER_PASS_SPECULAR_LIGHT) {
- g_data->render_passes |= EEVEE_RENDER_PASS_SPECULAR_COLOR;
+ if (pd->render_passes & EEVEE_RENDER_PASS_SPECULAR_LIGHT) {
+ pd->render_passes |= EEVEE_RENDER_PASS_SPECULAR_COLOR;
}
+}
- /* Calculate the number of material based render passes */
- uint num_render_passes = count_bits_i(stl->g_data->render_passes & EEVEE_RENDERPASSES_MATERIAL);
- if ((num_render_passes != 0 && stl->g_data->render_passes & EEVEE_RENDER_PASS_ENVIRONMENT) ==
- 0) {
- num_render_passes += 1;
+static void material_renderpass_init(EEVEE_FramebufferList *fbl,
+ GPUTexture **output_tx,
+ const eGPUTextureFormat format,
+ const bool do_clear)
+{
+ DRW_texture_ensure_fullscreen_2d(output_tx, format, 0);
+ /* Clear texture. */
+ if (do_clear) {
+ float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ /* TODO(fclem) replace by GPU_texture_clear once it is fast. */
+ GPU_framebuffer_texture_attach(fbl->material_accum_fb, *output_tx, 0, 0);
+ GPU_framebuffer_bind(fbl->material_accum_fb);
+ GPU_framebuffer_clear_color(fbl->material_accum_fb, clear);
+ GPU_framebuffer_bind(fbl->main_fb);
+ GPU_framebuffer_texture_detach(fbl->material_accum_fb, *output_tx);
}
- stl->g_data->render_passes_material_count = num_render_passes;
}
void EEVEE_material_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, uint tot_samples)
{
- const DRWContextState *draw_ctx = DRW_context_state_get();
EEVEE_FramebufferList *fbl = vedata->fbl;
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
EEVEE_TextureList *txl = vedata->txl;
EEVEE_StorageList *stl = vedata->stl;
- EEVEE_PassList *psl = vedata->psl;
EEVEE_EffectsInfo *effects = stl->effects;
+ EEVEE_PrivateData *pd = stl->g_data;
- float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ /* Should be enough precision for many samples. */
+ const eGPUTextureFormat texture_format = (tot_samples > 128) ? GPU_RGBA32F : GPU_RGBA16F;
+ const bool do_clear = DRW_state_is_image_render() || (effects->taa_current_sample == 1);
/* Create FrameBuffer. */
+ GPU_framebuffer_ensure_config(&fbl->material_accum_fb,
+ {GPU_ATTACHMENT_TEXTURE(dtxl->depth), GPU_ATTACHMENT_LEAVE});
- /* Should be enough precision for many samples. */
- const eGPUTextureFormat texture_format_material_accum = (tot_samples > 128) ? GPU_RGBA32F :
- GPU_RGBA16F;
- const eViewLayerEEVEEPassType render_passes = stl->g_data->render_passes &
- EEVEE_RENDERPASSES_MATERIAL;
- if (render_passes != 0) {
- GPU_framebuffer_ensure_config(&fbl->material_accum_fb,
- {GPU_ATTACHMENT_TEXTURE(dtxl->depth), GPU_ATTACHMENT_LEAVE});
- int render_pass_index = ((render_passes & EEVEE_RENDER_PASS_ENVIRONMENT) != 0) ? 0 : 1;
- for (int bit = 0; bit < 32; bit++) {
- eViewLayerEEVEEPassType bitflag = (1 << bit);
- if ((render_passes & bitflag) != 0) {
-
- DRW_texture_ensure_fullscreen_2d(
- &txl->material_accum[render_pass_index], texture_format_material_accum, 0);
-
- /* Clear texture. */
- if (DRW_state_is_image_render() || effects->taa_current_sample == 1) {
- GPU_framebuffer_texture_attach(
- fbl->material_accum_fb, txl->material_accum[render_pass_index], 0, 0);
- GPU_framebuffer_bind(fbl->material_accum_fb);
- GPU_framebuffer_clear_color(fbl->material_accum_fb, clear);
- GPU_framebuffer_bind(fbl->main_fb);
- GPU_framebuffer_texture_detach(fbl->material_accum_fb,
- txl->material_accum[render_pass_index]);
- }
- render_pass_index++;
- }
- }
+ if (pd->render_passes & EEVEE_RENDER_PASS_ENVIRONMENT) {
+ material_renderpass_init(fbl, &txl->env_accum, texture_format, do_clear);
+ }
+ if (pd->render_passes & EEVEE_RENDER_PASS_EMIT) {
+ material_renderpass_init(fbl, &txl->emit_accum, texture_format, do_clear);
+ }
+ if (pd->render_passes & EEVEE_RENDER_PASS_DIFFUSE_COLOR) {
+ material_renderpass_init(fbl, &txl->diff_color_accum, texture_format, do_clear);
+ }
+ if (pd->render_passes & EEVEE_RENDER_PASS_DIFFUSE_LIGHT) {
+ material_renderpass_init(fbl, &txl->diff_light_accum, texture_format, do_clear);
+ }
+ if (pd->render_passes & EEVEE_RENDER_PASS_SPECULAR_COLOR) {
+ material_renderpass_init(fbl, &txl->spec_color_accum, texture_format, do_clear);
+ }
+ if (pd->render_passes & EEVEE_RENDER_PASS_SPECULAR_LIGHT) {
+ material_renderpass_init(fbl, &txl->spec_light_accum, texture_format, do_clear);
- if ((render_passes & EEVEE_RENDER_PASS_SPECULAR_LIGHT) &&
- (effects->enabled_effects & EFFECT_SSR)) {
+ if (effects->enabled_effects & EFFECT_SSR) {
EEVEE_reflection_output_init(sldata, vedata, tot_samples);
}
+ }
+}
- if (render_passes & EEVEE_RENDER_PASS_ENVIRONMENT) {
- Scene *scene = draw_ctx->scene;
- World *wo = scene->world;
+static void material_renderpass_accumulate(EEVEE_FramebufferList *fbl,
+ DRWPass *renderpass,
+ EEVEE_PrivateData *pd,
+ GPUTexture *output_tx,
+ struct GPUUniformBuffer *renderpass_option_ubo)
+{
+ GPU_framebuffer_texture_attach(fbl->material_accum_fb, output_tx, 0, 0);
+ GPU_framebuffer_bind(fbl->material_accum_fb);
- if (wo && wo->use_nodes && wo->nodetree) {
- struct GPUMaterial *gpumat = EEVEE_material_world_background_get(scene, wo);
- if (GPU_material_status(gpumat) == GPU_MAT_SUCCESS) {
- DRWShadingGroup *grp = DRW_shgroup_material_create(gpumat, psl->material_accum_pass[0]);
- add_background_uniforms(grp, sldata, vedata);
- DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
- }
- }
- }
- }
+ pd->renderpass_ubo = renderpass_option_ubo;
+ DRW_draw_pass(renderpass);
+
+ GPU_framebuffer_texture_detach(fbl->material_accum_fb, output_tx);
}
void EEVEE_material_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_PassList *psl = vedata->psl;
- EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_PrivateData *pd = vedata->stl->g_data;
+ EEVEE_EffectsInfo *effects = vedata->stl->effects;
EEVEE_TextureList *txl = vedata->txl;
if (fbl->material_accum_fb != NULL) {
- for (int renderpass_index = 0; renderpass_index < stl->g_data->render_passes_material_count;
- renderpass_index++) {
- if (txl->material_accum[renderpass_index] != NULL) {
- GPU_framebuffer_texture_attach(
- fbl->material_accum_fb, txl->material_accum[renderpass_index], 0, 0);
- GPU_framebuffer_bind(fbl->material_accum_fb);
- DRW_draw_pass(psl->material_accum_pass[renderpass_index]);
- GPU_framebuffer_bind(fbl->main_fb);
- GPU_framebuffer_texture_detach(fbl->material_accum_fb,
- txl->material_accum[renderpass_index]);
- }
+ DRWPass *material_accum_ps = psl->material_accum_ps;
+ if (pd->render_passes & EEVEE_RENDER_PASS_ENVIRONMENT) {
+ material_renderpass_accumulate(
+ fbl, psl->background_accum_ps, pd, txl->env_accum, sldata->renderpass_ubo.combined);
}
- if ((stl->g_data->render_passes & EEVEE_RENDER_PASS_SPECULAR_LIGHT) &&
- (stl->effects->enabled_effects & EFFECT_SSR)) {
- EEVEE_reflection_output_accumulate(sldata, vedata);
+ if (pd->render_passes & EEVEE_RENDER_PASS_EMIT) {
+ material_renderpass_accumulate(
+ fbl, material_accum_ps, pd, txl->emit_accum, sldata->renderpass_ubo.emit);
}
- }
-}
-
-int EEVEE_material_output_pass_index_get(EEVEE_ViewLayerData *UNUSED(sldata),
- EEVEE_Data *vedata,
- eViewLayerEEVEEPassType renderpass_type)
-{
- EEVEE_StorageList *stl = vedata->stl;
-
- BLI_assert((stl->g_data->render_passes & EEVEE_RENDERPASSES_MATERIAL) != 0);
- BLI_assert((stl->g_data->render_passes & EEVEE_RENDERPASSES_MATERIAL & renderpass_type) != 0);
-
- /* pass_index 0 is reserved for the environment pass. */
- if ((stl->g_data->render_passes & EEVEE_RENDER_PASS_ENVIRONMENT & renderpass_type) != 0) {
- return 0;
- }
-
- /* pass_index 0 is reserved for the environment pass. Other passes start from index 1 */
- int index = 1;
- eViewLayerEEVEEPassType active_material_passes = stl->g_data->render_passes &
- EEVEE_RENDERPASSES_MATERIAL &
- ~EEVEE_RENDER_PASS_ENVIRONMENT;
+ if (pd->render_passes & EEVEE_RENDER_PASS_DIFFUSE_COLOR) {
+ material_renderpass_accumulate(
+ fbl, material_accum_ps, pd, txl->diff_color_accum, sldata->renderpass_ubo.diff_color);
+ }
+ if (pd->render_passes & EEVEE_RENDER_PASS_DIFFUSE_LIGHT) {
+ material_renderpass_accumulate(
+ fbl, material_accum_ps, pd, txl->diff_light_accum, sldata->renderpass_ubo.diff_light);
- for (int bitshift = 0; bitshift < 32; bitshift++) {
- eViewLayerEEVEEPassType pass_flag = (1 << bitshift);
- if (pass_flag == renderpass_type) {
- break;
+ if (effects->enabled_effects & EFFECT_SSS) {
+ EEVEE_subsurface_output_accumulate(sldata, vedata);
+ }
}
- if (active_material_passes & pass_flag) {
- index++;
+ if (pd->render_passes & EEVEE_RENDER_PASS_SPECULAR_COLOR) {
+ material_renderpass_accumulate(
+ fbl, material_accum_ps, pd, txl->spec_color_accum, sldata->renderpass_ubo.spec_color);
}
- }
+ if (pd->render_passes & EEVEE_RENDER_PASS_SPECULAR_LIGHT) {
+ material_renderpass_accumulate(
+ fbl, material_accum_ps, pd, txl->spec_light_accum, sldata->renderpass_ubo.spec_light);
- return index;
-}
+ if (effects->enabled_effects & EFFECT_SSR) {
+ EEVEE_reflection_output_accumulate(sldata, vedata);
+ }
+ }
-/* Get the pass index that contains the color pass for the given renderpass_type. */
-int EEVEE_material_output_color_pass_index_get(EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- eViewLayerEEVEEPassType renderpass_type)
-{
- BLI_assert(
- ELEM(renderpass_type, EEVEE_RENDER_PASS_DIFFUSE_LIGHT, EEVEE_RENDER_PASS_SPECULAR_LIGHT));
- eViewLayerEEVEEPassType color_pass_type;
- switch (renderpass_type) {
- case EEVEE_RENDER_PASS_DIFFUSE_LIGHT:
- color_pass_type = EEVEE_RENDER_PASS_DIFFUSE_COLOR;
- break;
- case EEVEE_RENDER_PASS_SPECULAR_LIGHT:
- color_pass_type = EEVEE_RENDER_PASS_SPECULAR_COLOR;
- break;
- default:
- color_pass_type = 0;
- BLI_assert(false);
+ /* Restore default. */
+ pd->renderpass_ubo = sldata->renderpass_ubo.combined;
+ GPU_framebuffer_bind(fbl->main_fb);
}
- return EEVEE_material_output_pass_index_get(sldata, vedata, color_pass_type);
}
+
/* \} */
diff --git a/source/blender/draw/engines/eevee/eevee_mist.c b/source/blender/draw/engines/eevee/eevee_mist.c
index cdcfd64d995..7b942784ee9 100644
--- a/source/blender/draw/engines/eevee/eevee_mist.c
+++ b/source/blender/draw/engines/eevee/eevee_mist.c
@@ -114,8 +114,7 @@ void EEVEE_mist_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRWShadingGroup *grp = DRW_shgroup_create(e_data.mist_sh, psl->mist_accum_ps);
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_uniform_vec3(grp, "mistSettings", &g_data->mist_start, 1);
DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
}
diff --git a/source/blender/draw/engines/eevee/eevee_occlusion.c b/source/blender/draw/engines/eevee/eevee_occlusion.c
index be4dfd07ce1..f5ebbe08dd1 100644
--- a/source/blender/draw/engines/eevee/eevee_occlusion.c
+++ b/source/blender/draw/engines/eevee/eevee_occlusion.c
@@ -170,8 +170,7 @@ void EEVEE_occlusion_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata
DRW_shgroup_uniform_texture_ref(grp, "normalBuffer", &effects->ssr_normal_input);
DRW_shgroup_uniform_texture_ref(grp, "horizonBuffer", &effects->gtao_horizons);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
}
else {
@@ -209,8 +208,7 @@ void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_shgroup_uniform_texture_ref(grp, "maxzBuffer", &txl->maxzbuffer);
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &effects->ao_src_depth);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_call(grp, quad, NULL);
DRW_PASS_CREATE(psl->ao_horizon_search_layer, DRW_STATE_WRITE_COLOR);
@@ -219,8 +217,7 @@ void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_shgroup_uniform_texture_ref(grp, "maxzBuffer", &txl->maxzbuffer);
DRW_shgroup_uniform_texture_ref(grp, "depthBufferLayered", &effects->ao_src_depth);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_uniform_int(grp, "layer", &stl->effects->ao_depth_layer, 1);
DRW_shgroup_call(grp, quad, NULL);
@@ -233,8 +230,7 @@ void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_shgroup_uniform_texture_ref(grp, "normalBuffer", &effects->ssr_normal_input);
DRW_shgroup_uniform_texture_ref(grp, "horizonBuffer", &effects->gtao_horizons);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_call(grp, quad, NULL);
}
}
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
index 264f301e52c..dbe2adef789 100644
--- a/source/blender/draw/engines/eevee/eevee_private.h
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -158,35 +158,34 @@ BLI_INLINE bool eevee_hdri_preview_overlay_enabled(const View3D *v3d)
(EEVEE_RENDER_PASS_EMIT | EEVEE_RENDER_PASS_DIFFUSE_COLOR | EEVEE_RENDER_PASS_DIFFUSE_LIGHT | \
EEVEE_RENDER_PASS_SPECULAR_COLOR | EEVEE_RENDER_PASS_SPECULAR_LIGHT | \
EEVEE_RENDER_PASS_ENVIRONMENT)
-#define MAX_MATERIAL_RENDER_PASSES 6
-#define MAX_MATERIAL_RENDER_PASSES_UBO 6
-/* World shader variations */
-enum {
- VAR_WORLD_BACKGROUND = 0,
- VAR_WORLD_PROBE = 1,
- VAR_WORLD_VOLUME = 2,
-};
/* Material shader variations */
enum {
VAR_MAT_MESH = (1 << 0),
- VAR_MAT_PROBE = (1 << 1),
+ VAR_MAT_VOLUME = (1 << 1),
VAR_MAT_HAIR = (1 << 2),
- VAR_MAT_BLEND = (1 << 3),
- VAR_MAT_VOLUME = (1 << 4),
+ VAR_MAT_PROBE = (1 << 3),
+ VAR_MAT_BLEND = (1 << 4),
VAR_MAT_LOOKDEV = (1 << 5),
VAR_MAT_HOLDOUT = (1 << 6),
- /* Max number of variation */
- /* IMPORTANT : Leave it last and set
- * it's value accordingly. */
- VAR_MAT_MAX = (1 << 7),
- /* These are options that are not counted in VAR_MAT_MAX
- * because they are not cumulative with the others above. */
- VAR_MAT_CLIP = (1 << 9),
- VAR_MAT_HASH = (1 << 10),
- VAR_MAT_MULT = (1 << 11),
- VAR_MAT_SHADOW = (1 << 12),
- VAR_MAT_REFRACT = (1 << 13),
+ VAR_MAT_HASH = (1 << 7),
+ VAR_MAT_DEPTH = (1 << 8),
+ VAR_MAT_REFRACT = (1 << 9),
+ VAR_WORLD_BACKGROUND = (1 << 10),
+ VAR_WORLD_PROBE = (1 << 11),
+ VAR_WORLD_VOLUME = (1 << 12),
+ VAR_DEFAULT = (1 << 13),
+};
+
+/* Material shader cache keys */
+enum {
+ /* HACK: This assumes the struct GPUShader will never be smaller than our variations.
+ * This allow us to only keep one ghash and avoid bigger keys comparissons/hashing.
+ * We combine the GPUShader pointer with the key. */
+ KEY_CULL = (1 << 0),
+ KEY_REFRACT = (1 << 1),
+ KEY_HAIR = (1 << 2),
+ KEY_SHADOW = (1 << 3),
};
/* ************ PROBE UBO ************* */
@@ -272,23 +271,26 @@ typedef struct EEVEE_PassList {
struct DRWPass *maxz_copydepth_ps;
struct DRWPass *maxz_copydepth_layer_ps;
- struct DRWPass *depth_pass;
- struct DRWPass *depth_pass_cull;
- struct DRWPass *depth_pass_clip;
- struct DRWPass *depth_pass_clip_cull;
- struct DRWPass *refract_depth_pass;
- struct DRWPass *refract_depth_pass_cull;
- struct DRWPass *refract_depth_pass_clip;
- struct DRWPass *refract_depth_pass_clip_cull;
- struct DRWPass *default_pass[VAR_MAT_MAX];
- struct DRWPass *sss_pass;
- struct DRWPass *sss_pass_cull;
- struct DRWPass *material_pass;
- struct DRWPass *material_pass_cull;
- struct DRWPass *material_accum_pass[MAX_MATERIAL_RENDER_PASSES];
- struct DRWPass *refract_pass;
+ /* Renderpass Accumulation. */
+ struct DRWPass *material_accum_ps;
+ struct DRWPass *background_accum_ps;
+
+ struct DRWPass *depth_ps;
+ struct DRWPass *depth_cull_ps;
+ struct DRWPass *depth_clip_ps;
+ struct DRWPass *depth_clip_cull_ps;
+ struct DRWPass *depth_refract_ps;
+ struct DRWPass *depth_refract_cull_ps;
+ struct DRWPass *depth_refract_clip_ps;
+ struct DRWPass *depth_refract_clip_cull_ps;
+ struct DRWPass *material_ps;
+ struct DRWPass *material_cull_ps;
+ struct DRWPass *material_refract_ps;
+ struct DRWPass *material_refract_cull_ps;
+ struct DRWPass *material_sss_ps;
+ struct DRWPass *material_sss_cull_ps;
struct DRWPass *transparent_pass;
- struct DRWPass *background_pass;
+ struct DRWPass *background_ps;
struct DRWPass *update_noise_pass;
struct DRWPass *lookdev_glossy_pass;
struct DRWPass *lookdev_diffuse_pass;
@@ -348,7 +350,12 @@ typedef struct EEVEE_TextureList {
struct GPUTexture *mist_accum;
struct GPUTexture *ao_accum;
struct GPUTexture *sss_accum;
- struct GPUTexture *material_accum[MAX_MATERIAL_RENDER_PASSES];
+ struct GPUTexture *env_accum;
+ struct GPUTexture *diff_color_accum;
+ struct GPUTexture *diff_light_accum;
+ struct GPUTexture *spec_color_accum;
+ struct GPUTexture *spec_light_accum;
+ struct GPUTexture *emit_accum;
struct GPUTexture *bloom_accum;
struct GPUTexture *ssr_accum;
struct GPUTexture *shadow_accum;
@@ -574,6 +581,7 @@ typedef struct EEVEE_EffectsInfo {
bool swap_double_buffer;
/* SSSS */
int sss_sample_count;
+ int sss_surface_count;
struct GPUTexture *sss_irradiance; /* Textures from pool */
struct GPUTexture *sss_radius;
struct GPUTexture *sss_albedo;
@@ -754,14 +762,22 @@ typedef struct EEVEE_ViewLayerData {
struct GPUUniformBuffer *planar_ubo;
/* Material Render passes */
- struct EEVEE_RenderPassData renderpass_data[MAX_MATERIAL_RENDER_PASSES_UBO];
- struct GPUUniformBuffer *renderpass_ubo[MAX_MATERIAL_RENDER_PASSES_UBO];
+ struct {
+ struct GPUUniformBuffer *combined;
+ struct GPUUniformBuffer *diff_color;
+ struct GPUUniformBuffer *diff_light;
+ struct GPUUniformBuffer *spec_color;
+ struct GPUUniformBuffer *spec_light;
+ struct GPUUniformBuffer *emit;
+ } renderpass_ubo;
/* Common Uniform Buffer */
struct EEVEE_CommonUniformBuffer common_data;
struct GPUUniformBuffer *common_ubo;
struct LightCache *fallback_lightcache;
+
+ struct BLI_memblock *material_cache;
} EEVEE_ViewLayerData;
/* ************ OBJECT DATA ************ */
@@ -809,14 +825,6 @@ typedef struct EEVEE_Data {
typedef struct EEVEE_PrivateData {
struct DRWShadingGroup *shadow_shgrp;
struct DRWShadingGroup *shadow_accum_shgrp;
- struct DRWShadingGroup *depth_shgrp;
- struct DRWShadingGroup *depth_shgrp_cull;
- struct DRWShadingGroup *depth_shgrp_clip;
- struct DRWShadingGroup *depth_shgrp_clip_cull;
- struct DRWShadingGroup *refract_depth_shgrp;
- struct DRWShadingGroup *refract_depth_shgrp_cull;
- struct DRWShadingGroup *refract_depth_shgrp_clip;
- struct DRWShadingGroup *refract_depth_shgrp_clip_cull;
struct DRWCallBuffer *planar_display_shgrp;
struct GHash *material_hash;
float background_alpha; /* TODO find a better place for this. */
@@ -862,9 +870,8 @@ typedef struct EEVEE_PrivateData {
GPUTexture *renderpass_input;
GPUTexture *renderpass_col_input;
GPUTexture *renderpass_light_input;
- /* The number of active material based render passes */
- uint render_passes_material_count;
-
+ /* Renderpass ubo reference used by material pass. */
+ struct GPUUniformBuffer *renderpass_ubo;
/** For rendering shadows. */
struct DRWView *cube_views[6];
/** For rendering probes. */
@@ -892,6 +899,7 @@ EEVEE_WorldEngineData *EEVEE_world_data_ensure(World *wo);
/* eevee_materials.c */
struct GPUTexture *EEVEE_materials_get_util_tex(void); /* XXX */
void EEVEE_materials_init(EEVEE_ViewLayerData *sldata,
+ EEVEE_Data *vedata,
EEVEE_StorageList *stl,
EEVEE_FramebufferList *fbl);
void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
@@ -908,31 +916,20 @@ void EEVEE_object_hair_cache_populate(EEVEE_Data *vedata,
Object *ob,
bool *cast_shadow);
void EEVEE_materials_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
-struct GPUMaterial *EEVEE_material_world_lightprobe_get(struct Scene *scene, struct World *wo);
-struct GPUMaterial *EEVEE_material_world_background_get(struct Scene *scene, struct World *wo);
-struct GPUMaterial *EEVEE_material_world_volume_get(struct Scene *scene, struct World *wo);
-struct GPUMaterial *EEVEE_material_mesh_get(
- struct Scene *scene, Material *ma, EEVEE_Data *vedata, bool use_blend, bool use_refract);
-struct GPUMaterial *EEVEE_material_mesh_volume_get(struct Scene *scene, Material *ma);
-struct GPUMaterial *EEVEE_material_mesh_depth_get(struct Scene *scene,
- Material *ma,
- bool use_hashed_alpha,
- bool is_shadow);
-struct GPUMaterial *EEVEE_material_hair_get(struct Scene *scene, Material *ma);
-struct GPUUniformBuffer *EEVEE_material_default_render_pass_ubo_get(EEVEE_ViewLayerData *sldata);
void EEVEE_materials_free(void);
-void EEVEE_materials_draw_opaque(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl);
void EEVEE_update_noise(EEVEE_PassList *psl, EEVEE_FramebufferList *fbl, const double offsets[3]);
void EEVEE_update_viewvecs(float invproj[4][4], float winmat[4][4], float (*r_viewvecs)[4]);
void EEVEE_material_renderpasses_init(EEVEE_Data *vedata);
void EEVEE_material_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, uint tot_samples);
void EEVEE_material_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
-int EEVEE_material_output_pass_index_get(EEVEE_ViewLayerData *UNUSED(sldata),
- EEVEE_Data *vedata,
- eViewLayerEEVEEPassType renderpass_type);
-int EEVEE_material_output_color_pass_index_get(EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- eViewLayerEEVEEPassType renderpass_type);
+void EEVEE_material_bind_resources(DRWShadingGroup *shgrp,
+ struct GPUMaterial *gpumat,
+ EEVEE_ViewLayerData *sldata,
+ EEVEE_Data *vedata,
+ int *ssr_id,
+ float *refract_depth,
+ bool use_ssrefraction,
+ bool use_alpha_blend);
/* eevee_lights.c */
void eevee_light_matrix_get(const EEVEE_Light *evli, float r_mat[4][4]);
void EEVEE_lights_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
@@ -943,16 +940,6 @@ void EEVEE_lights_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void eevee_contact_shadow_setup(const Light *la, EEVEE_Shadow *evsh);
void EEVEE_shadows_init(EEVEE_ViewLayerData *sldata);
void EEVEE_shadows_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
-void EEVEE_shadows_caster_add(EEVEE_ViewLayerData *sldata,
- EEVEE_StorageList *stl,
- struct GPUBatch *geom,
- Object *ob);
-void EEVEE_shadows_caster_material_add(EEVEE_ViewLayerData *sldata,
- EEVEE_PassList *psl,
- struct GPUMaterial *gpumat,
- struct GPUBatch *geom,
- struct Object *ob,
- const float *alpha_threshold);
void EEVEE_shadows_caster_register(EEVEE_ViewLayerData *sldata, struct Object *ob);
void EEVEE_shadows_update(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_shadows_cube_add(EEVEE_LightsInfo *linfo, EEVEE_Light *evli, struct Object *ob);
@@ -986,6 +973,7 @@ void EEVEE_random_rotation_m4(int sample_ofs, float scale, float r_mat[4][4]);
/* eevee_shaders.c */
void EEVEE_shaders_lightprobe_shaders_init(void);
+void EEVEE_shaders_material_shaders_init(void);
struct GPUShader *EEVEE_shaders_probe_filter_glossy_sh_get(void);
struct GPUShader *EEVEE_shaders_probe_default_sh_get(void);
struct GPUShader *EEVEE_shaders_probe_filter_diffuse_sh_get(void);
@@ -993,12 +981,22 @@ struct GPUShader *EEVEE_shaders_probe_filter_visibility_sh_get(void);
struct GPUShader *EEVEE_shaders_probe_grid_fill_sh_get(void);
struct GPUShader *EEVEE_shaders_probe_planar_downsample_sh_get(void);
struct GPUShader *EEVEE_shaders_default_studiolight_sh_get(void);
+struct GPUShader *EEVEE_shaders_default_background_sh_get(void);
struct GPUShader *EEVEE_shaders_background_studiolight_sh_get(void);
struct GPUShader *EEVEE_shaders_probe_cube_display_sh_get(void);
struct GPUShader *EEVEE_shaders_probe_grid_display_sh_get(void);
struct GPUShader *EEVEE_shaders_probe_planar_display_sh_get(void);
+struct GPUShader *EEVEE_shaders_update_noise_sh_get(void);
struct GPUShader *EEVEE_shaders_velocity_resolve_sh_get(void);
struct GPUShader *EEVEE_shaders_taa_resolve_sh_get(EEVEE_EffectsFlag enabled_effects);
+struct bNodeTree *EEVEE_shader_default_surface_nodetree(Material *ma);
+struct bNodeTree *EEVEE_shader_default_world_nodetree(World *wo);
+Material *EEVEE_material_default_diffuse_get(void);
+Material *EEVEE_material_default_glossy_get(void);
+Material *EEVEE_material_default_error_get(void);
+struct GPUMaterial *EEVEE_material_default_get(struct Scene *scene, Material *ma, int options);
+struct GPUMaterial *EEVEE_material_get(
+ EEVEE_Data *vedata, struct Scene *scene, Material *ma, World *wo, int options);
void EEVEE_shaders_free(void);
/* eevee_lightprobes.c */
@@ -1105,13 +1103,9 @@ void EEVEE_subsurface_output_init(EEVEE_ViewLayerData *sldata,
uint tot_samples);
void EEVEE_subsurface_add_pass(EEVEE_ViewLayerData *sldata,
EEVEE_Data *vedata,
- uint sss_id,
- struct GPUUniformBuffer *sss_profile);
-void EEVEE_subsurface_translucency_add_pass(EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- uint sss_id,
- struct GPUUniformBuffer *sss_profile,
- struct GPUTexture *sss_tex_profile);
+ Material *ma,
+ DRWShadingGroup *shgrp,
+ struct GPUMaterial *gpumat);
void EEVEE_subsurface_data_render(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_subsurface_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_subsurface_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c
index 076738dcbdf..89a5ad2198a 100644
--- a/source/blender/draw/engines/eevee/eevee_render.c
+++ b/source/blender/draw/engines/eevee/eevee_render.c
@@ -151,7 +151,7 @@ bool EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph *
* `EEVEE_effects_init` needs to go second for TAA. */
EEVEE_renderpasses_init(vedata);
EEVEE_effects_init(sldata, vedata, ob_camera_eval, false);
- EEVEE_materials_init(sldata, stl, fbl);
+ EEVEE_materials_init(sldata, vedata, stl, fbl);
EEVEE_shadows_init(sldata);
EEVEE_lightprobes_init(sldata, vedata);
@@ -463,7 +463,7 @@ static void eevee_render_draw_background(EEVEE_Data *vedata)
GPU_ATTACHMENT_NONE});
GPU_framebuffer_bind(fbl->main_fb);
- DRW_draw_pass(psl->background_pass);
+ DRW_draw_pass(psl->background_ps);
GPU_framebuffer_ensure_config(&fbl->main_fb,
{GPU_ATTACHMENT_LEAVE,
@@ -556,7 +556,7 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl
EEVEE_update_noise(psl, fbl, r);
EEVEE_temporal_sampling_matrices_calc(stl->effects, r);
EEVEE_volumes_set_jitter(sldata, stl->effects->taa_current_sample - 1);
- EEVEE_materials_init(sldata, stl, fbl);
+ EEVEE_materials_init(sldata, vedata, stl, fbl);
/* Refresh Probes
* Shadows needs to be updated for correct probes */
@@ -578,8 +578,7 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl
GPU_framebuffer_bind(fbl->main_fb);
GPU_framebuffer_clear_color_depth_stencil(fbl->main_fb, clear_col, clear_depth, clear_stencil);
/* Depth prepass */
- DRW_draw_pass(psl->depth_pass);
- DRW_draw_pass(psl->depth_pass_cull);
+ DRW_draw_pass(psl->depth_ps);
/* Create minmax texture */
EEVEE_create_minmax_buffer(vedata, dtxl->depth, -1);
EEVEE_occlusion_compute(sldata, vedata, dtxl->depth, -1);
@@ -587,16 +586,15 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl
/* Shading pass */
eevee_render_draw_background(vedata);
GPU_framebuffer_bind(fbl->main_fb);
- EEVEE_materials_draw_opaque(sldata, psl);
+ DRW_draw_pass(psl->material_ps);
EEVEE_subsurface_data_render(sldata, vedata);
/* Effects pre-transparency */
EEVEE_subsurface_compute(sldata, vedata);
EEVEE_reflection_compute(sldata, vedata);
EEVEE_refraction_compute(sldata, vedata);
/* Opaque refraction */
- DRW_draw_pass(psl->refract_depth_pass);
- DRW_draw_pass(psl->refract_depth_pass_cull);
- DRW_draw_pass(psl->refract_pass);
+ DRW_draw_pass(psl->depth_refract_ps);
+ DRW_draw_pass(psl->material_refract_ps);
/* Result NORMAL */
eevee_render_result_normal(rl, viewname, rect, vedata, sldata);
/* Volumetrics Resolve Opaque */
diff --git a/source/blender/draw/engines/eevee/eevee_renderpasses.c b/source/blender/draw/engines/eevee/eevee_renderpasses.c
index 9112e14dcf5..4a1880caf7d 100644
--- a/source/blender/draw/engines/eevee/eevee_renderpasses.c
+++ b/source/blender/draw/engines/eevee/eevee_renderpasses.c
@@ -201,8 +201,7 @@ void EEVEE_renderpasses_output_init(EEVEE_ViewLayerData *sldata,
grp, "inputSecondLightBuffer", &g_data->renderpass_light_input);
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_uniform_int(grp, "currentSample", &g_data->renderpass_current_sample, 1);
DRW_shgroup_uniform_int(grp, "renderpassType", &g_data->renderpass_type, 1);
DRW_shgroup_uniform_int(grp, "postProcessType", &g_data->renderpass_postprocess, 1);
@@ -225,7 +224,7 @@ void EEVEE_renderpasses_output_init(EEVEE_ViewLayerData *sldata,
* Only invoke this function for passes that need post-processing.
*
* After invoking this function the active framebuffer is set to `vedata->fbl->renderpass_fb`. */
-void EEVEE_renderpasses_postprocess(EEVEE_ViewLayerData *sldata,
+void EEVEE_renderpasses_postprocess(EEVEE_ViewLayerData *UNUSED(sldata),
EEVEE_Data *vedata,
eViewLayerEEVEEPassType renderpass_type)
{
@@ -276,22 +275,30 @@ void EEVEE_renderpasses_postprocess(EEVEE_ViewLayerData *sldata,
g_data->renderpass_input = txl->shadow_accum;
break;
}
- case EEVEE_RENDER_PASS_DIFFUSE_COLOR:
- case EEVEE_RENDER_PASS_SPECULAR_COLOR:
- case EEVEE_RENDER_PASS_ENVIRONMENT:
+ case EEVEE_RENDER_PASS_DIFFUSE_COLOR: {
+ g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_COLOR;
+ g_data->renderpass_input = txl->diff_color_accum;
+ break;
+ }
+ case EEVEE_RENDER_PASS_SPECULAR_COLOR: {
+ g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_COLOR;
+ g_data->renderpass_input = txl->spec_color_accum;
+ break;
+ }
+ case EEVEE_RENDER_PASS_ENVIRONMENT: {
+ g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_COLOR;
+ g_data->renderpass_input = txl->env_accum;
+ break;
+ }
case EEVEE_RENDER_PASS_EMIT: {
g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_COLOR;
- int renderpass_index = EEVEE_material_output_pass_index_get(sldata, vedata, renderpass_type);
- g_data->renderpass_input = txl->material_accum[renderpass_index];
+ g_data->renderpass_input = txl->emit_accum;
break;
}
case EEVEE_RENDER_PASS_SPECULAR_LIGHT: {
g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_LIGHT;
- int renderpass_index = EEVEE_material_output_pass_index_get(sldata, vedata, renderpass_type);
- int renderpass_index_color = EEVEE_material_output_color_pass_index_get(
- sldata, vedata, renderpass_type);
- g_data->renderpass_input = txl->material_accum[renderpass_index];
- g_data->renderpass_col_input = txl->material_accum[renderpass_index_color];
+ g_data->renderpass_input = txl->spec_light_accum;
+ g_data->renderpass_col_input = txl->spec_color_accum;
if ((stl->effects->enabled_effects & EFFECT_SSR) != 0) {
g_data->renderpass_postprocess = PASS_POST_TWO_LIGHT_BUFFERS;
g_data->renderpass_light_input = txl->ssr_accum;
@@ -303,11 +310,8 @@ void EEVEE_renderpasses_postprocess(EEVEE_ViewLayerData *sldata,
}
case EEVEE_RENDER_PASS_DIFFUSE_LIGHT: {
g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_LIGHT;
- int renderpass_index = EEVEE_material_output_pass_index_get(sldata, vedata, renderpass_type);
- int renderpass_index_color = EEVEE_material_output_color_pass_index_get(
- sldata, vedata, renderpass_type);
- g_data->renderpass_input = txl->material_accum[renderpass_index];
- g_data->renderpass_col_input = txl->material_accum[renderpass_index_color];
+ g_data->renderpass_input = txl->diff_light_accum;
+ g_data->renderpass_col_input = txl->diff_color_accum;
if ((stl->effects->enabled_effects & EFFECT_SSS) != 0) {
g_data->renderpass_postprocess = PASS_POST_TWO_LIGHT_BUFFERS;
g_data->renderpass_light_input = txl->sss_accum;
@@ -343,10 +347,6 @@ void EEVEE_renderpasses_output_accumulate(EEVEE_ViewLayerData *sldata,
if ((render_pass & EEVEE_RENDER_PASS_MIST) != 0) {
EEVEE_mist_output_accumulate(sldata, vedata);
}
- if ((render_pass & EEVEE_RENDER_PASS_DIFFUSE_LIGHT) != 0 &&
- (effects->enabled_effects & EFFECT_SSS) != 0) {
- EEVEE_subsurface_output_accumulate(sldata, vedata);
- }
if ((render_pass & EEVEE_RENDER_PASS_AO) != 0) {
EEVEE_occlusion_output_accumulate(sldata, vedata);
}
diff --git a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c
index 2e467fe8535..cece67334c5 100644
--- a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c
+++ b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c
@@ -237,8 +237,7 @@ void EEVEE_screen_raytrace_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *v
DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
if (!effects->reflection_trace_full) {
DRW_shgroup_uniform_ivec2(grp, "halfresOffset", effects->ssr_halfres_ofs, 1);
}
@@ -259,8 +258,7 @@ void EEVEE_screen_raytrace_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *v
DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_uniform_int(grp, "neighborOffset", &effects->ssr_neighbor_ofs, 1);
if ((effects->enabled_effects & EFFECT_GTAO) != 0) {
DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
diff --git a/source/blender/draw/engines/eevee/eevee_shaders.c b/source/blender/draw/engines/eevee/eevee_shaders.c
index 50b7c5c5f97..4d25f62a317 100644
--- a/source/blender/draw/engines/eevee/eevee_shaders.c
+++ b/source/blender/draw/engines/eevee/eevee_shaders.c
@@ -22,12 +22,20 @@
#include "DRW_render.h"
+#include "BKE_lib_id.h"
+#include "BKE_node.h"
+
+#include "BLI_dynstr.h"
#include "BLI_string_utils.h"
#include "MEM_guardedalloc.h"
+#include "GPU_material.h"
#include "GPU_shader.h"
+#include "NOD_shader.h"
+
+#include "eevee_engine.h"
#include "eevee_private.h"
static const char *filter_defines = "#define HAMMERSLEY_SIZE " STRINGIFY(HAMMERSLEY_SIZE) "\n"
@@ -61,6 +69,38 @@ static struct {
struct GPUShader *taa_resolve_sh;
struct GPUShader *taa_resolve_reproject_sh;
+ /* General purpose Shaders. */
+ struct GPUShader *default_background;
+ struct GPUShader *update_noise_sh;
+
+ /* Shader strings */
+ char *frag_shader_lib;
+ char *vert_shader_str;
+ char *vert_shadow_shader_str;
+ char *vert_background_shader_str;
+ char *vert_volume_shader_str;
+ char *geom_volume_shader_str;
+ char *volume_shader_lib;
+
+ /* LookDev Materials */
+ Material *glossy_mat;
+ Material *diffuse_mat;
+
+ Material *error_mat;
+
+ /* Default Material */
+ struct {
+ bNodeTree *ntree;
+ bNodeSocketValueRGBA *color_socket;
+ bNodeSocketValueFloat *metallic_socket;
+ bNodeSocketValueFloat *roughness_socket;
+ bNodeSocketValueFloat *specular_socket;
+ } surface;
+
+ struct {
+ bNodeTree *ntree;
+ bNodeSocketValueRGBA *color_socket;
+ } world;
} e_data = {NULL}; /* Engine data */
extern char datatoc_bsdf_common_lib_glsl[];
@@ -68,27 +108,42 @@ extern char datatoc_bsdf_sampling_lib_glsl[];
extern char datatoc_common_uniforms_lib_glsl[];
extern char datatoc_common_view_lib_glsl[];
+extern char datatoc_ambient_occlusion_lib_glsl[];
extern char datatoc_background_vert_glsl[];
+extern char datatoc_common_hair_lib_glsl[];
+extern char datatoc_cubemap_lib_glsl[];
extern char datatoc_default_world_frag_glsl[];
-extern char datatoc_lightprobe_geom_glsl[];
-extern char datatoc_lightprobe_vert_glsl[];
+extern char datatoc_irradiance_lib_glsl[];
extern char datatoc_lightprobe_cube_display_frag_glsl[];
extern char datatoc_lightprobe_cube_display_vert_glsl[];
extern char datatoc_lightprobe_filter_diffuse_frag_glsl[];
extern char datatoc_lightprobe_filter_glossy_frag_glsl[];
extern char datatoc_lightprobe_filter_visibility_frag_glsl[];
+extern char datatoc_lightprobe_geom_glsl[];
extern char datatoc_lightprobe_grid_display_frag_glsl[];
extern char datatoc_lightprobe_grid_display_vert_glsl[];
extern char datatoc_lightprobe_grid_fill_frag_glsl[];
+extern char datatoc_lightprobe_lib_glsl[];
extern char datatoc_lightprobe_planar_display_frag_glsl[];
extern char datatoc_lightprobe_planar_display_vert_glsl[];
extern char datatoc_lightprobe_planar_downsample_frag_glsl[];
extern char datatoc_lightprobe_planar_downsample_geom_glsl[];
extern char datatoc_lightprobe_planar_downsample_vert_glsl[];
-extern char datatoc_irradiance_lib_glsl[];
-extern char datatoc_lightprobe_lib_glsl[];
+extern char datatoc_lightprobe_vert_glsl[];
+extern char datatoc_lights_lib_glsl[];
+extern char datatoc_lit_surface_frag_glsl[];
+extern char datatoc_lit_surface_vert_glsl[];
+extern char datatoc_ltc_lib_glsl[];
extern char datatoc_octahedron_lib_glsl[];
-extern char datatoc_cubemap_lib_glsl[];
+extern char datatoc_prepass_frag_glsl[];
+extern char datatoc_raytrace_lib_glsl[];
+extern char datatoc_shadow_vert_glsl[];
+extern char datatoc_ssr_lib_glsl[];
+extern char datatoc_update_noise_frag_glsl[];
+extern char datatoc_volumetric_frag_glsl[];
+extern char datatoc_volumetric_geom_glsl[];
+extern char datatoc_volumetric_lib_glsl[];
+extern char datatoc_volumetric_vert_glsl[];
/* Velocity Resolve */
extern char datatoc_effect_velocity_resolve_frag_glsl[];
@@ -150,6 +205,64 @@ void EEVEE_shaders_lightprobe_shaders_init(void)
NULL);
}
+void EEVEE_shaders_material_shaders_init(void)
+{
+ e_data.frag_shader_lib = BLI_string_joinN(datatoc_common_view_lib_glsl,
+ datatoc_common_uniforms_lib_glsl,
+ datatoc_bsdf_common_lib_glsl,
+ datatoc_bsdf_sampling_lib_glsl,
+ datatoc_ambient_occlusion_lib_glsl,
+ datatoc_raytrace_lib_glsl,
+ datatoc_ssr_lib_glsl,
+ datatoc_octahedron_lib_glsl,
+ datatoc_cubemap_lib_glsl,
+ datatoc_irradiance_lib_glsl,
+ datatoc_lightprobe_lib_glsl,
+ datatoc_ltc_lib_glsl,
+ datatoc_lights_lib_glsl,
+ /* Add one for each Closure */
+ datatoc_lit_surface_frag_glsl,
+ datatoc_lit_surface_frag_glsl,
+ datatoc_lit_surface_frag_glsl,
+ datatoc_lit_surface_frag_glsl,
+ datatoc_lit_surface_frag_glsl,
+ datatoc_lit_surface_frag_glsl,
+ datatoc_lit_surface_frag_glsl,
+ datatoc_lit_surface_frag_glsl,
+ datatoc_lit_surface_frag_glsl,
+ datatoc_lit_surface_frag_glsl,
+ datatoc_lit_surface_frag_glsl,
+ datatoc_volumetric_lib_glsl);
+
+ e_data.volume_shader_lib = BLI_string_joinN(datatoc_common_view_lib_glsl,
+ datatoc_common_uniforms_lib_glsl,
+ datatoc_bsdf_common_lib_glsl,
+ datatoc_ambient_occlusion_lib_glsl,
+ datatoc_octahedron_lib_glsl,
+ datatoc_cubemap_lib_glsl,
+ datatoc_irradiance_lib_glsl,
+ datatoc_lightprobe_lib_glsl,
+ datatoc_ltc_lib_glsl,
+ datatoc_lights_lib_glsl,
+ datatoc_volumetric_lib_glsl,
+ datatoc_volumetric_frag_glsl);
+
+ e_data.vert_shader_str = BLI_string_joinN(
+ datatoc_common_view_lib_glsl, datatoc_common_hair_lib_glsl, datatoc_lit_surface_vert_glsl);
+
+ e_data.vert_shadow_shader_str = BLI_string_joinN(
+ datatoc_common_view_lib_glsl, datatoc_common_hair_lib_glsl, datatoc_shadow_vert_glsl);
+
+ e_data.vert_background_shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
+ datatoc_background_vert_glsl);
+
+ e_data.vert_volume_shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
+ datatoc_volumetric_vert_glsl);
+
+ e_data.geom_volume_shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
+ datatoc_volumetric_geom_glsl);
+}
+
GPUShader *EEVEE_shaders_probe_filter_glossy_sh_get(void)
{
return e_data.probe_filter_glossy_sh;
@@ -292,6 +405,26 @@ GPUShader *EEVEE_shaders_velocity_resolve_sh_get(void)
return e_data.velocity_resolve_sh;
}
+GPUShader *EEVEE_shaders_default_background_sh_get(void)
+{
+ if (e_data.default_background == NULL) {
+ e_data.default_background = DRW_shader_create_with_lib(datatoc_background_vert_glsl,
+ NULL,
+ datatoc_default_world_frag_glsl,
+ datatoc_common_view_lib_glsl,
+ NULL);
+ }
+ return e_data.default_background;
+}
+
+GPUShader *EEVEE_shaders_update_noise_sh_get(void)
+{
+ if (e_data.update_noise_sh == NULL) {
+ e_data.update_noise_sh = DRW_shader_create_fullscreen(datatoc_update_noise_frag_glsl, NULL);
+ }
+ return e_data.update_noise_sh;
+}
+
GPUShader *EEVEE_shaders_taa_resolve_sh_get(EEVEE_EffectsFlag enabled_effects)
{
GPUShader **sh;
@@ -316,8 +449,330 @@ GPUShader *EEVEE_shaders_taa_resolve_sh_get(EEVEE_EffectsFlag enabled_effects)
return *sh;
}
+Material *EEVEE_material_default_diffuse_get(void)
+{
+ if (!e_data.diffuse_mat) {
+ Material *ma = BKE_id_new_nomain(ID_MA, "EEVEEE default diffuse");
+
+ bNodeTree *ntree = ntreeAddTree(NULL, "Shader Nodetree", ntreeType_Shader->idname);
+ ma->nodetree = ntree;
+ ma->use_nodes = true;
+
+ bNode *bsdf = nodeAddStaticNode(NULL, ntree, SH_NODE_BSDF_DIFFUSE);
+ bNodeSocket *base_color = nodeFindSocket(bsdf, SOCK_IN, "Color");
+ copy_v3_fl(((bNodeSocketValueRGBA *)base_color->default_value)->value, 0.8f);
+
+ bNode *output = nodeAddStaticNode(NULL, ntree, SH_NODE_OUTPUT_MATERIAL);
+
+ nodeAddLink(ntree,
+ bsdf,
+ nodeFindSocket(bsdf, SOCK_OUT, "BSDF"),
+ output,
+ nodeFindSocket(output, SOCK_IN, "Surface"));
+
+ nodeSetActive(ntree, output);
+ e_data.diffuse_mat = ma;
+ }
+ return e_data.diffuse_mat;
+}
+
+Material *EEVEE_material_default_glossy_get(void)
+{
+ if (!e_data.glossy_mat) {
+ Material *ma = BKE_id_new_nomain(ID_MA, "EEVEEE default metal");
+
+ bNodeTree *ntree = ntreeAddTree(NULL, "Shader Nodetree", ntreeType_Shader->idname);
+ ma->nodetree = ntree;
+ ma->use_nodes = true;
+
+ bNode *bsdf = nodeAddStaticNode(NULL, ntree, SH_NODE_BSDF_GLOSSY);
+ bNodeSocket *base_color = nodeFindSocket(bsdf, SOCK_IN, "Color");
+ copy_v3_fl(((bNodeSocketValueRGBA *)base_color->default_value)->value, 1.0f);
+ bNodeSocket *roughness = nodeFindSocket(bsdf, SOCK_IN, "Roughness");
+ ((bNodeSocketValueFloat *)roughness->default_value)->value = 0.0f;
+
+ bNode *output = nodeAddStaticNode(NULL, ntree, SH_NODE_OUTPUT_MATERIAL);
+
+ nodeAddLink(ntree,
+ bsdf,
+ nodeFindSocket(bsdf, SOCK_OUT, "BSDF"),
+ output,
+ nodeFindSocket(output, SOCK_IN, "Surface"));
+
+ nodeSetActive(ntree, output);
+ e_data.glossy_mat = ma;
+ }
+ return e_data.glossy_mat;
+}
+
+Material *EEVEE_material_default_error_get(void)
+{
+ if (!e_data.error_mat) {
+ Material *ma = BKE_id_new_nomain(ID_MA, "EEVEEE default metal");
+
+ bNodeTree *ntree = ntreeAddTree(NULL, "Shader Nodetree", ntreeType_Shader->idname);
+ ma->nodetree = ntree;
+ ma->use_nodes = true;
+
+ /* Use emission and output material to be compatible with both World and Material. */
+ bNode *bsdf = nodeAddStaticNode(NULL, ntree, SH_NODE_EMISSION);
+ bNodeSocket *color = nodeFindSocket(bsdf, SOCK_IN, "Color");
+ copy_v3_fl3(((bNodeSocketValueRGBA *)color->default_value)->value, 1.0f, 0.0f, 1.0f);
+
+ bNode *output = nodeAddStaticNode(NULL, ntree, SH_NODE_OUTPUT_MATERIAL);
+
+ nodeAddLink(ntree,
+ bsdf,
+ nodeFindSocket(bsdf, SOCK_OUT, "Emission"),
+ output,
+ nodeFindSocket(output, SOCK_IN, "Surface"));
+
+ nodeSetActive(ntree, output);
+ e_data.error_mat = ma;
+ }
+ return e_data.error_mat;
+}
+
+/* Configure a default nodetree with the given material. */
+struct bNodeTree *EEVEE_shader_default_surface_nodetree(Material *ma)
+{
+ /* WARNING: This function is not threadsafe. Which is not a problem for the moment. */
+ if (!e_data.surface.ntree) {
+ bNodeTree *ntree = ntreeAddTree(NULL, "Shader Nodetree", ntreeType_Shader->idname);
+ bNode *bsdf = nodeAddStaticNode(NULL, ntree, SH_NODE_BSDF_PRINCIPLED);
+ bNode *output = nodeAddStaticNode(NULL, ntree, SH_NODE_OUTPUT_MATERIAL);
+ bNodeSocket *bsdf_out = nodeFindSocket(bsdf, SOCK_OUT, "BSDF");
+ bNodeSocket *output_in = nodeFindSocket(output, SOCK_IN, "Surface");
+ nodeAddLink(ntree, bsdf, bsdf_out, output, output_in);
+ nodeSetActive(ntree, output);
+
+ e_data.surface.color_socket = nodeFindSocket(bsdf, SOCK_IN, "Base Color")->default_value;
+ e_data.surface.metallic_socket = nodeFindSocket(bsdf, SOCK_IN, "Metallic")->default_value;
+ e_data.surface.roughness_socket = nodeFindSocket(bsdf, SOCK_IN, "Roughness")->default_value;
+ e_data.surface.specular_socket = nodeFindSocket(bsdf, SOCK_IN, "Specular")->default_value;
+ e_data.surface.ntree = ntree;
+ }
+ /* Update */
+ copy_v3_fl3(e_data.surface.color_socket->value, ma->r, ma->g, ma->b);
+ e_data.surface.metallic_socket->value = ma->metallic;
+ e_data.surface.roughness_socket->value = ma->roughness;
+ e_data.surface.specular_socket->value = ma->spec;
+
+ return e_data.surface.ntree;
+}
+
+/* Configure a default nodetree with the given world. */
+struct bNodeTree *EEVEE_shader_default_world_nodetree(World *wo)
+{
+ /* WARNING: This function is not threadsafe. Which is not a problem for the moment. */
+ if (!e_data.world.ntree) {
+ bNodeTree *ntree = ntreeAddTree(NULL, "Shader Nodetree", ntreeType_Shader->idname);
+ bNode *bg = nodeAddStaticNode(NULL, ntree, SH_NODE_BACKGROUND);
+ bNode *output = nodeAddStaticNode(NULL, ntree, SH_NODE_OUTPUT_WORLD);
+ bNodeSocket *bg_out = nodeFindSocket(bg, SOCK_OUT, "Background");
+ bNodeSocket *output_in = nodeFindSocket(output, SOCK_IN, "Surface");
+ nodeAddLink(ntree, bg, bg_out, output, output_in);
+ nodeSetActive(ntree, output);
+
+ e_data.world.color_socket = nodeFindSocket(bg, SOCK_IN, "Color")->default_value;
+ e_data.world.ntree = ntree;
+ }
+
+ copy_v3_fl3(e_data.world.color_socket->value, wo->horr, wo->horg, wo->horb);
+
+ return e_data.world.ntree;
+}
+
+static char *eevee_get_defines(int options)
+{
+ char *str = NULL;
+
+ DynStr *ds = BLI_dynstr_new();
+ BLI_dynstr_append(ds, SHADER_DEFINES);
+
+ if ((options & VAR_WORLD_BACKGROUND) != 0) {
+ BLI_dynstr_append(ds, "#define WORLD_BACKGROUND\n");
+ }
+ if ((options & VAR_MAT_VOLUME) != 0) {
+ BLI_dynstr_append(ds, "#define VOLUMETRICS\n");
+ }
+ if ((options & VAR_MAT_MESH) != 0) {
+ BLI_dynstr_append(ds, "#define MESH_SHADER\n");
+ }
+ if ((options & VAR_MAT_DEPTH) != 0) {
+ BLI_dynstr_append(ds, "#define DEPTH_SHADER\n");
+ }
+ if ((options & VAR_MAT_HAIR) != 0) {
+ BLI_dynstr_append(ds, "#define HAIR_SHADER\n");
+ }
+ if ((options & (VAR_MAT_PROBE | VAR_WORLD_PROBE)) != 0) {
+ BLI_dynstr_append(ds, "#define PROBE_CAPTURE\n");
+ }
+ if ((options & VAR_MAT_HASH) != 0) {
+ BLI_dynstr_append(ds, "#define USE_ALPHA_HASH\n");
+ }
+ if ((options & VAR_MAT_BLEND) != 0) {
+ BLI_dynstr_append(ds, "#define USE_ALPHA_BLEND\n");
+ }
+ if ((options & VAR_MAT_REFRACT) != 0) {
+ BLI_dynstr_append(ds, "#define USE_REFRACTION\n");
+ }
+ if ((options & VAR_MAT_LOOKDEV) != 0) {
+ BLI_dynstr_append(ds, "#define LOOKDEV\n");
+ }
+ if ((options & VAR_MAT_HOLDOUT) != 0) {
+ BLI_dynstr_append(ds, "#define HOLDOUT\n");
+ }
+
+ str = BLI_dynstr_get_cstring(ds);
+ BLI_dynstr_free(ds);
+
+ return str;
+}
+
+static char *eevee_get_vert(int options)
+{
+ char *str = NULL;
+
+ if ((options & VAR_MAT_VOLUME) != 0) {
+ str = BLI_strdup(e_data.vert_volume_shader_str);
+ }
+ else if ((options & (VAR_WORLD_PROBE | VAR_WORLD_BACKGROUND)) != 0) {
+ str = BLI_strdup(e_data.vert_background_shader_str);
+ }
+ else {
+ str = BLI_strdup(e_data.vert_shader_str);
+ }
+
+ return str;
+}
+
+static char *eevee_get_geom(int options)
+{
+ char *str = NULL;
+
+ if ((options & VAR_MAT_VOLUME) != 0) {
+ str = BLI_strdup(e_data.geom_volume_shader_str);
+ }
+
+ return str;
+}
+
+static char *eevee_get_frag(int options)
+{
+ char *str = NULL;
+
+ if ((options & VAR_MAT_VOLUME) != 0) {
+ str = BLI_strdup(e_data.volume_shader_lib);
+ }
+ else if ((options & VAR_MAT_DEPTH) != 0) {
+ str = BLI_string_joinN(e_data.frag_shader_lib, datatoc_prepass_frag_glsl);
+ }
+ else {
+ str = BLI_strdup(e_data.frag_shader_lib);
+ }
+
+ return str;
+}
+
+static struct GPUMaterial *eevee_material_get_ex(
+ struct Scene *scene, Material *ma, World *wo, int options, bool deferred)
+{
+ BLI_assert(ma || wo);
+ const bool is_volume = (options & VAR_MAT_VOLUME) != 0;
+ const bool is_default = (options & VAR_DEFAULT) != 0;
+ const void *engine = &DRW_engine_viewport_eevee_type;
+
+ GPUMaterial *mat = NULL;
+
+ if (ma) {
+ mat = DRW_shader_find_from_material(ma, engine, options, deferred);
+ }
+ else {
+ mat = DRW_shader_find_from_world(wo, engine, options, deferred);
+ }
+
+ if (mat) {
+ return mat;
+ }
+
+ char *defines = eevee_get_defines(options);
+ char *vert = eevee_get_vert(options);
+ char *geom = eevee_get_geom(options);
+ char *frag = eevee_get_frag(options);
+
+ if (ma) {
+ bNodeTree *ntree = !is_default ? ma->nodetree : EEVEE_shader_default_surface_nodetree(ma);
+ mat = DRW_shader_create_from_material(
+ scene, ma, ntree, engine, options, is_volume, vert, geom, frag, defines, deferred);
+ }
+ else {
+ bNodeTree *ntree = !is_default ? wo->nodetree : EEVEE_shader_default_world_nodetree(wo);
+ mat = DRW_shader_create_from_world(
+ scene, wo, ntree, engine, options, is_volume, vert, geom, frag, defines, deferred);
+ }
+
+ MEM_SAFE_FREE(defines);
+ MEM_SAFE_FREE(vert);
+ MEM_SAFE_FREE(geom);
+ MEM_SAFE_FREE(frag);
+
+ return mat;
+}
+
+/* Note: Compilation is not deferred. */
+struct GPUMaterial *EEVEE_material_default_get(struct Scene *scene, Material *ma, int options)
+{
+ Material *def_ma = (ma && (options & VAR_MAT_VOLUME)) ? BKE_material_default_volume() :
+ BKE_material_default_surface();
+ BLI_assert(def_ma->use_nodes && def_ma->nodetree);
+
+ return eevee_material_get_ex(scene, def_ma, NULL, options, false);
+}
+
+struct GPUMaterial *EEVEE_material_get(
+ EEVEE_Data *vedata, struct Scene *scene, Material *ma, World *wo, int options)
+{
+ if ((ma && (!ma->use_nodes || !ma->nodetree)) || (wo && (!wo->use_nodes || !wo->nodetree))) {
+ options |= VAR_DEFAULT;
+ }
+
+ /* Meh, implicit option. World probe cannot be deferred because they need
+ * to be rendered immediatly. */
+ const bool deferred = (options & VAR_WORLD_PROBE) == 0;
+
+ GPUMaterial *mat = eevee_material_get_ex(scene, ma, wo, options, deferred);
+
+ int status = GPU_material_status(mat);
+ switch (status) {
+ case GPU_MAT_SUCCESS:
+ break;
+ case GPU_MAT_QUEUED:
+ vedata->stl->g_data->queued_shaders_count++;
+ mat = EEVEE_material_default_get(scene, ma, options);
+ break;
+ case GPU_MAT_FAILED:
+ default:
+ ma = EEVEE_material_default_error_get();
+ mat = eevee_material_get_ex(scene, ma, NULL, options, false);
+ break;
+ }
+ /* Returned material should be ready to be drawn. */
+ BLI_assert(GPU_material_status(mat) == GPU_MAT_SUCCESS);
+ return mat;
+}
+
void EEVEE_shaders_free(void)
{
+ MEM_SAFE_FREE(e_data.frag_shader_lib);
+ MEM_SAFE_FREE(e_data.vert_shader_str);
+ MEM_SAFE_FREE(e_data.vert_shadow_shader_str);
+ MEM_SAFE_FREE(e_data.vert_background_shader_str);
+ MEM_SAFE_FREE(e_data.vert_volume_shader_str);
+ MEM_SAFE_FREE(e_data.geom_volume_shader_str);
+ MEM_SAFE_FREE(e_data.volume_shader_lib);
+ DRW_SHADER_FREE_SAFE(e_data.default_background);
+ DRW_SHADER_FREE_SAFE(e_data.update_noise_sh);
DRW_SHADER_FREE_SAFE(e_data.probe_default_sh);
DRW_SHADER_FREE_SAFE(e_data.probe_filter_glossy_sh);
DRW_SHADER_FREE_SAFE(e_data.probe_filter_diffuse_sh);
@@ -332,4 +787,27 @@ void EEVEE_shaders_free(void)
DRW_SHADER_FREE_SAFE(e_data.velocity_resolve_sh);
DRW_SHADER_FREE_SAFE(e_data.taa_resolve_sh);
DRW_SHADER_FREE_SAFE(e_data.taa_resolve_reproject_sh);
+
+ if (e_data.glossy_mat) {
+ BKE_id_free(NULL, e_data.glossy_mat);
+ e_data.glossy_mat = NULL;
+ }
+ if (e_data.diffuse_mat) {
+ BKE_id_free(NULL, e_data.diffuse_mat);
+ e_data.diffuse_mat = NULL;
+ }
+ if (e_data.error_mat) {
+ BKE_id_free(NULL, e_data.error_mat);
+ e_data.error_mat = NULL;
+ }
+ if (e_data.surface.ntree) {
+ ntreeFreeEmbeddedTree(e_data.surface.ntree);
+ MEM_freeN(e_data.surface.ntree);
+ e_data.surface.ntree = NULL;
+ }
+ if (e_data.world.ntree) {
+ ntreeFreeEmbeddedTree(e_data.world.ntree);
+ MEM_freeN(e_data.world.ntree);
+ e_data.world.ntree = NULL;
+ }
}
diff --git a/source/blender/draw/engines/eevee/eevee_shadows.c b/source/blender/draw/engines/eevee/eevee_shadows.c
index fb338d85fde..84c50a22ae6 100644
--- a/source/blender/draw/engines/eevee/eevee_shadows.c
+++ b/source/blender/draw/engines/eevee/eevee_shadows.c
@@ -159,47 +159,6 @@ void EEVEE_shadows_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
}
}
-/* Add a shadow caster to the shadowpasses */
-void EEVEE_shadows_caster_add(EEVEE_ViewLayerData *UNUSED(sldata),
- EEVEE_StorageList *stl,
- struct GPUBatch *geom,
- Object *ob)
-{
- DRW_shgroup_call(stl->g_data->shadow_shgrp, geom, ob);
-}
-
-void EEVEE_shadows_caster_material_add(EEVEE_ViewLayerData *sldata,
- EEVEE_PassList *psl,
- struct GPUMaterial *gpumat,
- struct GPUBatch *geom,
- struct Object *ob,
- const float *alpha_threshold)
-{
- /* TODO / PERF : reuse the same shading group for objects with the same material */
- DRWShadingGroup *grp = DRW_shgroup_material_create(gpumat, psl->shadow_pass);
-
- if (grp == NULL) {
- return;
- }
-
- /* Unfortunately needed for correctness but not 99% of the time not needed.
- * TODO detect when needed? */
- DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
- DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
- DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
- DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
- DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
- DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
-
- if (alpha_threshold != NULL) {
- DRW_shgroup_uniform_float(grp, "alphaThreshold", alpha_threshold, 1);
- }
-
- DRW_shgroup_call(grp, geom, ob);
-}
-
/* Make that object update shadow casting lights inside its influence bounding box. */
void EEVEE_shadows_caster_register(EEVEE_ViewLayerData *sldata, Object *ob)
{
@@ -470,8 +429,7 @@ void EEVEE_shadow_output_init(EEVEE_ViewLayerData *sldata,
DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_uniform_texture_ref(grp, "shadowCubeTexture", &sldata->shadow_cube_pool);
DRW_shgroup_uniform_texture_ref(grp, "shadowCascadeTexture", &sldata->shadow_cascade_pool);
diff --git a/source/blender/draw/engines/eevee/eevee_subsurface.c b/source/blender/draw/engines/eevee/eevee_subsurface.c
index 4f334812a8e..7674148f76a 100644
--- a/source/blender/draw/engines/eevee/eevee_subsurface.c
+++ b/source/blender/draw/engines/eevee/eevee_subsurface.c
@@ -29,7 +29,9 @@
#include "DEG_depsgraph_query.h"
#include "GPU_extensions.h"
+#include "GPU_material.h"
#include "GPU_texture.h"
+
#include "eevee_private.h"
static struct {
@@ -83,6 +85,7 @@ void EEVEE_subsurface_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
effects->sss_sample_count = 1 + scene_eval->eevee.sss_samples * 2;
+ effects->sss_surface_count = 0;
common_data->sss_jitter_threshold = scene_eval->eevee.sss_jitter_threshold;
}
@@ -221,70 +224,77 @@ void EEVEE_subsurface_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
void EEVEE_subsurface_add_pass(EEVEE_ViewLayerData *sldata,
EEVEE_Data *vedata,
- uint sss_id,
- struct GPUUniformBuffer *sss_profile)
+ Material *ma,
+ DRWShadingGroup *shgrp,
+ struct GPUMaterial *gpumat)
{
- DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
EEVEE_PassList *psl = vedata->psl;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_EffectsInfo *effects = stl->effects;
- struct GPUBatch *quad = DRW_cache_fullscreen_quad_get();
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
GPUTexture **depth_src = GPU_depth_blitting_workaround() ? &effects->sss_stencil : &dtxl->depth;
- DRWShadingGroup *grp = DRW_shgroup_create(e_data.sss_sh[0], psl->sss_blur_ps);
- DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
- DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src);
- DRW_shgroup_uniform_texture_ref(grp, "sssIrradiance", &effects->sss_irradiance);
- DRW_shgroup_uniform_texture_ref(grp, "sssRadius", &effects->sss_radius);
- DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
- DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
- DRW_shgroup_stencil_mask(grp, sss_id);
- DRW_shgroup_call(grp, quad, NULL);
-
- grp = DRW_shgroup_create(e_data.sss_sh[1], psl->sss_resolve_ps);
- DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
- DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src);
- DRW_shgroup_uniform_texture_ref(grp, "sssIrradiance", &effects->sss_blur);
- DRW_shgroup_uniform_texture_ref(grp, "sssAlbedo", &effects->sss_albedo);
- DRW_shgroup_uniform_texture_ref(grp, "sssRadius", &effects->sss_radius);
- DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
- DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
- DRW_shgroup_stencil_mask(grp, sss_id);
- DRW_shgroup_call(grp, quad, NULL);
-}
+ struct GPUTexture *sss_tex_profile = NULL;
+ struct GPUUniformBuffer *sss_profile = GPU_material_sss_profile_get(
+ gpumat, stl->effects->sss_sample_count, &sss_tex_profile);
-void EEVEE_subsurface_translucency_add_pass(EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- uint sss_id,
- struct GPUUniformBuffer *sss_profile,
- GPUTexture *sss_tex_profile)
-{
- DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
- EEVEE_PassList *psl = vedata->psl;
- EEVEE_StorageList *stl = vedata->stl;
- EEVEE_EffectsInfo *effects = stl->effects;
- struct GPUBatch *quad = DRW_cache_fullscreen_quad_get();
- GPUTexture **depth_src = GPU_depth_blitting_workaround() ? &effects->sss_stencil : &dtxl->depth;
+ if (!sss_profile) {
+ BLI_assert(0 && "SSS pass requested but no SSS data was found");
+ return;
+ }
+
+ /* Limit of 8 bit stencil buffer. ID 255 is refraction. */
+ if (effects->sss_surface_count >= 254) {
+ /* TODO : display message. */
+ printf("Error: Too many different Subsurface shader in the scene.\n");
+ return;
+ }
+
+ int sss_id = ++(effects->sss_surface_count);
+ /* Make main pass output stencil mask. */
+ DRW_shgroup_stencil_mask(shgrp, sss_id);
+
+ {
+ DRWShadingGroup *grp = DRW_shgroup_create(e_data.sss_sh[0], psl->sss_blur_ps);
+ DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
+ DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src);
+ DRW_shgroup_uniform_texture_ref(grp, "sssIrradiance", &effects->sss_irradiance);
+ DRW_shgroup_uniform_texture_ref(grp, "sssRadius", &effects->sss_radius);
+ DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
+ DRW_shgroup_stencil_mask(grp, sss_id);
+ DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
+
+ grp = DRW_shgroup_create(e_data.sss_sh[1], psl->sss_resolve_ps);
+ DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
+ DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src);
+ DRW_shgroup_uniform_texture_ref(grp, "sssIrradiance", &effects->sss_blur);
+ DRW_shgroup_uniform_texture_ref(grp, "sssAlbedo", &effects->sss_albedo);
+ DRW_shgroup_uniform_texture_ref(grp, "sssRadius", &effects->sss_radius);
+ DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
+ DRW_shgroup_stencil_mask(grp, sss_id);
+ DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
+ }
- DRWShadingGroup *grp = DRW_shgroup_create(e_data.sss_sh[2], psl->sss_translucency_ps);
- DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
- DRW_shgroup_uniform_texture(grp, "sssTexProfile", sss_tex_profile);
- DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src);
- DRW_shgroup_uniform_texture_ref(grp, "sssRadius", &effects->sss_radius);
- DRW_shgroup_uniform_texture_ref(grp, "sssShadowCubes", &sldata->shadow_cube_pool);
- DRW_shgroup_uniform_texture_ref(grp, "sssShadowCascades", &sldata->shadow_cascade_pool);
- DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
- DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
- DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
- DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
- DRW_shgroup_stencil_mask(grp, sss_id);
- DRW_shgroup_call(grp, quad, NULL);
+ if (ma->blend_flag & MA_BL_TRANSLUCENCY) {
+ DRWShadingGroup *grp = DRW_shgroup_create(e_data.sss_sh[2], psl->sss_translucency_ps);
+ DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
+ DRW_shgroup_uniform_texture(grp, "sssTexProfile", sss_tex_profile);
+ DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src);
+ DRW_shgroup_uniform_texture_ref(grp, "sssRadius", &effects->sss_radius);
+ DRW_shgroup_uniform_texture_ref(grp, "sssShadowCubes", &sldata->shadow_cube_pool);
+ DRW_shgroup_uniform_texture_ref(grp, "sssShadowCascades", &sldata->shadow_cascade_pool);
+ DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
+ DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
+ DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
+ DRW_shgroup_stencil_mask(grp, sss_id);
+ DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
+ }
}
void EEVEE_subsurface_data_render(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
@@ -310,8 +320,7 @@ void EEVEE_subsurface_data_render(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Dat
GPU_ATTACHMENT_TEXTURE(effects->sss_albedo)});
GPU_framebuffer_bind(fbl->main_fb);
- DRW_draw_pass(psl->sss_pass);
- DRW_draw_pass(psl->sss_pass_cull);
+ DRW_draw_pass(psl->material_sss_ps);
/* Restore */
GPU_framebuffer_ensure_config(&fbl->main_fb,
@@ -350,23 +359,15 @@ void EEVEE_subsurface_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
if (!DRW_pass_is_empty(psl->sss_translucency_ps)) {
/* We sample the shadow-maps using normal sampler. We need to disable Comparison mode.
* TODO(fclem) avoid this by using sampler objects.*/
- GPU_texture_bind(sldata->shadow_cube_pool, 0);
GPU_texture_compare_mode(sldata->shadow_cube_pool, false);
- GPU_texture_unbind(sldata->shadow_cube_pool);
- GPU_texture_bind(sldata->shadow_cascade_pool, 0);
GPU_texture_compare_mode(sldata->shadow_cascade_pool, false);
- GPU_texture_unbind(sldata->shadow_cascade_pool);
GPU_framebuffer_bind(fbl->sss_translucency_fb);
DRW_draw_pass(psl->sss_translucency_ps);
/* Reset original state. */
- GPU_texture_bind(sldata->shadow_cube_pool, 0);
GPU_texture_compare_mode(sldata->shadow_cube_pool, true);
- GPU_texture_unbind(sldata->shadow_cube_pool);
- GPU_texture_bind(sldata->shadow_cascade_pool, 0);
GPU_texture_compare_mode(sldata->shadow_cascade_pool, true);
- GPU_texture_unbind(sldata->shadow_cascade_pool);
}
/* 1. horizontal pass */
diff --git a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
index b70d872c4af..d57048f2c4e 100644
--- a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
+++ b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
@@ -292,8 +292,7 @@ void EEVEE_temporal_sampling_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data
DRW_shgroup_uniform_texture_ref(grp, "colorHistoryBuffer", &txl->taa_history);
DRW_shgroup_uniform_texture_ref(grp, "colorBuffer", &effects->source_buffer);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
if (effects->enabled_effects & EFFECT_TAA_REPROJECT) {
// DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c
index 83bd4fcf8d2..90860e94270 100644
--- a/source/blender/draw/engines/eevee/eevee_volumes.c
+++ b/source/blender/draw/engines/eevee/eevee_volumes.c
@@ -355,7 +355,7 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
struct World *wo = scene->world;
if (wo != NULL && wo->use_nodes && wo->nodetree &&
!LOOK_DEV_STUDIO_LIGHT_ENABLED(draw_ctx->v3d)) {
- struct GPUMaterial *mat = EEVEE_material_world_volume_get(scene, wo);
+ struct GPUMaterial *mat = EEVEE_material_get(vedata, scene, NULL, wo, VAR_MAT_VOLUME);
if (GPU_material_has_volume_output(mat)) {
grp = DRW_shgroup_material_create(mat, psl->volumetric_world_ps);
@@ -369,8 +369,7 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
/* Fix principle volumetric not working with world materials. */
ListBase gpu_grids = GPU_material_volume_grids(mat);
@@ -388,8 +387,7 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
/* If no world or volume material is present just clear the buffer with this drawcall */
grp = DRW_shgroup_create(e_data.volumetric_clear_sh, psl->volumetric_world_ps);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_call_procedural_triangles(grp, NULL, common_data->vol_tex_size[2]);
}
@@ -590,12 +588,10 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata,
return;
}
- struct GPUMaterial *mat = EEVEE_material_mesh_volume_get(scene, ma);
+ int mat_options = VAR_MAT_VOLUME | VAR_MAT_MESH;
+ struct GPUMaterial *mat = EEVEE_material_get(vedata, scene, ma, NULL, mat_options);
eGPUMaterialStatus status = GPU_material_status(mat);
- if (status == GPU_MAT_QUEUED) {
- vedata->stl->g_data->queued_shaders_count++;
- }
/* If shader failed to compile or is currently compiling. */
if (status != GPU_MAT_SUCCESS) {
return;
@@ -609,8 +605,7 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata,
DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
@@ -661,8 +656,7 @@ void EEVEE_volumes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_call_procedural_triangles(grp, NULL, common_data->vol_tex_size[2]);
@@ -671,8 +665,7 @@ void EEVEE_volumes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_shgroup_uniform_texture_ref(grp, "volumeScattering", &txl->volume_scatter);
DRW_shgroup_uniform_texture_ref(grp, "volumeExtinction", &txl->volume_transmit);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_call_procedural_triangles(
grp, NULL, USE_VOLUME_OPTI ? 1 : common_data->vol_tex_size[2]);
@@ -683,8 +676,7 @@ void EEVEE_volumes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_shgroup_uniform_texture_ref(grp, "inTransmittance", &txl->volume_transmit);
DRW_shgroup_uniform_texture_ref(grp, "inSceneDepth", &e_data.depth_src);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
}
@@ -775,12 +767,8 @@ void EEVEE_volumes_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
/* We sample the shadow-maps using shadow sampler. We need to enable Comparison mode.
* TODO(fclem) avoid this by using sampler objects.*/
- GPU_texture_bind(sldata->shadow_cube_pool, 0);
GPU_texture_compare_mode(sldata->shadow_cube_pool, true);
- GPU_texture_unbind(sldata->shadow_cube_pool);
- GPU_texture_bind(sldata->shadow_cascade_pool, 0);
GPU_texture_compare_mode(sldata->shadow_cascade_pool, true);
- GPU_texture_unbind(sldata->shadow_cascade_pool);
GPU_framebuffer_bind(fbl->volumetric_fb);
DRW_draw_pass(psl->volumetric_world_ps);
@@ -920,8 +908,7 @@ void EEVEE_volumes_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata,
DRW_shgroup_uniform_texture_ref(grp, "inTransmittance", &txl->volume_transmit);
DRW_shgroup_uniform_texture_ref(grp, "inSceneDepth", &e_data.depth_src);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
}
else {
/* There is no volumetrics in the scene. Use a shader to fill the accum textures with a default
diff --git a/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl b/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl
index 8662c0ecb6a..57b16418696 100644
--- a/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl
@@ -6,13 +6,9 @@
#if defined(MESH_SHADER)
# if !defined(USE_ALPHA_HASH)
-# if !defined(USE_ALPHA_CLIP)
-# if !defined(SHADOW_SHADER)
-# if !defined(USE_MULTIPLY)
-# if !defined(USE_ALPHA_BLEND)
-# define ENABLE_DEFERED_AO
-# endif
-# endif
+# if !defined(DEPTH_SHADER)
+# if !defined(USE_ALPHA_BLEND)
+# define ENABLE_DEFERED_AO
# endif
# endif
# endif
diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
index c3518198805..402d306df45 100644
--- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
@@ -928,7 +928,7 @@ Closure closure_emission(vec3 rgb)
/* Breaking this across multiple lines causes issues for some older GLSL compilers. */
/* clang-format off */
-# if defined(MESH_SHADER) && !defined(USE_ALPHA_HASH) && !defined(USE_ALPHA_CLIP) && !defined(SHADOW_SHADER)
+# if defined(MESH_SHADER) && !defined(DEPTH_SHADER)
/* clang-format on */
# ifndef USE_ALPHA_BLEND
layout(location = 0) out vec4 outRadiance;
@@ -1001,6 +1001,10 @@ void main()
outRadiance.rgb += cl.sss_irradiance.rgb * cl.sss_albedo.rgb * fac;
# endif
+# ifdef LOOKDEV
+ gl_FragDepth = 0.0;
+# endif
+
# ifndef USE_ALPHA_BLEND
float alpha_div = 1.0 / max(1e-8, alpha);
outRadiance.rgb *= alpha_div;
@@ -1011,6 +1015,6 @@ void main()
# endif
}
-# endif /* MESH_SHADER && !SHADOW_SHADER */
+# endif /* MESH_SHADER */
#endif /* VOLUMETRICS */
diff --git a/source/blender/draw/engines/eevee/shaders/effect_dof_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_dof_frag.glsl
index 5277bfa32bb..d56890769a7 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_dof_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_dof_frag.glsl
@@ -1,6 +1,4 @@
-uniform mat4 ProjectionMatrix;
-
uniform sampler2D colorBuffer;
uniform sampler2D depthBuffer;
diff --git a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
index 8c2619650b9..bc7879763c3 100644
--- a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
@@ -177,7 +177,7 @@ void CLOSURE_NAME(vec3 N
out_refr = vec3(0.0);
#endif
-#if defined(SHADOW_SHADER) || defined(WORLD_BACKGROUND)
+#if defined(DEPTH_SHADER) || defined(WORLD_BACKGROUND)
/* This makes shader resources become unused and avoid issues with samplers. (see T59747) */
return;
#else
diff --git a/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl b/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl
index cf20b3ff5b9..1b94fc2bee1 100644
--- a/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl
@@ -4,11 +4,12 @@ in vec3 pos;
in vec3 nor;
#endif
+#ifdef MESH_SHADER
out vec3 worldPosition;
out vec3 viewPosition;
-
out vec3 worldNormal;
out vec3 viewNormal;
+#endif
#ifdef HAIR_SHADER
out vec3 hairTangent;
@@ -41,22 +42,28 @@ void main()
hairThickness,
hairThickTime);
worldNormal = cross(hairTangent, binor);
- worldPosition = pos;
+ vec3 world_pos = pos;
#else
- worldPosition = point_object_to_world(pos);
- worldNormal = normalize(normal_object_to_world(nor));
+ vec3 world_pos = point_object_to_world(pos);
#endif
- /* No need to normalize since this is just a rotation. */
- viewNormal = normal_world_to_view(worldNormal);
+ gl_Position = point_world_to_ndc(world_pos);
+ /* Used for planar reflections */
+ gl_ClipDistance[0] = dot(vec4(world_pos, 1.0), clipPlanes[0]);
+
+#ifdef MESH_SHADER
+ worldPosition = world_pos;
viewPosition = point_world_to_view(worldPosition);
- gl_Position = point_world_to_ndc(worldPosition);
- /* Used for planar reflections */
- gl_ClipDistance[0] = dot(vec4(worldPosition, 1.0), clipPlanes[0]);
+# ifndef HAIR_SHADER
+ worldNormal = normalize(normal_object_to_world(nor));
+# endif
-#ifdef USE_ATTR
+ /* No need to normalize since this is just a rotation. */
+ viewNormal = normal_world_to_view(worldNormal);
+# ifdef USE_ATTR
pass_attr(pos);
+# endif
#endif
}
diff --git a/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl b/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl
index b49dbfceba2..9acd8f998f6 100644
--- a/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl
@@ -45,26 +45,22 @@ float hashed_alpha_threshold(vec3 co)
/* Find our final, uniformly distributed alpha threshold. */
float threshold = (x < one_a) ? ((x < a) ? cases.x : cases.y) : cases.z;
+ /* Jitter the threshold for TAA accumulation. */
+ threshold = fract(threshold + alphaHashOffset);
+
/* Avoids threshold == 0. */
threshold = clamp(threshold, 1.0e-6, 1.0);
- /* Jitter the threshold for TAA accumulation. */
- return fract(threshold + alphaHashOffset);
+ return threshold;
}
#endif
-#ifdef USE_ALPHA_CLIP
-uniform float alphaThreshold;
-#endif
+#define NODETREE_EXEC
void main()
{
- /* For now do nothing.
- * In the future, output object motion blur. */
-
-#if defined(USE_ALPHA_HASH) || defined(USE_ALPHA_CLIP)
-# define NODETREE_EXEC
+#if defined(USE_ALPHA_HASH)
Closure cl = nodetree_exec();
@@ -75,11 +71,6 @@ void main()
if (opacity < hashed_alpha_threshold(worldPosition)) {
discard;
}
-# elif defined(USE_ALPHA_CLIP)
- /* Alpha clip */
- if (opacity <= alphaThreshold) {
- discard;
- }
# endif
#endif
}
diff --git a/source/blender/draw/engines/external/external_engine.c b/source/blender/draw/engines/external/external_engine.c
index 6e636e4dc93..2f448b784ed 100644
--- a/source/blender/draw/engines/external/external_engine.c
+++ b/source/blender/draw/engines/external/external_engine.c
@@ -44,6 +44,11 @@
#define EXTERNAL_ENGINE "BLENDER_EXTERNAL"
+extern char datatoc_depth_frag_glsl[];
+extern char datatoc_depth_vert_glsl[];
+
+extern char datatoc_common_view_lib_glsl[];
+
/* *********** LISTS *********** */
/* GPUViewport.storage
@@ -106,7 +111,16 @@ static void external_engine_init(void *vedata)
/* Depth prepass */
if (!e_data.depth_sh) {
- e_data.depth_sh = DRW_shader_create_3d_depth_only(GPU_SHADER_CFG_DEFAULT);
+ const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[GPU_SHADER_CFG_DEFAULT];
+
+ e_data.depth_sh = GPU_shader_create_from_arrays({
+ .vert = (const char *[]){sh_cfg->lib,
+ datatoc_common_view_lib_glsl,
+ datatoc_depth_vert_glsl,
+ NULL},
+ .frag = (const char *[]){datatoc_depth_frag_glsl, NULL},
+ .defs = (const char *[]){sh_cfg->def, NULL},
+ });
}
if (!stl->g_data) {
@@ -277,7 +291,7 @@ static void external_draw_scene(void *vedata)
static void external_engine_free(void)
{
- /* All shaders are builtin. */
+ DRW_SHADER_FREE_SAFE(e_data.depth_sh);
}
static const DrawEngineDataSize external_data_size = DRW_VIEWPORT_DATA_SIZE(EXTERNAL_Data);
diff --git a/source/blender/draw/engines/gpencil/gpencil_antialiasing.c b/source/blender/draw/engines/gpencil/gpencil_antialiasing.c
index 4dd5e3b2da1..8955240c549 100644
--- a/source/blender/draw/engines/gpencil/gpencil_antialiasing.c
+++ b/source/blender/draw/engines/gpencil/gpencil_antialiasing.c
@@ -78,13 +78,8 @@ void GPENCIL_antialiasing_init(struct GPENCIL_Data *vedata)
false,
NULL);
- GPU_texture_bind(txl->smaa_search_tx, 0);
GPU_texture_filter_mode(txl->smaa_search_tx, true);
- GPU_texture_unbind(txl->smaa_search_tx);
-
- GPU_texture_bind(txl->smaa_area_tx, 0);
GPU_texture_filter_mode(txl->smaa_area_tx, true);
- GPU_texture_unbind(txl->smaa_area_tx);
}
{
diff --git a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
index 1344b649dff..2b811f1d52e 100644
--- a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
+++ b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
@@ -381,7 +381,7 @@ GPENCIL_tLayer *gpencil_layer_cache_add(GPENCIL_PrivateData *pd,
struct GPUShader *sh = GPENCIL_shader_geometry_get();
DRWShadingGroup *grp = tgp_layer->base_shgrp = DRW_shgroup_create(sh, tgp_layer->geom_ps);
- DRW_shgroup_uniform_texture_persistent(grp, "gpSceneDepthTexture", depth_tex);
+ DRW_shgroup_uniform_texture(grp, "gpSceneDepthTexture", depth_tex);
DRW_shgroup_uniform_texture_ref(grp, "gpMaskTexture", mask_tex);
DRW_shgroup_uniform_vec3_copy(grp, "gpNormal", tgp_ob->plane_normal);
DRW_shgroup_uniform_bool_copy(grp, "strokeOrder3d", tgp_ob->is_drawmode3d);
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c
index 4f586a1e9f3..495de7ef10b 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.c
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.c
@@ -91,6 +91,7 @@ void GPENCIL_engine_init(void *ved)
stl->pd->gp_object_pool = vldata->gp_object_pool;
stl->pd->gp_layer_pool = vldata->gp_layer_pool;
stl->pd->gp_vfx_pool = vldata->gp_vfx_pool;
+ stl->pd->view_layer = ctx->view_layer;
stl->pd->scene = ctx->scene;
stl->pd->v3d = ctx->v3d;
stl->pd->last_light_pool = NULL;
@@ -468,7 +469,7 @@ static void gpencil_layer_cache_populate(bGPDlayer *gpl,
/* Iterator dependent uniforms. */
DRWShadingGroup *grp = iter->grp = tgp_layer->base_shgrp;
- DRW_shgroup_uniform_block_persistent(grp, "gpLightBlock", iter->ubo_lights);
+ DRW_shgroup_uniform_block(grp, "gpLightBlock", iter->ubo_lights);
DRW_shgroup_uniform_block(grp, "gpMaterialBlock", iter->ubo_mat);
DRW_shgroup_uniform_texture(grp, "gpFillTexture", iter->tex_fill);
DRW_shgroup_uniform_texture(grp, "gpStrokeTexture", iter->tex_stroke);
@@ -598,6 +599,7 @@ void GPENCIL_cache_populate(void *ved, Object *ob)
GPENCIL_Data *vedata = (GPENCIL_Data *)ved;
GPENCIL_PrivateData *pd = vedata->stl->pd;
GPENCIL_TextureList *txl = vedata->txl;
+ const bool is_final_render = DRW_state_is_image_render();
/* object must be visible */
if (!(DRW_object_visibility_in_active_context(ob) & OB_VISIBLE_SELF)) {
@@ -617,7 +619,8 @@ void GPENCIL_cache_populate(void *ved, Object *ob)
bGPdata *gpd = (bGPdata *)ob->data;
bool do_onion = (!pd->is_render) ? pd->do_onion : (gpd->onion_flag & GP_ONION_GHOST_ALWAYS);
- BKE_gpencil_visible_stroke_iter(ob,
+ BKE_gpencil_visible_stroke_iter(is_final_render ? pd->view_layer : NULL,
+ ob,
gpencil_layer_cache_populate,
gpencil_stroke_cache_populate,
&iter,
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h
index f765dcf73de..cedd75af813 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.h
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.h
@@ -307,6 +307,8 @@ typedef struct GPENCIL_PrivateData {
float dof_params[2];
/* Used for DoF Setup. */
Object *camera;
+ /* Copy of draw_ctx->view_layer for convenience. */
+ struct ViewLayer *view_layer;
/* Copy of draw_ctx->scene for convenience. */
struct Scene *scene;
/* Copy of draw_ctx->vie3d for convenience. */
diff --git a/source/blender/draw/engines/overlay/overlay_armature.c b/source/blender/draw/engines/overlay/overlay_armature.c
index a538b7ffd5f..95fd918f8c1 100644
--- a/source/blender/draw/engines/overlay/overlay_armature.c
+++ b/source/blender/draw/engines/overlay/overlay_armature.c
@@ -184,7 +184,7 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_armature_sphere(false);
grp = DRW_shgroup_create(sh, armature_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_float_copy(grp, "alpha", 1.0f);
cb->point_solid = BUF_INSTANCE(grp, format, DRW_cache_bone_point_get());
@@ -196,7 +196,7 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_armature_shape(false);
grp = DRW_shgroup_create(sh, armature_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_float_copy(grp, "alpha", 1.0f);
cb->custom_solid = grp;
cb->box_solid = BUF_INSTANCE(grp, format, DRW_cache_bone_box_get());
@@ -212,29 +212,29 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_armature_sphere(true);
grp = DRW_shgroup_create(sh, armature_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
cb->point_outline = BUF_INSTANCE(grp, format, DRW_cache_bone_point_wire_outline_get());
sh = OVERLAY_shader_armature_shape(true);
cb->custom_outline = grp = DRW_shgroup_create(sh, armature_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
cb->box_outline = BUF_INSTANCE(grp, format, DRW_cache_bone_box_wire_get());
cb->octa_outline = BUF_INSTANCE(grp, format, DRW_cache_bone_octahedral_wire_get());
sh = OVERLAY_shader_armature_shape_wire();
cb->custom_wire = grp = DRW_shgroup_create(sh, armature_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
}
{
format = formats->instance_extra;
sh = OVERLAY_shader_armature_degrees_of_freedom();
grp = DRW_shgroup_create(sh, armature_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
cb->dof_lines = BUF_INSTANCE(grp, format, DRW_cache_bone_dof_lines_get());
grp = DRW_shgroup_create(sh, armature_transp_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
cb->dof_sphere = BUF_INSTANCE(grp, format, DRW_cache_bone_dof_sphere_get());
}
{
@@ -242,7 +242,7 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_armature_stick();
grp = DRW_shgroup_create(sh, armature_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
cb->stick = BUF_INSTANCE(grp, format, DRW_cache_bone_stick_get());
}
{
@@ -251,7 +251,7 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_armature_envelope(false);
grp = DRW_shgroup_create(sh, armature_ps);
DRW_shgroup_state_enable(grp, DRW_STATE_CULL_BACK);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_bool_copy(grp, "isDistance", false);
DRW_shgroup_uniform_float_copy(grp, "alpha", 1.0f);
cb->envelope_solid = BUF_INSTANCE(grp, format, DRW_cache_bone_envelope_solid_get());
@@ -266,14 +266,14 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_armature_envelope(true);
grp = DRW_shgroup_create(sh, armature_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
cb->envelope_outline = BUF_INSTANCE(grp, format, DRW_cache_bone_envelope_outline_get());
format = formats->instance_bone_envelope_distance;
sh = OVERLAY_shader_armature_envelope(false);
grp = DRW_shgroup_create(sh, armature_transp_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_bool_copy(grp, "isDistance", true);
DRW_shgroup_state_enable(grp, DRW_STATE_CULL_FRONT);
cb->envelope_distance = BUF_INSTANCE(grp, format, DRW_cache_bone_envelope_solid_get());
@@ -283,7 +283,7 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_armature_wire();
grp = DRW_shgroup_create(sh, armature_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
cb->wire = BUF_LINE(grp, format);
}
}
diff --git a/source/blender/draw/engines/overlay/overlay_extra.c b/source/blender/draw/engines/overlay/overlay_extra.c
index 71efc6b8d03..859f3f93b1d 100644
--- a/source/blender/draw/engines/overlay/overlay_extra.c
+++ b/source/blender/draw/engines/overlay/overlay_extra.c
@@ -81,8 +81,8 @@ void OVERLAY_extra_cache_init(OVERLAY_Data *vedata)
struct GPUTexture *tex = DRW_state_is_fbo() ? dtxl->depth : txl->dummy_depth_tx;
pd->extra_grid_grp = grp = DRW_shgroup_create(sh, psl->extra_grid_ps);
- DRW_shgroup_uniform_texture_persistent(grp, "depthBuffer", tex);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_texture(grp, "depthBuffer", tex);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_bool_copy(grp, "isTransform", (G.moving & G_TRANSFORM_OBJ) != 0);
}
@@ -112,7 +112,7 @@ void OVERLAY_extra_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_extra(is_select);
grp = DRW_shgroup_create(sh, extra_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
grp_sub = DRW_shgroup_create_sub(grp);
cb->camera_distances = BUF_INSTANCE(grp_sub, format, DRW_cache_camera_distances_get());
@@ -157,7 +157,7 @@ void OVERLAY_extra_cache_init(OVERLAY_Data *vedata)
{
format = formats->instance_extra;
grp = DRW_shgroup_create(sh, psl->extra_blend_ps); /* NOTE: not the same pass! */
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
grp_sub = DRW_shgroup_create_sub(grp);
DRW_shgroup_state_enable(grp_sub, DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK);
@@ -174,7 +174,7 @@ void OVERLAY_extra_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_extra_groundline();
grp = DRW_shgroup_create(sh, extra_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_state_enable(grp, DRW_STATE_BLEND_ALPHA);
cb->groundline = BUF_INSTANCE(grp, format, DRW_cache_groundline_get());
@@ -183,7 +183,7 @@ void OVERLAY_extra_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_extra_wire(false, is_select);
grp = DRW_shgroup_create(sh, extra_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
cb->extra_dashed_lines = BUF_LINE(grp, formats->pos_color);
cb->extra_lines = BUF_LINE(grp, formats->wire_extra);
@@ -192,20 +192,20 @@ void OVERLAY_extra_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_extra_wire(true, is_select);
cb->extra_wire = grp = DRW_shgroup_create(sh, extra_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
}
{
sh = OVERLAY_shader_extra_loose_point();
cb->extra_loose_points = grp = DRW_shgroup_create(sh, extra_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
}
{
format = formats->pos;
sh = OVERLAY_shader_extra_point();
grp = DRW_shgroup_create(sh, psl->extra_centers_ps); /* NOTE: not the same pass! */
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
grp_sub = DRW_shgroup_create_sub(grp);
DRW_shgroup_uniform_vec4_copy(grp_sub, "color", G_draw.block.colorActive);
@@ -1371,9 +1371,9 @@ static void OVERLAY_volume_extra(OVERLAY_ExtraCallBuffers *cb,
madd_v3fl_v3fl_v3fl_v3i(min, mds->p0, mds->cell_size, mds->res_min);
float voxel_cubemat[4][4] = {{0.0f}};
/* scale small cube to voxel size */
- voxel_cubemat[0][0] = 1.0f / (float)mds->base_res[0];
- voxel_cubemat[1][1] = 1.0f / (float)mds->base_res[1];
- voxel_cubemat[2][2] = 1.0f / (float)mds->base_res[2];
+ voxel_cubemat[0][0] = mds->cell_size[0] / 2.0f;
+ voxel_cubemat[1][1] = mds->cell_size[1] / 2.0f;
+ voxel_cubemat[2][2] = mds->cell_size[2] / 2.0f;
voxel_cubemat[3][3] = 1.0f;
/* translate small cube to corner */
copy_v3_v3(voxel_cubemat[3], min);
diff --git a/source/blender/draw/engines/overlay/overlay_facing.c b/source/blender/draw/engines/overlay/overlay_facing.c
index 9216ae61b3e..4eb4b8ae85b 100644
--- a/source/blender/draw/engines/overlay/overlay_facing.c
+++ b/source/blender/draw/engines/overlay/overlay_facing.c
@@ -41,7 +41,7 @@ void OVERLAY_facing_cache_init(OVERLAY_Data *vedata)
GPUShader *sh = OVERLAY_shader_facing();
pd->facing_grp[i] = DRW_shgroup_create(sh, psl->facing_ps[i]);
- DRW_shgroup_uniform_block_persistent(pd->facing_grp[i], "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(pd->facing_grp[i], "globalsBlock", G_draw.block_ubo);
}
if (!pd->use_in_front) {
diff --git a/source/blender/draw/engines/overlay/overlay_gpencil.c b/source/blender/draw/engines/overlay/overlay_gpencil.c
index 1397ef7b4b2..ccc914e0422 100644
--- a/source/blender/draw/engines/overlay/overlay_gpencil.c
+++ b/source/blender/draw/engines/overlay/overlay_gpencil.c
@@ -361,7 +361,7 @@ static void OVERLAY_gpencil_color_names(Object *ob)
int cfra = DEG_get_ctime(draw_ctx->depsgraph);
BKE_gpencil_visible_stroke_iter(
- ob, NULL, overlay_gpencil_draw_stroke_color_name, ob, false, cfra);
+ NULL, ob, NULL, overlay_gpencil_draw_stroke_color_name, ob, false, cfra);
}
void OVERLAY_gpencil_cache_populate(OVERLAY_Data *vedata, Object *ob)
diff --git a/source/blender/draw/engines/overlay/overlay_motion_path.c b/source/blender/draw/engines/overlay/overlay_motion_path.c
index 531e1faf715..168f6f8a17f 100644
--- a/source/blender/draw/engines/overlay/overlay_motion_path.c
+++ b/source/blender/draw/engines/overlay/overlay_motion_path.c
@@ -49,11 +49,11 @@ void OVERLAY_motion_path_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_motion_path_line();
pd->motion_path_lines_grp = grp = DRW_shgroup_create(sh, psl->motion_paths_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
sh = OVERLAY_shader_motion_path_vert();
pd->motion_path_points_grp = grp = DRW_shgroup_create(sh, psl->motion_paths_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
}
/* Just convert the CPU cache to GPU cache. */
diff --git a/source/blender/draw/engines/overlay/overlay_outline.c b/source/blender/draw/engines/overlay/overlay_outline.c
index 142421f58d8..99d22fc380f 100644
--- a/source/blender/draw/engines/overlay/overlay_outline.c
+++ b/source/blender/draw/engines/overlay/overlay_outline.c
@@ -259,7 +259,7 @@ static void OVERLAY_outline_gpencil(OVERLAY_PrivateData *pd, Object *ob)
}
BKE_gpencil_visible_stroke_iter(
- ob, gp_layer_cache_populate, gp_stroke_cache_populate, &iter, false, pd->cfra);
+ NULL, ob, gp_layer_cache_populate, gp_stroke_cache_populate, &iter, false, pd->cfra);
}
void OVERLAY_outline_cache_populate(OVERLAY_Data *vedata,
diff --git a/source/blender/draw/engines/overlay/overlay_particle.c b/source/blender/draw/engines/overlay/overlay_particle.c
index 98bc62ae66a..b891bb4ce4c 100644
--- a/source/blender/draw/engines/overlay/overlay_particle.c
+++ b/source/blender/draw/engines/overlay/overlay_particle.c
@@ -152,13 +152,13 @@ void OVERLAY_particle_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_particle_dot();
pd->particle_dots_grp = grp = DRW_shgroup_create(sh, psl->particle_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
- DRW_shgroup_uniform_texture_persistent(grp, "weightTex", G_draw.ramp);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_texture(grp, "weightTex", G_draw.ramp);
sh = OVERLAY_shader_particle_shape();
pd->particle_shapes_grp = grp = DRW_shgroup_create(sh, psl->particle_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
- DRW_shgroup_uniform_texture_persistent(grp, "weightTex", G_draw.ramp);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_texture(grp, "weightTex", G_draw.ramp);
}
void OVERLAY_particle_cache_populate(OVERLAY_Data *vedata, Object *ob)
diff --git a/source/blender/draw/engines/overlay/overlay_pointcloud.c b/source/blender/draw/engines/overlay/overlay_pointcloud.c
index a0de7aac1f1..b2a2d44bf73 100644
--- a/source/blender/draw/engines/overlay/overlay_pointcloud.c
+++ b/source/blender/draw/engines/overlay/overlay_pointcloud.c
@@ -46,7 +46,7 @@ void OVERLAY_pointcloud_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_pointcloud_dot();
pd->pointcloud_dots_grp = grp = DRW_shgroup_create(sh, psl->pointcloud_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
}
void OVERLAY_pointcloud_cache_populate(OVERLAY_Data *vedata, Object *ob)
diff --git a/source/blender/draw/engines/overlay/overlay_wireframe.c b/source/blender/draw/engines/overlay/overlay_wireframe.c
index cb36f0ed326..eebfc88fdce 100644
--- a/source/blender/draw/engines/overlay/overlay_wireframe.c
+++ b/source/blender/draw/engines/overlay/overlay_wireframe.c
@@ -91,7 +91,7 @@ void OVERLAY_wireframe_cache_init(OVERLAY_Data *vedata)
for (int use_coloring = 0; use_coloring < 2; use_coloring++) {
pd->wires_grp[xray][use_coloring] = grp = DRW_shgroup_create(wires_sh, pass);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_texture_ref(grp, "depthTex", depth_tx);
DRW_shgroup_uniform_float_copy(grp, "wireStepParam", pd->shdata.wire_step_param);
DRW_shgroup_uniform_bool_copy(grp, "useColoring", use_coloring);
@@ -197,13 +197,15 @@ void OVERLAY_wireframe_cache_populate(OVERLAY_Data *vedata,
struct GPUBatch *geom = NULL;
switch (ob->type) {
case OB_CURVE:
- if (ob->runtime.curve_cache && BKE_displist_has_faces(&ob->runtime.curve_cache->disp)) {
+ if (!pd->wireframe_mode && !use_wire && ob->runtime.curve_cache &&
+ BKE_displist_has_faces(&ob->runtime.curve_cache->disp)) {
break;
}
geom = DRW_cache_curve_edge_wire_get(ob);
break;
case OB_FONT:
- if (ob->runtime.curve_cache && BKE_displist_has_faces(&ob->runtime.curve_cache->disp)) {
+ if (!pd->wireframe_mode && !use_wire && ob->runtime.curve_cache &&
+ BKE_displist_has_faces(&ob->runtime.curve_cache->disp)) {
break;
}
geom = DRW_cache_text_loose_edges_get(ob);
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_effect_dof_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_effect_dof_frag.glsl
index 0efcfb35929..51007a9f246 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_effect_dof_frag.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_effect_dof_frag.glsl
@@ -4,7 +4,6 @@
* Converted and adapted from HLSL to GLSL by Clément Foucault
*/
-uniform mat4 ProjectionMatrix;
uniform vec2 invertedViewportSize;
uniform vec2 nearFar;
uniform vec3 dofParams;
diff --git a/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c b/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c
index cb8eb7d1e92..0e896c4b7bb 100644
--- a/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c
+++ b/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c
@@ -266,13 +266,8 @@ void workbench_antialiasing_engine_init(WORKBENCH_Data *vedata)
false,
NULL);
- GPU_texture_bind(txl->smaa_search_tx, 0);
GPU_texture_filter_mode(txl->smaa_search_tx, true);
- GPU_texture_unbind(txl->smaa_search_tx);
-
- GPU_texture_bind(txl->smaa_area_tx, 0);
GPU_texture_filter_mode(txl->smaa_area_tx, true);
- GPU_texture_unbind(txl->smaa_area_tx);
}
}
else {
diff --git a/source/blender/draw/engines/workbench/workbench_materials.c b/source/blender/draw/engines/workbench/workbench_materials.c
index 0b7d313342b..b36a4a3a494 100644
--- a/source/blender/draw/engines/workbench/workbench_materials.c
+++ b/source/blender/draw/engines/workbench/workbench_materials.c
@@ -284,11 +284,11 @@ DRWShadingGroup *workbench_image_setup_ex(WORKBENCH_PrivateData *wpd,
*grp_tex = grp = DRW_shgroup_create_sub(grp);
if (tex_tile_data) {
- DRW_shgroup_uniform_texture_persistent(grp, "imageTileArray", tex);
- DRW_shgroup_uniform_texture_persistent(grp, "imageTileData", tex_tile_data);
+ DRW_shgroup_uniform_texture(grp, "imageTileArray", tex);
+ DRW_shgroup_uniform_texture(grp, "imageTileData", tex_tile_data);
}
else {
- DRW_shgroup_uniform_texture_persistent(grp, "imageTexture", tex);
+ DRW_shgroup_uniform_texture(grp, "imageTexture", tex);
}
DRW_shgroup_uniform_bool_copy(grp, "imagePremult", (ima && ima->alpha_mode == IMA_ALPHA_PREMUL));
DRW_shgroup_uniform_bool_copy(grp, "imageNearest", (interp == SHD_INTERP_CLOSEST));
diff --git a/source/blender/draw/engines/workbench/workbench_opaque.c b/source/blender/draw/engines/workbench/workbench_opaque.c
index c9c43e785ca..27d5b71f35c 100644
--- a/source/blender/draw/engines/workbench/workbench_opaque.c
+++ b/source/blender/draw/engines/workbench/workbench_opaque.c
@@ -95,21 +95,21 @@ void workbench_opaque_cache_init(WORKBENCH_Data *data)
DRW_shgroup_uniform_bool_copy(grp, "useMatcap", use_matcap);
wpd->prepass[opaque][infront][hair].vcol_shgrp = grp = DRW_shgroup_create(sh, pass);
- DRW_shgroup_uniform_block_persistent(grp, "material_block", wpd->material_ubo_curr);
+ DRW_shgroup_uniform_block(grp, "material_block", wpd->material_ubo_curr);
DRW_shgroup_uniform_int_copy(grp, "materialIndex", 0); /* Default material. (uses vcol) */
DRW_shgroup_uniform_bool_copy(grp, "useMatcap", use_matcap);
sh = workbench_shader_opaque_image_get(wpd, hair, false);
wpd->prepass[opaque][infront][hair].image_shgrp = grp = DRW_shgroup_create(sh, pass);
- DRW_shgroup_uniform_block_persistent(grp, "material_block", wpd->material_ubo_curr);
+ DRW_shgroup_uniform_block(grp, "material_block", wpd->material_ubo_curr);
DRW_shgroup_uniform_int_copy(grp, "materialIndex", 0); /* Default material. */
DRW_shgroup_uniform_bool_copy(grp, "useMatcap", use_matcap);
sh = workbench_shader_opaque_image_get(wpd, hair, true);
wpd->prepass[opaque][infront][hair].image_tiled_shgrp = grp = DRW_shgroup_create(sh, pass);
- DRW_shgroup_uniform_block_persistent(grp, "material_block", wpd->material_ubo_curr);
+ DRW_shgroup_uniform_block(grp, "material_block", wpd->material_ubo_curr);
DRW_shgroup_uniform_int_copy(grp, "materialIndex", 0); /* Default material. */
DRW_shgroup_uniform_bool_copy(grp, "useMatcap", use_matcap);
}
@@ -123,9 +123,9 @@ void workbench_opaque_cache_init(WORKBENCH_Data *data)
sh = workbench_shader_composite_get(wpd);
grp = DRW_shgroup_create(sh, psl->composite_ps);
- DRW_shgroup_uniform_block_persistent(grp, "world_block", wpd->world_ubo);
- DRW_shgroup_uniform_texture_persistent(grp, "materialBuffer", wpd->material_buffer_tx);
- DRW_shgroup_uniform_texture_persistent(grp, "normalBuffer", wpd->normal_buffer_tx);
+ DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo);
+ DRW_shgroup_uniform_texture(grp, "materialBuffer", wpd->material_buffer_tx);
+ DRW_shgroup_uniform_texture(grp, "normalBuffer", wpd->normal_buffer_tx);
DRW_shgroup_uniform_bool_copy(grp, "forceShadowing", false);
DRW_shgroup_stencil_mask(grp, 0x00);
@@ -137,8 +137,8 @@ void workbench_opaque_cache_init(WORKBENCH_Data *data)
struct GPUTexture *spec_tx = wpd->studio_light->matcap_specular.gputexture;
const bool use_spec = workbench_is_specular_highlight_enabled(wpd);
spec_tx = (use_spec && spec_tx) ? spec_tx : diff_tx;
- DRW_shgroup_uniform_texture_persistent(grp, "matcapDiffuseImage", diff_tx);
- DRW_shgroup_uniform_texture_persistent(grp, "matcapSpecularImage", spec_tx);
+ DRW_shgroup_uniform_texture(grp, "matcapDiffuseImage", diff_tx);
+ DRW_shgroup_uniform_texture(grp, "matcapSpecularImage", spec_tx);
}
DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
diff --git a/source/blender/draw/engines/workbench/workbench_shader.c b/source/blender/draw/engines/workbench/workbench_shader.c
index 2e796056029..99366779b22 100644
--- a/source/blender/draw/engines/workbench/workbench_shader.c
+++ b/source/blender/draw/engines/workbench/workbench_shader.c
@@ -23,6 +23,7 @@
#include "DRW_render.h"
#include "BLI_dynstr.h"
+#include "BLI_string_utils.h"
#include "workbench_engine.h"
#include "workbench_private.h"
@@ -359,32 +360,24 @@ void workbench_shader_depth_of_field_get(GPUShader **prepare_sh,
GPUShader **resolve_sh)
{
if (e_data.dof_prepare_sh == NULL) {
- e_data.dof_prepare_sh = DRW_shader_create_fullscreen(datatoc_workbench_effect_dof_frag_glsl,
- "#define PREPARE\n");
-
- e_data.dof_downsample_sh = DRW_shader_create_fullscreen(datatoc_workbench_effect_dof_frag_glsl,
- "#define DOWNSAMPLE\n");
+ char *frag = BLI_string_joinN(datatoc_common_view_lib_glsl,
+ datatoc_workbench_effect_dof_frag_glsl);
+ e_data.dof_prepare_sh = DRW_shader_create_fullscreen(frag, "#define PREPARE\n");
+ e_data.dof_downsample_sh = DRW_shader_create_fullscreen(frag, "#define DOWNSAMPLE\n");
#if 0 /* TODO(fclem) finish COC min_max optimization */
- e_data.dof_flatten_v_sh = DRW_shader_create_fullscreen(datatoc_workbench_effect_dof_frag_glsl,
+ e_data.dof_flatten_v_sh = DRW_shader_create_fullscreen(frag,
"#define FLATTEN_VERTICAL\n");
-
- e_data.dof_flatten_h_sh = DRW_shader_create_fullscreen(datatoc_workbench_effect_dof_frag_glsl,
+ e_data.dof_flatten_h_sh = DRW_shader_create_fullscreen(frag,
"#define FLATTEN_HORIZONTAL\n");
-
- e_data.dof_dilate_v_sh = DRW_shader_create_fullscreen(datatoc_workbench_effect_dof_frag_glsl,
+ e_data.dof_dilate_v_sh = DRW_shader_create_fullscreen(frag,
"#define DILATE_VERTICAL\n");
-
- e_data.dof_dilate_h_sh = DRW_shader_create_fullscreen(datatoc_workbench_effect_dof_frag_glsl,
+ e_data.dof_dilate_h_sh = DRW_shader_create_fullscreen(frag,
"#define DILATE_HORIZONTAL\n");
#endif
- e_data.dof_blur1_sh = DRW_shader_create_fullscreen(datatoc_workbench_effect_dof_frag_glsl,
- "#define BLUR1\n");
-
- e_data.dof_blur2_sh = DRW_shader_create_fullscreen(datatoc_workbench_effect_dof_frag_glsl,
- "#define BLUR2\n");
-
- e_data.dof_resolve_sh = DRW_shader_create_fullscreen(datatoc_workbench_effect_dof_frag_glsl,
- "#define RESOLVE\n");
+ e_data.dof_blur1_sh = DRW_shader_create_fullscreen(frag, "#define BLUR1\n");
+ e_data.dof_blur2_sh = DRW_shader_create_fullscreen(frag, "#define BLUR2\n");
+ e_data.dof_resolve_sh = DRW_shader_create_fullscreen(frag, "#define RESOLVE\n");
+ MEM_freeN(frag);
}
*prepare_sh = e_data.dof_prepare_sh;
diff --git a/source/blender/draw/engines/workbench/workbench_transparent.c b/source/blender/draw/engines/workbench/workbench_transparent.c
index 39aa721a41c..5fd8229304a 100644
--- a/source/blender/draw/engines/workbench/workbench_transparent.c
+++ b/source/blender/draw/engines/workbench/workbench_transparent.c
@@ -67,7 +67,7 @@ void workbench_transparent_engine_init(WORKBENCH_Data *data)
static void workbench_transparent_lighting_uniforms(WORKBENCH_PrivateData *wpd,
DRWShadingGroup *grp)
{
- DRW_shgroup_uniform_block_persistent(grp, "world_block", wpd->world_ubo);
+ DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo);
DRW_shgroup_uniform_bool_copy(grp, "forceShadowing", false);
if (STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)) {
@@ -78,8 +78,8 @@ static void workbench_transparent_lighting_uniforms(WORKBENCH_PrivateData *wpd,
struct GPUTexture *spec_tx = wpd->studio_light->matcap_specular.gputexture;
const bool use_spec = workbench_is_specular_highlight_enabled(wpd);
spec_tx = (use_spec && spec_tx) ? spec_tx : diff_tx;
- DRW_shgroup_uniform_texture_persistent(grp, "matcapDiffuseImage", diff_tx);
- DRW_shgroup_uniform_texture_persistent(grp, "matcapSpecularImage", spec_tx);
+ DRW_shgroup_uniform_texture(grp, "matcapDiffuseImage", diff_tx);
+ DRW_shgroup_uniform_texture(grp, "matcapSpecularImage", spec_tx);
}
}
@@ -116,20 +116,20 @@ void workbench_transparent_cache_init(WORKBENCH_Data *data)
workbench_transparent_lighting_uniforms(wpd, grp);
wpd->prepass[transp][infront][hair].vcol_shgrp = grp = DRW_shgroup_create(sh, pass);
- DRW_shgroup_uniform_block_persistent(grp, "material_block", wpd->material_ubo_curr);
+ DRW_shgroup_uniform_block(grp, "material_block", wpd->material_ubo_curr);
DRW_shgroup_uniform_int_copy(grp, "materialIndex", 0); /* Default material. (uses vcol) */
sh = workbench_shader_transparent_image_get(wpd, hair, false);
wpd->prepass[transp][infront][hair].image_shgrp = grp = DRW_shgroup_create(sh, pass);
- DRW_shgroup_uniform_block_persistent(grp, "material_block", wpd->material_ubo_curr);
+ DRW_shgroup_uniform_block(grp, "material_block", wpd->material_ubo_curr);
DRW_shgroup_uniform_int_copy(grp, "materialIndex", 0); /* Default material. */
workbench_transparent_lighting_uniforms(wpd, grp);
sh = workbench_shader_transparent_image_get(wpd, hair, true);
wpd->prepass[transp][infront][hair].image_tiled_shgrp = grp = DRW_shgroup_create(sh, pass);
- DRW_shgroup_uniform_block_persistent(grp, "material_block", wpd->material_ubo_curr);
+ DRW_shgroup_uniform_block(grp, "material_block", wpd->material_ubo_curr);
DRW_shgroup_uniform_int_copy(grp, "materialIndex", 0); /* Default material. */
workbench_transparent_lighting_uniforms(wpd, grp);
}
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
index d3585b02b7d..b002f68e4d2 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -221,10 +221,7 @@ struct GPUShader *DRW_shader_create_with_transform_feedback(const char *vert,
const eGPUShaderTFBType prim_type,
const char **varying_names,
const int varying_count);
-struct GPUShader *DRW_shader_create_2d(const char *frag, const char *defines);
-struct GPUShader *DRW_shader_create_3d(const char *frag, const char *defines);
struct GPUShader *DRW_shader_create_fullscreen(const char *frag, const char *defines);
-struct GPUShader *DRW_shader_create_3d_depth_only(eGPUShaderConfig slot);
struct GPUMaterial *DRW_shader_find_from_world(struct World *wo,
const void *engine_type,
const int options,
@@ -235,6 +232,7 @@ struct GPUMaterial *DRW_shader_find_from_material(struct Material *ma,
bool deferred);
struct GPUMaterial *DRW_shader_create_from_world(struct Scene *scene,
struct World *wo,
+ struct bNodeTree *ntree,
const void *engine_type,
const int options,
const bool is_volume_shader,
@@ -245,6 +243,7 @@ struct GPUMaterial *DRW_shader_create_from_world(struct Scene *scene,
bool deferred);
struct GPUMaterial *DRW_shader_create_from_material(struct Scene *scene,
struct Material *ma,
+ struct bNodeTree *ntree,
const void *engine_type,
const int options,
const bool is_volume_shader,
@@ -376,6 +375,8 @@ DRWShadingGroup *DRW_shgroup_transform_feedback_create(struct GPUShader *shader,
DRWPass *pass,
struct GPUVertBuf *tf_target);
+void DRW_shgroup_add_material_resources(DRWShadingGroup *grp, struct GPUMaterial *material);
+
/* return final visibility */
typedef bool(DRWCallVisibilityFn)(bool vis_in, void *user_data);
@@ -471,18 +472,15 @@ void DRW_shgroup_clear_framebuffer(DRWShadingGroup *shgroup,
void DRW_shgroup_uniform_texture(DRWShadingGroup *shgroup,
const char *name,
const struct GPUTexture *tex);
-void DRW_shgroup_uniform_texture_persistent(DRWShadingGroup *shgroup,
- const char *name,
- const struct GPUTexture *tex);
-void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup,
- const char *name,
- const struct GPUUniformBuffer *ubo);
-void DRW_shgroup_uniform_block_persistent(DRWShadingGroup *shgroup,
- const char *name,
- const struct GPUUniformBuffer *ubo);
void DRW_shgroup_uniform_texture_ref(DRWShadingGroup *shgroup,
const char *name,
struct GPUTexture **tex);
+void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup,
+ const char *name,
+ const struct GPUUniformBuffer *ubo);
+void DRW_shgroup_uniform_block_ref(DRWShadingGroup *shgroup,
+ const char *name,
+ struct GPUUniformBuffer **ubo);
void DRW_shgroup_uniform_float(DRWShadingGroup *shgroup,
const char *name,
const float *value,
@@ -541,6 +539,8 @@ bool DRW_shgroup_is_empty(DRWShadingGroup *shgroup);
/* Passes */
DRWPass *DRW_pass_create(const char *name, DRWState state);
+DRWPass *DRW_pass_create_instance(const char *name, DRWPass *original, DRWState state);
+void DRW_pass_link(DRWPass *first, DRWPass *second);
/* TODO Replace with passes inheritance. */
void DRW_pass_state_set(DRWPass *pass, DRWState state);
void DRW_pass_state_add(DRWPass *pass, DRWState state);
@@ -554,6 +554,8 @@ void DRW_pass_sort_shgroup_reverse(DRWPass *pass);
bool DRW_pass_is_empty(DRWPass *pass);
#define DRW_PASS_CREATE(pass, state) (pass = DRW_pass_create(#pass, state))
+#define DRW_PASS_INSTANCE_CREATE(pass, original, state) \
+ (pass = DRW_pass_create_instance(#pass, (original), state))
/* Views */
DRWView *DRW_view_create(const float viewmat[4][4],
@@ -707,6 +709,8 @@ typedef struct DRWContextState {
struct Depsgraph *depsgraph;
+ struct TaskGraph *task_graph;
+
eObjectMode object_mode;
eGPUShaderConfig sh_cfg;
diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c
index 23d0d74534d..c23ea3d7c82 100644
--- a/source/blender/draw/intern/draw_cache.c
+++ b/source/blender/draw/intern/draw_cache.c
@@ -3534,13 +3534,15 @@ void drw_batch_cache_generate_requested(Object *ob)
struct Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob);
switch (ob->type) {
case OB_MESH:
- DRW_mesh_batch_cache_create_requested(ob, (Mesh *)ob->data, scene, is_paint_mode, use_hide);
+ DRW_mesh_batch_cache_create_requested(
+ DST.task_graph, ob, (Mesh *)ob->data, scene, is_paint_mode, use_hide);
break;
case OB_CURVE:
case OB_FONT:
case OB_SURF:
if (mesh_eval) {
- DRW_mesh_batch_cache_create_requested(ob, mesh_eval, scene, is_paint_mode, use_hide);
+ DRW_mesh_batch_cache_create_requested(
+ DST.task_graph, ob, mesh_eval, scene, is_paint_mode, use_hide);
}
DRW_curve_batch_cache_create_requested(ob);
break;
diff --git a/source/blender/draw/intern/draw_cache_extract.h b/source/blender/draw/intern/draw_cache_extract.h
index b2fea957227..f203c2ff1ea 100644
--- a/source/blender/draw/intern/draw_cache_extract.h
+++ b/source/blender/draw/intern/draw_cache_extract.h
@@ -23,6 +23,8 @@
#ifndef __DRAW_CACHE_EXTRACT_H__
#define __DRAW_CACHE_EXTRACT_H__
+struct TaskGraph;
+
/* Vertex Group Selection and display options */
typedef struct DRW_MeshWeightState {
int defgroup_active;
@@ -249,7 +251,8 @@ typedef struct MeshBatchCache {
bool no_loose_wire;
} MeshBatchCache;
-void mesh_buffer_cache_create_requested(MeshBatchCache *cache,
+void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph,
+ MeshBatchCache *cache,
MeshBufferCache mbc,
Mesh *me,
const bool is_editmode,
diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.c b/source/blender/draw/intern/draw_cache_extract_mesh.c
index cbb5f5f06ff..0fd6bf54856 100644
--- a/source/blender/draw/intern/draw_cache_extract_mesh.c
+++ b/source/blender/draw/intern/draw_cache_extract_mesh.c
@@ -134,15 +134,12 @@ typedef struct MeshRenderData {
float (*poly_normals)[3];
int *lverts, *ledges;
} MeshRenderData;
-
static MeshRenderData *mesh_render_data_create(Mesh *me,
const bool is_editmode,
const bool is_paint_mode,
const float obmat[4][4],
const bool do_final,
const bool do_uvedit,
- const eMRIterType iter_type,
- const eMRDataType data_flag,
const DRW_MeshCDMask *UNUSED(cd_used),
const ToolSettings *ts)
{
@@ -152,9 +149,6 @@ static MeshRenderData *mesh_render_data_create(Mesh *me,
copy_m4_m4(mr->obmat, obmat);
- const bool is_auto_smooth = (me->flag & ME_AUTOSMOOTH) != 0;
- const float split_angle = is_auto_smooth ? me->smoothresh : (float)M_PI;
-
if (is_editmode) {
BLI_assert(me->edit_mesh->mesh_eval_cage && me->edit_mesh->mesh_eval_final);
mr->bm = me->edit_mesh->bm;
@@ -244,7 +238,32 @@ static MeshRenderData *mesh_render_data_create(Mesh *me,
mr->v_origindex = CustomData_get_layer(&mr->me->vdata, CD_ORIGINDEX);
mr->e_origindex = CustomData_get_layer(&mr->me->edata, CD_ORIGINDEX);
mr->p_origindex = CustomData_get_layer(&mr->me->pdata, CD_ORIGINDEX);
+ }
+ else {
+ /* BMesh */
+ BMesh *bm = mr->bm;
+
+ mr->vert_len = bm->totvert;
+ mr->edge_len = bm->totedge;
+ mr->loop_len = bm->totloop;
+ mr->poly_len = bm->totface;
+ mr->tri_len = poly_to_tri_count(mr->poly_len, mr->loop_len);
+ }
+ return mr;
+}
+
+/* Part of the creation of the MeshRenderData that happens in a thread. */
+static void mesh_render_data_update(MeshRenderData *mr,
+ const eMRIterType iter_type,
+ const eMRDataType data_flag)
+{
+ Mesh *me = mr->me;
+ const bool is_auto_smooth = (me->flag & ME_AUTOSMOOTH) != 0;
+ const float split_angle = is_auto_smooth ? me->smoothresh : (float)M_PI;
+
+ if (mr->extract_type != MR_EXTRACT_BMESH) {
+ /* Mesh */
if (data_flag & (MR_DATA_POLY_NOR | MR_DATA_LOOP_NOR | MR_DATA_TAN_LOOP_NOR)) {
mr->poly_normals = MEM_mallocN(sizeof(*mr->poly_normals) * mr->poly_len, __func__);
BKE_mesh_calc_normals_poly((MVert *)mr->mvert,
@@ -323,13 +342,6 @@ static MeshRenderData *mesh_render_data_create(Mesh *me,
else {
/* BMesh */
BMesh *bm = mr->bm;
-
- mr->vert_len = bm->totvert;
- mr->edge_len = bm->totedge;
- mr->loop_len = bm->totloop;
- mr->poly_len = bm->totface;
- mr->tri_len = poly_to_tri_count(mr->poly_len, mr->loop_len);
-
if (data_flag & MR_DATA_POLY_NOR) {
/* Use bmface->no instead. */
}
@@ -394,7 +406,6 @@ static MeshRenderData *mesh_render_data_create(Mesh *me,
mr->loop_loose_len = mr->vert_loose_len + mr->edge_loose_len * 2;
}
}
- return mr;
}
static void mesh_render_data_free(MeshRenderData *mr)
@@ -742,46 +753,15 @@ static const MeshExtract extract_lines = {
0,
false,
};
-
/** \} */
/* ---------------------------------------------------------------------- */
-/** \name Extract Loose Edges Indices
+/** \name Extract Loose Edges Sub Buffer
* \{ */
-static void *extract_lines_loose_init(const MeshRenderData *UNUSED(mr), void *UNUSED(buf))
-{
- return NULL;
-}
-
-static void extract_lines_loose_ledge_mesh(const MeshRenderData *UNUSED(mr),
- int UNUSED(e),
- const MEdge *UNUSED(medge),
- void *UNUSED(elb))
-{
- /* This function is intentionally empty. The existence of this functions ensures that
- * `iter_type` `MR_ITER_LVERT` is set when initializing the `MeshRenderData` (See
- * `mesh_extract_iter_type`). This flag ensures that `mr->edge_loose_len` field is filled. This
- * field we use in the `extract_lines_loose_finish` function to create a subrange from the
- * `ibo.lines`. */
-}
-
-static void extract_lines_loose_ledge_bmesh(const MeshRenderData *UNUSED(mr),
- int UNUSED(e),
- BMEdge *UNUSED(eed),
- void *UNUSED(elb))
-{
- /* This function is intentionally empty. The existence of this functions ensures that
- * `iter_type` `MR_ITER_LVERT` is set when initializing the `MeshRenderData` (See
- * `mesh_extract_iter_type`). This flag ensures that `mr->edge_loose_len` field is filled. This
- * field we use in the `extract_lines_loose_finish` function to create a subrange from the
- * `ibo.lines`. */
-}
-
-static void extract_lines_loose_finish(const MeshRenderData *mr,
- void *UNUSED(ibo),
- void *UNUSED(elb))
+static void extract_lines_loose_subbuffer(const MeshRenderData *mr)
{
+ BLI_assert(mr->cache->final.ibo.lines);
/* Multiply by 2 because these are edges indices. */
const int start = mr->edge_len * 2;
const int len = mr->edge_loose_len * 2;
@@ -790,17 +770,24 @@ static void extract_lines_loose_finish(const MeshRenderData *mr,
mr->cache->no_loose_wire = (len == 0);
}
-static const MeshExtract extract_lines_loose = {
- extract_lines_loose_init,
- NULL,
- NULL,
+static void extract_lines_with_lines_loose_finish(const MeshRenderData *mr, void *ibo, void *elb)
+{
+ GPU_indexbuf_build_in_place(elb, ibo);
+ extract_lines_loose_subbuffer(mr);
+ MEM_freeN(elb);
+}
+
+static const MeshExtract extract_lines_with_lines_loose = {
+ extract_lines_init,
NULL,
NULL,
- extract_lines_loose_ledge_bmesh,
- extract_lines_loose_ledge_mesh,
+ extract_lines_loop_bmesh,
+ extract_lines_loop_mesh,
+ extract_lines_ledge_bmesh,
+ extract_lines_ledge_mesh,
NULL,
NULL,
- extract_lines_loose_finish,
+ extract_lines_with_lines_loose_finish,
0,
false,
};
@@ -1716,8 +1703,8 @@ static void extract_lnor_hq_loop_mesh(
}
/* Flag for paint mode overlay.
- * Only use MR_EXTRACT_MAPPED in edit mode where it is used to display the edge-normals. In paint
- * mode it will use the unmapped data to draw the wireframe. */
+ * Only use MR_EXTRACT_MAPPED in edit mode where it is used to display the edge-normals. In
+ * paint mode it will use the unmapped data to draw the wireframe. */
if (mpoly->flag & ME_HIDE ||
(mr->edit_bmesh && mr->extract_type == MR_EXTRACT_MAPPED && (mr->v_origindex) &&
mr->v_origindex[mloop->v] == ORIGINDEX_NONE)) {
@@ -1795,8 +1782,8 @@ static void extract_lnor_loop_mesh(
}
/* Flag for paint mode overlay.
- * Only use MR_EXTRACT_MAPPED in edit mode where it is used to display the edge-normals. In paint
- * mode it will use the unmapped data to draw the wireframe. */
+ * Only use MR_EXTRACT_MAPPED in edit mode where it is used to display the edge-normals. In
+ * paint mode it will use the unmapped data to draw the wireframe. */
if (mpoly->flag & ME_HIDE ||
(mr->edit_bmesh && mr->extract_type == MR_EXTRACT_MAPPED && (mr->v_origindex) &&
mr->v_origindex[mloop->v] == ORIGINDEX_NONE)) {
@@ -2162,10 +2149,10 @@ static void *extract_vcol_init(const MeshRenderData *mr, void *buf)
GPUVertFormat format = {0};
GPU_vertformat_deinterleave(&format);
- CustomData *cd_ldata = &mr->me->ldata;
+ CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata;
uint32_t vcol_layers = mr->cache->cd_used.vcol;
- for (int i = 0; i < 8; i++) {
+ for (int i = 0; i < MAX_MCOL; i++) {
if (vcol_layers & (1 << i)) {
char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
const char *layer_name = CustomData_get_layer_name(cd_ldata, CD_MLOOPCOL, i);
@@ -2197,14 +2184,32 @@ static void *extract_vcol_init(const MeshRenderData *mr, void *buf)
} gpuMeshVcol;
gpuMeshVcol *vcol_data = (gpuMeshVcol *)vbo->data;
- for (int i = 0; i < 8; i++) {
+ for (int i = 0; i < MAX_MCOL; i++) {
if (vcol_layers & (1 << i)) {
- MLoopCol *mcol = (MLoopCol *)CustomData_get_layer_n(cd_ldata, CD_MLOOPCOL, i);
- for (int l = 0; l < mr->loop_len; l++, mcol++, vcol_data++) {
- vcol_data->r = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol->r]);
- vcol_data->g = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol->g]);
- vcol_data->b = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol->b]);
- vcol_data->a = unit_float_to_ushort_clamp(mcol->a * (1.0f / 255.0f));
+ if (mr->extract_type == MR_EXTRACT_BMESH) {
+ int cd_ofs = CustomData_get_n_offset(cd_ldata, CD_MLOOPCOL, i);
+ BMIter f_iter, l_iter;
+ BMFace *efa;
+ BMLoop *loop;
+ BM_ITER_MESH (efa, &f_iter, mr->bm, BM_FACES_OF_MESH) {
+ BM_ITER_ELEM (loop, &l_iter, efa, BM_LOOPS_OF_FACE) {
+ const MLoopCol *mloopcol = BM_ELEM_CD_GET_VOID_P(loop, cd_ofs);
+ vcol_data->r = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->r]);
+ vcol_data->g = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->g]);
+ vcol_data->b = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->b]);
+ vcol_data->a = unit_float_to_ushort_clamp(mloopcol->a * (1.0f / 255.0f));
+ vcol_data++;
+ }
+ }
+ }
+ else {
+ const MLoopCol *mloopcol = (MLoopCol *)CustomData_get_layer_n(cd_ldata, CD_MLOOPCOL, i);
+ for (int l = 0; l < mr->loop_len; l++, mloopcol++, vcol_data++) {
+ vcol_data->r = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->r]);
+ vcol_data->g = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->g]);
+ vcol_data->b = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->b]);
+ vcol_data->a = unit_float_to_ushort_clamp(mloopcol->a * (1.0f / 255.0f));
+ }
}
}
}
@@ -4522,10 +4527,14 @@ static const MeshExtract extract_fdot_idx = {
/** \} */
/* ---------------------------------------------------------------------- */
-/** \name Extract Loop
+/** \name ExtractTaskData
* \{ */
+typedef struct ExtractUserData {
+ void *user_data;
+} ExtractUserData;
typedef struct ExtractTaskData {
+ void *next, *prev;
const MeshRenderData *mr;
const MeshExtract *extract;
eMRIterType iter_type;
@@ -4533,9 +4542,16 @@ typedef struct ExtractTaskData {
/** Decremented each time a task is finished. */
int32_t *task_counter;
void *buf;
- void *user_data;
+ ExtractUserData *user_data;
} ExtractTaskData;
+static void extract_task_data_free(void *data)
+{
+ ExtractTaskData *task_data = data;
+ MEM_SAFE_FREE(task_data->user_data);
+ MEM_freeN(task_data);
+}
+
BLI_INLINE void mesh_extract_iter(const MeshRenderData *mr,
const eMRIterType iter_type,
int start,
@@ -4612,31 +4628,184 @@ BLI_INLINE void mesh_extract_iter(const MeshRenderData *mr,
}
}
-static void extract_run(TaskPool *__restrict UNUSED(pool), void *taskdata)
+static void extract_init(ExtractTaskData *data)
{
- ExtractTaskData *data = taskdata;
- mesh_extract_iter(
- data->mr, data->iter_type, data->start, data->end, data->extract, data->user_data);
+ data->user_data->user_data = data->extract->init(data->mr, data->buf);
+}
+
+static void extract_run(void *__restrict taskdata)
+{
+ ExtractTaskData *data = (ExtractTaskData *)taskdata;
+ mesh_extract_iter(data->mr,
+ data->iter_type,
+ data->start,
+ data->end,
+ data->extract,
+ data->user_data->user_data);
/* If this is the last task, we do the finish function. */
int remainin_tasks = atomic_sub_and_fetch_int32(data->task_counter, 1);
if (remainin_tasks == 0 && data->extract->finish != NULL) {
- data->extract->finish(data->mr, data->buf, data->user_data);
+ data->extract->finish(data->mr, data->buf, data->user_data->user_data);
+ }
+}
+
+static void extract_init_and_run(void *__restrict taskdata)
+{
+ extract_init((ExtractTaskData *)taskdata);
+ extract_run(taskdata);
+}
+
+/** \} */
+
+/* ---------------------------------------------------------------------- */
+/** \name Task Node - Update Mesh Render Data
+ * \{ */
+typedef struct MeshRenderDataUpdateTaskData {
+ MeshRenderData *mr;
+ eMRIterType iter_type;
+ eMRDataType data_flag;
+} MeshRenderDataUpdateTaskData;
+
+static void mesh_render_data_update_task_data_free(MeshRenderDataUpdateTaskData *taskdata)
+{
+ BLI_assert(taskdata);
+ mesh_render_data_free(taskdata->mr);
+ MEM_freeN(taskdata);
+}
+
+static void mesh_extract_render_data_node_exec(void *__restrict task_data)
+{
+ MeshRenderDataUpdateTaskData *update_task_data = task_data;
+ mesh_render_data_update(
+ update_task_data->mr, update_task_data->iter_type, update_task_data->data_flag);
+}
+
+static struct TaskNode *mesh_extract_render_data_node_create(struct TaskGraph *task_graph,
+ MeshRenderData *mr,
+ const eMRIterType iter_type,
+ const eMRDataType data_flag)
+{
+ MeshRenderDataUpdateTaskData *task_data = MEM_mallocN(sizeof(MeshRenderDataUpdateTaskData),
+ __func__);
+ task_data->mr = mr;
+ task_data->iter_type = iter_type;
+ task_data->data_flag = data_flag;
+
+ struct TaskNode *task_node = BLI_task_graph_node_create(
+ task_graph,
+ mesh_extract_render_data_node_exec,
+ task_data,
+ (TaskGraphNodeFreeFunction)mesh_render_data_update_task_data_free);
+ return task_node;
+}
+
+/** \} */
+
+/* ---------------------------------------------------------------------- */
+/** \name Task Node - Extract Single Threaded
+ * \{ */
+typedef struct ExtractSingleThreadedTaskData {
+ ListBase task_datas;
+} ExtractSingleThreadedTaskData;
+
+static void extract_single_threaded_task_data_free(ExtractSingleThreadedTaskData *taskdata)
+{
+ BLI_assert(taskdata);
+ LISTBASE_FOREACH_MUTABLE (ExtractTaskData *, td, &taskdata->task_datas) {
+ extract_task_data_free(td);
+ }
+ BLI_listbase_clear(&taskdata->task_datas);
+ MEM_freeN(taskdata);
+}
+
+static void extract_single_threaded_task_node_exec(void *__restrict task_data)
+{
+ ExtractSingleThreadedTaskData *extract_task_data = task_data;
+ LISTBASE_FOREACH (ExtractTaskData *, td, &extract_task_data->task_datas) {
+ extract_init_and_run(td);
+ }
+}
+
+static struct TaskNode *extract_single_threaded_task_node_create(
+ struct TaskGraph *task_graph, ExtractSingleThreadedTaskData *task_data)
+{
+ struct TaskNode *task_node = BLI_task_graph_node_create(
+ task_graph,
+ extract_single_threaded_task_node_exec,
+ task_data,
+ (TaskGraphNodeFreeFunction)extract_single_threaded_task_data_free);
+ return task_node;
+}
+
+/** \} */
+
+/* ---------------------------------------------------------------------- */
+/** \name Task Node - UserData Initializer
+ * \{ */
+typedef struct UserDataInitTaskData {
+ ListBase task_datas;
+ int32_t *task_counters;
+
+} UserDataInitTaskData;
+
+static void user_data_init_task_data_free(UserDataInitTaskData *taskdata)
+{
+ BLI_assert(taskdata);
+ LISTBASE_FOREACH_MUTABLE (ExtractTaskData *, td, &taskdata->task_datas) {
+ extract_task_data_free(td);
+ }
+ BLI_listbase_clear(&taskdata->task_datas);
+ MEM_SAFE_FREE(taskdata->task_counters);
+ MEM_freeN(taskdata);
+}
+
+static void user_data_init_task_data_exec(void *__restrict task_data)
+{
+ UserDataInitTaskData *extract_task_data = task_data;
+ LISTBASE_FOREACH (ExtractTaskData *, td, &extract_task_data->task_datas) {
+ extract_init(td);
}
}
-static void extract_range_task_create(
- TaskPool *task_pool, ExtractTaskData *taskdata, const eMRIterType type, int start, int length)
+static struct TaskNode *user_data_init_task_node_create(struct TaskGraph *task_graph,
+ UserDataInitTaskData *task_data)
+{
+ struct TaskNode *task_node = BLI_task_graph_node_create(
+ task_graph,
+ user_data_init_task_data_exec,
+ task_data,
+ (TaskGraphNodeFreeFunction)user_data_init_task_data_free);
+ return task_node;
+}
+
+/** \} */
+/* ---------------------------------------------------------------------- */
+/** \name Extract Loop
+ * \{ */
+
+static void extract_range_task_create(struct TaskGraph *task_graph,
+ struct TaskNode *task_node_user_data_init,
+ ExtractTaskData *taskdata,
+ const eMRIterType type,
+ int start,
+ int length)
{
taskdata = MEM_dupallocN(taskdata);
atomic_add_and_fetch_int32(taskdata->task_counter, 1);
taskdata->iter_type = type;
taskdata->start = start;
taskdata->end = start + length;
- BLI_task_pool_push(task_pool, extract_run, taskdata, true, NULL);
+ struct TaskNode *task_node = BLI_task_graph_node_create(
+ task_graph, extract_run, taskdata, MEM_freeN);
+ BLI_task_graph_edge_create(task_node_user_data_init, task_node);
}
-static void extract_task_create(TaskPool *task_pool,
+static void extract_task_create(struct TaskGraph *task_graph,
+ struct TaskNode *task_node_mesh_render_data,
+ struct TaskNode *task_node_user_data_init,
+ ListBase *single_threaded_task_datas,
+ ListBase *user_data_init_task_datas,
const Scene *scene,
const MeshRenderData *mr,
const MeshExtract *extract,
@@ -4654,58 +4823,75 @@ static void extract_task_create(TaskPool *task_pool,
/* Divide extraction of the VBO/IBO into sensible chunks of works. */
ExtractTaskData *taskdata = MEM_mallocN(sizeof(*taskdata), "ExtractTaskData");
+ taskdata->next = NULL;
+ taskdata->prev = NULL;
taskdata->mr = mr;
taskdata->extract = extract;
taskdata->buf = buf;
- taskdata->user_data = extract->init(mr, buf);
+
+ /* ExtractUserData is shared between the iterations as it holds counters to detect if the
+ * extraction is finished. To make sure the duplication of the userdata does not create a new
+ * instance of the counters we allocate the userdata in its own container.
+ *
+ * This structure makes sure that when extract_init is called, that the user data of all
+ * iterations are updated. */
+ taskdata->user_data = MEM_callocN(sizeof(ExtractUserData), __func__);
taskdata->iter_type = mesh_extract_iter_type(extract);
taskdata->task_counter = task_counter;
taskdata->start = 0;
taskdata->end = INT_MAX;
/* Simple heuristic. */
- const bool use_thread = (mr->loop_len + mr->loop_loose_len) > 8192;
+ const int chunk_size = 8192;
+ const bool use_thread = (mr->loop_len + mr->loop_loose_len) > chunk_size;
if (use_thread && extract->use_threading) {
+
/* Divide task into sensible chunks. */
- const int chunk_size = 8192;
if (taskdata->iter_type & MR_ITER_LOOPTRI) {
for (int i = 0; i < mr->tri_len; i += chunk_size) {
- extract_range_task_create(task_pool, taskdata, MR_ITER_LOOPTRI, i, chunk_size);
+ extract_range_task_create(
+ task_graph, task_node_user_data_init, taskdata, MR_ITER_LOOPTRI, i, chunk_size);
}
}
if (taskdata->iter_type & MR_ITER_LOOP) {
for (int i = 0; i < mr->poly_len; i += chunk_size) {
- extract_range_task_create(task_pool, taskdata, MR_ITER_LOOP, i, chunk_size);
+ extract_range_task_create(
+ task_graph, task_node_user_data_init, taskdata, MR_ITER_LOOP, i, chunk_size);
}
}
if (taskdata->iter_type & MR_ITER_LEDGE) {
for (int i = 0; i < mr->edge_loose_len; i += chunk_size) {
- extract_range_task_create(task_pool, taskdata, MR_ITER_LEDGE, i, chunk_size);
+ extract_range_task_create(
+ task_graph, task_node_user_data_init, taskdata, MR_ITER_LEDGE, i, chunk_size);
}
}
if (taskdata->iter_type & MR_ITER_LVERT) {
for (int i = 0; i < mr->vert_loose_len; i += chunk_size) {
- extract_range_task_create(task_pool, taskdata, MR_ITER_LVERT, i, chunk_size);
+ extract_range_task_create(
+ task_graph, task_node_user_data_init, taskdata, MR_ITER_LVERT, i, chunk_size);
}
}
- MEM_freeN(taskdata);
+ BLI_addtail(user_data_init_task_datas, taskdata);
}
else if (use_thread) {
/* One task for the whole VBO. */
(*task_counter)++;
- BLI_task_pool_push(task_pool, extract_run, taskdata, true, NULL);
+ struct TaskNode *one_task = BLI_task_graph_node_create(
+ task_graph, extract_init_and_run, taskdata, extract_task_data_free);
+ BLI_task_graph_edge_create(task_node_mesh_render_data, one_task);
}
else {
/* Single threaded extraction. */
(*task_counter)++;
- extract_run(NULL, taskdata);
- MEM_freeN(taskdata);
+ BLI_addtail(single_threaded_task_datas, taskdata);
}
}
-void mesh_buffer_cache_create_requested(MeshBatchCache *cache,
+void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph,
+ MeshBatchCache *cache,
MeshBufferCache mbc,
Mesh *me,
+
const bool is_editmode,
const bool is_paint_mode,
const float obmat[4][4],
@@ -4717,9 +4903,41 @@ void mesh_buffer_cache_create_requested(MeshBatchCache *cache,
const ToolSettings *ts,
const bool use_hide)
{
+ /* For each mesh where batches needs to be updated a sub-graph will be added to the task_graph.
+ * This sub-graph starts with an extract_render_data_node. This fills/converts the required data
+ * from Mesh.
+ *
+ * Small extractions and extractions that can't be multi-threaded are grouped in a single
+ * `extract_single_threaded_task_node`.
+ *
+ * Other extractions will create a node for each loop exceeding 8192 items. these nodes are
+ * linked to the `user_data_init_task_node`. the `user_data_init_task_node` prepares the userdata
+ * needed for the extraction based on the data extracted from the mesh. counters are used to
+ * check if the finalize of a task has to be called.
+ *
+ * Mesh extraction sub graph
+ *
+ * +----------------------+
+ * +-----> | extract_task1_loop_1 |
+ * | +----------------------+
+ * +------------------+ +----------------------+ +----------------------+
+ * | mesh_render_data | --> | | --> | extract_task1_loop_2 |
+ * +------------------+ | | +----------------------+
+ * | | | +----------------------+
+ * | | user_data_init | --> | extract_task2_loop_1 |
+ * v | | +----------------------+
+ * +------------------+ | | +----------------------+
+ * | single_threaded | | | --> | extract_task2_loop_2 |
+ * +------------------+ +----------------------+ +----------------------+
+ * | +----------------------+
+ * +-----> | extract_task2_loop_3 |
+ * +----------------------+
+ */
eMRIterType iter_flag = 0;
eMRDataType data_flag = 0;
+ const bool do_lines_loose_subbuffer = mbc.ibo.lines_loose != NULL;
+
#define TEST_ASSIGN(type, type_lowercase, name) \
do { \
if (DRW_TEST_ASSIGN_##type(mbc.type_lowercase.name)) { \
@@ -4757,7 +4975,6 @@ void mesh_buffer_cache_create_requested(MeshBatchCache *cache,
TEST_ASSIGN(IBO, ibo, fdots);
TEST_ASSIGN(IBO, ibo, lines_paint_mask);
TEST_ASSIGN(IBO, ibo, lines_adjacency);
- TEST_ASSIGN(IBO, ibo, lines_loose);
TEST_ASSIGN(IBO, ibo, edituv_tris);
TEST_ASSIGN(IBO, ibo, edituv_lines);
TEST_ASSIGN(IBO, ibo, edituv_points);
@@ -4769,16 +4986,8 @@ void mesh_buffer_cache_create_requested(MeshBatchCache *cache,
double rdata_start = PIL_check_seconds_timer();
#endif
- MeshRenderData *mr = mesh_render_data_create(me,
- is_editmode,
- is_paint_mode,
- obmat,
- do_final,
- do_uvedit,
- iter_flag,
- data_flag,
- cd_layer_used,
- ts);
+ MeshRenderData *mr = mesh_render_data_create(
+ me, is_editmode, is_paint_mode, obmat, do_final, do_uvedit, cd_layer_used, ts);
mr->cache = cache; /* HACK */
mr->use_hide = use_hide;
mr->use_subsurf_fdots = use_subsurf_fdots;
@@ -4788,20 +4997,32 @@ void mesh_buffer_cache_create_requested(MeshBatchCache *cache,
double rdata_end = PIL_check_seconds_timer();
#endif
- TaskPool *task_pool;
-
- /* Create a suspended pool as the finalize method could be called too early.
- * See `extract_run`. */
- task_pool = BLI_task_pool_create_suspended(NULL, TASK_PRIORITY_HIGH);
-
size_t counters_size = (sizeof(mbc) / sizeof(void *)) * sizeof(int32_t);
int32_t *task_counters = MEM_callocN(counters_size, __func__);
int counter_used = 0;
+ struct TaskNode *task_node_mesh_render_data = mesh_extract_render_data_node_create(
+ task_graph, mr, iter_flag, data_flag);
+ ExtractSingleThreadedTaskData *single_threaded_task_data = MEM_callocN(
+ sizeof(ExtractSingleThreadedTaskData), __func__);
+ UserDataInitTaskData *user_data_init_task_data = MEM_callocN(sizeof(UserDataInitTaskData),
+ __func__);
+ user_data_init_task_data->task_counters = task_counters;
+ struct TaskNode *task_node_user_data_init = user_data_init_task_node_create(
+ task_graph, user_data_init_task_data);
+
#define EXTRACT(buf, name) \
if (mbc.buf.name) { \
- extract_task_create( \
- task_pool, scene, mr, &extract_##name, mbc.buf.name, &task_counters[counter_used++]); \
+ extract_task_create(task_graph, \
+ task_node_mesh_render_data, \
+ task_node_user_data_init, \
+ &single_threaded_task_data->task_datas, \
+ &user_data_init_task_data->task_datas, \
+ scene, \
+ mr, \
+ &extract_##name, \
+ mbc.buf.name, \
+ &task_counters[counter_used++]); \
} \
((void)0)
@@ -4829,7 +5050,33 @@ void mesh_buffer_cache_create_requested(MeshBatchCache *cache,
EXTRACT(vbo, skin_roots);
EXTRACT(ibo, tris);
- EXTRACT(ibo, lines);
+ if (mbc.ibo.lines) {
+ /* When `lines` and `lines_loose` are requested, schedule lines extraction that also creates
+ * the `lines_loose` sub-buffer. */
+ const MeshExtract *lines_extractor = do_lines_loose_subbuffer ?
+ &extract_lines_with_lines_loose :
+ &extract_lines;
+ extract_task_create(task_graph,
+ task_node_mesh_render_data,
+ task_node_user_data_init,
+ &single_threaded_task_data->task_datas,
+ &user_data_init_task_data->task_datas,
+ scene,
+ mr,
+ lines_extractor,
+ mbc.ibo.lines,
+ &task_counters[counter_used++]);
+ }
+ else {
+ if (do_lines_loose_subbuffer) {
+ /* When `lines_loose` is requested without `lines` we can create the sub-buffer on the fly as
+ * the `lines` buffer should then already be up-to-date.
+ * (see `DRW_batch_requested(cache->batch.loose_edges, GPU_PRIM_LINES)` in
+ * `DRW_mesh_batch_cache_create_requested`).
+ */
+ extract_lines_loose_subbuffer(mr);
+ }
+ }
EXTRACT(ibo, points);
EXTRACT(ibo, fdots);
EXTRACT(ibo, lines_paint_mask);
@@ -4839,27 +5086,29 @@ void mesh_buffer_cache_create_requested(MeshBatchCache *cache,
EXTRACT(ibo, edituv_points);
EXTRACT(ibo, edituv_fdots);
- /* TODO(fclem) Ideally, we should have one global pool for all
- * objects and wait for finish only before drawing when buffers
- * need to be ready. */
- BLI_task_pool_work_and_wait(task_pool);
-
- /* The next task(s) rely on the result of the tasks above. */
+ /* Only create the edge when there are user datas that needs to be inited.
+ * The task is still part of the graph so the task_data will be freed when the graph is freed.
+ */
+ if (!BLI_listbase_is_empty(&user_data_init_task_data->task_datas)) {
+ BLI_task_graph_edge_create(task_node_mesh_render_data, task_node_user_data_init);
+ }
- /* The `lines_loose` is a sub buffer from `ibo.lines`.
- * We schedule it here due to potential synchronization issues.*/
- EXTRACT(ibo, lines_loose);
+ if (!BLI_listbase_is_empty(&single_threaded_task_data->task_datas)) {
+ struct TaskNode *task_node = extract_single_threaded_task_node_create(
+ task_graph, single_threaded_task_data);
+ BLI_task_graph_edge_create(task_node_mesh_render_data, task_node);
+ }
+ else {
+ extract_single_threaded_task_data_free(single_threaded_task_data);
+ }
- BLI_task_pool_work_and_wait(task_pool);
+ /* Trigger the sub-graph for this mesh. */
+ BLI_task_graph_node_push_work(task_node_mesh_render_data);
#undef EXTRACT
- BLI_task_pool_free(task_pool);
- MEM_freeN(task_counters);
-
- mesh_render_data_free(mr);
-
#ifdef DEBUG_TIME
+ BLI_task_graph_work_and_wait(task_graph);
double end = PIL_check_seconds_timer();
static double avg = 0;
diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h
index daa46252331..80649143537 100644
--- a/source/blender/draw/intern/draw_cache_impl.h
+++ b/source/blender/draw/intern/draw_cache_impl.h
@@ -31,6 +31,7 @@ struct ListBase;
struct ModifierData;
struct PTCacheEdit;
struct ParticleSystem;
+struct TaskGraph;
struct Curve;
struct Hair;
@@ -150,7 +151,8 @@ int DRW_volume_material_count_get(struct Volume *volume);
struct GPUBatch *DRW_volume_batch_cache_get_wireframes_face(struct Volume *volume);
/* Mesh */
-void DRW_mesh_batch_cache_create_requested(struct Object *ob,
+void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph,
+ struct Object *ob,
struct Mesh *me,
const struct Scene *scene,
const bool is_paint_mode,
diff --git a/source/blender/draw/intern/draw_cache_impl_gpencil.c b/source/blender/draw/intern/draw_cache_impl_gpencil.c
index ee148e0934d..b4974330043 100644
--- a/source/blender/draw/intern/draw_cache_impl_gpencil.c
+++ b/source/blender/draw/intern/draw_cache_impl_gpencil.c
@@ -102,6 +102,7 @@ static GpencilBatchCache *gpencil_batch_cache_init(Object *ob, int cfra)
cache->is_dirty = true;
cache->cache_frame = cfra;
+
return cache;
}
@@ -385,7 +386,8 @@ static void gpencil_batches_ensure(Object *ob, GpencilBatchCache *cache, int cfr
.vert_len = 1, /* Start at 1 for the gl_InstanceID trick to work (see vert shader). */
.tri_len = 0,
};
- BKE_gpencil_visible_stroke_iter(ob, NULL, gp_object_verts_count_cb, &iter, do_onion, cfra);
+ BKE_gpencil_visible_stroke_iter(
+ NULL, ob, NULL, gp_object_verts_count_cb, &iter, do_onion, cfra);
/* Create VBOs. */
GPUVertFormat *format = gpencil_stroke_format();
@@ -401,7 +403,7 @@ static void gpencil_batches_ensure(Object *ob, GpencilBatchCache *cache, int cfr
GPU_indexbuf_init(&iter.ibo, GPU_PRIM_TRIS, iter.tri_len, iter.vert_len);
/* Fill buffers with data. */
- BKE_gpencil_visible_stroke_iter(ob, NULL, gpencil_stroke_iter_cb, &iter, do_onion, cfra);
+ BKE_gpencil_visible_stroke_iter(NULL, ob, NULL, gpencil_stroke_iter_cb, &iter, do_onion, cfra);
/* Mark last 2 verts as invalid. */
for (int i = 0; i < 2; i++) {
@@ -475,7 +477,7 @@ GPUBatch *DRW_cache_gpencil_face_wireframe_get(Object *ob)
/* IMPORTANT: Keep in sync with gpencil_edit_batches_ensure() */
bool do_onion = true;
- BKE_gpencil_visible_stroke_iter(ob, NULL, gp_lines_indices_cb, &iter, do_onion, cfra);
+ BKE_gpencil_visible_stroke_iter(NULL, ob, NULL, gp_lines_indices_cb, &iter, do_onion, cfra);
GPUIndexBuf *ibo = GPU_indexbuf_build(&iter.ibo);
@@ -724,7 +726,8 @@ static void gpencil_edit_batches_ensure(Object *ob, GpencilBatchCache *cache, in
iter.verts = (gpEditVert *)cache->edit_vbo->data;
/* Fill buffers with data. */
- BKE_gpencil_visible_stroke_iter(ob, NULL, gpencil_edit_stroke_iter_cb, &iter, do_onion, cfra);
+ BKE_gpencil_visible_stroke_iter(
+ NULL, ob, NULL, gpencil_edit_stroke_iter_cb, &iter, do_onion, cfra);
/* Create the batches */
cache->edit_points_batch = GPU_batch_create(GPU_PRIM_POINTS, cache->vbo, NULL);
diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c
index 237c7bddfad..99e285a18f1 100644
--- a/source/blender/draw/intern/draw_cache_impl_mesh.c
+++ b/source/blender/draw/intern/draw_cache_impl_mesh.c
@@ -33,6 +33,7 @@
#include "BLI_math_bits.h"
#include "BLI_math_vector.h"
#include "BLI_string.h"
+#include "BLI_task.h"
#include "BLI_utildefines.h"
#include "DNA_mesh_types.h"
@@ -1019,9 +1020,14 @@ void DRW_mesh_batch_cache_free_old(Mesh *me, int ctime)
}
/* Can be called for any surface type. Mesh *me is the final mesh. */
-void DRW_mesh_batch_cache_create_requested(
- Object *ob, Mesh *me, const Scene *scene, const bool is_paint_mode, const bool use_hide)
-{
+void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph,
+ Object *ob,
+ Mesh *me,
+ const Scene *scene,
+ const bool is_paint_mode,
+ const bool use_hide)
+{
+ BLI_assert(task_graph);
GPUIndexBuf **saved_elem_ranges = NULL;
const ToolSettings *ts = NULL;
if (scene) {
@@ -1378,7 +1384,8 @@ void DRW_mesh_batch_cache_create_requested(
false;
if (do_uvcage) {
- mesh_buffer_cache_create_requested(cache,
+ mesh_buffer_cache_create_requested(task_graph,
+ cache,
cache->uv_cage,
me,
is_editmode,
@@ -1394,7 +1401,8 @@ void DRW_mesh_batch_cache_create_requested(
}
if (do_cage) {
- mesh_buffer_cache_create_requested(cache,
+ mesh_buffer_cache_create_requested(task_graph,
+ cache,
cache->cage,
me,
is_editmode,
@@ -1409,7 +1417,8 @@ void DRW_mesh_batch_cache_create_requested(
true);
}
- mesh_buffer_cache_create_requested(cache,
+ mesh_buffer_cache_create_requested(task_graph,
+ cache,
cache->final,
me,
is_editmode,
@@ -1422,10 +1431,12 @@ void DRW_mesh_batch_cache_create_requested(
scene,
ts,
use_hide);
-
#ifdef DEBUG
check:
/* Make sure all requested batches have been setup. */
+ /* TODO(jbakker): we should move this to the draw_manager but that needs refactoring and
+ * additional looping.*/
+ BLI_task_graph_work_and_wait(task_graph);
for (int i = 0; i < sizeof(cache->batch) / sizeof(void *); i++) {
BLI_assert(!DRW_batch_requested(((GPUBatch **)&cache->batch)[i], 0));
}
diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h
index f14cdc0dbde..656d72b2808 100644
--- a/source/blender/draw/intern/draw_common.h
+++ b/source/blender/draw/intern/draw_common.h
@@ -172,23 +172,11 @@ bool DRW_object_axis_orthogonal_to_view(Object *ob, int axis);
/* This creates a shading group with display hairs.
* The draw call is already added by this function, just add additional uniforms. */
-struct DRWShadingGroup *DRW_shgroup_hair_create(struct Object *object,
- struct ParticleSystem *psys,
- struct ModifierData *md,
- struct DRWPass *hair_pass,
- struct GPUShader *shader);
-
struct DRWShadingGroup *DRW_shgroup_hair_create_sub(struct Object *object,
struct ParticleSystem *psys,
struct ModifierData *md,
struct DRWShadingGroup *shgrp);
-struct DRWShadingGroup *DRW_shgroup_material_hair_create(struct Object *object,
- struct ParticleSystem *psys,
- struct ModifierData *md,
- struct DRWPass *hair_pass,
- struct GPUMaterial *material);
-
void DRW_hair_init(void);
void DRW_hair_update(void);
void DRW_hair_free(void);
diff --git a/source/blender/draw/intern/draw_hair.c b/source/blender/draw/intern/draw_hair.c
index 27de7cc1c7c..2fdaf0d5345 100644
--- a/source/blender/draw/intern/draw_hair.c
+++ b/source/blender/draw/intern/draw_hair.c
@@ -124,13 +124,10 @@ void DRW_hair_init(void)
}
}
-static DRWShadingGroup *drw_shgroup_create_hair_procedural_ex(Object *object,
- ParticleSystem *psys,
- ModifierData *md,
- DRWPass *hair_pass,
- DRWShadingGroup *shgrp_parent,
- struct GPUMaterial *gpu_mat,
- GPUShader *gpu_shader)
+DRWShadingGroup *DRW_shgroup_hair_create_sub(Object *object,
+ ParticleSystem *psys,
+ ModifierData *md,
+ DRWShadingGroup *shgrp_parent)
{
/* TODO(fclem): Pass the scene as parameter */
const DRWContextState *draw_ctx = DRW_context_state_get();
@@ -154,24 +151,7 @@ static DRWShadingGroup *drw_shgroup_create_hair_procedural_ex(Object *object,
need_ft_update = hair_ensure_procedural_data(object, &hair_cache, subdiv, thickness_res);
}
- DRWShadingGroup *shgrp;
- if (shgrp_parent) {
- shgrp = DRW_shgroup_create_sub(shgrp_parent);
- }
- else if (gpu_mat) {
- shgrp = DRW_shgroup_material_create(gpu_mat, hair_pass);
- }
- else if (gpu_shader) {
- shgrp = DRW_shgroup_create(gpu_shader, hair_pass);
- }
- else {
- shgrp = NULL;
- BLI_assert(0);
- }
-
- if (shgrp == NULL) {
- return NULL;
- }
+ DRWShadingGroup *shgrp = DRW_shgroup_create_sub(shgrp_parent);
/* TODO optimize this. Only bind the ones GPUMaterial needs. */
for (int i = 0; i < hair_cache->num_uv_layers; i++) {
@@ -284,29 +264,6 @@ static DRWShadingGroup *drw_shgroup_create_hair_procedural_ex(Object *object,
return shgrp;
}
-DRWShadingGroup *DRW_shgroup_hair_create(
- Object *object, ParticleSystem *psys, ModifierData *md, DRWPass *hair_pass, GPUShader *shader)
-{
- return drw_shgroup_create_hair_procedural_ex(object, psys, md, hair_pass, NULL, NULL, shader);
-}
-
-DRWShadingGroup *DRW_shgroup_hair_create_sub(Object *object,
- ParticleSystem *psys,
- ModifierData *md,
- DRWShadingGroup *shgrp)
-{
- return drw_shgroup_create_hair_procedural_ex(object, psys, md, NULL, shgrp, NULL, NULL);
-}
-
-DRWShadingGroup *DRW_shgroup_material_hair_create(Object *object,
- ParticleSystem *psys,
- ModifierData *md,
- DRWPass *hair_pass,
- struct GPUMaterial *material)
-{
- return drw_shgroup_create_hair_procedural_ex(object, psys, md, hair_pass, NULL, material, NULL);
-}
-
void DRW_hair_update(void)
{
#ifndef USE_TRANSFORM_FEEDBACK
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index bdef6d50db8..08c6a0e8da8 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -27,6 +27,7 @@
#include "BLI_memblock.h"
#include "BLI_rect.h"
#include "BLI_string.h"
+#include "BLI_task.h"
#include "BLI_threads.h"
#include "BLF_api.h"
@@ -115,17 +116,6 @@ static ListBase DRW_engines = {NULL, NULL};
static void drw_state_prepare_clean_for_draw(DRWManager *dst)
{
memset(dst, 0x0, offsetof(DRWManager, gl_context));
-
- /* Maybe not the best place for this. */
- if (!DST.uniform_names.buffer) {
- DST.uniform_names.buffer = MEM_callocN(DRW_UNIFORM_BUFFER_NAME, "Name Buffer");
- DST.uniform_names.buffer_len = DRW_UNIFORM_BUFFER_NAME;
- }
- else if (DST.uniform_names.buffer_len > DRW_UNIFORM_BUFFER_NAME) {
- DST.uniform_names.buffer = MEM_reallocN(DST.uniform_names.buffer, DRW_UNIFORM_BUFFER_NAME);
- DST.uniform_names.buffer_len = DRW_UNIFORM_BUFFER_NAME;
- }
- DST.uniform_names.buffer_ofs = 0;
}
/* This function is used to reset draw manager to a state
@@ -140,6 +130,23 @@ static void drw_state_ensure_not_reused(DRWManager *dst)
#endif
/* -------------------------------------------------------------------- */
+/** \name Threading
+ * \{ */
+static void drw_task_graph_init(void)
+{
+ BLI_assert(DST.task_graph == NULL);
+ DST.task_graph = BLI_task_graph_create();
+}
+
+static void drw_task_graph_deinit(void)
+{
+ BLI_task_graph_work_and_wait(DST.task_graph);
+ BLI_task_graph_free(DST.task_graph);
+ DST.task_graph = NULL;
+}
+/* \} */
+
+/* -------------------------------------------------------------------- */
/** \name Settings
* \{ */
@@ -588,9 +595,6 @@ static void drw_viewport_var_init(void)
ED_view3d_init_mats_rv3d(DST.draw_ctx.object_edit, rv3d);
}
- /* Alloc array of texture reference. */
- memset(&DST.RST, 0x0, sizeof(DST.RST));
-
if (G_draw.view_ubo == NULL) {
G_draw.view_ubo = DRW_uniformbuffer_create(sizeof(DRWViewUboStorage), NULL);
}
@@ -1428,6 +1432,7 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph,
/* reuse if caller sets */
.evil_C = DST.draw_ctx.evil_C,
};
+ drw_task_graph_init();
drw_context_state_init();
drw_viewport_var_init();
@@ -1492,6 +1497,7 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph,
#endif
}
+ drw_task_graph_deinit();
DRW_stats_begin();
GPU_framebuffer_bind(DST.default_framebuffer);
@@ -1772,7 +1778,6 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph)
DST.options.is_image_render = true;
DST.options.is_scene_render = true;
DST.options.draw_background = scene->r.alphamode == R_ADDSKY;
-
DST.draw_ctx = (DRWContextState){
.scene = scene,
.view_layer = view_layer,
@@ -1857,9 +1862,9 @@ void DRW_render_object_iter(
void (*callback)(void *vedata, Object *ob, RenderEngine *engine, struct Depsgraph *depsgraph))
{
const DRWContextState *draw_ctx = DRW_context_state_get();
-
DRW_hair_init();
+ drw_task_graph_init();
const int object_type_exclude_viewport = draw_ctx->v3d ?
draw_ctx->v3d->object_type_exclude_viewport :
0;
@@ -1882,6 +1887,7 @@ void DRW_render_object_iter(
DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END;
drw_duplidata_free();
+ drw_task_graph_deinit();
}
/* Assume a valid gl context is bound (and that the gl_context_mutex has been acquired).
@@ -2053,7 +2059,7 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph,
DST.viewport = viewport;
DST.options.is_select = true;
-
+ drw_task_graph_init();
/* Get list of enabled engines */
if (use_obedit) {
drw_engines_enable_overlays();
@@ -2163,6 +2169,7 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph,
}
drw_duplidata_free();
+ drw_task_graph_deinit();
drw_engines_cache_finish();
DRW_render_instance_buffer_finish();
@@ -2243,7 +2250,7 @@ static void drw_draw_depth_loop_imp(struct Depsgraph *depsgraph,
.engine_type = engine_type,
.depsgraph = depsgraph,
};
-
+ drw_task_graph_init();
drw_engines_data_validate();
/* Setup framebuffer */
@@ -2287,6 +2294,7 @@ static void drw_draw_depth_loop_imp(struct Depsgraph *depsgraph,
DRW_render_instance_buffer_finish();
}
+ drw_task_graph_deinit();
/* Start Drawing */
DRW_state_reset();
@@ -2376,7 +2384,7 @@ void DRW_draw_select_id(Depsgraph *depsgraph, ARegion *region, View3D *v3d, cons
.obact = OBACT(view_layer),
.depsgraph = depsgraph,
};
-
+ drw_task_graph_init();
drw_context_state_init();
/* Setup viewport */
@@ -2411,6 +2419,7 @@ void DRW_draw_select_id(Depsgraph *depsgraph, ARegion *region, View3D *v3d, cons
drw_resource_buffer_finish(DST.vmempool);
#endif
}
+ drw_task_graph_deinit();
/* Start Drawing */
DRW_state_reset();
@@ -2474,8 +2483,10 @@ void DRW_draw_depth_object(
else {
batch = DRW_mesh_batch_cache_get_surface(me);
}
-
- DRW_mesh_batch_cache_create_requested(object, me, scene, false, true);
+ struct TaskGraph *task_graph = BLI_task_graph_create();
+ DRW_mesh_batch_cache_create_requested(task_graph, object, me, scene, false, true);
+ BLI_task_graph_work_and_wait(task_graph);
+ BLI_task_graph_free(task_graph);
const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED :
GPU_SHADER_CFG_DEFAULT;
@@ -2721,8 +2732,6 @@ void DRW_engines_free(void)
DRW_TEXTURE_FREE_SAFE(G_draw.ramp);
DRW_TEXTURE_FREE_SAFE(G_draw.weight_ramp);
- MEM_SAFE_FREE(DST.uniform_names.buffer);
-
if (DST.draw_list) {
GPU_draw_list_discard(DST.draw_list);
}
diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h
index f6d8179b193..733711a06da 100644
--- a/source/blender/draw/intern/draw_manager.h
+++ b/source/blender/draw/intern/draw_manager.h
@@ -31,6 +31,7 @@
#include "BLI_assert.h"
#include "BLI_linklist.h"
#include "BLI_memblock.h"
+#include "BLI_task.h"
#include "BLI_threads.h"
#include "GPU_batch.h"
@@ -276,10 +277,9 @@ typedef enum {
DRW_UNIFORM_FLOAT,
DRW_UNIFORM_FLOAT_COPY,
DRW_UNIFORM_TEXTURE,
- DRW_UNIFORM_TEXTURE_PERSIST,
DRW_UNIFORM_TEXTURE_REF,
DRW_UNIFORM_BLOCK,
- DRW_UNIFORM_BLOCK_PERSIST,
+ DRW_UNIFORM_BLOCK_REF,
DRW_UNIFORM_TFEEDBACK_TARGET,
/** Per drawcall uniforms/UBO */
DRW_UNIFORM_BLOCK_OBMATS,
@@ -290,7 +290,6 @@ typedef enum {
DRW_UNIFORM_BASE_INSTANCE,
DRW_UNIFORM_MODEL_MATRIX,
DRW_UNIFORM_MODEL_MATRIX_INVERSE,
- DRW_UNIFORM_MODELVIEWPROJECTION_MATRIX,
/* WARNING: set DRWUniform->type
* bit length accordingly. */
} DRWUniformType;
@@ -299,15 +298,28 @@ struct DRWUniform {
union {
/* For reference or array/vector types. */
const void *pvalue;
- /* Single values. */
+ /* DRW_UNIFORM_TEXTURE */
+ struct {
+ union {
+ GPUTexture *texture;
+ GPUTexture **texture_ref;
+ };
+ eGPUSamplerState sampler_state;
+ };
+ /* DRW_UNIFORM_BLOCK */
+ union {
+ GPUUniformBuffer *block;
+ GPUUniformBuffer **block_ref;
+ };
+ /* DRW_UNIFORM_FLOAT_COPY */
float fvalue[4];
+ /* DRW_UNIFORM_INT_COPY */
int ivalue[4];
};
- int location;
+ int location; /* Use as binding point for textures and ubos. */
uint32_t type : 5; /* DRWUniformType */
uint32_t length : 5; /* cannot be more than 16 */
uint32_t arraysize : 5; /* cannot be more than 16 too */
- uint32_t name_ofs : 17; /* name offset in name buffer. */
};
struct DRWShadingGroup {
@@ -342,6 +354,13 @@ struct DRWPass {
DRWShadingGroup *last;
} shgroups;
+ /* Draw the shgroups of this pass instead.
+ * This avoid duplicating drawcalls/shgroups
+ * for similar passes. */
+ DRWPass *original;
+ /* Link list of additional passes to render. */
+ DRWPass *next;
+
DRWResourceHandle handle;
DRWState state;
char name[MAX_PASS_NAME];
@@ -525,6 +544,8 @@ typedef struct DRWManager {
uint select_id;
#endif
+ struct TaskGraph *task_graph;
+
/* ---------- Nothing after this point is cleared after use ----------- */
/* gl_context serves as the offset for clearing only
@@ -537,31 +558,11 @@ typedef struct DRWManager {
GPUDrawList *draw_list;
- /** GPU Resource State: Memory storage between drawing. */
- struct {
- /* High end GPUs supports up to 32 binds per shader stage.
- * We only use textures during the vertex and fragment stage,
- * so 2 * 32 slots is a nice limit. */
- GPUTexture *bound_texs[DST_MAX_SLOTS];
- uint64_t bound_tex_slots;
- uint64_t bound_tex_slots_persist;
-
- GPUUniformBuffer *bound_ubos[DST_MAX_SLOTS];
- uint64_t bound_ubo_slots;
- uint64_t bound_ubo_slots_persist;
- } RST;
-
struct {
/* TODO(fclem) optimize: use chunks. */
DRWDebugLine *lines;
DRWDebugSphere *spheres;
} debug;
-
- struct {
- char *buffer;
- uint buffer_len;
- uint buffer_ofs;
- } uniform_names;
} DRWManager;
extern DRWManager DST; /* TODO: get rid of this and allow multi-threaded rendering. */
diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c
index aa401bcffa5..376bc69b392 100644
--- a/source/blender/draw/intern/draw_manager_data.c
+++ b/source/blender/draw/intern/draw_manager_data.c
@@ -170,13 +170,20 @@ void drw_resource_buffer_finish(ViewportMemoryPool *vmempool)
/** \name Uniforms (DRW_shgroup_uniform)
* \{ */
-static DRWUniform *drw_shgroup_uniform_create_ex(DRWShadingGroup *shgroup,
- int loc,
- DRWUniformType type,
- const void *value,
- int length,
- int arraysize)
-{
+static void drw_shgroup_uniform_create_ex(DRWShadingGroup *shgroup,
+ int loc,
+ DRWUniformType type,
+ const void *value,
+ eGPUSamplerState sampler_state,
+ int length,
+ int arraysize)
+{
+ if (loc == -1) {
+ /* Nice to enable eventually, for now eevee uses uniforms that might not exist. */
+ // BLI_assert(0);
+ return;
+ }
+
DRWUniformChunk *unichunk = shgroup->uniforms;
/* Happens on first uniform or if chunk is full. */
if (!unichunk || unichunk->uniform_used == unichunk->uniform_len) {
@@ -202,22 +209,24 @@ static DRWUniform *drw_shgroup_uniform_create_ex(DRWShadingGroup *shgroup,
BLI_assert(length <= 4);
memcpy(uni->fvalue, value, sizeof(float) * length);
break;
+ case DRW_UNIFORM_BLOCK:
+ uni->block = (GPUUniformBuffer *)value;
+ break;
+ case DRW_UNIFORM_BLOCK_REF:
+ uni->block_ref = (GPUUniformBuffer **)value;
+ break;
+ case DRW_UNIFORM_TEXTURE:
+ uni->texture = (GPUTexture *)value;
+ uni->sampler_state = sampler_state;
+ break;
+ case DRW_UNIFORM_TEXTURE_REF:
+ uni->texture_ref = (GPUTexture **)value;
+ uni->sampler_state = sampler_state;
+ break;
default:
uni->pvalue = (const float *)value;
break;
}
-
- return uni;
-}
-
-static void drw_shgroup_builtin_uniform(
- DRWShadingGroup *shgroup, int builtin, const void *value, int length, int arraysize)
-{
- int loc = GPU_shader_get_builtin_uniform(shgroup->shader, builtin);
-
- if (loc != -1) {
- drw_shgroup_uniform_create_ex(shgroup, loc, DRW_UNIFORM_FLOAT, value, length, arraysize);
- }
}
static void drw_shgroup_uniform(DRWShadingGroup *shgroup,
@@ -227,61 +236,29 @@ static void drw_shgroup_uniform(DRWShadingGroup *shgroup,
int length,
int arraysize)
{
- int location;
- if (ELEM(type, DRW_UNIFORM_BLOCK, DRW_UNIFORM_BLOCK_PERSIST)) {
- location = GPU_shader_get_uniform_block(shgroup->shader, name);
- }
- else {
- location = GPU_shader_get_uniform(shgroup->shader, name);
- }
-
- if (location == -1) {
- /* Nice to enable eventually, for now eevee uses uniforms that might not exist. */
- // BLI_assert(0);
- return;
- }
-
BLI_assert(arraysize > 0 && arraysize <= 16);
BLI_assert(length >= 0 && length <= 16);
-
- DRWUniform *uni = drw_shgroup_uniform_create_ex(
- shgroup, location, type, value, length, arraysize);
-
- /* If location is -2, the uniform has not yet been queried.
- * We save the name for query just before drawing. */
- if (location == -2 || DRW_DEBUG_USE_UNIFORM_NAME) {
- int ofs = DST.uniform_names.buffer_ofs;
- int max_len = DST.uniform_names.buffer_len - ofs;
- size_t len = strlen(name) + 1;
-
- if (len >= max_len) {
- DST.uniform_names.buffer_len += MAX2(DST.uniform_names.buffer_len, len);
- DST.uniform_names.buffer = MEM_reallocN(DST.uniform_names.buffer,
- DST.uniform_names.buffer_len);
- }
-
- char *dst = DST.uniform_names.buffer + ofs;
- memcpy(dst, name, len); /* Copies NULL terminator. */
-
- DST.uniform_names.buffer_ofs += len;
- uni->name_ofs = ofs;
- }
+ BLI_assert(!ELEM(type,
+ DRW_UNIFORM_BLOCK,
+ DRW_UNIFORM_BLOCK_REF,
+ DRW_UNIFORM_TEXTURE,
+ DRW_UNIFORM_TEXTURE_REF));
+ int location = GPU_shader_get_uniform(shgroup->shader, name);
+ drw_shgroup_uniform_create_ex(shgroup, location, type, value, 0, length, arraysize);
}
void DRW_shgroup_uniform_texture(DRWShadingGroup *shgroup, const char *name, const GPUTexture *tex)
{
BLI_assert(tex != NULL);
- drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_TEXTURE, tex, 0, 1);
+ int loc = GPU_shader_get_texture_binding(shgroup->shader, name);
+ drw_shgroup_uniform_create_ex(shgroup, loc, DRW_UNIFORM_TEXTURE, tex, GPU_SAMPLER_MAX, 0, 1);
}
-/* Same as DRW_shgroup_uniform_texture but is guaranteed to be bound if shader does not change
- * between shgrp. */
-void DRW_shgroup_uniform_texture_persistent(DRWShadingGroup *shgroup,
- const char *name,
- const GPUTexture *tex)
+void DRW_shgroup_uniform_texture_ref(DRWShadingGroup *shgroup, const char *name, GPUTexture **tex)
{
BLI_assert(tex != NULL);
- drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_TEXTURE_PERSIST, tex, 0, 1);
+ int loc = GPU_shader_get_texture_binding(shgroup->shader, name);
+ drw_shgroup_uniform_create_ex(shgroup, loc, DRW_UNIFORM_TEXTURE_REF, tex, GPU_SAMPLER_MAX, 0, 1);
}
void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup,
@@ -289,22 +266,17 @@ void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup,
const GPUUniformBuffer *ubo)
{
BLI_assert(ubo != NULL);
- drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_BLOCK, ubo, 0, 1);
+ int loc = GPU_shader_get_uniform_block_binding(shgroup->shader, name);
+ drw_shgroup_uniform_create_ex(shgroup, loc, DRW_UNIFORM_BLOCK, ubo, 0, 0, 1);
}
-/* Same as DRW_shgroup_uniform_block but is guaranteed to be bound if shader does not change
- * between shgrp. */
-void DRW_shgroup_uniform_block_persistent(DRWShadingGroup *shgroup,
- const char *name,
- const GPUUniformBuffer *ubo)
+void DRW_shgroup_uniform_block_ref(DRWShadingGroup *shgroup,
+ const char *name,
+ GPUUniformBuffer **ubo)
{
BLI_assert(ubo != NULL);
- drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_BLOCK_PERSIST, ubo, 0, 1);
-}
-
-void DRW_shgroup_uniform_texture_ref(DRWShadingGroup *shgroup, const char *name, GPUTexture **tex)
-{
- drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_TEXTURE_REF, tex, 0, 1);
+ int loc = GPU_shader_get_uniform_block_binding(shgroup->shader, name);
+ drw_shgroup_uniform_create_ex(shgroup, loc, DRW_UNIFORM_BLOCK_REF, ubo, 0, 0, 1);
}
void DRW_shgroup_uniform_bool(DRWShadingGroup *shgroup,
@@ -441,7 +413,7 @@ void DRW_shgroup_uniform_vec4_array_copy(DRWShadingGroup *shgroup,
const float (*value)[4],
int arraysize)
{
- int location = GPU_shader_get_uniform_ensure(shgroup->shader, name);
+ int location = GPU_shader_get_uniform(shgroup->shader, name);
if (location == -1) {
/* Nice to enable eventually, for now eevee uses uniforms that might not exist. */
@@ -450,7 +422,8 @@ void DRW_shgroup_uniform_vec4_array_copy(DRWShadingGroup *shgroup,
}
for (int i = 0; i < arraysize; i++) {
- drw_shgroup_uniform_create_ex(shgroup, location + i, DRW_UNIFORM_FLOAT_COPY, &value[i], 4, 1);
+ drw_shgroup_uniform_create_ex(
+ shgroup, location + i, DRW_UNIFORM_FLOAT_COPY, &value[i], 0, 4, 1);
}
}
@@ -1196,52 +1169,49 @@ static void drw_shgroup_init(DRWShadingGroup *shgroup, GPUShader *shader)
shgroup->uniforms = NULL;
/* TODO(fclem) make them builtin. */
- int view_ubo_location = GPU_shader_get_uniform_block(shader, "viewBlock");
- int model_ubo_location = GPU_shader_get_uniform_block(shader, "modelBlock");
- int info_ubo_location = GPU_shader_get_uniform_block(shader, "infoBlock");
+ int view_ubo_location = GPU_shader_get_uniform_block_binding(shader, "viewBlock");
+ int model_ubo_location = GPU_shader_get_uniform_block_binding(shader, "modelBlock");
+ int info_ubo_location = GPU_shader_get_uniform_block_binding(shader, "infoBlock");
int baseinst_location = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_BASE_INSTANCE);
int chunkid_location = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_RESOURCE_CHUNK);
int resourceid_location = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_RESOURCE_ID);
if (chunkid_location != -1) {
drw_shgroup_uniform_create_ex(
- shgroup, chunkid_location, DRW_UNIFORM_RESOURCE_CHUNK, NULL, 0, 1);
+ shgroup, chunkid_location, DRW_UNIFORM_RESOURCE_CHUNK, NULL, 0, 0, 1);
}
if (resourceid_location != -1) {
drw_shgroup_uniform_create_ex(
- shgroup, resourceid_location, DRW_UNIFORM_RESOURCE_ID, NULL, 0, 1);
+ shgroup, resourceid_location, DRW_UNIFORM_RESOURCE_ID, NULL, 0, 0, 1);
}
if (baseinst_location != -1) {
drw_shgroup_uniform_create_ex(
- shgroup, baseinst_location, DRW_UNIFORM_BASE_INSTANCE, NULL, 0, 1);
+ shgroup, baseinst_location, DRW_UNIFORM_BASE_INSTANCE, NULL, 0, 0, 1);
}
if (model_ubo_location != -1) {
drw_shgroup_uniform_create_ex(
- shgroup, model_ubo_location, DRW_UNIFORM_BLOCK_OBMATS, NULL, 0, 1);
+ shgroup, model_ubo_location, DRW_UNIFORM_BLOCK_OBMATS, NULL, 0, 0, 1);
}
else {
+ /* Note: This is only here to support old hardware fallback where uniform buffer is still
+ * too slow or buggy. */
int model = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODEL);
int modelinverse = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODEL_INV);
- int modelviewprojection = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MVP);
if (model != -1) {
- drw_shgroup_uniform_create_ex(shgroup, model, DRW_UNIFORM_MODEL_MATRIX, NULL, 0, 1);
+ drw_shgroup_uniform_create_ex(shgroup, model, DRW_UNIFORM_MODEL_MATRIX, NULL, 0, 0, 1);
}
if (modelinverse != -1) {
drw_shgroup_uniform_create_ex(
- shgroup, modelinverse, DRW_UNIFORM_MODEL_MATRIX_INVERSE, NULL, 0, 1);
- }
- if (modelviewprojection != -1) {
- drw_shgroup_uniform_create_ex(
- shgroup, modelviewprojection, DRW_UNIFORM_MODELVIEWPROJECTION_MATRIX, NULL, 0, 1);
+ shgroup, modelinverse, DRW_UNIFORM_MODEL_MATRIX_INVERSE, NULL, 0, 0, 1);
}
}
if (info_ubo_location != -1) {
drw_shgroup_uniform_create_ex(
- shgroup, info_ubo_location, DRW_UNIFORM_BLOCK_OBINFOS, NULL, 0, 1);
+ shgroup, info_ubo_location, DRW_UNIFORM_BLOCK_OBINFOS, NULL, 0, 0, 1);
/* Abusing this loc to tell shgroup we need the obinfos. */
shgroup->objectinfo = 1;
@@ -1252,25 +1222,21 @@ static void drw_shgroup_init(DRWShadingGroup *shgroup, GPUShader *shader)
if (view_ubo_location != -1) {
drw_shgroup_uniform_create_ex(
- shgroup, view_ubo_location, DRW_UNIFORM_BLOCK_PERSIST, G_draw.view_ubo, 0, 1);
- }
- else {
- /* Only here to support builtin shaders. This should not be used by engines. */
- /* TODO remove. */
- DRWViewUboStorage *storage = &DST.view_storage_cpy;
- drw_shgroup_builtin_uniform(shgroup, GPU_UNIFORM_VIEW, storage->viewmat, 16, 1);
- drw_shgroup_builtin_uniform(shgroup, GPU_UNIFORM_VIEW_INV, storage->viewinv, 16, 1);
- drw_shgroup_builtin_uniform(shgroup, GPU_UNIFORM_VIEWPROJECTION, storage->persmat, 16, 1);
- drw_shgroup_builtin_uniform(shgroup, GPU_UNIFORM_VIEWPROJECTION_INV, storage->persinv, 16, 1);
- drw_shgroup_builtin_uniform(shgroup, GPU_UNIFORM_PROJECTION, storage->winmat, 16, 1);
- drw_shgroup_builtin_uniform(shgroup, GPU_UNIFORM_PROJECTION_INV, storage->wininv, 16, 1);
- drw_shgroup_builtin_uniform(shgroup, GPU_UNIFORM_CLIPPLANES, storage->clipplanes, 4, 6);
+ shgroup, view_ubo_location, DRW_UNIFORM_BLOCK, G_draw.view_ubo, 0, 0, 1);
}
/* Not supported. */
BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODELVIEW_INV) == -1);
BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODELVIEW) == -1);
BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_NORMAL) == -1);
+ BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_VIEW) == -1);
+ BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_VIEW_INV) == -1);
+ BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_VIEWPROJECTION) == -1);
+ BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_VIEWPROJECTION_INV) == -1);
+ BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_PROJECTION) == -1);
+ BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_PROJECTION_INV) == -1);
+ BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_CLIPPLANES) == -1);
+ BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MVP) == -1);
}
static DRWShadingGroup *drw_shgroup_create_ex(struct GPUShader *shader, DRWPass *pass)
@@ -1308,18 +1274,20 @@ static DRWShadingGroup *drw_shgroup_material_create_ex(GPUPass *gpupass, DRWPass
static void drw_shgroup_material_texture(DRWShadingGroup *grp,
GPUMaterialTexture *tex,
const char *name,
+ eGPUSamplerState state,
int textarget)
{
GPUTexture *gputex = GPU_texture_from_blender(tex->ima, tex->iuser, NULL, textarget);
- DRW_shgroup_uniform_texture(grp, name, gputex);
+
+ int loc = GPU_shader_get_texture_binding(grp->shader, name);
+ drw_shgroup_uniform_create_ex(grp, loc, DRW_UNIFORM_TEXTURE, gputex, state, 0, 1);
GPUTexture **gputex_ref = BLI_memblock_alloc(DST.vmempool->images);
*gputex_ref = gputex;
GPU_texture_ref(gputex);
}
-static DRWShadingGroup *drw_shgroup_material_inputs(DRWShadingGroup *grp,
- struct GPUMaterial *material)
+void DRW_shgroup_add_material_resources(DRWShadingGroup *grp, struct GPUMaterial *material)
{
ListBase textures = GPU_material_textures(material);
@@ -1328,11 +1296,14 @@ static DRWShadingGroup *drw_shgroup_material_inputs(DRWShadingGroup *grp,
if (tex->ima) {
/* Image */
if (tex->tiled_mapping_name[0]) {
- drw_shgroup_material_texture(grp, tex, tex->sampler_name, GL_TEXTURE_2D_ARRAY);
- drw_shgroup_material_texture(grp, tex, tex->tiled_mapping_name, GL_TEXTURE_1D_ARRAY);
+ drw_shgroup_material_texture(
+ grp, tex, tex->sampler_name, tex->sampler_state, GL_TEXTURE_2D_ARRAY);
+ drw_shgroup_material_texture(
+ grp, tex, tex->tiled_mapping_name, tex->sampler_state, GL_TEXTURE_1D_ARRAY);
}
else {
- drw_shgroup_material_texture(grp, tex, tex->sampler_name, GL_TEXTURE_2D);
+ drw_shgroup_material_texture(
+ grp, tex, tex->sampler_name, tex->sampler_state, GL_TEXTURE_2D);
}
}
else if (tex->colorband) {
@@ -1345,8 +1316,6 @@ static DRWShadingGroup *drw_shgroup_material_inputs(DRWShadingGroup *grp,
if (ubo != NULL) {
DRW_shgroup_uniform_block(grp, GPU_UBO_BLOCK_NAME, ubo);
}
-
- return grp;
}
GPUVertFormat *DRW_shgroup_instance_format_array(const DRWInstanceAttrFormat attrs[],
@@ -1371,7 +1340,7 @@ DRWShadingGroup *DRW_shgroup_material_create(struct GPUMaterial *material, DRWPa
if (shgroup) {
drw_shgroup_init(shgroup, GPU_pass_shader_get(gpupass));
- drw_shgroup_material_inputs(shgroup, material);
+ DRW_shgroup_add_material_resources(shgroup, material);
}
return shgroup;
}
@@ -1390,7 +1359,7 @@ DRWShadingGroup *DRW_shgroup_transform_feedback_create(struct GPUShader *shader,
BLI_assert(tf_target != NULL);
DRWShadingGroup *shgroup = drw_shgroup_create_ex(shader, pass);
drw_shgroup_init(shgroup, shader);
- drw_shgroup_uniform_create_ex(shgroup, 0, DRW_UNIFORM_TFEEDBACK_TARGET, tf_target, 0, 1);
+ drw_shgroup_uniform_create_ex(shgroup, 0, DRW_UNIFORM_TFEEDBACK_TARGET, tf_target, 0, 0, 1);
return shgroup;
}
@@ -1922,9 +1891,28 @@ DRWPass *DRW_pass_create(const char *name, DRWState state)
pass->handle = DST.pass_handle;
DRW_handle_increment(&DST.pass_handle);
+ pass->original = NULL;
+ pass->next = NULL;
+
+ return pass;
+}
+
+DRWPass *DRW_pass_create_instance(const char *name, DRWPass *original, DRWState state)
+{
+ DRWPass *pass = DRW_pass_create(name, state);
+ pass->original = original;
+
return pass;
}
+/* Link two passes so that they are both rendered if the first one is being drawn. */
+void DRW_pass_link(DRWPass *first, DRWPass *second)
+{
+ BLI_assert(first != second);
+ BLI_assert(first->next == NULL);
+ first->next = second;
+}
+
bool DRW_pass_is_empty(DRWPass *pass)
{
LISTBASE_FOREACH (DRWShadingGroup *, shgroup, &pass->shgroups) {
diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c
index 6c62d4d2405..144ce573460 100644
--- a/source/blender/draw/intern/draw_manager_exec.c
+++ b/source/blender/draw/intern/draw_manager_exec.c
@@ -22,6 +22,7 @@
#include "draw_manager.h"
+#include "BLI_alloca.h"
#include "BLI_math.h"
#include "BLI_math_bits.h"
#include "BLI_memblock.h"
@@ -65,7 +66,6 @@ typedef struct DRWCommandsState {
/* Legacy matrix support. */
int obmat_loc;
int obinv_loc;
- int mvp_loc;
/* Selection ID state. */
GPUVertBuf *select_buf;
uint select_id;
@@ -655,8 +655,7 @@ static void draw_compute_culling(DRWView *view)
BLI_INLINE void draw_legacy_matrix_update(DRWShadingGroup *shgroup,
DRWResourceHandle *handle,
float obmat_loc,
- float obinv_loc,
- float mvp_loc)
+ float obinv_loc)
{
/* Still supported for compatibility with gpu_shader_* but should be forbidden. */
DRWObjectMatrix *ob_mats = DRW_memblock_elem_from_handle(DST.vmempool->obmats, handle);
@@ -666,13 +665,6 @@ BLI_INLINE void draw_legacy_matrix_update(DRWShadingGroup *shgroup,
if (obinv_loc != -1) {
GPU_shader_uniform_vector(shgroup->shader, obinv_loc, 16, 1, (float *)ob_mats->modelinverse);
}
- /* Still supported for compatibility with gpu_shader_* but should be forbidden
- * and is slow (since it does not cache the result). */
- if (mvp_loc != -1) {
- float mvp[4][4];
- mul_m4_m4m4(mvp, DST.view_active->storage.persmat, ob_mats->model);
- GPU_shader_uniform_vector(shgroup->shader, mvp_loc, 16, 1, (float *)mvp);
- }
}
BLI_INLINE void draw_geometry_bind(DRWShadingGroup *shgroup, GPUBatch *geom)
@@ -744,107 +736,6 @@ BLI_INLINE void draw_indirect_call(DRWShadingGroup *shgroup, DRWCommandsState *s
}
}
-enum {
- BIND_NONE = 0,
- BIND_TEMP = 1, /* Release slot after this shading group. */
- BIND_PERSIST = 2, /* Release slot only after the next shader change. */
-};
-
-static void set_bound_flags(uint64_t *slots, uint64_t *persist_slots, int slot_idx, char bind_type)
-{
- uint64_t slot = 1llu << (unsigned long)slot_idx;
- *slots |= slot;
- if (bind_type == BIND_PERSIST) {
- *persist_slots |= slot;
- }
-}
-
-static int get_empty_slot_index(uint64_t slots)
-{
- uint64_t empty_slots = ~slots;
- /* Find first empty slot using bitscan. */
- if (empty_slots != 0) {
- if ((empty_slots & 0xFFFFFFFFlu) != 0) {
- return (int)bitscan_forward_uint(empty_slots);
- }
- else {
- return (int)bitscan_forward_uint(empty_slots >> 32) + 32;
- }
- }
- else {
- /* Greater than GPU_max_textures() */
- return 99999;
- }
-}
-
-static void bind_texture(GPUTexture *tex, char bind_type)
-{
- int idx = GPU_texture_bound_number(tex);
- if (idx == -1) {
- /* Texture isn't bound yet. Find an empty slot and bind it. */
- idx = get_empty_slot_index(DST.RST.bound_tex_slots);
-
- if (idx < GPU_max_textures()) {
- GPUTexture **gpu_tex_slot = &DST.RST.bound_texs[idx];
- /* Unbind any previous texture. */
- if (*gpu_tex_slot != NULL) {
- GPU_texture_unbind(*gpu_tex_slot);
- }
- GPU_texture_bind(tex, idx);
- *gpu_tex_slot = tex;
- }
- else {
- printf("Not enough texture slots! Reduce number of textures used by your shader.\n");
- return;
- }
- }
- else {
- /* This texture slot was released but the tex
- * is still bound. Just flag the slot again. */
- BLI_assert(DST.RST.bound_texs[idx] == tex);
- }
- set_bound_flags(&DST.RST.bound_tex_slots, &DST.RST.bound_tex_slots_persist, idx, bind_type);
-}
-
-static void bind_ubo(GPUUniformBuffer *ubo, char bind_type)
-{
- int idx = GPU_uniformbuffer_bindpoint(ubo);
- if (idx == -1) {
- /* UBO isn't bound yet. Find an empty slot and bind it. */
- idx = get_empty_slot_index(DST.RST.bound_ubo_slots);
-
- /* [0..1] are reserved ubo slots. */
- idx += 2;
-
- if (idx < GPU_max_ubo_binds()) {
- GPUUniformBuffer **gpu_ubo_slot = &DST.RST.bound_ubos[idx];
- /* Unbind any previous UBO. */
- if (*gpu_ubo_slot != NULL) {
- GPU_uniformbuffer_unbind(*gpu_ubo_slot);
- }
- GPU_uniformbuffer_bind(ubo, idx);
- *gpu_ubo_slot = ubo;
- }
- else {
- /* printf so user can report bad behavior */
- printf("Not enough ubo slots! This should not happen!\n");
- /* This is not depending on user input.
- * It is our responsibility to make sure there is enough slots. */
- BLI_assert(0);
- return;
- }
- }
- else {
- BLI_assert(idx < 64);
- /* This UBO slot was released but the UBO is
- * still bound here. Just flag the slot again. */
- BLI_assert(DST.RST.bound_ubos[idx] == ubo);
- }
- /* Remove offset for flag bitfield. */
- idx -= 2;
- set_bound_flags(&DST.RST.bound_ubo_slots, &DST.RST.bound_ubo_slots_persist, idx, bind_type);
-}
-
#ifndef NDEBUG
/**
* Opengl specification is strict on buffer binding.
@@ -900,28 +791,6 @@ static bool ubo_bindings_validate(DRWShadingGroup *shgroup)
}
#endif
-static void release_texture_slots(bool with_persist)
-{
- if (with_persist) {
- DST.RST.bound_tex_slots = 0;
- DST.RST.bound_tex_slots_persist = 0;
- }
- else {
- DST.RST.bound_tex_slots &= DST.RST.bound_tex_slots_persist;
- }
-}
-
-static void release_ubo_slots(bool with_persist)
-{
- if (with_persist) {
- DST.RST.bound_ubo_slots = 0;
- DST.RST.bound_ubo_slots_persist = 0;
- }
- else {
- DST.RST.bound_ubo_slots &= DST.RST.bound_ubo_slots_persist;
- }
-}
-
static void draw_update_uniforms(DRWShadingGroup *shgroup,
DRWCommandsState *state,
bool *use_tfeedback)
@@ -929,69 +798,42 @@ static void draw_update_uniforms(DRWShadingGroup *shgroup,
for (DRWUniformChunk *unichunk = shgroup->uniforms; unichunk; unichunk = unichunk->next) {
DRWUniform *uni = unichunk->uniforms;
for (int i = 0; i < unichunk->uniform_used; i++, uni++) {
- GPUTexture *tex;
- GPUUniformBuffer *ubo;
- if (uni->location == -2) {
- uni->location = GPU_shader_get_uniform_ensure(shgroup->shader,
- DST.uniform_names.buffer + uni->name_ofs);
- if (uni->location == -1) {
- continue;
- }
- }
- const void *data = uni->pvalue;
- if (ELEM(uni->type, DRW_UNIFORM_INT_COPY, DRW_UNIFORM_FLOAT_COPY)) {
- data = uni->fvalue;
- }
switch (uni->type) {
case DRW_UNIFORM_INT_COPY:
+ GPU_shader_uniform_vector_int(
+ shgroup->shader, uni->location, uni->length, uni->arraysize, uni->ivalue);
+ break;
case DRW_UNIFORM_INT:
GPU_shader_uniform_vector_int(
- shgroup->shader, uni->location, uni->length, uni->arraysize, data);
+ shgroup->shader, uni->location, uni->length, uni->arraysize, uni->pvalue);
break;
case DRW_UNIFORM_FLOAT_COPY:
+ GPU_shader_uniform_vector(
+ shgroup->shader, uni->location, uni->length, uni->arraysize, uni->fvalue);
+ break;
case DRW_UNIFORM_FLOAT:
GPU_shader_uniform_vector(
- shgroup->shader, uni->location, uni->length, uni->arraysize, data);
+ shgroup->shader, uni->location, uni->length, uni->arraysize, uni->pvalue);
break;
case DRW_UNIFORM_TEXTURE:
- tex = (GPUTexture *)uni->pvalue;
- BLI_assert(tex);
- bind_texture(tex, BIND_TEMP);
- GPU_shader_uniform_texture(shgroup->shader, uni->location, tex);
- break;
- case DRW_UNIFORM_TEXTURE_PERSIST:
- tex = (GPUTexture *)uni->pvalue;
- BLI_assert(tex);
- bind_texture(tex, BIND_PERSIST);
- GPU_shader_uniform_texture(shgroup->shader, uni->location, tex);
+ GPU_texture_bind_ex(uni->texture, uni->sampler_state, uni->location, false);
break;
case DRW_UNIFORM_TEXTURE_REF:
- tex = *((GPUTexture **)uni->pvalue);
- BLI_assert(tex);
- bind_texture(tex, BIND_TEMP);
- GPU_shader_uniform_texture(shgroup->shader, uni->location, tex);
+ GPU_texture_bind_ex(*uni->texture_ref, uni->sampler_state, uni->location, false);
break;
case DRW_UNIFORM_BLOCK:
- ubo = (GPUUniformBuffer *)uni->pvalue;
- bind_ubo(ubo, BIND_TEMP);
- GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo);
+ GPU_uniformbuffer_bind(uni->block, uni->location);
break;
- case DRW_UNIFORM_BLOCK_PERSIST:
- ubo = (GPUUniformBuffer *)uni->pvalue;
- bind_ubo(ubo, BIND_PERSIST);
- GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo);
+ case DRW_UNIFORM_BLOCK_REF:
+ GPU_uniformbuffer_bind(*uni->block_ref, uni->location);
break;
case DRW_UNIFORM_BLOCK_OBMATS:
state->obmats_loc = uni->location;
- ubo = DST.vmempool->matrices_ubo[0];
- GPU_uniformbuffer_bind(ubo, 0);
- GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo);
+ GPU_uniformbuffer_bind(DST.vmempool->matrices_ubo[0], uni->location);
break;
case DRW_UNIFORM_BLOCK_OBINFOS:
state->obinfos_loc = uni->location;
- ubo = DST.vmempool->obinfos_ubo[0];
- GPU_uniformbuffer_bind(ubo, 1);
- GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo);
+ GPU_uniformbuffer_bind(DST.vmempool->obinfos_ubo[0], uni->location);
break;
case DRW_UNIFORM_RESOURCE_CHUNK:
state->chunkid_loc = uni->location;
@@ -1001,9 +843,9 @@ static void draw_update_uniforms(DRWShadingGroup *shgroup,
state->resourceid_loc = uni->location;
break;
case DRW_UNIFORM_TFEEDBACK_TARGET:
- BLI_assert(data && (*use_tfeedback == false));
- *use_tfeedback = GPU_shader_transform_feedback_enable(shgroup->shader,
- ((GPUVertBuf *)data)->vbo_id);
+ BLI_assert(uni->pvalue && (*use_tfeedback == false));
+ *use_tfeedback = GPU_shader_transform_feedback_enable(
+ shgroup->shader, ((GPUVertBuf *)uni->pvalue)->vbo_id);
break;
/* Legacy/Fallback support. */
case DRW_UNIFORM_BASE_INSTANCE:
@@ -1015,9 +857,6 @@ static void draw_update_uniforms(DRWShadingGroup *shgroup,
case DRW_UNIFORM_MODEL_MATRIX_INVERSE:
state->obinv_loc = uni->location;
break;
- case DRW_UNIFORM_MODELVIEWPROJECTION_MATRIX:
- state->mvp_loc = uni->location;
- break;
}
}
}
@@ -1110,7 +949,7 @@ static void draw_call_resource_bind(DRWCommandsState *state, const DRWResourceHa
}
if (state->obmats_loc != -1) {
GPU_uniformbuffer_unbind(DST.vmempool->matrices_ubo[state->resource_chunk]);
- GPU_uniformbuffer_bind(DST.vmempool->matrices_ubo[chunk], 0);
+ GPU_uniformbuffer_bind(DST.vmempool->matrices_ubo[chunk], state->obmats_loc);
}
if (state->obinfos_loc != -1) {
GPU_uniformbuffer_unbind(DST.vmempool->obinfos_ubo[state->resource_chunk]);
@@ -1153,10 +992,8 @@ static void draw_call_single_do(DRWShadingGroup *shgroup,
draw_call_resource_bind(state, &handle);
/* TODO This is Legacy. Need to be removed. */
- if (state->obmats_loc == -1 &&
- (state->obmat_loc != -1 || state->obinv_loc != -1 || state->mvp_loc != -1)) {
- draw_legacy_matrix_update(
- shgroup, &handle, state->obmat_loc, state->obinv_loc, state->mvp_loc);
+ if (state->obmats_loc == -1 && (state->obmat_loc != -1 || state->obinv_loc != -1)) {
+ draw_legacy_matrix_update(shgroup, &handle, state->obmat_loc, state->obinv_loc);
}
if (G.f & G_FLAG_PICKSEL) {
@@ -1262,7 +1099,6 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
.resourceid_loc = -1,
.obmat_loc = -1,
.obinv_loc = -1,
- .mvp_loc = -1,
.drw_state_enabled = 0,
.drw_state_disabled = 0,
};
@@ -1273,6 +1109,11 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
if (shader_changed) {
if (DST.shader) {
GPU_shader_unbind();
+
+ /* Unbinding can be costly. Skip in normal condition. */
+ if (G.debug & G_DEBUG_GPU) {
+ GPU_texture_unbind_all();
+ }
}
GPU_shader_bind(shgroup->shader);
DST.shader = shgroup->shader;
@@ -1283,9 +1124,6 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
DST.batch = NULL;
}
- release_ubo_slots(shader_changed);
- release_texture_slots(shader_changed);
-
draw_update_uniforms(shgroup, &state, &use_tfeedback);
drw_state_set(pass_state);
@@ -1426,6 +1264,11 @@ static void drw_draw_pass_ex(DRWPass *pass,
DRWShadingGroup *start_group,
DRWShadingGroup *end_group)
{
+ if (pass->original) {
+ start_group = pass->original->shgroups.first;
+ end_group = pass->original->shgroups.last;
+ }
+
if (start_group == NULL) {
return;
}
@@ -1462,24 +1305,9 @@ static void drw_draw_pass_ex(DRWPass *pass,
}
}
- /* Clear Bound textures */
- for (int i = 0; i < DST_MAX_SLOTS; i++) {
- if (DST.RST.bound_texs[i] != NULL) {
- GPU_texture_unbind(DST.RST.bound_texs[i]);
- DST.RST.bound_texs[i] = NULL;
- }
- }
-
- /* Clear Bound Ubos */
- for (int i = 0; i < DST_MAX_SLOTS; i++) {
- if (DST.RST.bound_ubos[i] != NULL) {
- GPU_uniformbuffer_unbind(DST.RST.bound_ubos[i]);
- DST.RST.bound_ubos[i] = NULL;
- }
- }
-
if (DST.shader) {
GPU_shader_unbind();
+ GPU_texture_unbind_all();
DST.shader = NULL;
}
@@ -1511,7 +1339,9 @@ static void drw_draw_pass_ex(DRWPass *pass,
void DRW_draw_pass(DRWPass *pass)
{
- drw_draw_pass_ex(pass, pass->shgroups.first, pass->shgroups.last);
+ for (; pass; pass = pass->next) {
+ drw_draw_pass_ex(pass, pass->shgroups.first, pass->shgroups.last);
+ }
}
/* Draw only a subset of shgroups. Used in special situations as grease pencil strokes */
diff --git a/source/blender/draw/intern/draw_manager_shader.c b/source/blender/draw/intern/draw_manager_shader.c
index 0d6527421d0..6304b707cb9 100644
--- a/source/blender/draw/intern/draw_manager_shader.c
+++ b/source/blender/draw/intern/draw_manager_shader.c
@@ -343,27 +343,12 @@ GPUShader *DRW_shader_create_with_transform_feedback(const char *vert,
__func__);
}
-GPUShader *DRW_shader_create_2d(const char *frag, const char *defines)
-{
- return GPU_shader_create(datatoc_gpu_shader_2D_vert_glsl, frag, NULL, NULL, defines, __func__);
-}
-
-GPUShader *DRW_shader_create_3d(const char *frag, const char *defines)
-{
- return GPU_shader_create(datatoc_gpu_shader_3D_vert_glsl, frag, NULL, NULL, defines, __func__);
-}
-
GPUShader *DRW_shader_create_fullscreen(const char *frag, const char *defines)
{
return GPU_shader_create(
datatoc_common_fullscreen_vert_glsl, frag, NULL, NULL, defines, __func__);
}
-GPUShader *DRW_shader_create_3d_depth_only(eGPUShaderConfig sh_cfg)
-{
- return GPU_shader_get_builtin_shader_with_config(GPU_SHADER_3D_DEPTH_ONLY, sh_cfg);
-}
-
GPUMaterial *DRW_shader_find_from_world(World *wo,
const void *engine_type,
const int options,
@@ -398,6 +383,7 @@ GPUMaterial *DRW_shader_find_from_material(Material *ma,
GPUMaterial *DRW_shader_create_from_world(struct Scene *scene,
World *wo,
+ struct bNodeTree *ntree,
const void *engine_type,
const int options,
const bool is_volume_shader,
@@ -408,7 +394,7 @@ GPUMaterial *DRW_shader_create_from_world(struct Scene *scene,
bool deferred)
{
GPUMaterial *mat = NULL;
- if (DRW_state_is_image_render()) {
+ if (DRW_state_is_image_render() || !deferred) {
mat = GPU_material_from_nodetree_find(&wo->gpumaterial, engine_type, options);
}
@@ -416,7 +402,7 @@ GPUMaterial *DRW_shader_create_from_world(struct Scene *scene,
scene = (Scene *)DEG_get_original_id(&DST.draw_ctx.scene->id);
mat = GPU_material_from_nodetree(scene,
NULL,
- wo->nodetree,
+ ntree,
&wo->gpumaterial,
engine_type,
options,
@@ -437,6 +423,7 @@ GPUMaterial *DRW_shader_create_from_world(struct Scene *scene,
GPUMaterial *DRW_shader_create_from_material(struct Scene *scene,
Material *ma,
+ struct bNodeTree *ntree,
const void *engine_type,
const int options,
const bool is_volume_shader,
@@ -447,7 +434,7 @@ GPUMaterial *DRW_shader_create_from_material(struct Scene *scene,
bool deferred)
{
GPUMaterial *mat = NULL;
- if (DRW_state_is_image_render()) {
+ if (DRW_state_is_image_render() || !deferred) {
mat = GPU_material_from_nodetree_find(&ma->gpumaterial, engine_type, options);
}
@@ -455,7 +442,7 @@ GPUMaterial *DRW_shader_create_from_material(struct Scene *scene,
scene = (Scene *)DEG_get_original_id(&DST.draw_ctx.scene->id);
mat = GPU_material_from_nodetree(scene,
ma,
- ma->nodetree,
+ ntree,
&ma->gpumaterial,
engine_type,
options,
diff --git a/source/blender/draw/intern/draw_manager_texture.c b/source/blender/draw/intern/draw_manager_texture.c
index 6abab38e1e6..0cb6535b1c1 100644
--- a/source/blender/draw/intern/draw_manager_texture.c
+++ b/source/blender/draw/intern/draw_manager_texture.c
@@ -61,17 +61,17 @@ static bool drw_texture_format_supports_framebuffer(eGPUTextureFormat format)
void drw_texture_set_parameters(GPUTexture *tex, DRWTextureFlag flags)
{
- GPU_texture_bind(tex, 0);
if (flags & DRW_TEX_MIPMAP) {
GPU_texture_mipmap_mode(tex, true, flags & DRW_TEX_FILTER);
+ GPU_texture_bind(tex, 0);
GPU_texture_generate_mipmap(tex);
+ GPU_texture_unbind(tex);
}
else {
GPU_texture_filter_mode(tex, flags & DRW_TEX_FILTER);
}
GPU_texture_wrap_mode(tex, flags & DRW_TEX_WRAP, true);
GPU_texture_compare_mode(tex, flags & DRW_TEX_COMPARE);
- GPU_texture_unbind(tex);
}
GPUTexture *DRW_texture_create_1d(int w,