diff options
Diffstat (limited to 'source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc')
-rw-r--r-- | source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc index 2e2444a8e3d..5ee34d7fdb2 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc @@ -25,6 +25,7 @@ #include "GPU_capabilities.h" +#include "draw_subdivision.h" #include "extract_mesh.h" namespace blender::draw { @@ -216,6 +217,86 @@ static void extract_edge_fac_finish(const MeshRenderData *mr, MEM_SAFE_FREE(data->edge_loop_count); } +/* Different function than the one used for the non-subdivision case, as we directly take care of + * the buggy AMD driver case. */ +static GPUVertFormat *get_subdiv_edge_fac_format() +{ + static GPUVertFormat format = {0}; + if (format.attr_len == 0) { + if (GPU_crappy_amd_driver()) { + GPU_vertformat_attr_add(&format, "wd", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); + } + else { + GPU_vertformat_attr_add(&format, "wd", GPU_COMP_U8, 1, GPU_FETCH_INT_TO_FLOAT_UNIT); + } + } + return &format; +} + +static void extract_edge_fac_init_subdiv(const DRWSubdivCache *subdiv_cache, + const MeshRenderData *mr, + struct MeshBatchCache *cache, + void *buffer, + void *UNUSED(data)) +{ + GPUVertBuf *edge_idx = cache->final.buff.vbo.edge_idx; + GPUVertBuf *pos_nor = cache->final.buff.vbo.pos_nor; + GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buffer); + GPU_vertbuf_init_build_on_device( + vbo, get_subdiv_edge_fac_format(), subdiv_cache->num_subdiv_loops + mr->loop_loose_len); + + /* Create a temporary buffer for the edge original indices if it was not requested. */ + const bool has_edge_idx = edge_idx != nullptr; + GPUVertBuf *loop_edge_idx = nullptr; + if (has_edge_idx) { + loop_edge_idx = edge_idx; + } + else { + loop_edge_idx = GPU_vertbuf_calloc(); + draw_subdiv_init_origindex_buffer( + loop_edge_idx, + static_cast<int *>(GPU_vertbuf_get_data(subdiv_cache->edges_orig_index)), + subdiv_cache->num_subdiv_loops, + 0); + } + + draw_subdiv_build_edge_fac_buffer(subdiv_cache, pos_nor, loop_edge_idx, vbo); + + if (!has_edge_idx) { + GPU_vertbuf_discard(loop_edge_idx); + } +} + +static void extract_edge_fac_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache, + const MeshRenderData *UNUSED(mr), + const MeshExtractLooseGeom *loose_geom, + void *buffer, + void *UNUSED(data)) +{ + if (loose_geom->edge_len == 0) { + return; + } + + GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buffer); + + /* Make sure buffer is active for sending loose data. */ + GPU_vertbuf_use(vbo); + + uint offset = subdiv_cache->num_subdiv_loops; + for (int i = 0; i < loose_geom->edge_len; i++) { + if (GPU_crappy_amd_driver()) { + float loose_edge_fac[2] = {1.0f, 1.0f}; + GPU_vertbuf_update_sub(vbo, offset * sizeof(float), sizeof(loose_edge_fac), loose_edge_fac); + } + else { + char loose_edge_fac[2] = {255, 255}; + GPU_vertbuf_update_sub(vbo, offset * sizeof(char), sizeof(loose_edge_fac), loose_edge_fac); + } + + offset += 2; + } +} + constexpr MeshExtract create_extractor_edge_fac() { MeshExtract extractor = {nullptr}; @@ -224,6 +305,8 @@ constexpr MeshExtract create_extractor_edge_fac() extractor.iter_poly_mesh = extract_edge_fac_iter_poly_mesh; extractor.iter_ledge_bm = extract_edge_fac_iter_ledge_bm; extractor.iter_ledge_mesh = extract_edge_fac_iter_ledge_mesh; + extractor.init_subdiv = extract_edge_fac_init_subdiv; + extractor.iter_loose_geom_subdiv = extract_edge_fac_loose_geom_subdiv; extractor.finish = extract_edge_fac_finish; extractor.data_type = MR_DATA_POLY_NOR; extractor.data_size = sizeof(MeshExtract_EdgeFac_Data); |