From 7ac49a07c60111fe75805a5eb72824ab7d0bc777 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Mon, 17 Dec 2018 11:37:27 +0100 Subject: [PATCH] Mesh Batch Cache: Port Texture paint batches to new batch request --- .../shaders/workbench_prepass_vert.glsl | 3 +- .../engines/workbench/workbench_deferred.c | 25 +-- .../engines/workbench/workbench_forward.c | 37 ++--- .../draw/intern/draw_cache_impl_mesh.c | 154 ++++++------------ .../blender/draw/modes/paint_texture_mode.c | 37 ++--- .../modes/shaders/paint_texture_vert.glsl | 5 +- source/blender/gpu/GPU_batch.h | 7 + 7 files changed, 95 insertions(+), 173 deletions(-) diff --git a/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl index 62040da8524..7c5b528c40d 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl @@ -8,7 +8,8 @@ uniform mat3 NormalMatrix; #ifndef HAIR_SHADER in vec3 pos; in vec3 nor; -in vec2 uv; +in vec2 u; /* active texture layer */ +#define uv u #else /* HAIR_SHADER */ # ifdef V3D_SHADING_TEXTURE_COLOR uniform samplerBuffer u; /* active texture layer */ diff --git a/source/blender/draw/engines/workbench/workbench_deferred.c b/source/blender/draw/engines/workbench/workbench_deferred.c index 065efa4053a..617108b1bde 100644 --- a/source/blender/draw/engines/workbench/workbench_deferred.c +++ b/source/blender/draw/engines/workbench/workbench_deferred.c @@ -822,23 +822,16 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob) const Mesh *me = ob->data; if (me->mloopuv) { const int materials_len = MAX2(1, (is_sculpt_mode ? 1 : ob->totcol)); - struct GPUMaterial **gpumat_array = BLI_array_alloca(gpumat_array, materials_len); - struct GPUBatch **geom_array = me->totcol ? DRW_cache_mesh_surface_texpaint_get(ob) : NULL; - if (materials_len > 0 && geom_array) { - for (int i = 0; i < materials_len; i++) { - if (geom_array[i] == NULL) { - continue; - } - - Material *mat = give_current_material(ob, i + 1); - Image *image; - ED_object_get_active_image(ob, i + 1, &image, NULL, NULL, NULL); - int color_type = workbench_material_determine_color_type(wpd, image, ob); - material = get_or_create_material_data(vedata, ob, mat, image, color_type); - DRW_shgroup_call_object_add(material->shgrp, geom_array[i], ob); - } - is_drawn = true; + struct GPUBatch **geom_array = DRW_cache_mesh_surface_texpaint_get(ob); + for (int i = 0; i < materials_len; i++) { + Material *mat = give_current_material(ob, i + 1); + Image *image; + ED_object_get_active_image(ob, i + 1, &image, NULL, NULL, NULL); + int color_type = workbench_material_determine_color_type(wpd, image, ob); + material = get_or_create_material_data(vedata, ob, mat, image, color_type); + DRW_shgroup_call_object_add(material->shgrp, geom_array[i], ob); } + is_drawn = true; } } diff --git a/source/blender/draw/engines/workbench/workbench_forward.c b/source/blender/draw/engines/workbench/workbench_forward.c index 5ccf17f6113..3b755b31156 100644 --- a/source/blender/draw/engines/workbench/workbench_forward.c +++ b/source/blender/draw/engines/workbench/workbench_forward.c @@ -503,33 +503,26 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob) const Mesh *me = ob->data; if (me->mloopuv) { const int materials_len = MAX2(1, (is_sculpt_mode ? 1 : ob->totcol)); - struct GPUMaterial **gpumat_array = BLI_array_alloca(gpumat_array, materials_len); - struct GPUBatch **geom_array = me->totcol ? DRW_cache_mesh_surface_texpaint_get(ob) : NULL; - if (materials_len > 0 && geom_array) { - for (int i = 0; i < materials_len; i++) { - if (geom_array[i] == NULL) { - continue; - } + struct GPUBatch **geom_array = DRW_cache_mesh_surface_texpaint_get(ob); + for (int i = 0; i < materials_len; i++) { + Material *mat = give_current_material(ob, i + 1); + Image *image; + ED_object_get_active_image(ob, i + 1, &image, NULL, NULL, NULL); + /* use OB_SOLID when no texture could be determined */ - Material *mat = give_current_material(ob, i + 1); - Image *image; - ED_object_get_active_image(ob, i + 1, &image, NULL, NULL, NULL); + int color_type = wpd->shading.color_type; + if (color_type == V3D_SHADING_TEXTURE_COLOR) { /* use OB_SOLID when no texture could be determined */ - - int color_type = wpd->shading.color_type; - if (color_type == V3D_SHADING_TEXTURE_COLOR) { - /* use OB_SOLID when no texture could be determined */ - if (image == NULL) { - color_type = V3D_SHADING_MATERIAL_COLOR; - } + if (image == NULL) { + color_type = V3D_SHADING_MATERIAL_COLOR; } - - material = get_or_create_material_data(vedata, ob, mat, image, color_type); - DRW_shgroup_call_object_add(material->shgrp_object_outline, geom_array[i], ob); - DRW_shgroup_call_object_add(material->shgrp, geom_array[i], ob); } - is_drawn = true; + + material = get_or_create_material_data(vedata, ob, mat, image, color_type); + DRW_shgroup_call_object_add(material->shgrp_object_outline, geom_array[i], ob); + DRW_shgroup_call_object_add(material->shgrp, geom_array[i], ob); } + is_drawn = true; } } diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c index 3aeeafc7891..1aa7a850da5 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.c +++ b/source/blender/draw/intern/draw_cache_impl_mesh.c @@ -323,6 +323,17 @@ static void mesh_cd_layers_type_merge( } } +static void mesh_cd_calc_active_uv_layer( + const Mesh *me, ushort cd_lused[CD_NUMTYPES]) +{ + const CustomData *cd_ldata = (me->edit_btmesh) ? &me->edit_btmesh->bm->ldata : &me->ldata; + + int layer = CustomData_get_active_layer(cd_ldata, CD_MLOOPUV); + if (layer != -1) { + cd_lused[CD_MLOOPUV] |= (1 << layer); + } +} + static void mesh_cd_calc_used_gpu_layers( const Mesh *me, uchar cd_vused[CD_NUMTYPES], ushort cd_lused[CD_NUMTYPES], struct GPUMaterial **gpumat_array, int gpumat_array_len) @@ -2625,84 +2636,6 @@ void DRW_mesh_batch_cache_free(Mesh *me) /* GPUBatch cache usage. */ -static GPUVertBuf *mesh_batch_cache_get_tri_uv_active( - MeshRenderData *rdata, MeshBatchCache *cache) -{ - BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPUV)); - - - if (cache->tri_aligned_uv == NULL) { - const MLoopUV *mloopuv = rdata->mloopuv; - int layer_offset; - BMEditMesh *embm = rdata->edit_bmesh; - - /* edit mode */ - if (rdata->edit_bmesh) { - BMesh *bm = embm->bm; - layer_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); - if (layer_offset == -1) { - return NULL; - } - } - else if (mloopuv == NULL) { - return NULL; - } - - uint vidx = 0; - - static GPUVertFormat format = { 0 }; - static struct { uint uv; } attr_id; - if (format.attr_len == 0) { - attr_id.uv = GPU_vertformat_attr_add(&format, "uv", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - } - - const int tri_len = mesh_render_data_looptri_len_get(rdata); - - GPUVertBuf *vbo = cache->tri_aligned_uv = GPU_vertbuf_create_with_format(&format); - - const int vbo_len_capacity = tri_len * 3; - int vbo_len_used = 0; - GPU_vertbuf_data_alloc(vbo, vbo_len_capacity); - - /* get uv's from active UVMap */ - if (rdata->edit_bmesh) { - for (uint i = 0; i < tri_len; i++) { - const BMLoop **bm_looptri = (const BMLoop **)embm->looptris[i]; - if (BM_elem_flag_test(bm_looptri[0]->f, BM_ELEM_HIDDEN)) { - continue; - } - for (uint t = 0; t < 3; t++) { - const BMLoop *loop = bm_looptri[t]; - const int index = BM_elem_index_get(loop); - if (index != -1) { - const float *elem = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(loop, layer_offset))->uv; - GPU_vertbuf_attr_set(vbo, attr_id.uv, vidx++, elem); - } - } - } - } - else { - /* object mode */ - for (int i = 0; i < tri_len; i++) { - const MLoopTri *mlt = &rdata->mlooptri[i]; - GPU_vertbuf_attr_set(vbo, attr_id.uv, vidx++, mloopuv[mlt->tri[0]].uv); - GPU_vertbuf_attr_set(vbo, attr_id.uv, vidx++, mloopuv[mlt->tri[1]].uv); - GPU_vertbuf_attr_set(vbo, attr_id.uv, vidx++, mloopuv[mlt->tri[2]].uv); - } - } - - vbo_len_used = vidx; - - if (vbo_len_capacity != vbo_len_used) { - GPU_vertbuf_data_resize(vbo, vbo_len_used); - } - - UNUSED_VARS_NDEBUG(vbo_len_used); - } - - return cache->tri_aligned_uv; -} - static void mesh_create_pos_and_nor_tess(MeshRenderData *rdata, GPUVertBuf *vbo, bool use_hide) { static GPUVertFormat format = { 0 }; @@ -5155,13 +5088,12 @@ GPUBatch **DRW_mesh_batch_cache_get_surface_shaded( char **auto_layer_names, int **auto_layer_is_srgb, int *auto_layer_count) { MeshBatchCache *cache = mesh_batch_cache_get(me); - - BLI_assert(gpumat_array_len == cache->mat_len); - uchar cd_vneeded[CD_NUMTYPES] = {0}; ushort cd_lneeded[CD_NUMTYPES] = {0}; mesh_cd_calc_used_gpu_layers(me, cd_vneeded, cd_lneeded, gpumat_array, gpumat_array_len); + BLI_assert(gpumat_array_len == cache->mat_len); + bool cd_overlap = mesh_cd_layers_type_overlap(cache->cd_vused, cache->cd_lused, cd_vneeded, cd_lneeded); if (cd_overlap == false) { @@ -5175,48 +5107,50 @@ GPUBatch **DRW_mesh_batch_cache_get_surface_shaded( &cache->auto_layer_is_srgb, &cache->auto_layer_len); } - if (auto_layer_names) { *auto_layer_names = cache->auto_layer_names; *auto_layer_is_srgb = cache->auto_layer_is_srgb; *auto_layer_count = cache->auto_layer_len; } - for (int i = 0; i < cache->mat_len; ++i) { DRW_batch_request(&cache->surf_per_mat[i]); } return cache->surf_per_mat; } +static void texpaint_request_active_uv(MeshBatchCache *cache, Mesh *me) +{ + uchar cd_vneeded[CD_NUMTYPES] = {0}; + ushort cd_lneeded[CD_NUMTYPES] = {0}; + mesh_cd_calc_active_uv_layer(me, cd_lneeded); + if (cd_lneeded[CD_MLOOPUV] == 0) { + /* This should not happen. */ + BLI_assert(!"No uv layer available in texpaint, but batches requested anyway!"); + } + bool cd_overlap = mesh_cd_layers_type_overlap(cache->cd_vused, cache->cd_lused, + cd_vneeded, cd_lneeded); + if (cd_overlap == false) { + /* XXX TODO(fclem): We are writting to batch cache here. Need to make this thread safe. */ + mesh_cd_layers_type_merge(cache->cd_vneeded, cache->cd_lneeded, + cd_vneeded, cd_lneeded); + } +} + GPUBatch **DRW_mesh_batch_cache_get_surface_texpaint(Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); - UNUSED_VARS(cache); - /* TODO */ - return NULL; + texpaint_request_active_uv(cache, me); + for (int i = 0; i < cache->mat_len; ++i) { + DRW_batch_request(&cache->surf_per_mat[i]); + } + return cache->surf_per_mat; } GPUBatch *DRW_mesh_batch_cache_get_surface_texpaint_single(Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); - - if (cache->texpaint_triangles_single == NULL) { - /* create batch from DM */ - const int datatype = - MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOPUV; - MeshRenderData *rdata = mesh_render_data_create(me, datatype); - - GPUVertBuf *vbo = mesh_batch_cache_get_tri_pos_and_normals_final(rdata, cache, false); - - cache->texpaint_triangles_single = GPU_batch_create( - GPU_PRIM_TRIS, vbo, NULL); - GPUVertBuf *vbo_uv = mesh_batch_cache_get_tri_uv_active(rdata, cache); - if (vbo_uv) { - GPU_batch_vertbuf_add(cache->texpaint_triangles_single, vbo_uv); - } - mesh_render_data_free(rdata); - } - return cache->texpaint_triangles_single; + texpaint_request_active_uv(cache, me); + return DRW_batch_request(&cache->batch.surface); } GPUBatch *DRW_mesh_batch_cache_get_texpaint_loop_wire(Mesh *me) @@ -5799,12 +5733,12 @@ void DRW_mesh_batch_cache_create_requested(Object *UNUSED(ob), Mesh *me) } } } + /* We can't discard batches at this point as they have been + * referenced for drawing. Just clear them in place. */ for (int i = 0; i < cache->mat_len; ++i) { - /* 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])); + GPU_BATCH_CLEAR_SAFE(cache->surf_per_mat[i]); } + GPU_BATCH_CLEAR_SAFE(cache->batch.surface); mesh_cd_layers_type_merge(cache->cd_vused, cache->cd_lused, cache->cd_vneeded, cache->cd_lneeded); @@ -5818,6 +5752,10 @@ void DRW_mesh_batch_cache_create_requested(Object *UNUSED(ob), Mesh *me) if (DRW_batch_requested(cache->batch.surface, GPU_PRIM_TRIS)) { DRW_ibo_request(cache->batch.surface, &cache->ibo.surface_tris); DRW_vbo_request(cache->batch.surface, &cache->ordered.loop_pos_nor); + /* For paint overlay. Active layer should have been queried. */ + if (cache->cd_lused[CD_MLOOPUV] != 0) { + DRW_vbo_request(cache->batch.surface, &cache->ordered.loop_uv_tan); + } } if (DRW_batch_requested(cache->batch.all_verts, GPU_PRIM_POINTS)) { DRW_vbo_request(cache->batch.all_verts, &cache->ordered.pos_nor); diff --git a/source/blender/draw/modes/paint_texture_mode.c b/source/blender/draw/modes/paint_texture_mode.c index f22fa4d8721..8e78d2f03b4 100644 --- a/source/blender/draw/modes/paint_texture_mode.c +++ b/source/blender/draw/modes/paint_texture_mode.c @@ -295,40 +295,31 @@ static void PAINT_TEXTURE_cache_populate(void *vedata, Object *ob) const bool use_surface = draw_ctx->v3d->overlay.texture_paint_mode_opacity != 0.0; //DRW_object_is_mode_shade(ob) == true; const bool use_material_slots = (scene->toolsettings->imapaint.mode == IMAGEPAINT_MODE_MATERIAL); const bool use_face_sel = (me_orig->editflag & ME_EDIT_PAINT_FACE_SEL) != 0; - bool ok = false; if (use_surface) { if (me->mloopuv != NULL) { - if (use_material_slots || use_face_sel) { - struct GPUBatch **geom_array = me->totcol ? DRW_cache_mesh_surface_texpaint_get(ob) : NULL; - if ((me->totcol == 0) || (geom_array == NULL)) { - struct GPUBatch *geom = DRW_cache_mesh_surface_get(ob); - DRW_shgroup_call_add(stl->g_data->shgroup_fallback, geom, ob->obmat); - ok = true; - } - else { - for (int i = 0; i < me->totcol; i++) { - const int index = use_material_slots ? i : 0; - if (stl->g_data->shgroup_image_array[index]) { - DRW_shgroup_call_add(stl->g_data->shgroup_image_array[index], geom_array[i], ob->obmat); - } - else { - DRW_shgroup_call_add(stl->g_data->shgroup_fallback, geom_array[i], ob->obmat); - } - ok = true; + if (use_material_slots) { + int mat_nr = max_ii(1, me->totcol); + struct GPUBatch **geom_array = DRW_cache_mesh_surface_texpaint_get(ob); + + for (int i = 0; i < mat_nr; i++) { + const int index = use_material_slots ? i : 0; + if (stl->g_data->shgroup_image_array[index]) { + DRW_shgroup_call_add(stl->g_data->shgroup_image_array[index], geom_array[i], ob->obmat); + } + else { + DRW_shgroup_call_add(stl->g_data->shgroup_fallback, geom_array[i], ob->obmat); } } } else { - struct GPUBatch *geom = DRW_cache_mesh_surface_texpaint_single_get(ob); - if (geom && stl->g_data->shgroup_image_array[0]) { + if (stl->g_data->shgroup_image_array[0]) { + struct GPUBatch *geom = DRW_cache_mesh_surface_texpaint_single_get(ob); DRW_shgroup_call_add(stl->g_data->shgroup_image_array[0], geom, ob->obmat); - ok = true; } } } - - if (!ok) { + else { struct GPUBatch *geom = DRW_cache_mesh_surface_get(ob); DRW_shgroup_call_add(stl->g_data->shgroup_fallback, geom, ob->obmat); } diff --git a/source/blender/draw/modes/shaders/paint_texture_vert.glsl b/source/blender/draw/modes/shaders/paint_texture_vert.glsl index 4ce12e048fa..8eae494cc35 100644 --- a/source/blender/draw/modes/shaders/paint_texture_vert.glsl +++ b/source/blender/draw/modes/shaders/paint_texture_vert.glsl @@ -1,7 +1,7 @@ uniform mat4 ModelViewProjectionMatrix; -in vec2 uv; +in vec2 u; /* active uv map */ in vec3 pos; out vec2 uv_interp; @@ -10,6 +10,5 @@ void main() { gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); - uv_interp = uv; - + uv_interp = u; } diff --git a/source/blender/gpu/GPU_batch.h b/source/blender/gpu/GPU_batch.h index d47df08afb6..c77f0707ee5 100644 --- a/source/blender/gpu/GPU_batch.h +++ b/source/blender/gpu/GPU_batch.h @@ -197,6 +197,13 @@ void gpu_batch_exit(void); } \ } while (0) +#define GPU_BATCH_CLEAR_SAFE(batch) do { \ + if (batch != NULL) { \ + GPU_batch_clear(batch); \ + memset(batch, 0, sizeof(*(batch))); \ + } \ +} while (0) + #define GPU_BATCH_DISCARD_ARRAY_SAFE(_batch_array, _len) do { \ if (_batch_array != NULL) { \ BLI_assert(_len > 0); \