From f96fffe0db53145872a3d60bb8f4bd3b24e8d32b Mon Sep 17 00:00:00 2001 From: mano-wii Date: Mon, 4 Mar 2019 10:18:57 -0300 Subject: Fix/workaround T62167: Random crash when displaying wireframes. Some old AMD drivers crash when a vbo with stride 1 is used a few times. I have not found a real solution to this problem. So the solution was to use a vbo with stride 4 (which in theory is less efficient and takes up more memory space). --- .../blender/draw/intern/draw_cache_impl_displist.c | 23 +++++++++++++--- source/blender/draw/intern/draw_cache_impl_mesh.c | 32 ++++++++++++++++++---- source/blender/gpu/GPU_extensions.h | 1 + source/blender/gpu/intern/gpu_extensions.c | 6 ++++ 4 files changed, 53 insertions(+), 9 deletions(-) (limited to 'source') diff --git a/source/blender/draw/intern/draw_cache_impl_displist.c b/source/blender/draw/intern/draw_cache_impl_displist.c index b9555c5e54b..63514acf1c2 100644 --- a/source/blender/draw/intern/draw_cache_impl_displist.c +++ b/source/blender/draw/intern/draw_cache_impl_displist.c @@ -35,6 +35,7 @@ #include "BKE_displist.h" #include "GPU_batch.h" +#include "GPU_extensions.h" #include "draw_cache_impl.h" /* own include */ @@ -206,10 +207,16 @@ void DRW_displist_vertbuf_create_pos_and_nor(ListBase *lb, GPUVertBuf *vbo) void DRW_displist_vertbuf_create_wiredata(ListBase *lb, GPUVertBuf *vbo) { static GPUVertFormat format = { 0 }; - // static struct { uint wd; } attr_id; /* UNUSED */ + static struct { uint wd; } attr_id; if (format.attr_len == 0) { /* initialize vertex format */ - /* attr_id.wd = */ GPU_vertformat_attr_add(&format, "wd", GPU_COMP_U8, 1, GPU_FETCH_INT_TO_FLOAT_UNIT); + if (!GPU_crappy_amd_driver()) { + /* Some AMD drivers strangely crash with a vbo with this format. */ + attr_id.wd = GPU_vertformat_attr_add(&format, "wd", GPU_COMP_U8, 1, GPU_FETCH_INT_TO_FLOAT_UNIT); + } + else { + attr_id.wd = GPU_vertformat_attr_add(&format, "wd", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); + } } int vbo_len_used = curve_render_surface_vert_len_get(lb); @@ -217,8 +224,16 @@ void DRW_displist_vertbuf_create_wiredata(ListBase *lb, GPUVertBuf *vbo) GPU_vertbuf_init_with_format(vbo, &format); GPU_vertbuf_data_alloc(vbo, vbo_len_used); - BLI_assert(vbo->format.stride == 1); - memset(vbo->data, 0xFF, (size_t)vbo_len_used); + if (vbo->format.stride == 1) { + memset(vbo->data, 0xFF, (size_t)vbo_len_used); + } + else { + GPUVertBufRaw wd_step; + GPU_vertbuf_attr_get_raw_data(vbo, attr_id.wd, &wd_step); + for (int i = 0; i < vbo_len_used; i++) { + *((float *)GPU_vertbuf_raw_step(&wd_step)) = 1.0f; + } + } } void DRW_displist_indexbuf_create_triangles_in_order(ListBase *lb, GPUIndexBuf *ibo) diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c index 25dec2b491f..1feea1b09ba 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.c +++ b/source/blender/draw/intern/draw_cache_impl_mesh.c @@ -52,6 +52,7 @@ #include "bmesh.h" #include "GPU_batch.h" +#include "GPU_extensions.h" #include "GPU_material.h" #include "DRW_render.h" @@ -2671,12 +2672,34 @@ static float mesh_loop_edge_factor_get( return d; } +static void vertbuf_raw_step_u8(GPUVertBufRaw *wd_step, const uchar wiredata) +{ + *((uchar *)GPU_vertbuf_raw_step(wd_step)) = wiredata; +} + +static void vertbuf_raw_step_u8_to_f32(GPUVertBufRaw *wd_step, const uchar wiredata) +{ + *((float *)GPU_vertbuf_raw_step(wd_step)) = wiredata / 255.0f; +} + static void mesh_create_loop_edge_fac(MeshRenderData *rdata, GPUVertBuf *vbo) { static GPUVertFormat format = { 0 }; static struct { uint wd; } attr_id; + static union { float f; uchar u; } data; + static void (*vertbuf_raw_step)(GPUVertBufRaw *, const uchar); if (format.attr_len == 0) { - attr_id.wd = GPU_vertformat_attr_add(&format, "wd", GPU_COMP_U8, 1, GPU_FETCH_INT_TO_FLOAT_UNIT); + if (!GPU_crappy_amd_driver()) { + /* Some AMD drivers strangely crash with a vbo with this format. */ + attr_id.wd = GPU_vertformat_attr_add(&format, "wd", GPU_COMP_U8, 1, GPU_FETCH_INT_TO_FLOAT_UNIT); + vertbuf_raw_step = vertbuf_raw_step_u8; + data.u = UCHAR_MAX; + } + else { + attr_id.wd = GPU_vertformat_attr_add(&format, "wd", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); + vertbuf_raw_step = vertbuf_raw_step_u8_to_f32; + data.f = 1.0f; + } } const int poly_len = mesh_render_data_polys_len_get(rdata); const int loop_len = mesh_render_data_loops_len_get(rdata); @@ -2699,7 +2722,7 @@ static void mesh_create_loop_edge_fac(MeshRenderData *rdata, GPUVertBuf *vbo) BM_ITER_MESH_INDEX (efa, &iter_efa, bm, BM_FACES_OF_MESH, f) { BM_ITER_ELEM (loop, &iter_loop, efa, BM_LOOPS_OF_FACE) { float ratio = mesh_loop_edge_factor_get(efa->no, loop->v->co, loop->v->no, loop->next->v->co); - *((uchar *)GPU_vertbuf_raw_step(&wd_step)) = ratio * 255; + vertbuf_raw_step(&wd_step, ratio * 255); } } BLI_assert(GPU_vertbuf_raw_used(&wd_step) == loop_len); @@ -2736,7 +2759,7 @@ static void mesh_create_loop_edge_fac(MeshRenderData *rdata, GPUVertBuf *vbo) ed->flag ^= ME_EDGE_TMP_TAG; if (use_edge_render) { - *((uchar *)GPU_vertbuf_raw_step(&wd_step)) = (ed->flag & ME_EDGERENDER) ? 255 : 0; + vertbuf_raw_step(&wd_step, (ed->flag & ME_EDGERENDER) ? 255 : 0); } else { float vnor_f[3]; @@ -2745,7 +2768,7 @@ static void mesh_create_loop_edge_fac(MeshRenderData *rdata, GPUVertBuf *vbo) mvert[ml1->v].co, vnor_f, mvert[ml2->v].co); - *((uchar *)GPU_vertbuf_raw_step(&wd_step)) = ratio * 253 + 1; + vertbuf_raw_step(&wd_step, ratio * 253 + 1); } } } @@ -2753,7 +2776,6 @@ static void mesh_create_loop_edge_fac(MeshRenderData *rdata, GPUVertBuf *vbo) for (int l = 0; l < loop_len; l++, mloop++) { MEdge *ed = (MEdge *)rdata->medge + mloop->e; if (ed->flag & ME_EDGE_TMP_TAG) { - uchar data = 255; GPU_vertbuf_attr_set(vbo, attr_id.wd, l, &data); } } diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h index 59cd4aa2776..3154119592d 100644 --- a/source/blender/gpu/GPU_extensions.h +++ b/source/blender/gpu/GPU_extensions.h @@ -47,6 +47,7 @@ void GPU_get_dfdy_factors(float fac[2]); bool GPU_mip_render_workaround(void); bool GPU_depth_blitting_workaround(void); bool GPU_unused_fb_slot_workaround(void); +bool GPU_crappy_amd_driver(void); bool GPU_mem_stats_supported(void); void GPU_mem_stats_get(int *totalmem, int *freemem); diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index b1c8a972980..6fb40b06177 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -211,6 +211,12 @@ bool GPU_unused_fb_slot_workaround(void) return GG.unused_fb_slot_workaround; } +bool GPU_crappy_amd_driver(void) +{ + /* Currently are the same drivers with the `unused_fb_slot` problem. */ + return GPU_unused_fb_slot_workaround(); +} + void gpu_extensions_init(void) { /* during 2.8 development each platform has its own OpenGL minimum requirements -- cgit v1.2.3