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.
This commit is contained in:
parent
64929398fb
commit
9fb32b2b29
Notes:
blender-bot
2023-02-14 12:01:57 +01:00
Referenced by issue #84459, Wireframe not displaying with AMD GPU Referenced by issue #83216, Potential candidates for corrective releases Referenced by issue #77348, Blender LTS: Maintenance Task 2.83
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue