From 9fb32b2b2921bd3b92bf9d6faa9c23b262da6464 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Mon, 11 Jan 2021 08:44:53 +0100 Subject: Fix T84459: Wireframe not displaying with AMD GPU Issue appears to be caused by AMD graphics driver later than 20.11.1 and affects older GPUs (Polaris/FIJI cards). Wireframe drawing uses the same OpenGL data type for storing normals what is known to be faulty. This patch enabled storing the normals using GPU_COMP_I16. It also solves the normals drawing in edit mode for vertex and loop normals. --- .../blender/draw/intern/draw_cache_extract_mesh.c | 219 +++++++++++++++++++-- 1 file changed, 207 insertions(+), 12 deletions(-) (limited to 'source/blender/draw') diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.c b/source/blender/draw/intern/draw_cache_extract_mesh.c index 576c029390c..68c5128bacd 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh.c +++ b/source/blender/draw/intern/draw_cache_extract_mesh.c @@ -1907,7 +1907,7 @@ typedef struct PosNorLoop { typedef struct MeshExtract_PosNor_Data { PosNorLoop *vbo_data; - GPUPackedNormal packed_nor[]; + GPUNormal normals[]; } MeshExtract_PosNor_Data; static void *extract_pos_nor_init(const MeshRenderData *mr, @@ -1926,7 +1926,7 @@ static void *extract_pos_nor_init(const MeshRenderData *mr, GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len); /* Pack normals per vert, reduce amount of computation. */ - size_t packed_nor_len = sizeof(GPUPackedNormal) * mr->vert_len; + size_t packed_nor_len = sizeof(GPUNormal) * mr->vert_len; MeshExtract_PosNor_Data *data = MEM_mallocN(sizeof(*data) + packed_nor_len, __func__); data->vbo_data = (PosNorLoop *)GPU_vertbuf_get_data(vbo); @@ -1936,13 +1936,13 @@ static void *extract_pos_nor_init(const MeshRenderData *mr, BMVert *eve; int v; BM_ITER_MESH_INDEX (eve, &iter, mr->bm, BM_VERTS_OF_MESH, v) { - data->packed_nor[v] = GPU_normal_convert_i10_v3(bm_vert_no_get(mr, eve)); + data->normals[v].low = GPU_normal_convert_i10_v3(bm_vert_no_get(mr, eve)); } } else { const MVert *mv = mr->mvert; for (int v = 0; v < mr->vert_len; v++, mv++) { - data->packed_nor[v] = GPU_normal_convert_i10_s3(mv->no); + data->normals[v].low = GPU_normal_convert_i10_s3(mv->no); } } return data; @@ -1957,7 +1957,7 @@ static void extract_pos_nor_iter_poly_bm(const MeshRenderData *mr, { PosNorLoop *vert = &data->vbo_data[l_index]; copy_v3_v3(vert->pos, bm_vert_co_get(mr, l->v)); - vert->nor = data->packed_nor[BM_elem_index_get(l->v)]; + vert->nor = data->normals[BM_elem_index_get(l->v)].low; BMFace *efa = l->f; vert->nor.w = BM_elem_flag_test(efa, BM_ELEM_HIDDEN) ? -1 : 0; } @@ -1974,7 +1974,7 @@ static void extract_pos_nor_iter_poly_mesh(const MeshRenderData *mr, PosNorLoop *vert = &data->vbo_data[ml_index]; const MVert *mv = &mr->mvert[ml->v]; copy_v3_v3(vert->pos, mv->co); - vert->nor = data->packed_nor[ml->v]; + vert->nor = data->normals[ml->v].low; /* Flag for paint mode overlay. */ if (mp->flag & ME_HIDE || mv->flag & ME_HIDE || ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->v_origindex) && @@ -2002,8 +2002,8 @@ static void extract_pos_nor_iter_ledge_bm(const MeshRenderData *mr, PosNorLoop *vert = &data->vbo_data[l_index]; copy_v3_v3(vert[0].pos, bm_vert_co_get(mr, eed->v1)); copy_v3_v3(vert[1].pos, bm_vert_co_get(mr, eed->v2)); - vert[0].nor = data->packed_nor[BM_elem_index_get(eed->v1)]; - vert[1].nor = data->packed_nor[BM_elem_index_get(eed->v2)]; + vert[0].nor = data->normals[BM_elem_index_get(eed->v1)].low; + vert[1].nor = data->normals[BM_elem_index_get(eed->v2)].low; } EXTRACT_LEDGE_FOREACH_BM_END; } @@ -2019,8 +2019,8 @@ static void extract_pos_nor_iter_ledge_mesh(const MeshRenderData *mr, PosNorLoop *vert = &data->vbo_data[ml_index]; copy_v3_v3(vert[0].pos, mr->mvert[med->v1].co); copy_v3_v3(vert[1].pos, mr->mvert[med->v2].co); - vert[0].nor = data->packed_nor[med->v1]; - vert[1].nor = data->packed_nor[med->v2]; + vert[0].nor = data->normals[med->v1].low; + vert[1].nor = data->normals[med->v2].low; } EXTRACT_LEDGE_FOREACH_MESH_END; } @@ -2036,7 +2036,7 @@ static void extract_pos_nor_iter_lvert_bm(const MeshRenderData *mr, const int l_index = offset + lvert_index; PosNorLoop *vert = &data->vbo_data[l_index]; copy_v3_v3(vert->pos, bm_vert_co_get(mr, eve)); - vert->nor = data->packed_nor[BM_elem_index_get(eve)]; + vert->nor = data->normals[BM_elem_index_get(eve)].low; } EXTRACT_LVERT_FOREACH_BM_END; } @@ -2053,7 +2053,7 @@ static void extract_pos_nor_iter_lvert_mesh(const MeshRenderData *mr, const int v_index = mr->lverts[lvert_index]; PosNorLoop *vert = &data->vbo_data[ml_index]; copy_v3_v3(vert->pos, mv->co); - vert->nor = data->packed_nor[v_index]; + vert->nor = data->normals[v_index].low; } EXTRACT_LVERT_FOREACH_MESH_END; } @@ -2080,6 +2080,198 @@ static const MeshExtract extract_pos_nor = { }; /** \} */ +/* ---------------------------------------------------------------------- */ +/** \name Extract Position and High Quality Vertex Normal + * \{ */ + +typedef struct PosNorHQLoop { + float pos[3]; + short nor[4]; +} PosNorHQLoop; + +typedef struct MeshExtract_PosNorHQ_Data { + PosNorHQLoop *vbo_data; + GPUNormal normals[]; +} MeshExtract_PosNorHQ_Data; + +static void *extract_pos_nor_hq_init(const MeshRenderData *mr, + struct MeshBatchCache *UNUSED(cache), + void *buf) +{ + static GPUVertFormat format = {0}; + if (format.attr_len == 0) { + /* WARNING Adjust #PosNorHQLoop struct accordingly. */ + GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); + GPU_vertformat_alias_add(&format, "vnor"); + } + GPUVertBuf *vbo = buf; + GPU_vertbuf_init_with_format(vbo, &format); + GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len); + + /* Pack normals per vert, reduce amount of computation. */ + size_t packed_nor_len = sizeof(GPUNormal) * mr->vert_len; + MeshExtract_PosNorHQ_Data *data = MEM_mallocN(sizeof(*data) + packed_nor_len, __func__); + data->vbo_data = (PosNorHQLoop *)GPU_vertbuf_get_data(vbo); + + /* Quicker than doing it for each loop. */ + if (mr->extract_type == MR_EXTRACT_BMESH) { + BMIter iter; + BMVert *eve; + int v; + BM_ITER_MESH_INDEX (eve, &iter, mr->bm, BM_VERTS_OF_MESH, v) { + normal_float_to_short_v3(data->normals[v].high, bm_vert_no_get(mr, eve)); + } + } + else { + const MVert *mv = mr->mvert; + for (int v = 0; v < mr->vert_len; v++, mv++) { + copy_v3_v3_short(data->normals[v].high, mv->no); + } + } + return data; +} + +static void extract_pos_nor_hq_iter_poly_bm(const MeshRenderData *mr, + const ExtractPolyBMesh_Params *params, + void *_data) +{ + MeshExtract_PosNorHQ_Data *data = _data; + EXTRACT_POLY_AND_LOOP_FOREACH_BM_BEGIN(l, l_index, params, mr) + { + PosNorHQLoop *vert = &data->vbo_data[l_index]; + copy_v3_v3(vert->pos, bm_vert_co_get(mr, l->v)); + copy_v3_v3_short(vert->nor, data->normals[BM_elem_index_get(l->v)].high); + + BMFace *efa = l->f; + vert->nor[3] = BM_elem_flag_test(efa, BM_ELEM_HIDDEN) ? -1 : 0; + } + EXTRACT_POLY_AND_LOOP_FOREACH_BM_END(l); +} + +static void extract_pos_nor_hq_iter_poly_mesh(const MeshRenderData *mr, + const ExtractPolyMesh_Params *params, + void *_data) +{ + MeshExtract_PosNorHQ_Data *data = _data; + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_BEGIN(mp, mp_index, ml, ml_index, params, mr) + { + PosNorHQLoop *vert = &data->vbo_data[ml_index]; + const MVert *mv = &mr->mvert[ml->v]; + copy_v3_v3(vert->pos, mv->co); + copy_v3_v3_short(vert->nor, data->normals[ml->v].high); + + /* Flag for paint mode overlay. */ + if (mp->flag & ME_HIDE || mv->flag & ME_HIDE || + ((mr->extract_type == MR_EXTRACT_MAPPED) && (mr->v_origindex) && + (mr->v_origindex[ml->v] == ORIGINDEX_NONE))) { + vert->nor[3] = -1; + } + else if (mv->flag & SELECT) { + vert->nor[3] = 1; + } + else { + vert->nor[3] = 0; + } + } + EXTRACT_POLY_AND_LOOP_FOREACH_MESH_END; +} + +static void extract_pos_nor_hq_iter_ledge_bm(const MeshRenderData *mr, + const ExtractLEdgeBMesh_Params *params, + void *_data) +{ + MeshExtract_PosNorHQ_Data *data = _data; + EXTRACT_LEDGE_FOREACH_BM_BEGIN(eed, ledge_index, params) + { + int l_index = mr->loop_len + ledge_index * 2; + PosNorHQLoop *vert = &data->vbo_data[l_index]; + copy_v3_v3(vert[0].pos, bm_vert_co_get(mr, eed->v1)); + copy_v3_v3(vert[1].pos, bm_vert_co_get(mr, eed->v2)); + copy_v3_v3_short(vert[0].nor, data->normals[BM_elem_index_get(eed->v1)].high); + vert[0].nor[3] = 0; + copy_v3_v3_short(vert[1].nor, data->normals[BM_elem_index_get(eed->v2)].high); + vert[1].nor[3] = 0; + } + EXTRACT_LEDGE_FOREACH_BM_END; +} + +static void extract_pos_nor_hq_iter_ledge_mesh(const MeshRenderData *mr, + const ExtractLEdgeMesh_Params *params, + void *_data) +{ + MeshExtract_PosNorHQ_Data *data = _data; + EXTRACT_LEDGE_FOREACH_MESH_BEGIN(med, ledge_index, params, mr) + { + const int ml_index = mr->loop_len + ledge_index * 2; + PosNorHQLoop *vert = &data->vbo_data[ml_index]; + copy_v3_v3(vert[0].pos, mr->mvert[med->v1].co); + copy_v3_v3(vert[1].pos, mr->mvert[med->v2].co); + copy_v3_v3_short(vert[0].nor, data->normals[med->v1].high); + vert[0].nor[3] = 0; + copy_v3_v3_short(vert[1].nor, data->normals[med->v2].high); + vert[1].nor[3] = 0; + } + EXTRACT_LEDGE_FOREACH_MESH_END; +} + +static void extract_pos_nor_hq_iter_lvert_bm(const MeshRenderData *mr, + const ExtractLVertBMesh_Params *params, + void *_data) +{ + MeshExtract_PosNorHQ_Data *data = _data; + const int offset = mr->loop_len + (mr->edge_loose_len * 2); + EXTRACT_LVERT_FOREACH_BM_BEGIN(eve, lvert_index, params) + { + const int l_index = offset + lvert_index; + PosNorHQLoop *vert = &data->vbo_data[l_index]; + copy_v3_v3(vert->pos, bm_vert_co_get(mr, eve)); + copy_v3_v3_short(vert->nor, data->normals[BM_elem_index_get(eve)].high); + vert->nor[3] = 0; + } + EXTRACT_LVERT_FOREACH_BM_END; +} + +static void extract_pos_nor_hq_iter_lvert_mesh(const MeshRenderData *mr, + const ExtractLVertMesh_Params *params, + void *_data) +{ + MeshExtract_PosNorHQ_Data *data = _data; + const int offset = mr->loop_len + (mr->edge_loose_len * 2); + EXTRACT_LVERT_FOREACH_MESH_BEGIN(mv, lvert_index, params, mr) + { + const int ml_index = offset + lvert_index; + const int v_index = mr->lverts[lvert_index]; + PosNorHQLoop *vert = &data->vbo_data[ml_index]; + copy_v3_v3(vert->pos, mv->co); + copy_v3_v3_short(vert->nor, data->normals[v_index].high); + vert->nor[3] = 0; + } + EXTRACT_LVERT_FOREACH_MESH_END; +} + +static void extract_pos_nor_hq_finish(const MeshRenderData *UNUSED(mr), + struct MeshBatchCache *UNUSED(cache), + void *UNUSED(vbo), + void *data) +{ + MEM_freeN(data); +} + +static const MeshExtract extract_pos_nor_hq = { + .init = extract_pos_nor_hq_init, + .iter_poly_bm = extract_pos_nor_hq_iter_poly_bm, + .iter_poly_mesh = extract_pos_nor_hq_iter_poly_mesh, + .iter_ledge_bm = extract_pos_nor_hq_iter_ledge_bm, + .iter_ledge_mesh = extract_pos_nor_hq_iter_ledge_mesh, + .iter_lvert_bm = extract_pos_nor_hq_iter_lvert_bm, + .iter_lvert_mesh = extract_pos_nor_hq_iter_lvert_mesh, + .finish = extract_pos_nor_hq_finish, + .data_flag = 0, + .use_threading = true, +}; + +/** \} */ /* ---------------------------------------------------------------------- */ /** \name Extract HQ Loop Normal * \{ */ @@ -5583,6 +5775,9 @@ static void extract_task_create(struct TaskGraph *task_graph, if (do_hq_normals && (extract == &extract_lnor)) { extract = &extract_lnor_hq; } + if (do_hq_normals && (extract == &extract_pos_nor)) { + extract = &extract_pos_nor_hq; + } if (do_hq_normals && (extract == &extract_tan)) { extract = &extract_tan_hq; } -- cgit v1.2.3