[Bf-blender-cvs] [18d05660130] blender2.8: Curve Batch Cache: Add back support for shaded geometry

Clément Foucault noreply at git.blender.org
Fri Dec 14 16:36:16 CET 2018


Commit: 18d056601303b96fcc934c639421e1fd59b36b63
Author: Clément Foucault
Date:   Fri Dec 14 00:42:16 2018 +0100
Branches: blender2.8
https://developer.blender.org/rB18d056601303b96fcc934c639421e1fd59b36b63

Curve Batch Cache: Add back support for shaded geometry

This changes a bit the batches data structure. Instead of using one
vbo per material we use one for all material and use index buffers for
selecting the correct triangles.

This is less optimized than before but has potential to become more
optimized by merging the wireframe data vbo into the shading one.

Also the index buffers are not strictly necessary and could be just
ranges inside the buffer. But this needs more adding things inside
GPUIndexBuf.

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

M	source/blender/draw/intern/draw_cache.c
M	source/blender/draw/intern/draw_cache_impl.h
M	source/blender/draw/intern/draw_cache_impl_curve.c
M	source/blender/draw/intern/draw_cache_impl_displist.c
M	source/blender/draw/intern/draw_cache_impl_metaball.c

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

diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c
index 3e49d890327..dbd05baa144 100644
--- a/source/blender/draw/intern/draw_cache.c
+++ b/source/blender/draw/intern/draw_cache.c
@@ -3703,7 +3703,7 @@ bool DRW_ibo_requested(GPUIndexBuf *ibo)
 {
 	/* TODO do not rely on data uploaded. This prevents multithreading.
 	 * (need access to a gl context) */
-	return (ibo != NULL && ibo->ibo_id == 0);
+	return (ibo != NULL && ibo->ibo_id == 0 && ibo->data == NULL);
 }
 
 void DRW_vbo_request(GPUBatch *batch, GPUVertBuf **vbo)
diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h
index 6df7a896ffa..114d694041e 100644
--- a/source/blender/draw/intern/draw_cache_impl.h
+++ b/source/blender/draw/intern/draw_cache_impl.h
@@ -82,13 +82,13 @@ struct GPUBatch **DRW_metaball_batch_cache_get_surface_shaded(struct Object *ob,
 struct GPUBatch *DRW_metaball_batch_cache_get_wireframes_face(struct Object *ob);
 
 /* DispList */
-struct GPUVertBuf *DRW_displist_vertbuf_calc_pos_with_normals(struct ListBase *lb, struct GPUVertBuf *vbo);
-struct GPUIndexBuf *DRW_displist_indexbuf_calc_triangles_in_order(struct ListBase *lb, struct GPUIndexBuf *vbo);
-struct GPUIndexBuf **DRW_displist_indexbuf_calc_triangles_in_order_split_by_material(
-        struct ListBase *lb, uint gpumat_array_len);
-struct GPUBatch **DRW_displist_batch_calc_tri_pos_normals_and_uv_split_by_material(
-        struct ListBase *lb, uint gpumat_array_len);
-struct GPUBatch *DRW_displist_create_edges_overlay_batch(ListBase *lb, struct GPUVertBuf *vbo);
+void DRW_displist_vertbuf_create_pos_and_nor(struct ListBase *lb, struct GPUVertBuf *vbo);
+void DRW_displist_vertbuf_create_pos_and_nor_and_uv_tess(
+        struct ListBase *lb, struct GPUVertBuf *vbo_pos_nor, struct GPUVertBuf *vbo_uv);
+void DRW_displist_vertbuf_create_wireframe_data_tess(struct ListBase *lb, struct GPUVertBuf *vbo);
+void DRW_displist_indexbuf_create_triangles_in_order(struct ListBase *lb, struct GPUIndexBuf *vbo);
+void DRW_displist_indexbuf_create_triangles_tess_split_by_material(
+        struct ListBase *lb, struct GPUIndexBuf **ibo_mat, uint mat_len);
 
 /* Lattice */
 struct GPUBatch *DRW_lattice_batch_cache_get_all_edges(struct Lattice *lt, bool use_weight, const int actdef);
diff --git a/source/blender/draw/intern/draw_cache_impl_curve.c b/source/blender/draw/intern/draw_cache_impl_curve.c
index ac991336e05..a2bf950e129 100644
--- a/source/blender/draw/intern/draw_cache_impl_curve.c
+++ b/source/blender/draw/intern/draw_cache_impl_curve.c
@@ -40,6 +40,7 @@
 
 #include "GPU_batch.h"
 #include "GPU_texture.h"
+#include "GPU_material.h"
 
 #include "UI_resources.h"
 
@@ -297,6 +298,47 @@ static int curve_render_data_normal_len_get(const CurveRenderData *rdata)
 	return rdata->normal.len;
 }
 
+static void curve_cd_calc_used_gpu_layers(int *cd_layers, struct GPUMaterial **gpumat_array, int gpumat_array_len)
+{
+	GPUVertexAttribs gattribs = {{{0}}};
+	for (int i = 0; i < gpumat_array_len; i++) {
+		struct GPUMaterial *gpumat = gpumat_array[i];
+		if (gpumat == NULL) {
+			continue;
+		}
+		GPU_material_vertex_attributes(gpumat, &gattribs);
+		for (int j = 0; j < gattribs.totlayer; j++) {
+			const char *name = gattribs.layer[j].name;
+			int type = gattribs.layer[j].type;
+
+			/* Curves cannot have named layers.
+			 * Note: We could relax this assumption later. */
+			if (name[0] != '\0') {
+				continue;
+			}
+
+			if (type == CD_AUTO_FROM_NAME) {
+				type = CD_MTFACE;
+			}
+
+			switch (type) {
+				case CD_MTFACE:
+					*cd_layers |= CD_MLOOPUV;
+					break;
+				case CD_TANGENT:
+					/* Currently unsupported */
+					// *cd_layers |= CD_TANGENT;
+					break;
+				case CD_MCOL:
+					/* Curve object don't have Color data. */
+					break;
+				case CD_ORCO:
+					*cd_layers |= CD_ORCO;
+					break;
+			}
+		}
+	}
+}
 
 /* ---------------------------------------------------------------------- */
 /* Curve GPUBatch Cache */
@@ -310,6 +352,7 @@ typedef struct CurveBatchCache {
 
 	struct {
 		GPUVertBuf *pos_nor;
+		GPUVertBuf *uv;
 
 		GPUVertBuf *wireframe_data;
 	} tess;
@@ -346,6 +389,7 @@ typedef struct CurveBatchCache {
 	GPUIndexBuf **surf_per_mat_tris;
 	GPUBatch **surf_per_mat;
 	int mat_len;
+	int cd_used, cd_needed;
 
 	/* settings to determine if cache is invalid */
 	bool is_dirty;
@@ -362,6 +406,10 @@ static bool curve_batch_cache_valid(Curve *cu)
 		return false;
 	}
 
+	if (cache->mat_len != max_ii(1, cu->totcol)) {
+		return false;
+	}
+
 	if (cache->is_dirty) {
 		return false;
 	}
@@ -401,6 +449,17 @@ static void curve_batch_cache_init(Curve *cu)
 	}
 #endif
 
+	cache->cd_used = 0;
+	cache->mat_len = max_ii(1, cu->totcol);
+	cache->surf_per_mat_tris = MEM_mallocN(sizeof(*cache->surf_per_mat_tris) * cache->mat_len, __func__);
+	cache->surf_per_mat = MEM_mallocN(sizeof(*cache->surf_per_mat) * cache->mat_len, __func__);
+
+	/* TODO Might be wiser to alloc in one chunck. */
+	for (int i = 0; i < cache->mat_len; ++i) {
+		cache->surf_per_mat_tris[i] = MEM_callocN(sizeof(GPUIndexBuf), "GPUIndexBuf");
+		cache->surf_per_mat[i] = MEM_callocN(sizeof(GPUBatch), "GPUBatch");
+	}
+
 	cache->is_editmode = (cu->editnurb != NULL) || (cu->editfont != NULL);
 
 	cache->is_dirty = false;
@@ -472,6 +531,7 @@ static void curve_batch_cache_clear(Curve *cu)
 	MEM_SAFE_FREE(cache->surf_per_mat_tris);
 	MEM_SAFE_FREE(cache->surf_per_mat);
 	cache->mat_len = 0;
+	cache->cd_used = 0;
 }
 
 void DRW_curve_batch_cache_free(Curve *cu)
@@ -786,46 +846,16 @@ GPUBatch **DRW_curve_batch_cache_get_surface_shaded(
         struct Curve *cu,
         struct GPUMaterial **gpumat_array, uint gpumat_array_len)
 {
-#if 0
 	CurveBatchCache *cache = curve_batch_cache_get(cu);
 
-	if (cache->surface.mat_len != gpumat_array_len) {
-		GPU_BATCH_DISCARD_ARRAY_SAFE(cache->surface.shaded_triangles, cache->surface.mat_len);
-	}
-
-	if (cache->surface.shaded_triangles == NULL) {
-		CurveRenderData *rdata = curve_render_data_create(cu, ob_curve_cache, CU_DATATYPE_SURFACE);
-		ListBase *lb = &rdata->ob_curve_cache->disp;
-
-		cache->surface.mat_len = gpumat_array_len;
-		if (cu->flag & CU_UV_ORCO) {
-			cache->surface.shaded_triangles = DRW_displist_batch_calc_tri_pos_normals_and_uv_split_by_material(
-			        lb, gpumat_array_len);
-		}
-		else {
-			cache->surface.shaded_triangles = MEM_mallocN(
-			        sizeof(*cache->surface.shaded_triangles) * gpumat_array_len, __func__);
-			GPUIndexBuf **el = DRW_displist_indexbuf_calc_triangles_in_order_split_by_material(
-			        lb, gpumat_array_len);
-
-			if (cache->surface.verts == NULL) {
-				cache->surface.verts = DRW_displist_vertbuf_calc_pos_with_normals(lb);
-			}
-
-			for (int i = 0; i < gpumat_array_len; ++i) {
-				cache->surface.shaded_triangles[i] = GPU_batch_create_ex(
-				        GPU_PRIM_TRIS, cache->surface.verts, el[i], GPU_BATCH_OWNS_INDEX);
-			}
+	BLI_assert(gpumat_array_len == cache->mat_len);
 
-			MEM_freeN(el); /* Save `el` in cache? */
-		}
+	curve_cd_calc_used_gpu_layers(&cache->cd_needed, gpumat_array, gpumat_array_len);
 
-		curve_render_data_free(rdata);
+	for (int i = 0; i < cache->mat_len; ++i) {
+		DRW_batch_request(&cache->surf_per_mat[i]);
 	}
-
-	return cache->surface.shaded_triangles;
-#endif
-	return NULL;
+	return cache->surf_per_mat;
 }
 
 GPUBatch *DRW_curve_batch_cache_get_wireframes_face(Curve *cu)
@@ -847,6 +877,18 @@ void DRW_curve_batch_cache_create_requested(Object *ob)
 	Curve *me = (Curve *)ob->data;
 	CurveBatchCache *cache = curve_batch_cache_get(me);
 
+	/* Verify that all surface batches have needed attrib layers. */
+	/* TODO(fclem): We could be a bit smarter here and only do it per material. */
+	for (int i = 0; i < cache->mat_len; ++i) {
+		if ((cache->cd_used & cache->cd_needed) != cache->cd_needed) {
+			/* We can't discard batches at this point as they have been
+			 * referenced for drawing. Just clear them in place. */
+			GPU_batch_clear(cache->surf_per_mat[i]);
+			memset(cache->surf_per_mat[i], 0, sizeof(*cache->surf_per_mat[i]));
+		}
+	}
+	cache->cd_used = cache->cd_needed;
+
 	/* Init batches and request VBOs & IBOs */
 	if (DRW_batch_requested(cache->batch.surfaces, GPU_PRIM_TRIS)) {
 		DRW_ibo_request(cache->batch.surfaces, &cache->ibo.surfaces_tris);
@@ -857,7 +899,6 @@ void DRW_curve_batch_cache_create_requested(Object *ob)
 		DRW_vbo_request(cache->batch.curves, &cache->ordered.curves_pos);
 	}
 	if (DRW_batch_requested(cache->batch.wire_triangles, GPU_PRIM_TRIS)) {
-		DRW_vbo_request(cache->batch.wire_triangles, &cache->tess.pos_nor);
 		DRW_vbo_request(cache->batch.wire_triangles, &cache->tess.wireframe_data);
 	}
 
@@ -879,12 +920,24 @@ void DRW_curve_batch_cache_create_requested(Object *ob)
 	if (DRW_batch_requested(cache->batch.edit_normals, GPU_PRIM_LINES)) {
 		DRW_vbo_request(cache->batch.edit_normals, &cache->edit.curves_nor);
 	}
+	for (int i = 0; i < cache->mat_len; ++i) {
+		if (DRW_batch_requested(cache->surf_per_mat[i], GPU_PRIM_TRIS)) {
+			if (cache->mat_len > 1) {
+				DRW_ibo_request(cache->surf_per_mat[i], &cache->surf_per_mat_tris[i]);
+			}
+			if (cache->cd_used & CD_MLOOPUV) {
+				DRW_vbo_request(cache->surf_per_mat[i], &cache->tess.uv);
+			}
+			DRW_vbo_request(cache->surf_per_mat[i], &cache->tess.pos_nor);
+		}
+	}
 
 	/* Generate MeshRenderData flags */
 	int mr_flag = 0;
 	DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->ordered.pos_nor, CU_DATATYPE_SURFACE);
 	DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->ordered.curves_pos, CU_DATATYPE_WIRE);
 	DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->tess.pos_nor, CU_DATATYPE_SURFACE);
+	DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->tess.uv, CU_DATATYPE_SURFACE);
 	DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_flag, cache->tess.wireframe_data, CU_DATATYPE_SURFACE);
 	DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->ibo.surfaces_tris, CU_DATATYPE_SURFACE);
 	DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->ibo.curves_lines, CU_DATATYPE_WIRE);
@@ -896,6 +949,10 @@ void DRW_curve_batch_cache_create_requested(Object *ob)
 	DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->ibo.edit_verts_points, CU_DATATYPE_OVERLAY);
 	DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_flag, cache->ibo.edit_lines, CU_DATATYPE_OVER

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list