[Bf-blender-cvs] [13261304a33] blender2.8: DRW: Add new Draw Manager OpenGL Context.

Clément Foucault noreply at git.blender.org
Mon Feb 26 20:10:14 CET 2018


Commit: 13261304a331b4cff37de477ddf19c915ed64b2c
Author: Clément Foucault
Date:   Mon Feb 26 19:41:17 2018 +0100
Branches: blender2.8
https://developer.blender.org/rB13261304a331b4cff37de477ddf19c915ed64b2c

DRW: Add new Draw Manager OpenGL Context.

This separate context allows two things:
- It allows viewports in multi-windows configuration.
- F12 render can use this context in a separate thread and do a non-blocking render.

The downside is that the context cannot be used while rendering so a request to refresh a viewport will lock the UI. This is something that will be adressed in the future.

Under the hood what does that mean:
- Not adding more mess with VAOs management in gawain.
- Doing depth only draw for operators / selection needs to be done in an offscreen buffer.
- The 3D cursor "autodis" operator is still reading the backbuffer so we need to copy the result to it.
- All FBOs needed by the drawmanager must to be created/destroyed with its context active.
- We cannot use batches created for UI in the DRW context and vice-versa. There is a clear separation of resources that enables the use of safe multi-threading.

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

M	source/blender/draw/DRW_engine.h
M	source/blender/draw/intern/draw_cache.c
M	source/blender/draw/intern/draw_manager.c
M	source/blender/editors/render/render_internal.c
M	source/blender/editors/render/render_opengl.c
M	source/blender/editors/space_view3d/space_view3d.c
M	source/blender/editors/space_view3d/view3d_draw.c
M	source/blender/editors/space_view3d/view3d_view.c
M	source/blender/gpu/CMakeLists.txt
M	source/blender/gpu/GPU_batch.h
M	source/blender/gpu/GPU_shader.h
M	source/blender/gpu/intern/gpu_batch_presets.c
M	source/blender/gpu/intern/gpu_shader.c
M	source/blender/gpu/intern/gpu_viewport.c
A	source/blender/gpu/shaders/gpu_shader_image_depth_copy_frag.glsl
M	source/blender/windowmanager/CMakeLists.txt
M	source/blender/windowmanager/WM_api.h
M	source/blender/windowmanager/intern/wm_init_exit.c
M	source/blender/windowmanager/intern/wm_window.c
M	source/blender/windowmanager/wm_window.h

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

diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h
index 9baad113c42..9ed8f776f34 100644
--- a/source/blender/draw/DRW_engine.h
+++ b/source/blender/draw/DRW_engine.h
@@ -125,4 +125,9 @@ void EDIT_ARMATURE_collection_settings_create(struct IDProperty *properties);
 void PAINT_WEIGHT_collection_settings_create(struct IDProperty *properties);
 void PAINT_VERTEX_collection_settings_create(struct IDProperty *properties);
 
+void DRW_opengl_context_create(void);
+void DRW_opengl_context_destroy(void);
+void DRW_opengl_context_enable(void);
+void DRW_opengl_context_disable(void);
+
 #endif /* __DRW_ENGINE_H__ */
diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c
index 3b4180c0375..6b1a3356b51 100644
--- a/source/blender/draw/intern/draw_cache.c
+++ b/source/blender/draw/intern/draw_cache.c
@@ -45,6 +45,7 @@ static struct DRWShapeCache {
 	Gwn_Batch *drw_single_vertice;
 	Gwn_Batch *drw_fullscreen_quad;
 	Gwn_Batch *drw_quad;
+	Gwn_Batch *drw_sphere;
 	Gwn_Batch *drw_screenspace_circle;
 	Gwn_Batch *drw_plain_axes;
 	Gwn_Batch *drw_single_arrow;
@@ -266,7 +267,6 @@ Gwn_Batch *DRW_cache_fullscreen_quad_get(void)
 Gwn_Batch *DRW_cache_quad_get(void)
 {
 	if (!SHC.drw_quad) {
-		/* Use a triangle instead of a real quad */
 		float pos[4][2] = {{-1.0f, -1.0f}, { 1.0f, -1.0f}, {1.0f,  1.0f}, {-1.0f,  1.0f}};
 		float uvs[4][2] = {{ 0.0f,  0.0f}, { 1.0f,  0.0f}, {1.0f,  1.0f}, { 0.0f,  1.0f}};
 
@@ -294,7 +294,10 @@ Gwn_Batch *DRW_cache_quad_get(void)
 /* Sphere */
 Gwn_Batch *DRW_cache_sphere_get(void)
 {
-	return GPU_batch_preset_sphere(2);
+	if (!SHC.drw_sphere) {
+		SHC.drw_sphere = gpu_batch_sphere(32, 24);
+	}
+	return SHC.drw_sphere;
 }
 
 /** \} */
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index 99ea5b259c0..3845ee6a65e 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -30,6 +30,7 @@
 #include "BLI_rect.h"
 #include "BLI_string.h"
 #include "BLI_string_utils.h"
+#include "BLI_threads.h"
 
 #include "BIF_glutil.h"
 
@@ -82,6 +83,7 @@
 
 #include "WM_api.h"
 #include "WM_types.h"
+#include "wm_window.h"
 
 #include "draw_manager_text.h"
 #include "draw_manager_profiling.h"
@@ -97,6 +99,8 @@
 #include "engines/basic/basic_engine.h"
 #include "engines/external/external_engine.h"
 
+#include "../../../intern/gawain/gawain/gwn_context.h"
+
 #include "DEG_depsgraph.h"
 #include "DEG_depsgraph_query.h"
 
@@ -369,6 +373,13 @@ static struct DRWMatrixOveride {
 
 ListBase DRW_engines = {NULL, NULL};
 
+/* Unique ghost context used by the draw manager. */
+static void *g_ogl_context = NULL;
+static Gwn_Context *g_gwn_context = NULL;
+
+/* Mutex to lock the drw manager and avoid concurent context usage. */
+static ThreadMutex g_ogl_context_mutex = BLI_MUTEX_INITIALIZER;
+
 #ifdef USE_GPU_SELECT
 static unsigned int g_DRW_select_id = (unsigned int)-1;
 
@@ -3440,6 +3451,7 @@ void DRW_draw_render_loop_ex(
         ARegion *ar, View3D *v3d, const eObjectMode object_mode,
         const bContext *evil_C)
 {
+
 	Scene *scene = DEG_get_evaluated_scene(depsgraph);
 	ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
 	RegionView3D *rv3d = ar->regiondata;
@@ -3626,6 +3638,11 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph)
 	RenderData *r = &scene->r;
 	Render *render = engine->re;
 	const EvaluationContext *eval_ctx = RE_GetEvalCtx(render);
+	/* Changing Context */
+	DRW_opengl_context_enable();
+	/* IMPORTANT: We dont support immediate mode in render mode!
+	 * This shall remain in effect until immediate mode supports
+	 * multiple threads. */
 
 	/* Reset before using it. */
 	memset(&DST, 0x0, sizeof(DST));
@@ -3705,6 +3722,9 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph)
 	glEnable(GL_SCISSOR_TEST);
 	GPU_framebuffer_restore();
 
+	/* Changing Context */
+	DRW_opengl_context_disable();
+
 #ifdef DEBUG
 	/* Avoid accidental reuse. */
 	memset(&DST, 0xFF, sizeof(DST));
@@ -3722,6 +3742,37 @@ void DRW_render_object_iter(
 	DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END
 }
 
+static struct DRWSelectBuffer {
+	struct GPUFrameBuffer *framebuffer;
+	struct GPUTexture *texture_depth;
+} g_select_buffer = {NULL};
+
+static void draw_select_framebuffer_setup(const rcti *rect)
+{
+	if (g_select_buffer.framebuffer == NULL) {
+		g_select_buffer.framebuffer = GPU_framebuffer_create();
+	}
+
+	/* If size mismatch recreate the texture. */
+	if ((g_select_buffer.texture_depth != NULL) &&
+		((GPU_texture_width(g_select_buffer.texture_depth) != BLI_rcti_size_x(rect)) ||
+		(GPU_texture_height(g_select_buffer.texture_depth) != BLI_rcti_size_y(rect))))
+	{
+		GPU_texture_free(g_select_buffer.texture_depth);
+		g_select_buffer.texture_depth = NULL;
+	}
+
+	if (g_select_buffer.texture_depth == NULL) {
+		g_select_buffer.texture_depth = GPU_texture_create_depth(BLI_rcti_size_x(rect), BLI_rcti_size_y(rect), NULL);
+
+		GPU_framebuffer_texture_attach(g_select_buffer.framebuffer, g_select_buffer.texture_depth, 0, 0);
+
+		if (!GPU_framebuffer_check_valid(g_select_buffer.framebuffer, NULL)) {
+			printf("Error invalid selection framebuffer\n");
+		}
+	}
+}
+
 /* Must run after all instance datas have been added. */
 void DRW_render_instance_buffer_finish(void)
 {
@@ -3767,13 +3818,20 @@ void DRW_draw_select_loop(
 		}
 	}
 
+	gpuPushAttrib(GPU_ENABLE_BIT | GPU_VIEWPORT_BIT);
+	glDisable(GL_SCISSOR_TEST);
+
 	struct GPUViewport *viewport = GPU_viewport_create();
 	GPU_viewport_size_set(viewport, (const int[2]){BLI_rcti_size_x(rect), BLI_rcti_size_y(rect)});
 
-	bool cache_is_dirty;
 	DST.viewport = viewport;
 	v3d->zbuf = true;
 
+	/* Setup framebuffer */
+	draw_select_framebuffer_setup(rect);
+	GPU_framebuffer_bind(g_select_buffer.framebuffer);
+	DRW_framebuffer_clear(false, true, false, NULL, 1.0f);
+
 	DST.options.is_select = true;
 
 	/* Get list of enabled engines */
@@ -3786,7 +3844,6 @@ void DRW_draw_select_loop(
 	}
 
 	/* Setup viewport */
-	cache_is_dirty = true;
 
 	/* Instead of 'DRW_context_state_init(C, &DST.draw_ctx)', assign from args */
 	DST.draw_ctx = (DRWContextState){
@@ -3802,10 +3859,7 @@ void DRW_draw_select_loop(
 	/* Init engines */
 	drw_engines_init();
 
-	/* TODO : tag to refresh by the dependency graph */
-	/* ideally only refresh when objects are added/removed */
-	/* or render properties / materials change */
-	if (cache_is_dirty) {
+	{
 		drw_engines_cache_init();
 
 		if (use_obedit) {
@@ -3843,16 +3897,57 @@ void DRW_draw_select_loop(
 	/* Avoid accidental reuse. */
 	memset(&DST, 0xFF, sizeof(DST));
 #endif
+	GPU_framebuffer_restore();
 
 	/* Cleanup for selection state */
 	GPU_viewport_free(viewport);
 	MEM_freeN(viewport);
 
+	/* Restore Drawing area. */
+	gpuPopAttrib();
+	glEnable(GL_SCISSOR_TEST);
+
 	/* restore */
 	rv3d->viewport = backup_viewport;
 #endif  /* USE_GPU_SELECT */
 }
 
+static void draw_depth_texture_to_screen(GPUTexture *texture)
+{
+	const float w = (float)GPU_texture_width(texture);
+	const float h = (float)GPU_texture_height(texture);
+
+	Gwn_VertFormat *format = immVertexFormat();
+	unsigned int texcoord = GWN_vertformat_attr_add(format, "texCoord", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+	unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+
+	immBindBuiltinProgram(GPU_SHADER_3D_IMAGE_DEPTH_COPY);
+
+	GPU_texture_bind(texture, 0);
+
+	immUniform1i("image", 0); /* default GL_TEXTURE0 unit */
+
+	immBegin(GWN_PRIM_TRI_STRIP, 4);
+
+	immAttrib2f(texcoord, 0.0f, 0.0f);
+	immVertex2f(pos, 0.0f, 0.0f);
+
+	immAttrib2f(texcoord, 1.0f, 0.0f);
+	immVertex2f(pos, w, 0.0f);
+
+	immAttrib2f(texcoord, 0.0f, 1.0f);
+	immVertex2f(pos, 0.0f, h);
+
+	immAttrib2f(texcoord, 1.0f, 1.0f);
+	immVertex2f(pos, w, h);
+
+	immEnd();
+
+	GPU_texture_unbind(texture);
+
+	immUnbindProgram();
+}
+
 /**
  * object mode select-loop, see: ED_view3d_draw_depth_loop (legacy drawing).
  */
@@ -3865,6 +3960,8 @@ void DRW_draw_depth_loop(
 	ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
 	RegionView3D *rv3d = ar->regiondata;
 
+	DRW_opengl_context_enable();
+
 	/* backup (_never_ use rv3d->viewport) */
 	void *backup_viewport = rv3d->viewport;
 	rv3d->viewport = NULL;
@@ -3872,9 +3969,17 @@ void DRW_draw_depth_loop(
 	/* Reset before using it. */
 	memset(&DST, 0x0, sizeof(DST));
 
+	gpuPushAttrib(GPU_ENABLE_BIT | GPU_VIEWPORT_BIT);
+	glDisable(GL_SCISSOR_TEST);
+
 	struct GPUViewport *viewport = GPU_viewport_create();
 	GPU_viewport_size_set(viewport, (const int[2]){ar->winx, ar->winy});
 
+	/* Setup framebuffer */
+	draw_select_framebuffer_setup(&ar->winrct);
+	GPU_framebuffer_bind(g_select_buffer.framebuffer);
+	DRW_framebuffer_clear(false, true, false, NULL, 1.0f);
+
 	bool cache_is_dirty;
 	DST.viewport = viewport;
 	v3d->zbuf = true;
@@ -3935,10 +4040,35 @@ void DRW_draw_depth_loop(
 	memset(&DST, 0xFF, sizeof(DST));
 #endif
 
+	/* TODO: Reading depth for operators should be done here. */
+
+	GPU_framebuffer_restore();
+
 	/* Cleanup for selection state */
 	GPU_viewport_free(viewport);
 	MEM_freeN(viewport);
 
+	/* Restore Drawing area. */
+	gpuPopAttrib();
+	glEnable(GL_SCISSOR_TEST);
+
+	/* Changin context */
+	DRW_opengl_context_disable();
+
+	/* XXX Drawing the resulting buffer to the BACK_BUFFER */
+	gpuPushMatrix();
+	gpuPushProjectionMatrix();
+	wmOrtho2_region_pixelspace(ar);
+	gpuLoadIdentity();
+
+	glEnable(GL_DEPTH_TEST); /* Cannot write to depth buffer without testing */
+	glDepthFunc(GL_ALWAYS);
+	draw_depth_texture_to_screen(g_select_buffer.texture_depth);
+	glDepthFunc(GL_LEQUAL);
+
+	gpuPopMatrix();
+	gpuPopProjectionMatrix();
+
 	/* restore */
 	rv3d->viewport = backup_viewport;
 }
@@ -4139,6 +4269,11 @@ extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */
 extern struct GPUTexture *globals_ramp; /* draw_common.c */
 void DRW_engines_free(void)
 {
+	DRW_opengl_context_enable();
+
+	DRW_TEXTURE_FREE_SAFE(g_select_buffer.texture_depth);
+	DRW_FRAMEBUFFER_FREE_SAFE(g_select_buffer.framebuffer);
+
 	DRW_shape_cache_free();
 	DRW_stats_free();
 	DRW_globals_free();
@@ -4164,9 +4299,86 @@ void DRW_engines_free(void)
 	MEM_SAFE_FREE(RS

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list