diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2019-07-14 17:49:44 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2019-08-14 20:05:26 +0300 |
commit | 9c010c44f4201ab114b3facc69d0343525a1779f (patch) | |
tree | 744271becd24cead6c900e4f023d8c0bfa6138b6 /source/blender/draw/intern/draw_cache_extract.h | |
parent | 45a45f7d66211e82a3a3288782ad9523e8fdc516 (diff) |
Mesh Batch Cache: Refactor + Multithread
For clarity sake, the batch cache now uses exclusively per Loop attributes.
While this is a bit of a waste of VRAM (for the few case where per vert
attribs are enough) it reduces the complexity and amount of overall VBO
to update in general situations.
This patch also makes the VertexBuffers filling multithreaded. This make
the update of dense meshes a bit faster. The main bottleneck is the
IndexBuffers update which cannot be multithreaded efficiently (have to
increment a counter and/or do a final sorting pass).
We introduce the concept of "extract" functions/step.
All extract functions are executed in one thread each and if possible,
using multiple thread for looping over all elements.
Reviewed By: brecht
Differential Revision: http://developer.blender.org/D5424
Diffstat (limited to 'source/blender/draw/intern/draw_cache_extract.h')
-rw-r--r-- | source/blender/draw/intern/draw_cache_extract.h | 249 |
1 files changed, 249 insertions, 0 deletions
diff --git a/source/blender/draw/intern/draw_cache_extract.h b/source/blender/draw/intern/draw_cache_extract.h new file mode 100644 index 00000000000..5a06210fe8e --- /dev/null +++ b/source/blender/draw/intern/draw_cache_extract.h @@ -0,0 +1,249 @@ +/* + * 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 2019, Blender Foundation. + */ + +/** \file + * \ingroup draw + */ + +#ifndef __DRAW_CACHE_EXTRACT_MESH_H__ +#define __DRAW_CACHE_EXTRACT_MESH_H__ + +/* Vertex Group Selection and display options */ +typedef struct DRW_MeshWeightState { + int defgroup_active; + int defgroup_len; + + short flags; + char alert_mode; + + /* Set of all selected bones for Multipaint. */ + bool *defgroup_sel; /* [defgroup_len] */ + int defgroup_sel_count; +} DRW_MeshWeightState; + +/* DRW_MeshWeightState.flags */ +enum { + DRW_MESH_WEIGHT_STATE_MULTIPAINT = (1 << 0), + DRW_MESH_WEIGHT_STATE_AUTO_NORMALIZE = (1 << 1), +}; + +typedef struct DRW_MeshCDMask { + uint32_t uv : 8; + uint32_t tan : 8; + uint32_t vcol : 8; + uint32_t orco : 1; + uint32_t tan_orco : 1; +} DRW_MeshCDMask; + +typedef enum eMRIterType { + MR_ITER_LOOPTRI = 1 << 0, + MR_ITER_LOOP = 1 << 1, + MR_ITER_LEDGE = 1 << 2, + MR_ITER_LVERT = 1 << 3, +} eMRIterType; + +typedef enum eMRDataType { + MR_DATA_POLY_NOR = 1 << 1, + MR_DATA_LOOP_NOR = 1 << 2, + MR_DATA_LOOPTRI = 1 << 3, + /** Force loop normals calculation. */ + MR_DATA_TAN_LOOP_NOR = 1 << 4, +} eMRDataType; + +typedef enum eMRExtractType { + MR_EXTRACT_BMESH, + MR_EXTRACT_MAPPED, + MR_EXTRACT_MESH, +} eMRExtractType; + +BLI_INLINE int mesh_render_mat_len_get(Mesh *me) +{ + return MAX2(1, me->totcol); +} + +typedef struct MeshBufferCache { + /* Every VBO below contains at least enough + * data for every loops in the mesh (except fdots). + * For some VBOs, it extends to (in this exact order) : + * loops + loose_edges*2 + loose_verts */ + struct { + GPUVertBuf *pos_nor; /* extend */ + GPUVertBuf *lnor; /* extend */ + GPUVertBuf *edge_fac; /* extend */ + GPUVertBuf *weights; /* extend */ + GPUVertBuf *uv_tan; + GPUVertBuf *vcol; + GPUVertBuf *orco; + /* Only for edit mode. */ + GPUVertBuf *edit_data; /* extend */ + GPUVertBuf *edituv_data; + GPUVertBuf *stretch_area; + GPUVertBuf *stretch_angle; + GPUVertBuf *mesh_analysis; + GPUVertBuf *fdots_pos; + GPUVertBuf *fdots_nor; + GPUVertBuf *fdots_uv; + // GPUVertBuf *fdots_edit_data; /* inside fdots_nor for now. */ + GPUVertBuf *fdots_edituv_data; + /* Selection */ + GPUVertBuf *vert_idx; /* extend */ + GPUVertBuf *edge_idx; /* extend */ + GPUVertBuf *poly_idx; + GPUVertBuf *fdot_idx; + } vbo; + /* Index Buffers: + * Only need to be updated when topology changes. */ + struct { + /* Indices to vloops. */ + GPUIndexBuf *tris; /* Ordered per material. */ + GPUIndexBuf *lines; /* Loose edges last. */ + GPUIndexBuf *points; + GPUIndexBuf *fdots; + /* 3D overlays. */ + GPUIndexBuf *lines_paint_mask; /* no loose edges. */ + GPUIndexBuf *lines_adjacency; + /* Uv overlays. (visibility can differ from 3D view) */ + GPUIndexBuf *edituv_tris; + GPUIndexBuf *edituv_lines; + GPUIndexBuf *edituv_points; + GPUIndexBuf *edituv_fdots; + } ibo; +} MeshBufferCache; + +typedef enum DRWBatchFlag { + MBC_SURFACE = (1 << 0), + MBC_SURFACE_WEIGHTS = (1 << 1), + MBC_EDIT_TRIANGLES = (1 << 2), + MBC_EDIT_VERTICES = (1 << 3), + MBC_EDIT_EDGES = (1 << 4), + MBC_EDIT_VNOR = (1 << 5), + MBC_EDIT_LNOR = (1 << 6), + MBC_EDIT_FACEDOTS = (1 << 7), + MBC_EDIT_MESH_ANALYSIS = (1 << 8), + MBC_EDITUV_FACES_STRECH_AREA = (1 << 9), + MBC_EDITUV_FACES_STRECH_ANGLE = (1 << 10), + MBC_EDITUV_FACES = (1 << 11), + MBC_EDITUV_EDGES = (1 << 12), + MBC_EDITUV_VERTS = (1 << 13), + MBC_EDITUV_FACEDOTS = (1 << 14), + MBC_EDIT_SELECTION_VERTS = (1 << 15), + MBC_EDIT_SELECTION_EDGES = (1 << 16), + MBC_EDIT_SELECTION_FACES = (1 << 17), + MBC_EDIT_SELECTION_FACEDOTS = (1 << 18), + MBC_ALL_VERTS = (1 << 19), + MBC_ALL_EDGES = (1 << 20), + MBC_LOOSE_EDGES = (1 << 21), + MBC_EDGE_DETECTION = (1 << 22), + MBC_WIRE_EDGES = (1 << 23), + MBC_WIRE_LOOPS = (1 << 24), + MBC_WIRE_LOOPS_UVS = (1 << 25), + MBC_SURF_PER_MAT = (1 << 26), +} DRWBatchFlag; + +#define MBC_EDITUV \ + (MBC_EDITUV_FACES_STRECH_AREA | MBC_EDITUV_FACES_STRECH_ANGLE | MBC_EDITUV_FACES | \ + MBC_EDITUV_EDGES | MBC_EDITUV_VERTS | MBC_EDITUV_FACEDOTS | MBC_WIRE_LOOPS_UVS) + +#define FOREACH_MESH_BUFFER_CACHE(batch_cache, mbc) \ + for (MeshBufferCache *mbc = &batch_cache->final; \ + mbc == &batch_cache->final || mbc == &batch_cache->cage || mbc == &batch_cache->uv_cage; \ + mbc = (mbc == &batch_cache->final) ? \ + &batch_cache->cage : \ + ((mbc == &batch_cache->cage) ? &batch_cache->uv_cage : NULL)) + +typedef struct MeshBatchCache { + MeshBufferCache final, cage, uv_cage; + + struct { + /* Surfaces / Render */ + GPUBatch *surface; + GPUBatch *surface_weights; + /* Edit mode */ + GPUBatch *edit_triangles; + GPUBatch *edit_vertices; + GPUBatch *edit_edges; + GPUBatch *edit_vnor; + GPUBatch *edit_lnor; + GPUBatch *edit_fdots; + GPUBatch *edit_mesh_analysis; + /* Edit UVs */ + GPUBatch *edituv_faces_strech_area; + GPUBatch *edituv_faces_strech_angle; + GPUBatch *edituv_faces; + GPUBatch *edituv_edges; + GPUBatch *edituv_verts; + GPUBatch *edituv_fdots; + /* Edit selection */ + GPUBatch *edit_selection_verts; + GPUBatch *edit_selection_edges; + GPUBatch *edit_selection_faces; + GPUBatch *edit_selection_fdots; + /* Common display / Other */ + GPUBatch *all_verts; + GPUBatch *all_edges; + GPUBatch *loose_edges; + GPUBatch *edge_detection; + GPUBatch *wire_edges; /* Individual edges with face normals. */ + GPUBatch *wire_loops; /* Loops around faces. no edges between selected faces */ + GPUBatch *wire_loops_uvs; /* Same as wire_loops but only has uvs. */ + } batch; + + GPUBatch **surface_per_mat; + + /* arrays of bool uniform names (and value) that will be use to + * set srgb conversion for auto attributes.*/ + char *auto_layer_names; + int *auto_layer_is_srgb; + int auto_layer_len; + + DRWBatchFlag batch_requested; + DRWBatchFlag batch_ready; + + /* settings to determine if cache is invalid */ + int edge_len; + int tri_len; + int poly_len; + int vert_len; + int mat_len; + bool is_dirty; /* Instantly invalidates cache, skipping mesh check */ + bool is_editmode; + bool is_uvsyncsel; + + struct DRW_MeshWeightState weight_state; + + DRW_MeshCDMask cd_used, cd_needed, cd_used_over_time; + + int lastmatch; + + /* Valid only if edge_detection is up to date. */ + bool is_manifold; + + bool no_loose_wire; +} MeshBatchCache; + +void mesh_buffer_cache_create_requested(MeshBatchCache *cache, + MeshBufferCache mbc, + Mesh *me, + const bool do_final, + const bool do_uvedit, + const bool use_subsurf_fdots, + const DRW_MeshCDMask *cd_layer_used, + const ToolSettings *ts, + const bool use_hide); + +#endif /* __DRAW_CACHE_EXTRACT_MESH_H__ */ |