[Bf-blender-cvs] [3a209c28575] blender2.8: DRW: Deferred compilation initial implementation.

Clément Foucault noreply at git.blender.org
Tue Mar 6 16:45:36 CET 2018


Commit: 3a209c285754a08339c654d075b5d273fa264c08
Author: Clément Foucault
Date:   Mon Mar 5 00:54:31 2018 +0100
Branches: blender2.8
https://developer.blender.org/rB3a209c285754a08339c654d075b5d273fa264c08

DRW: Deferred compilation initial implementation.

===================================================================

M	source/blender/draw/DRW_engine.h
M	source/blender/draw/engines/eevee/eevee_materials.c
M	source/blender/draw/intern/DRW_render.h
M	source/blender/draw/intern/draw_manager.c
M	source/blender/draw/intern/draw_manager.h
M	source/blender/draw/intern/draw_manager_shader.c
M	source/blender/gpu/GPU_material.h
M	source/blender/gpu/intern/gpu_codegen.c
M	source/blender/gpu/intern/gpu_codegen.h
M	source/blender/gpu/intern/gpu_material.c

===================================================================

diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h
index 4043f39b46d..cc4c0ed10e8 100644
--- a/source/blender/draw/DRW_engine.h
+++ b/source/blender/draw/DRW_engine.h
@@ -46,6 +46,7 @@ struct ViewContext;
 struct ViewportEngineData;
 struct View3D;
 struct rcti;
+struct GPUMaterial;
 struct GPUOffScreen;
 struct GPUViewport;
 struct RenderEngine;
@@ -136,4 +137,6 @@ void DRW_opengl_context_destroy(void);
 void DRW_opengl_context_enable(void);
 void DRW_opengl_context_disable(void);
 
+void DRW_deferred_shader_remove(struct GPUMaterial *mat);
+
 #endif /* __DRW_ENGINE_H__ */
diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c
index 31ef26a1e9e..1cf49d7166c 100644
--- a/source/blender/draw/engines/eevee/eevee_materials.c
+++ b/source/blender/draw/engines/eevee/eevee_materials.c
@@ -630,8 +630,8 @@ struct GPUMaterial *EEVEE_material_world_lightprobe_get(struct Scene *scene, Wor
 	if (mat != NULL) {
 		return mat;
 	}
-	return GPU_material_from_nodetree(
-	        scene, wo->nodetree, &wo->gpumaterial, engine, options,
+	return DRW_shader_create_from_world(
+	        scene, wo, engine, options,
 	        datatoc_background_vert_glsl, NULL, e_data.frag_shader_lib,
 	        SHADER_DEFINES "#define PROBE_CAPTURE\n");
 }
@@ -645,8 +645,8 @@ struct GPUMaterial *EEVEE_material_world_background_get(struct Scene *scene, Wor
 	if (mat != NULL) {
 		return mat;
 	}
-	return GPU_material_from_nodetree(
-	        scene, wo->nodetree, &wo->gpumaterial, engine, options,
+	return DRW_shader_create_from_world(
+	        scene, wo, engine, options,
 	        datatoc_background_vert_glsl, NULL, e_data.frag_shader_lib,
 	        SHADER_DEFINES "#define WORLD_BACKGROUND\n");
 }
@@ -663,8 +663,8 @@ struct GPUMaterial *EEVEE_material_world_volume_get(struct Scene *scene, World *
 
 	char *defines = eevee_get_volume_defines(options);
 
-	mat = GPU_material_from_nodetree(
-	        scene, wo->nodetree, &wo->gpumaterial, engine, options,
+	mat = DRW_shader_create_from_world(
+	        scene, wo, engine, options,
 	        datatoc_volumetric_vert_glsl, datatoc_volumetric_geom_glsl, e_data.volume_shader_lib,
 	        defines);
 
@@ -698,8 +698,8 @@ struct GPUMaterial *EEVEE_material_mesh_get(
 
 	char *defines = eevee_get_defines(options);
 
-	mat = GPU_material_from_nodetree(
-	        scene, ma->nodetree, &ma->gpumaterial, engine, options,
+	mat = DRW_shader_create_from_material(
+	        scene, ma, engine, options,
 	        datatoc_lit_surface_vert_glsl, NULL, e_data.frag_shader_lib,
 	        defines);
 
@@ -720,8 +720,8 @@ struct GPUMaterial *EEVEE_material_mesh_volume_get(struct Scene *scene, Material
 
 	char *defines = eevee_get_volume_defines(options);
 
-	mat = GPU_material_from_nodetree(
-	        scene, ma->nodetree, &ma->gpumaterial, engine, options,
+	mat = DRW_shader_create_from_material(
+	        scene, ma, engine, options,
 	        datatoc_volumetric_vert_glsl, datatoc_volumetric_geom_glsl, e_data.volume_shader_lib,
 	        defines);
 
@@ -758,8 +758,8 @@ struct GPUMaterial *EEVEE_material_mesh_depth_get(
 	        e_data.frag_shader_lib,
 	        datatoc_prepass_frag_glsl);
 
-	mat = GPU_material_from_nodetree(
-	        scene, ma->nodetree, &ma->gpumaterial, engine, options,
+	mat = DRW_shader_create_from_material(
+	        scene, ma, engine, options,
 	        (is_shadow) ? datatoc_shadow_vert_glsl : datatoc_lit_surface_vert_glsl,
 	        (is_shadow) ? datatoc_shadow_geom_glsl : NULL,
 	        frag_str,
@@ -786,8 +786,8 @@ struct GPUMaterial *EEVEE_material_hair_get(
 
 	char *defines = eevee_get_defines(options);
 
-	mat = GPU_material_from_nodetree(
-	        scene, ma->nodetree, &ma->gpumaterial, engine, options,
+	mat = DRW_shader_create_from_material(
+	        scene, ma, engine, options,
 	        datatoc_lit_surface_vert_glsl, NULL, e_data.frag_shader_lib,
 	        defines);
 
@@ -883,17 +883,24 @@ void EEVEE_materials_cache_init(EEVEE_Data *vedata)
 			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);
-				grp = DRW_shgroup_material_create(gpumat, psl->background_pass);
 
-				if (grp) {
-					DRW_shgroup_uniform_float(grp, "backgroundAlpha", &stl->g_data->background_alpha, 1);
-					DRW_shgroup_call_add(grp, geom, NULL);
-				}
-				else {
-					/* Shader failed : pink background */
-					static float pink[3] = {1.0f, 0.0f, 1.0f};
-					col = pink;
+				switch (GPU_material_status(gpumat)) {
+					case GPU_MAT_SUCCESS:
+						grp = DRW_shgroup_material_create(gpumat, psl->background_pass);
+						DRW_shgroup_uniform_float(grp, "backgroundAlpha", &stl->g_data->background_alpha, 1);
+						DRW_shgroup_call_add(grp, geom, NULL);
+						break;
+					case GPU_MAT_QUEUED:
+						/* TODO Bypass probe compilation. */
+						col = compile_col;
+						break;
+					case GPU_MAT_FAILED:
+					default:
+						col = error_col;
+						break;
 				}
 			}
 		}
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
index d8885bd77c5..4815c117a8c 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -268,6 +268,12 @@ 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(void);
+struct GPUMaterial *DRW_shader_create_from_world(
+        struct Scene *scene, struct World *wo, const void *engine_type, int options,
+        const char *vert, const char *geom, const char *frag_lib, const char *defines);
+struct GPUMaterial *DRW_shader_create_from_material(
+        struct Scene *scene, struct Material *ma, const void *engine_type, int options,
+        const char *vert, const char *geom, const char *frag_lib, const char *defines);
 void DRW_shader_free(struct GPUShader *shader);
 #define DRW_SHADER_FREE_SAFE(shader) do { \
 	if (shader != NULL) { \
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index 8feffa246ef..ac39bbf132a 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -1957,6 +1957,7 @@ void DRW_opengl_context_create(void)
 
 	immDeactivate();
 	/* This changes the active context. */
+	DRW_deferred_compiler_init();
 	DST.ogl_context = WM_opengl_context_create();
 	/* Be sure to create gawain.context too. */
 	DST.gwn_context = GWN_context_create();
@@ -1971,6 +1972,7 @@ void DRW_opengl_context_destroy(void)
 {
 	BLI_assert(BLI_thread_is_main());
 	if (DST.ogl_context != NULL) {
+		DRW_deferred_compiler_exit();
 		WM_opengl_context_activate(DST.ogl_context);
 		GWN_context_active_set(DST.gwn_context);
 		GWN_context_discard(DST.gwn_context);
diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h
index f8989a0703a..3c6682050cf 100644
--- a/source/blender/draw/intern/draw_manager.h
+++ b/source/blender/draw/intern/draw_manager.h
@@ -356,4 +356,7 @@ void *drw_viewport_engine_data_ensure(void *engine_type);
 
 void drw_state_set(DRWState state);
 
+void DRW_deferred_compiler_init(void);
+void DRW_deferred_compiler_exit(void);
+
 #endif /* __DRAW_MANAGER_H__ */
diff --git a/source/blender/draw/intern/draw_manager_shader.c b/source/blender/draw/intern/draw_manager_shader.c
index e9d2ac14e57..27605012993 100644
--- a/source/blender/draw/intern/draw_manager_shader.c
+++ b/source/blender/draw/intern/draw_manager_shader.c
@@ -25,15 +25,181 @@
 
 #include "draw_manager.h"
 
+#include "DNA_world_types.h"
+#include "DNA_material_types.h"
+
+#include "BLI_listbase.h"
 #include "BLI_string.h"
 #include "BLI_string_utils.h"
+#include "BLI_threads.h"
+#include "BLI_task.h"
 
 #include "GPU_shader.h"
+#include "GPU_material.h"
+
+#include "WM_api.h"
 
 extern char datatoc_gpu_shader_2D_vert_glsl[];
 extern char datatoc_gpu_shader_3D_vert_glsl[];
 extern char datatoc_gpu_shader_fullscreen_vert_glsl[];
 
+
+/* -------------------------------------------------------------------- */
+
+/** \name Deferred Compilation (DRW_deferred)
+ *
+ * Since compiling shader can take a long time, we do it in a non blocking
+ * manner in another thread.
+ *
+ * \{ */
+
+typedef struct DRWDeferredShader {
+	struct DRWDeferredShader *prev, *next;
+
+	GPUMaterial *mat;
+	char *vert, *geom, *frag, *defs;
+
+	ThreadMutex compilation_mutex;
+} DRWDeferredShader;
+
+typedef struct DRWShaderCompiler {
+	ListBase queue; /* DRWDeferredShader */
+	ThreadMutex list_mutex;
+
+	DRWDeferredShader *mat_compiling;
+	ThreadMutex compilation_mutex;
+
+	TaskScheduler *task_scheduler; /* NULL if nothing is running. */
+	TaskPool *task_pool;
+
+	void *ogl_context;
+} DRWShaderCompiler;
+
+static DRWShaderCompiler DSC = {{NULL}};
+
+static void drw_deferred_shader_free(DRWDeferredShader *dsh)
+{
+	/* Make sure it is not queued before freeing. */
+	BLI_assert(BLI_findindex(&DSC.queue, dsh) == -1);
+
+	MEM_SAFE_FREE(dsh->vert);
+	MEM_SAFE_FREE(dsh->geom);
+	MEM_SAFE_FREE(dsh->frag);
+	MEM_SAFE_FREE(dsh->defs);
+
+	MEM_freeN(dsh);
+}
+
+static void drw_deferred_shader_compilation_exec(TaskPool * __restrict UNUSED(pool), void *UNUSED(taskdata), int UNUSED(threadid))
+{
+	WM_opengl_context_activate(DSC.ogl_context);
+
+	while (true) {
+		BLI_mutex_lock(&DSC.list_mutex);
+		DSC.mat_compiling = BLI_pophead(&DSC.queue);
+		if (DSC.mat_compiling == NULL) {
+			break;
+		}
+		BLI_mutex_lock(&DSC.compilation_mutex);
+		BLI_mutex_unlock(&DSC.list_mutex);
+
+		/* Do the compilation. */
+		GPU_material_generate_pass(
+		        DSC.mat_compiling->mat,
+		        DSC.mat_compiling->vert,
+		        DSC.mat_compiling->geom,
+		        DSC.mat_compiling->frag,
+		        DSC.mat_compiling->defs);
+
+		BLI_mutex_unlock(&DSC.compilation_mutex);
+
+		drw_deferred_shader_free(DSC.mat_compiling);
+	}
+
+	WM_opengl_context_release(DSC.ogl_context);
+	BLI_mutex_unloc

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list