diff options
author | Campbell Barton <ideasman42@gmail.com> | 2017-06-29 13:11:16 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2017-06-29 13:11:16 +0300 |
commit | fd3589e4c969d2e08b864e0e60c8c25f23e50145 (patch) | |
tree | 9be9f85d2de50f32dd736ded6a6bc15cfb520f4a /source/blender/draw/intern/draw_cache_impl_mesh.c | |
parent | 34566aa96910e29eceb45d29c9d50471452f8d73 (diff) |
DwM: optimize mesh batch conversion
- Replace GWN_vertbuf_attr_set with Gwn_VertBufRaw & GWN_vertbuf_raw_step
to avoid intermediate copy.
- Avoid extra conversion step with: float[3] -> short[3] -> Gwn_PackedNormal.
We can skip the short[3].
Gives approx 6% speedup here.
Diffstat (limited to 'source/blender/draw/intern/draw_cache_impl_mesh.c')
-rw-r--r-- | source/blender/draw/intern/draw_cache_impl_mesh.c | 198 |
1 files changed, 94 insertions, 104 deletions
diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c index 13b94c00dc6..6c62cf3b0f6 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.c +++ b/source/blender/draw/intern/draw_cache_impl_mesh.c @@ -190,8 +190,8 @@ typedef struct MeshRenderData { float (*poly_normals)[3]; float (*vert_weight_color)[3]; char (*vert_color)[3]; - short (*poly_normals_short)[3]; - short (*vert_normals_short)[3]; + Gwn_PackedNormal *poly_normals_pack; + Gwn_PackedNormal *vert_normals_pack; bool *edge_select_bool; } MeshRenderData; @@ -760,8 +760,8 @@ static void mesh_render_data_free(MeshRenderData *rdata) MEM_SAFE_FREE(rdata->edges_adjacent_polys); MEM_SAFE_FREE(rdata->mlooptri); MEM_SAFE_FREE(rdata->poly_normals); - MEM_SAFE_FREE(rdata->poly_normals_short); - MEM_SAFE_FREE(rdata->vert_normals_short); + MEM_SAFE_FREE(rdata->poly_normals_pack); + MEM_SAFE_FREE(rdata->vert_normals_pack); MEM_SAFE_FREE(rdata->vert_weight_color); MEM_SAFE_FREE(rdata->edge_select_bool); MEM_SAFE_FREE(rdata->vert_color); @@ -870,20 +870,20 @@ static int mesh_render_data_polys_len_get(const MeshRenderData *rdata) /** \name Internal Cache (Lazy Initialization) * \{ */ -/** Ensure #MeshRenderData.poly_normals_short */ -static void mesh_render_data_ensure_poly_normals_short(MeshRenderData *rdata) +/** Ensure #MeshRenderData.poly_normals_pack */ +static void mesh_render_data_ensure_poly_normals_pack(MeshRenderData *rdata) { - short (*pnors_short)[3] = rdata->poly_normals_short; - if (pnors_short == NULL) { + Gwn_PackedNormal *pnors_pack = rdata->poly_normals_pack; + if (pnors_pack == NULL) { if (rdata->edit_bmesh) { BMesh *bm = rdata->edit_bmesh->bm; BMIter fiter; BMFace *efa; int i; - pnors_short = rdata->poly_normals_short = MEM_mallocN(sizeof(*pnors_short) * rdata->poly_len, __func__); + pnors_pack = rdata->poly_normals_pack = MEM_mallocN(sizeof(*pnors_pack) * rdata->poly_len, __func__); BM_ITER_MESH_INDEX(efa, &fiter, bm, BM_FACES_OF_MESH, i) { - normal_float_to_short_v3(pnors_short[i], efa->no); + pnors_pack[i] = GWN_normal_convert_i10_v3(efa->no); } } else { @@ -896,28 +896,28 @@ static void mesh_render_data_ensure_poly_normals_short(MeshRenderData *rdata) rdata->mloop, rdata->mpoly, rdata->loop_len, rdata->poly_len, pnors, true); } - pnors_short = rdata->poly_normals_short = MEM_mallocN(sizeof(*pnors_short) * rdata->poly_len, __func__); + pnors_pack = rdata->poly_normals_pack = MEM_mallocN(sizeof(*pnors_pack) * rdata->poly_len, __func__); for (int i = 0; i < rdata->poly_len; i++) { - normal_float_to_short_v3(pnors_short[i], pnors[i]); + pnors_pack[i] = GWN_normal_convert_i10_v3(pnors[i]); } } } } -/** Ensure #MeshRenderData.vert_normals_short */ -static void mesh_render_data_ensure_vert_normals_short(MeshRenderData *rdata) +/** Ensure #MeshRenderData.vert_normals_pack */ +static void mesh_render_data_ensure_vert_normals_pack(MeshRenderData *rdata) { - short (*vnors_short)[3] = rdata->vert_normals_short; - if (vnors_short == NULL) { + Gwn_PackedNormal *vnors_pack = rdata->vert_normals_pack; + if (vnors_pack == NULL) { if (rdata->edit_bmesh) { BMesh *bm = rdata->edit_bmesh->bm; BMIter viter; BMVert *eve; int i; - vnors_short = rdata->vert_normals_short = MEM_mallocN(sizeof(*vnors_short) * rdata->vert_len, __func__); + vnors_pack = rdata->vert_normals_pack = MEM_mallocN(sizeof(*vnors_pack) * rdata->vert_len, __func__); BM_ITER_MESH_INDEX(eve, &viter, bm, BM_VERT, i) { - normal_float_to_short_v3(vnors_short[i], eve->no); + vnors_pack[i] = GWN_normal_convert_i10_v3(eve->no); } } else { @@ -1268,63 +1268,6 @@ static void mesh_render_data_looptri_tans_get( } } -static bool mesh_render_data_looptri_cos_nors_smooth_get( - MeshRenderData *rdata, const int tri_idx, const bool use_hide, - float *(*r_vert_cos)[3], short **r_tri_nor, short *(*r_vert_nors)[3], bool *r_is_smooth) -{ - BLI_assert(rdata->types & MR_DATATYPE_VERT); - BLI_assert(rdata->types & MR_DATATYPE_LOOPTRI); - BLI_assert(rdata->types & MR_DATATYPE_LOOP); - BLI_assert(rdata->types & MR_DATATYPE_POLY); - - if (rdata->edit_bmesh) { - const BMLoop **bm_looptri = (const BMLoop **)rdata->edit_bmesh->looptris[tri_idx]; - - /* Assume 'use_hide' */ - if (BM_elem_flag_test(bm_looptri[0]->f, BM_ELEM_HIDDEN)) { - return false; - } - - mesh_render_data_ensure_poly_normals_short(rdata); - mesh_render_data_ensure_vert_normals_short(rdata); - - short (*pnors_short)[3] = rdata->poly_normals_short; - short (*vnors_short)[3] = rdata->vert_normals_short; - - (*r_vert_cos)[0] = bm_looptri[0]->v->co; - (*r_vert_cos)[1] = bm_looptri[1]->v->co; - (*r_vert_cos)[2] = bm_looptri[2]->v->co; - *r_tri_nor = pnors_short[BM_elem_index_get(bm_looptri[0]->f)]; - (*r_vert_nors)[0] = vnors_short[BM_elem_index_get(bm_looptri[0]->v)]; - (*r_vert_nors)[1] = vnors_short[BM_elem_index_get(bm_looptri[1]->v)]; - (*r_vert_nors)[2] = vnors_short[BM_elem_index_get(bm_looptri[2]->v)]; - - *r_is_smooth = BM_elem_flag_test_bool(bm_looptri[0]->f, BM_ELEM_SMOOTH); - } - else { - const MLoopTri *mlt = &rdata->mlooptri[tri_idx]; - - if (use_hide && (rdata->mpoly[mlt->poly].flag & ME_HIDE)) { - return false; - } - - mesh_render_data_ensure_poly_normals_short(rdata); - - short (*pnors_short)[3] = rdata->poly_normals_short; - - (*r_vert_cos)[0] = rdata->mvert[rdata->mloop[mlt->tri[0]].v].co; - (*r_vert_cos)[1] = rdata->mvert[rdata->mloop[mlt->tri[1]].v].co; - (*r_vert_cos)[2] = rdata->mvert[rdata->mloop[mlt->tri[2]].v].co; - *r_tri_nor = pnors_short[mlt->poly]; - (*r_vert_nors)[0] = rdata->mvert[rdata->mloop[mlt->tri[0]].v].no; - (*r_vert_nors)[1] = rdata->mvert[rdata->mloop[mlt->tri[1]].v].no; - (*r_vert_nors)[2] = rdata->mvert[rdata->mloop[mlt->tri[2]].v].no; - - *r_is_smooth = (rdata->mpoly[mlt->poly].flag & ME_SMOOTH) != 0; - } - return true; -} - /* First 2 bytes are bit flags * 3rd is for sharp edges * 4rd is for creased edges */ @@ -1981,8 +1924,6 @@ static Gwn_VertBuf *mesh_batch_cache_get_tri_pos_and_normals_ex( BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY)); if (*r_vbo == NULL) { - unsigned int vidx = 0, nidx = 0; - static Gwn_VertFormat format = { 0 }; static struct { uint pos, nor; } attr_id; if (format.attrib_ct == 0) { @@ -1998,41 +1939,90 @@ static Gwn_VertBuf *mesh_batch_cache_get_tri_pos_and_normals_ex( int vbo_len_used = 0; GWN_vertbuf_data_alloc(vbo, vbo_len_capacity); - for (int i = 0; i < tri_len; i++) { - float *tri_vert_cos[3]; - short *tri_nor, *tri_vert_nors[3]; - bool is_smooth; + Gwn_VertBufRaw pos_step, nor_step; + GWN_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step); + GWN_vertbuf_attr_get_raw_data(vbo, attr_id.nor, &nor_step); - if (mesh_render_data_looptri_cos_nors_smooth_get( - rdata, i, use_hide, &tri_vert_cos, &tri_nor, &tri_vert_nors, &is_smooth)) - { - if (is_smooth) { - Gwn_PackedNormal snor_pack[3] = { - GWN_normal_convert_i10_s3(tri_vert_nors[0]), - GWN_normal_convert_i10_s3(tri_vert_nors[1]), - GWN_normal_convert_i10_s3(tri_vert_nors[2]) - }; - Gwn_PackedNormal *snor[3] = { &snor_pack[0], &snor_pack[1], &snor_pack[2] }; - - GWN_vertbuf_attr_set(vbo, attr_id.nor, nidx++, snor[0]); - GWN_vertbuf_attr_set(vbo, attr_id.nor, nidx++, snor[1]); - GWN_vertbuf_attr_set(vbo, attr_id.nor, nidx++, snor[2]); + if (rdata->edit_bmesh) { + mesh_render_data_ensure_poly_normals_pack(rdata); + mesh_render_data_ensure_vert_normals_pack(rdata); + + Gwn_PackedNormal *pnors_pack = rdata->poly_normals_pack; + Gwn_PackedNormal *vnors_pack = rdata->vert_normals_pack; + + for (int i = 0; i < tri_len; i++) { + const BMLoop **bm_looptri = (const BMLoop **)rdata->edit_bmesh->looptris[i]; + const BMFace *bm_face = bm_looptri[0]->f; + + /* use_hide always for edit-mode */ + if (BM_elem_flag_test(bm_face, BM_ELEM_HIDDEN)) { + continue; + } + + const uint vtri[3] = { + BM_elem_index_get(bm_looptri[0]->v), + BM_elem_index_get(bm_looptri[1]->v), + BM_elem_index_get(bm_looptri[2]->v), + }; + + if (BM_elem_flag_test(bm_face, BM_ELEM_SMOOTH)) { + for (uint t = 0; t < 3; t++) { + *((Gwn_PackedNormal *)GWN_vertbuf_raw_step(&nor_step)) = vnors_pack[vtri[t]]; + } } else { - Gwn_PackedNormal snor_pack = GWN_normal_convert_i10_s3(tri_nor); - Gwn_PackedNormal *snor = &snor_pack; + const Gwn_PackedNormal *snor_pack = &pnors_pack[BM_elem_index_get(bm_face)]; + for (uint t = 0; t < 3; t++) { + *((Gwn_PackedNormal *)GWN_vertbuf_raw_step(&nor_step)) = *snor_pack; + } + } - GWN_vertbuf_attr_set(vbo, attr_id.nor, nidx++, snor); - GWN_vertbuf_attr_set(vbo, attr_id.nor, nidx++, snor); - GWN_vertbuf_attr_set(vbo, attr_id.nor, nidx++, snor); + for (uint t = 0; t < 3; t++) { + copy_v3_v3(GWN_vertbuf_raw_step(&pos_step), bm_looptri[t]->v->co); } + } + } + else { + + /* Use normals from vertex */ + mesh_render_data_ensure_poly_normals_pack(rdata); - GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, tri_vert_cos[0]); - GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, tri_vert_cos[1]); - GWN_vertbuf_attr_set(vbo, attr_id.pos, vidx++, tri_vert_cos[2]); + for (int i = 0; i < tri_len; i++) { + const MLoopTri *mlt = &rdata->mlooptri[i]; + const MPoly *mp = &rdata->mpoly[mlt->poly]; + + if (use_hide && (mp->flag & ME_HIDE)) { + continue; + } + + const uint vtri[3] = { + rdata->mloop[mlt->tri[0]].v, + rdata->mloop[mlt->tri[1]].v, + rdata->mloop[mlt->tri[2]].v, + }; + + if (mp->flag & ME_SMOOTH) { + for (uint t = 0; t < 3; t++) { + const MVert *mv = &rdata->mvert[vtri[t]]; + *((Gwn_PackedNormal *)GWN_vertbuf_raw_step(&nor_step)) = GWN_normal_convert_i10_s3(mv->no); + } + } + else { + const Gwn_PackedNormal *pnors_pack = &rdata->poly_normals_pack[mlt->poly]; + for (uint t = 0; t < 3; t++) { + *((Gwn_PackedNormal *)GWN_vertbuf_raw_step(&nor_step)) = *pnors_pack; + } + } + + for (uint t = 0; t < 3; t++) { + const MVert *mv = &rdata->mvert[vtri[t]]; + copy_v3_v3(GWN_vertbuf_raw_step(&pos_step), mv->co); + } } } - vbo_len_used = vidx; + + vbo_len_used = GWN_vertbuf_raw_used(&pos_step); + BLI_assert(vbo_len_used == GWN_vertbuf_raw_used(&nor_step)); if (vbo_len_capacity != vbo_len_used) { GWN_vertbuf_data_resize(vbo, vbo_len_used); |