Blender  V3.3
extract_mesh_vbo_uv.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2021 Blender Foundation. All rights reserved. */
3 
8 #include "BLI_string.h"
9 
10 #include "draw_subdivision.h"
11 #include "extract_mesh.hh"
12 
13 namespace blender::draw {
14 
15 /* ---------------------------------------------------------------------- */
19 /* Initialize the vertex format to be used for UVs. Return true if any UV layer is
20  * found, false otherwise. */
22  MeshBatchCache *cache,
23  CustomData *cd_ldata,
24  eMRExtractType extract_type,
25  uint32_t &r_uv_layers)
26 {
28 
29  uint32_t uv_layers = cache->cd_used.uv;
30  /* HACK to fix T68857 */
31  if (extract_type == MR_EXTRACT_BMESH && cache->cd_used.edit_uv == 1) {
32  int layer = CustomData_get_active_layer(cd_ldata, CD_MLOOPUV);
33  if (layer != -1) {
34  uv_layers |= (1 << layer);
35  }
36  }
37 
38  r_uv_layers = uv_layers;
39 
40  for (int i = 0; i < MAX_MTFACE; i++) {
41  if (uv_layers & (1 << i)) {
42  char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
43  const char *layer_name = CustomData_get_layer_name(cd_ldata, CD_MLOOPUV, i);
44 
45  GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME);
46  /* UV layer name. */
47  BLI_snprintf(attr_name, sizeof(attr_name), "a%s", attr_safe_name);
49  /* Active render layer name. */
50  if (i == CustomData_get_render_layer(cd_ldata, CD_MLOOPUV)) {
52  }
53  /* Active display layer name. */
54  if (i == CustomData_get_active_layer(cd_ldata, CD_MLOOPUV)) {
56  /* Alias to `pos` for edit uvs. */
58  }
59  /* Stencil mask uv layer name. */
60  if (i == CustomData_get_stencil_layer(cd_ldata, CD_MLOOPUV)) {
62  }
63  }
64  }
65 
66  if (format->attr_len == 0) {
68  return false;
69  }
70 
71  return true;
72 }
73 
74 static void extract_uv_init(const MeshRenderData *mr,
75  MeshBatchCache *cache,
76  void *buf,
77  void *UNUSED(tls_data))
78 {
79  GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
80  GPUVertFormat format = {0};
81 
82  CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata;
83  int v_len = mr->loop_len;
84  uint32_t uv_layers = cache->cd_used.uv;
85  if (!mesh_extract_uv_format_init(&format, cache, cd_ldata, mr->extract_type, uv_layers)) {
86  /* VBO will not be used, only allocate minimum of memory. */
87  v_len = 1;
88  }
89 
91  GPU_vertbuf_data_alloc(vbo, v_len);
92 
93  float(*uv_data)[2] = (float(*)[2])GPU_vertbuf_get_data(vbo);
94  for (int i = 0; i < MAX_MTFACE; i++) {
95  if (uv_layers & (1 << i)) {
96  if (mr->extract_type == MR_EXTRACT_BMESH) {
97  int cd_ofs = CustomData_get_n_offset(cd_ldata, CD_MLOOPUV, i);
98  BMIter f_iter;
99  BMFace *efa;
100  BM_ITER_MESH (efa, &f_iter, mr->bm, BM_FACES_OF_MESH) {
101  BMLoop *l_iter, *l_first;
102  l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
103  do {
104  MLoopUV *luv = (MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_iter, cd_ofs);
105  memcpy(uv_data, luv->uv, sizeof(*uv_data));
106  uv_data++;
107  } while ((l_iter = l_iter->next) != l_first);
108  }
109  }
110  else {
111  const MLoopUV *layer_data = (const MLoopUV *)CustomData_get_layer_n(
112  cd_ldata, CD_MLOOPUV, i);
113  for (int ml_index = 0; ml_index < mr->loop_len; ml_index++, uv_data++, layer_data++) {
114  memcpy(uv_data, layer_data->uv, sizeof(*uv_data));
115  }
116  }
117  }
118  }
119 }
120 
121 static void extract_uv_init_subdiv(const DRWSubdivCache *subdiv_cache,
122  const MeshRenderData *UNUSED(mr),
123  MeshBatchCache *cache,
124  void *buffer,
125  void *UNUSED(data))
126 {
127  Mesh *coarse_mesh = subdiv_cache->mesh;
128  GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buffer);
129  GPUVertFormat format = {0};
130 
131  uint v_len = subdiv_cache->num_subdiv_loops;
132  uint uv_layers;
134  &format, cache, &coarse_mesh->ldata, MR_EXTRACT_MESH, uv_layers)) {
135  /* TODO(kevindietrich): handle this more gracefully. */
136  v_len = 1;
137  }
138 
140 
141  if (uv_layers == 0) {
142  return;
143  }
144 
145  /* Index of the UV layer in the compact buffer. Used UV layers are stored in a single buffer. */
146  int pack_layer_index = 0;
147  for (int i = 0; i < MAX_MTFACE; i++) {
148  if (uv_layers & (1 << i)) {
149  const int offset = (int)subdiv_cache->num_subdiv_loops * pack_layer_index++;
150  draw_subdiv_extract_uvs(subdiv_cache, vbo, i, offset);
151  }
152  }
153 }
154 
156 {
157  MeshExtract extractor = {nullptr};
158  extractor.init = extract_uv_init;
160  extractor.data_type = MR_DATA_NONE;
161  extractor.data_size = 0;
162  extractor.use_threading = false;
163  extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.uv);
164  return extractor;
165 }
166 
169 } // namespace blender::draw
170 
typedef float(TangentPoint)[2]
const char * CustomData_get_layer_name(const struct CustomData *data, int type, int n)
int CustomData_get_active_layer(const struct CustomData *data, int type)
int CustomData_get_stencil_layer(const struct CustomData *data, int type)
void * CustomData_get_layer_n(const struct CustomData *data, int type, int n)
int CustomData_get_n_offset(const struct CustomData *data, int type, int n)
int CustomData_get_render_layer(const struct CustomData *data, int type)
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
unsigned int uint
Definition: BLI_sys_types.h:67
#define UNUSED(x)
@ CD_MLOOPUV
#define MAX_MTFACE
struct GPUVertBuf GPUVertBuf
void GPU_vertbuf_data_alloc(GPUVertBuf *, uint v_len)
#define GPU_vertbuf_init_with_format(verts, format)
void * GPU_vertbuf_get_data(const GPUVertBuf *verts)
void GPU_vertbuf_init_build_on_device(GPUVertBuf *verts, GPUVertFormat *format, uint v_len)
void GPU_vertformat_safe_attr_name(const char *attr_name, char *r_safe_name, uint max_len)
@ GPU_FETCH_FLOAT
uint GPU_vertformat_attr_add(GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
#define GPU_MAX_SAFE_ATTR_NAME
void GPU_vertformat_alias_add(GPUVertFormat *, const char *alias)
void GPU_vertformat_deinterleave(GPUVertFormat *format)
@ GPU_COMP_F32
#define BM_FACE_FIRST_LOOP(p)
Definition: bmesh_class.h:622
#define BM_ELEM_CD_GET_VOID_P(ele, offset)
Definition: bmesh_class.h:541
#define BM_ITER_MESH(ele, iter, bm, itype)
@ BM_FACES_OF_MESH
@ MR_DATA_NONE
void draw_subdiv_extract_uvs(const DRWSubdivCache *cache, GPUVertBuf *uvs, const int face_varying_channel, const int dst_offset)
Extraction of Mesh data into VBO to feed to GPU.
eMRExtractType
Definition: extract_mesh.hh:30
@ MR_EXTRACT_BMESH
Definition: extract_mesh.hh:31
@ MR_EXTRACT_MESH
Definition: extract_mesh.hh:33
const MeshExtract extract_uv
ccl_global float * buffer
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
format
Definition: logImageCore.h:38
static void extract_uv_init_subdiv(const DRWSubdivCache *subdiv_cache, const MeshRenderData *UNUSED(mr), MeshBatchCache *cache, void *buffer, void *UNUSED(data))
static bool mesh_extract_uv_format_init(GPUVertFormat *format, MeshBatchCache *cache, CustomData *cd_ldata, eMRExtractType extract_type, uint32_t &r_uv_layers)
constexpr MeshExtract create_extractor_uv()
static void extract_uv_init(const MeshRenderData *mr, MeshBatchCache *cache, void *buf, void *UNUSED(tls_data))
unsigned int uint32_t
Definition: stdint.h:80
struct BMLoop * next
Definition: bmesh_class.h:233
CustomData ldata
Definition: bmesh_class.h:337
struct Mesh * mesh
DRW_MeshCDMask cd_used
size_t mesh_buffer_offset
eMRDataType data_type
ExtractInitSubdivFn * init_subdiv
size_t data_size
bool use_threading
ExtractInitFn * init
eMRExtractType extract_type
Definition: extract_mesh.hh:37
CustomData ldata