Merge branch 'master' into blender2.8
[blender.git] / source / blender / draw / intern / draw_cache_impl_particles.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2017 by Blender Foundation.
19  * All rights reserved.
20  *
21  * Contributor(s): Blender Foundation, Mike Erwin, Dalai Felinto
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file draw_cache_impl_particles.c
27  *  \ingroup draw
28  *
29  * \brief Particle API for render engines
30  */
31
32 #include "DRW_render.h"
33
34 #include "MEM_guardedalloc.h"
35
36 #include "BLI_utildefines.h"
37 #include "BLI_math_vector.h"
38 #include "BLI_string.h"
39 #include "BLI_ghash.h"
40
41 #include "DNA_mesh_types.h"
42 #include "DNA_meshdata_types.h"
43 #include "DNA_modifier_types.h"
44 #include "DNA_particle_types.h"
45 #include "DNA_customdata_types.h"
46
47 #include "BKE_mesh.h"
48 #include "BKE_modifier.h"
49 #include "BKE_particle.h"
50 #include "BKE_pointcache.h"
51
52 #include "ED_particle.h"
53
54 #include "GPU_batch.h"
55
56 #include "DEG_depsgraph_query.h"
57
58 #include "draw_cache_impl.h"  /* own include */
59 #include "draw_hair_private.h"
60
61 static void particle_batch_cache_clear(ParticleSystem *psys);
62
63 /* ---------------------------------------------------------------------- */
64 /* Particle GPUBatch Cache */
65
66 typedef struct ParticlePointCache {
67         GPUVertBuf *pos;
68         GPUBatch *points;
69         int elems_len;
70         int point_len;
71 } ParticlePointCache;
72
73 typedef struct ParticleBatchCache {
74         /* Object mode strands for hair and points for particle,
75          * strands for paths when in edit mode.
76          */
77         ParticleHairCache hair;    /* Used for hair strands */
78         ParticlePointCache point;  /* Used for particle points. */
79
80         /* Control points when in edit mode. */
81         ParticleHairCache edit_hair;
82
83         GPUVertBuf *edit_pos;
84         GPUBatch *edit_strands;
85
86         GPUVertBuf *edit_inner_pos;
87         GPUBatch *edit_inner_points;
88         int edit_inner_point_len;
89
90         GPUVertBuf *edit_tip_pos;
91         GPUBatch *edit_tip_points;
92         int edit_tip_point_len;
93
94         /* Settings to determine if cache is invalid. */
95         bool is_dirty;
96         bool edit_is_weight;
97 } ParticleBatchCache;
98
99 /* GPUBatch cache management. */
100
101 typedef struct HairAttributeID {
102         uint pos;
103         uint tan;
104         uint ind;
105 } HairAttributeID;
106
107 typedef struct EditStrandData {
108         float pos[3];
109         uchar color;
110 } EditStrandData;
111
112 static GPUVertFormat *edit_points_vert_format_get(uint *r_pos_id, uint *r_color_id)
113 {
114         static GPUVertFormat edit_point_format = { 0 };
115         static uint pos_id, color_id;
116         if (edit_point_format.attr_len == 0) {
117                 /* Keep in sync with EditStrandData */
118                 pos_id = GPU_vertformat_attr_add(&edit_point_format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
119                 color_id = GPU_vertformat_attr_add(&edit_point_format, "color", GPU_COMP_U8, 1, GPU_FETCH_INT_TO_FLOAT_UNIT);
120         }
121         *r_pos_id = pos_id;
122         *r_color_id = color_id;
123         return &edit_point_format;
124 }
125
126 static bool particle_batch_cache_valid(ParticleSystem *psys)
127 {
128         ParticleBatchCache *cache = psys->batch_cache;
129
130         if (cache == NULL) {
131                 return false;
132         }
133
134         if (cache->is_dirty == false) {
135                 return true;
136         }
137         else {
138                 return false;
139         }
140
141         return true;
142 }
143
144 static void particle_batch_cache_init(ParticleSystem *psys)
145 {
146         ParticleBatchCache *cache = psys->batch_cache;
147
148         if (!cache) {
149                 cache = psys->batch_cache = MEM_callocN(sizeof(*cache), __func__);
150         }
151         else {
152                 memset(cache, 0, sizeof(*cache));
153         }
154
155         cache->is_dirty = false;
156 }
157
158 static ParticleBatchCache *particle_batch_cache_get(ParticleSystem *psys)
159 {
160         if (!particle_batch_cache_valid(psys)) {
161                 particle_batch_cache_clear(psys);
162                 particle_batch_cache_init(psys);
163         }
164         return psys->batch_cache;
165 }
166
167 void DRW_particle_batch_cache_dirty_tag(ParticleSystem *psys, int mode)
168 {
169         ParticleBatchCache *cache = psys->batch_cache;
170         if (cache == NULL) {
171                 return;
172         }
173         switch (mode) {
174                 case BKE_PARTICLE_BATCH_DIRTY_ALL:
175                         cache->is_dirty = true;
176                         break;
177                 default:
178                         BLI_assert(0);
179         }
180 }
181
182 static void particle_batch_cache_clear_point(ParticlePointCache *point_cache)
183 {
184         GPU_BATCH_DISCARD_SAFE(point_cache->points);
185         GPU_VERTBUF_DISCARD_SAFE(point_cache->pos);
186 }
187
188 static void particle_batch_cache_clear_hair(ParticleHairCache *hair_cache)
189 {
190         /* TODO more granular update tagging. */
191         GPU_VERTBUF_DISCARD_SAFE(hair_cache->proc_point_buf);
192         DRW_TEXTURE_FREE_SAFE(hair_cache->point_tex);
193
194         GPU_VERTBUF_DISCARD_SAFE(hair_cache->proc_strand_buf);
195         DRW_TEXTURE_FREE_SAFE(hair_cache->strand_tex);
196
197         for (int i = 0; i < MAX_MTFACE; ++i) {
198                 GPU_VERTBUF_DISCARD_SAFE(hair_cache->proc_uv_buf[i]);
199                 DRW_TEXTURE_FREE_SAFE(hair_cache->uv_tex[i]);
200         }
201         for (int i = 0; i < MAX_MCOL; ++i) {
202                 GPU_VERTBUF_DISCARD_SAFE(hair_cache->proc_col_buf[i]);
203                 DRW_TEXTURE_FREE_SAFE(hair_cache->col_tex[i]);
204         }
205         for (int i = 0; i < MAX_HAIR_SUBDIV; ++i) {
206                 GPU_VERTBUF_DISCARD_SAFE(hair_cache->final[i].proc_buf);
207                 DRW_TEXTURE_FREE_SAFE(hair_cache->final[i].proc_tex);
208                 for (int j = 0; j < MAX_THICKRES; ++j) {
209                         GPU_BATCH_DISCARD_SAFE(hair_cache->final[i].proc_hairs[j]);
210                 }
211         }
212
213         /* "Normal" legacy hairs */
214         GPU_BATCH_DISCARD_SAFE(hair_cache->hairs);
215         GPU_VERTBUF_DISCARD_SAFE(hair_cache->pos);
216         GPU_INDEXBUF_DISCARD_SAFE(hair_cache->indices);
217 }
218
219 static void particle_batch_cache_clear(ParticleSystem *psys)
220 {
221         ParticleBatchCache *cache = psys->batch_cache;
222         if (!cache) {
223                 return;
224         }
225
226         particle_batch_cache_clear_point(&cache->point);
227         particle_batch_cache_clear_hair(&cache->hair);
228
229         particle_batch_cache_clear_hair(&cache->edit_hair);
230
231         GPU_BATCH_DISCARD_SAFE(cache->edit_inner_points);
232         GPU_VERTBUF_DISCARD_SAFE(cache->edit_inner_pos);
233         GPU_BATCH_DISCARD_SAFE(cache->edit_tip_points);
234         GPU_VERTBUF_DISCARD_SAFE(cache->edit_tip_pos);
235 }
236
237 void DRW_particle_batch_cache_free(ParticleSystem *psys)
238 {
239         particle_batch_cache_clear(psys);
240         MEM_SAFE_FREE(psys->batch_cache);
241 }
242
243 static void count_cache_segment_keys(
244         ParticleCacheKey **pathcache,
245         const int num_path_cache_keys,
246         ParticleHairCache *hair_cache)
247 {
248         for (int i = 0; i < num_path_cache_keys; i++) {
249                 ParticleCacheKey *path = pathcache[i];
250                 if (path->segments > 0) {
251                         hair_cache->strands_len++;
252                         hair_cache->elems_len += path->segments + 2;
253                         hair_cache->point_len += path->segments + 1;
254                 }
255         }
256 }
257
258 static void ensure_seg_pt_count(
259         PTCacheEdit *edit,
260         ParticleSystem *psys,
261         ParticleHairCache *hair_cache)
262 {
263         if ((hair_cache->pos != NULL && hair_cache->indices != NULL) ||
264             (hair_cache->proc_point_buf != NULL))
265         {
266                 return;
267         }
268
269         hair_cache->strands_len = 0;
270         hair_cache->elems_len = 0;
271         hair_cache->point_len = 0;
272
273         if (edit != NULL && edit->pathcache != NULL) {
274                 count_cache_segment_keys(edit->pathcache, edit->totcached, hair_cache);
275         }
276         else {
277                 if (psys->pathcache &&
278                     (!psys->childcache || (psys->part->draw & PART_DRAW_PARENT)))
279                 {
280                         count_cache_segment_keys(psys->pathcache, psys->totpart, hair_cache);
281                 }
282                 if (psys->childcache) {
283                         const int child_count = psys->totchild * psys->part->disp / 100;
284                         count_cache_segment_keys(psys->childcache, child_count, hair_cache);
285                 }
286         }
287 }
288
289 static void particle_pack_mcol(MCol *mcol, ushort r_scol[3])
290 {
291         /* Convert to linear ushort and swizzle */
292         r_scol[0] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol->b]);
293         r_scol[1] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol->g]);
294         r_scol[2] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol->r]);
295 }
296
297 /* Used by parent particles and simple children. */
298 static void particle_calculate_parent_uvs(
299         ParticleSystem *psys,
300         ParticleSystemModifierData *psmd,
301         const int num_uv_layers,
302         const int parent_index,
303         /*const*/ MTFace **mtfaces,
304         float (*r_uv)[2])
305 {
306         if (psmd == NULL) {
307                 return;
308         }
309         const int emit_from = psmd->psys->part->from;
310         if (!ELEM(emit_from, PART_FROM_FACE, PART_FROM_VOLUME)) {
311                 return;
312         }
313         ParticleData *particle = &psys->particles[parent_index];
314         int num = particle->num_dmcache;
315         if (num == DMCACHE_NOTFOUND || num == DMCACHE_ISCHILD) {
316                 if (particle->num < psmd->mesh_final->totface) {
317                         num = particle->num;
318                 }
319         }
320         if (num != DMCACHE_NOTFOUND && num != DMCACHE_ISCHILD) {
321                 MFace *mface = &psmd->mesh_final->mface[num];
322                 for (int j = 0; j < num_uv_layers; j++) {
323                         psys_interpolate_uvs(
324                                 mtfaces[j] + num,
325                                 mface->v4,
326                                 particle->fuv,
327                                 r_uv[j]);
328                 }
329         }
330 }
331
332 static void particle_calculate_parent_mcol(
333         ParticleSystem *psys,
334         ParticleSystemModifierData *psmd,
335         const int num_uv_layers,
336         const int parent_index,
337         /*const*/ MCol **mcols,
338         MCol *r_mcol)
339 {
340         if (psmd == NULL) {
341                 return;
342         }
343         const int emit_from = psmd->psys->part->from;
344         if (!ELEM(emit_from, PART_FROM_FACE, PART_FROM_VOLUME)) {
345                 return;
346         }
347         ParticleData *particle = &psys->particles[parent_index];
348         int num = particle->num_dmcache;
349         if (num == DMCACHE_NOTFOUND || num == DMCACHE_ISCHILD) {
350                 if (particle->num < psmd->mesh_final->totface) {
351                         num = particle->num;
352                 }
353         }
354         if (num != DMCACHE_NOTFOUND && num != DMCACHE_ISCHILD) {
355                 MFace *mface = &psmd->mesh_final->mface[num];
356                 for (int j = 0; j < num_uv_layers; j++) {
357                         psys_interpolate_mcol(
358                                 mcols[j] + num,
359                                 mface->v4,
360                                 particle->fuv,
361                                 &r_mcol[j]);
362                 }
363         }
364 }
365
366 /* Used by interpolated children. */
367 static void particle_interpolate_children_uvs(
368         ParticleSystem *psys,
369         ParticleSystemModifierData *psmd,
370         const int num_uv_layers,
371         const int child_index,
372         /*const*/ MTFace **mtfaces,
373         float (*r_uv)[2])
374 {
375         if (psmd == NULL) {
376                 return;
377         }
378         const int emit_from = psmd->psys->part->from;
379         if (!ELEM(emit_from, PART_FROM_FACE, PART_FROM_VOLUME)) {
380                 return;
381         }
382         ChildParticle *particle = &psys->child[child_index];
383         int num = particle->num;
384         if (num != DMCACHE_NOTFOUND) {
385                 MFace *mface = &psmd->mesh_final->mface[num];
386                 for (int j = 0; j < num_uv_layers; j++) {
387                         psys_interpolate_uvs(
388                                 mtfaces[j] + num,
389                                 mface->v4,
390                                 particle->fuv,
391                                 r_uv[j]);
392                 }
393         }
394 }
395
396 static void particle_interpolate_children_mcol(
397         ParticleSystem *psys,
398         ParticleSystemModifierData *psmd,
399         const int num_col_layers,
400         const int child_index,
401         /*const*/ MCol **mcols,
402         MCol *r_mcol)
403 {
404         if (psmd == NULL) {
405                 return;
406         }
407         const int emit_from = psmd->psys->part->from;
408         if (!ELEM(emit_from, PART_FROM_FACE, PART_FROM_VOLUME)) {
409                 return;
410         }
411         ChildParticle *particle = &psys->child[child_index];
412         int num = particle->num;
413         if (num != DMCACHE_NOTFOUND) {
414                 MFace *mface = &psmd->mesh_final->mface[num];
415                 for (int j = 0; j < num_col_layers; j++) {
416                         psys_interpolate_mcol(
417                                 mcols[j] + num,
418                                 mface->v4,
419                                 particle->fuv,
420                                 &r_mcol[j]);
421                 }
422         }
423 }
424
425 static void particle_calculate_uvs(
426         ParticleSystem *psys,
427         ParticleSystemModifierData *psmd,
428         const bool is_simple,
429         const int num_uv_layers,
430         const int parent_index,
431         const int child_index,
432         /*const*/ MTFace **mtfaces,
433         float (**r_parent_uvs)[2],
434         float (**r_uv)[2])
435 {
436         if (psmd == NULL) {
437                 return;
438         }
439         if (is_simple) {
440                 if (r_parent_uvs[parent_index] != NULL) {
441                         *r_uv = r_parent_uvs[parent_index];
442                 }
443                 else {
444                         *r_uv = MEM_callocN(sizeof(**r_uv) * num_uv_layers, "Particle UVs");
445                 }
446         }
447         else {
448                 *r_uv = MEM_callocN(sizeof(**r_uv) * num_uv_layers, "Particle UVs");
449         }
450         if (child_index == -1) {
451                 /* Calculate UVs for parent particles. */
452                 if (is_simple) {
453                         r_parent_uvs[parent_index] = *r_uv;
454                 }
455                 particle_calculate_parent_uvs(
456                         psys, psmd, num_uv_layers, parent_index, mtfaces, *r_uv);
457         }
458         else {
459                 /* Calculate UVs for child particles. */
460                 if (!is_simple) {
461                         particle_interpolate_children_uvs(
462                                 psys, psmd, num_uv_layers, child_index, mtfaces, *r_uv);
463                 }
464                 else if (!r_parent_uvs[psys->child[child_index].parent]) {
465                         r_parent_uvs[psys->child[child_index].parent] = *r_uv;
466                         particle_calculate_parent_uvs(
467                                 psys, psmd, num_uv_layers, parent_index, mtfaces, *r_uv);
468                 }
469         }
470 }
471
472 static void particle_calculate_mcol(
473         ParticleSystem *psys,
474         ParticleSystemModifierData *psmd,
475         const bool is_simple,
476         const int num_col_layers,
477         const int parent_index,
478         const int child_index,
479         /*const*/ MCol **mcols,
480         MCol **r_parent_mcol,
481         MCol **r_mcol)
482 {
483         if (psmd == NULL) {
484                 return;
485         }
486         if (is_simple) {
487                 if (r_parent_mcol[parent_index] != NULL) {
488                         *r_mcol = r_parent_mcol[parent_index];
489                 }
490                 else {
491                         *r_mcol = MEM_callocN(sizeof(**r_mcol) * num_col_layers, "Particle MCol");
492                 }
493         }
494         else {
495                 *r_mcol = MEM_callocN(sizeof(**r_mcol) * num_col_layers, "Particle MCol");
496         }
497         if (child_index == -1) {
498                 /* Calculate MCols for parent particles. */
499                 if (is_simple) {
500                         r_parent_mcol[parent_index] = *r_mcol;
501                 }
502                 particle_calculate_parent_mcol(
503                         psys, psmd, num_col_layers, parent_index, mcols, *r_mcol);
504         }
505         else {
506                 /* Calculate MCols for child particles. */
507                 if (!is_simple) {
508                         particle_interpolate_children_mcol(
509                                 psys, psmd, num_col_layers, child_index, mcols, *r_mcol);
510                 }
511                 else if (!r_parent_mcol[psys->child[child_index].parent]) {
512                         r_parent_mcol[psys->child[child_index].parent] = *r_mcol;
513                         particle_calculate_parent_mcol(
514                                 psys, psmd, num_col_layers, parent_index, mcols, *r_mcol);
515                 }
516         }
517 }
518
519 /* Will return last filled index. */
520 typedef enum ParticleSource {
521         PARTICLE_SOURCE_PARENT,
522         PARTICLE_SOURCE_CHILDREN,
523 } ParticleSource;
524 static int particle_batch_cache_fill_segments(
525         ParticleSystem *psys,
526         ParticleSystemModifierData *psmd,
527         ParticleCacheKey **path_cache,
528         const ParticleSource particle_source,
529         const int global_offset,
530         const int start_index,
531         const int num_path_keys,
532         const int num_uv_layers,
533         const int num_col_layers,
534         /*const*/ MTFace **mtfaces,
535         /*const*/ MCol **mcols,
536         uint *uv_id,
537         uint *col_id,
538         float (***r_parent_uvs)[2],
539         MCol ***r_parent_mcol,
540         GPUIndexBufBuilder *elb,
541         HairAttributeID *attr_id,
542         ParticleHairCache *hair_cache)
543 {
544         const bool is_simple = (psys->part->childtype == PART_CHILD_PARTICLES);
545         const bool is_child = (particle_source == PARTICLE_SOURCE_CHILDREN);
546         if (is_simple && *r_parent_uvs == NULL) {
547                 /* TODO(sergey): For edit mode it should be edit->totcached. */
548                 *r_parent_uvs = MEM_callocN(
549                         sizeof(*r_parent_uvs) * psys->totpart,
550                         "Parent particle UVs");
551         }
552         if (is_simple && *r_parent_mcol == NULL) {
553                 *r_parent_mcol = MEM_callocN(
554                         sizeof(*r_parent_mcol) * psys->totpart,
555                         "Parent particle MCol");
556         }
557         int curr_point = start_index;
558         for (int i = 0; i < num_path_keys; i++) {
559                 ParticleCacheKey *path = path_cache[i];
560                 if (path->segments <= 0) {
561                         continue;
562                 }
563                 float tangent[3];
564                 float (*uv)[2] = NULL;
565                 MCol *mcol = NULL;
566                 particle_calculate_mcol(
567                         psys, psmd,
568                         is_simple, num_col_layers,
569                         is_child ? psys->child[i].parent : i,
570                         is_child ? i : -1,
571                         mcols,
572                         *r_parent_mcol, &mcol);
573                 particle_calculate_uvs(
574                         psys, psmd,
575                         is_simple, num_uv_layers,
576                         is_child ? psys->child[i].parent : i,
577                         is_child ? i : -1,
578                         mtfaces,
579                         *r_parent_uvs, &uv);
580                 for (int j = 0; j < path->segments; j++) {
581                         if (j == 0) {
582                                 sub_v3_v3v3(tangent, path[j + 1].co, path[j].co);
583                         }
584                         else {
585                                 sub_v3_v3v3(tangent, path[j + 1].co, path[j - 1].co);
586                         }
587                         GPU_vertbuf_attr_set(hair_cache->pos, attr_id->pos, curr_point, path[j].co);
588                         GPU_vertbuf_attr_set(hair_cache->pos, attr_id->tan, curr_point, tangent);
589                         GPU_vertbuf_attr_set(hair_cache->pos, attr_id->ind, curr_point, &i);
590                         if (psmd != NULL) {
591                                 for (int k = 0; k < num_uv_layers; k++) {
592                                         GPU_vertbuf_attr_set(
593                                                 hair_cache->pos, uv_id[k], curr_point,
594                                                 (is_simple && is_child) ?
595                                                 (*r_parent_uvs)[psys->child[i].parent][k] : uv[k]);
596                                 }
597                                 for (int k = 0; k < num_col_layers; k++) {
598                                         /* TODO Put the conversion outside the loop */
599                                         ushort scol[4];
600                                         particle_pack_mcol(
601                                                 (is_simple && is_child) ?
602                                                 &(*r_parent_mcol)[psys->child[i].parent][k] : &mcol[k],
603                                                 scol);
604                                         GPU_vertbuf_attr_set(hair_cache->pos, col_id[k], curr_point, scol);
605                                 }
606                         }
607                         GPU_indexbuf_add_generic_vert(elb, curr_point);
608                         curr_point++;
609                 }
610                 sub_v3_v3v3(tangent, path[path->segments].co, path[path->segments - 1].co);
611
612                 int global_index = i + global_offset;
613                 GPU_vertbuf_attr_set(hair_cache->pos, attr_id->pos, curr_point, path[path->segments].co);
614                 GPU_vertbuf_attr_set(hair_cache->pos, attr_id->tan, curr_point, tangent);
615                 GPU_vertbuf_attr_set(hair_cache->pos, attr_id->ind, curr_point, &global_index);
616
617                 if (psmd != NULL) {
618                         for (int k = 0; k < num_uv_layers; k++) {
619                                 GPU_vertbuf_attr_set(
620                                         hair_cache->pos, uv_id[k], curr_point,
621                                         (is_simple && is_child) ?
622                                         (*r_parent_uvs)[psys->child[i].parent][k] : uv[k]);
623                         }
624                         for (int k = 0; k < num_col_layers; k++) {
625                                 /* TODO Put the conversion outside the loop */
626                                 ushort scol[4];
627                                 particle_pack_mcol(
628                                         (is_simple && is_child) ?
629                                         &(*r_parent_mcol)[psys->child[i].parent][k] : &mcol[k],
630                                         scol);
631                                 GPU_vertbuf_attr_set(hair_cache->pos, col_id[k], curr_point, scol);
632                         }
633                         if (!is_simple) {
634                                 MEM_freeN(uv);
635                                 MEM_freeN(mcol);
636                         }
637                 }
638                 /* Finish the segment and add restart primitive. */
639                 GPU_indexbuf_add_generic_vert(elb, curr_point);
640                 GPU_indexbuf_add_primitive_restart(elb);
641                 curr_point++;
642         }
643         return curr_point;
644 }
645
646 static void particle_batch_cache_fill_segments_proc_pos(
647         ParticleCacheKey **path_cache,
648         const int num_path_keys,
649         GPUVertBufRaw *attr_step)
650 {
651         for (int i = 0; i < num_path_keys; i++) {
652                 ParticleCacheKey *path = path_cache[i];
653                 if (path->segments <= 0) {
654                         continue;
655                 }
656                 float total_len = 0.0f;
657                 float *co_prev = NULL, *seg_data_first;
658                 for (int j = 0; j <= path->segments; j++) {
659                         float *seg_data = (float *)GPU_vertbuf_raw_step(attr_step);
660                         copy_v3_v3(seg_data, path[j].co);
661                         if (co_prev) {
662                                 total_len += len_v3v3(co_prev, path[j].co);
663                         }
664                         else {
665                                 seg_data_first = seg_data;
666                         }
667                         seg_data[3] = total_len;
668                         co_prev = path[j].co;
669                 }
670                 if (total_len > 0.0f) {
671                         /* Divide by total length to have a [0-1] number. */
672                         for (int j = 0; j <= path->segments; j++, seg_data_first += 4) {
673                                 seg_data_first[3] /= total_len;
674                         }
675                 }
676         }
677 }
678
679 static float particle_key_select_ratio(const PTCacheEdit *edit, int strand, float t)
680 {
681         const PTCacheEditPoint *point = &edit->points[strand];
682         float edit_key_seg_t = 1.0f / (point->totkey - 1);
683         if (t == 1.0) {
684                 return (point->keys[point->totkey - 1].flag & PEK_SELECT) ? 1.0f : 0.0;
685         }
686         else {
687                 float interp = t / edit_key_seg_t;
688                 int index = (int)interp;
689                 interp -= floorf(interp); /* Time between 2 edit key */
690                 float s1 = (point->keys[index].flag & PEK_SELECT) ? 1.0f : 0.0;
691                 float s2 = (point->keys[index + 1].flag & PEK_SELECT) ? 1.0f : 0.0;
692                 return s1 + interp * (s2 - s1);
693         }
694 }
695
696 static float particle_key_weight(const ParticleData *particle, int strand, float t)
697 {
698         const ParticleData *part = particle + strand;
699         const HairKey *hkeys = part->hair;
700         float edit_key_seg_t = 1.0f / (part->totkey - 1);
701         if (t == 1.0) {
702                 return hkeys[part->totkey - 1].weight;
703         }
704         else {
705                 float interp = t / edit_key_seg_t;
706                 int index = (int)interp;
707                 interp -= floorf(interp); /* Time between 2 edit key */
708                 float s1 = hkeys[index].weight;
709                 float s2 = hkeys[index + 1].weight;
710                 return s1 + interp * (s2 - s1);
711         }
712 }
713
714 static int particle_batch_cache_fill_segments_edit(
715         const PTCacheEdit *edit, /* NULL for weight data */
716         const ParticleData *particle, /* NULL for select data */
717         ParticleCacheKey **path_cache,
718         const int start_index,
719         const int num_path_keys,
720         GPUIndexBufBuilder *elb,
721         GPUVertBufRaw *attr_step)
722 {
723         int curr_point = start_index;
724         for (int i = 0; i < num_path_keys; i++) {
725                 ParticleCacheKey *path = path_cache[i];
726                 if (path->segments <= 0) {
727                         continue;
728                 }
729                 for (int j = 0; j <= path->segments; j++) {
730                         EditStrandData *seg_data = (EditStrandData *)GPU_vertbuf_raw_step(attr_step);
731                         copy_v3_v3(seg_data->pos, path[j].co);
732                         float strand_t = (float)(j) / path->segments;
733                         if (particle) {
734                                 float weight = particle_key_weight(particle, i, strand_t);
735                                 /* NaN or unclamped become 0xFF */
736                                 seg_data->color = (uchar)((weight <= 1.0f) ? 0xFE * weight : 0xFF);
737                         }
738                         else {
739                                 float selected = particle_key_select_ratio(edit, i, strand_t);
740                                 seg_data->color = (uchar)(0xFF * selected);
741                         }
742                         GPU_indexbuf_add_generic_vert(elb, curr_point);
743                         curr_point++;
744                 }
745                 /* Finish the segment and add restart primitive. */
746                 GPU_indexbuf_add_primitive_restart(elb);
747         }
748         return curr_point;
749 }
750
751 static int particle_batch_cache_fill_segments_indices(
752         ParticleCacheKey **path_cache,
753         const int start_index,
754         const int num_path_keys,
755         const int res,
756         GPUIndexBufBuilder *elb)
757 {
758         int curr_point = start_index;
759         for (int i = 0; i < num_path_keys; i++) {
760                 ParticleCacheKey *path = path_cache[i];
761                 if (path->segments <= 0) {
762                         continue;
763                 }
764                 for (int k = 0; k < res; k++) {
765                         GPU_indexbuf_add_generic_vert(elb, curr_point++);
766                 }
767                 GPU_indexbuf_add_primitive_restart(elb);
768         }
769         return curr_point;
770 }
771
772 static int particle_batch_cache_fill_strands_data(
773         ParticleSystem *psys,
774         ParticleSystemModifierData *psmd,
775         ParticleCacheKey **path_cache,
776         const ParticleSource particle_source,
777         const int start_index,
778         const int num_path_keys,
779         GPUVertBufRaw *data_step,
780         float (***r_parent_uvs)[2], GPUVertBufRaw *uv_step, MTFace **mtfaces, int num_uv_layers,
781         MCol ***r_parent_mcol, GPUVertBufRaw *col_step, MCol **mcols, int num_col_layers)
782 {
783         const bool is_simple = (psys->part->childtype == PART_CHILD_PARTICLES);
784         const bool is_child = (particle_source == PARTICLE_SOURCE_CHILDREN);
785         if (is_simple && *r_parent_uvs == NULL) {
786                 /* TODO(sergey): For edit mode it should be edit->totcached. */
787                 *r_parent_uvs = MEM_callocN(
788                         sizeof(*r_parent_uvs) * psys->totpart,
789                         "Parent particle UVs");
790         }
791         if (is_simple && *r_parent_mcol == NULL) {
792                 *r_parent_mcol = MEM_callocN(
793                         sizeof(*r_parent_mcol) * psys->totpart,
794                         "Parent particle MCol");
795         }
796         int curr_point = start_index;
797         for (int i = 0; i < num_path_keys; i++) {
798                 ParticleCacheKey *path = path_cache[i];
799                 if (path->segments <= 0) {
800                         continue;
801                 }
802
803                 uint *seg_data = (uint *)GPU_vertbuf_raw_step(data_step);
804                 *seg_data = (curr_point & 0xFFFFFF) | (path->segments << 24);
805                 curr_point += path->segments + 1;
806
807                 if (psmd != NULL) {
808                         float (*uv)[2] = NULL;
809                         MCol *mcol = NULL;
810
811                         particle_calculate_uvs(
812                                 psys, psmd,
813                                 is_simple, num_uv_layers,
814                                 is_child ? psys->child[i].parent : i,
815                                 is_child ? i : -1,
816                                 mtfaces,
817                                 *r_parent_uvs, &uv);
818
819                         particle_calculate_mcol(
820                                 psys, psmd,
821                                 is_simple, num_col_layers,
822                                 is_child ? psys->child[i].parent : i,
823                                 is_child ? i : -1,
824                                 mcols,
825                                 *r_parent_mcol, &mcol);
826
827                         for (int k = 0; k < num_uv_layers; k++) {
828                                 float *t_uv = (float *)GPU_vertbuf_raw_step(uv_step + k);
829                                 copy_v2_v2(t_uv, uv[k]);
830                         }
831                         for (int k = 0; k < num_col_layers; k++) {
832                                 ushort *scol = (ushort *)GPU_vertbuf_raw_step(col_step + k);
833                                 particle_pack_mcol(
834                                         (is_simple && is_child) ?
835                                         &(*r_parent_mcol)[psys->child[i].parent][k] : &mcol[k],
836                                         scol);
837                         }
838                         if (!is_simple) {
839                                 MEM_freeN(uv);
840                                 MEM_freeN(mcol);
841                         }
842                 }
843         }
844         return curr_point;
845 }
846
847 static void particle_batch_cache_ensure_procedural_final_points(
848         ParticleHairCache *cache,
849         int subdiv)
850 {
851         /* Same format as point_tex. */
852         GPUVertFormat format = { 0 };
853         GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
854
855         cache->final[subdiv].proc_buf = GPU_vertbuf_create_with_format(&format);
856
857         /* Create a destination buffer for the transform feedback. Sized appropriately */
858         /* Those are points! not line segments. */
859         GPU_vertbuf_data_alloc(cache->final[subdiv].proc_buf, cache->final[subdiv].strands_res * cache->strands_len);
860
861         /* Create vbo immediately to bind to texture buffer. */
862         GPU_vertbuf_use(cache->final[subdiv].proc_buf);
863
864         cache->final[subdiv].proc_tex = GPU_texture_create_from_vertbuf(cache->final[subdiv].proc_buf);
865 }
866
867 static void particle_batch_cache_ensure_procedural_strand_data(
868         PTCacheEdit *edit,
869         ParticleSystem *psys,
870         ModifierData *md,
871         ParticleHairCache *cache)
872 {
873         int active_uv = 0;
874         int active_col = 0;
875
876         ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md;
877
878         if (psmd != NULL && psmd->mesh_final != NULL) {
879                 if (CustomData_has_layer(&psmd->mesh_final->ldata, CD_MLOOPUV)) {
880                         cache->num_uv_layers = CustomData_number_of_layers(&psmd->mesh_final->ldata, CD_MLOOPUV);
881                         active_uv = CustomData_get_active_layer(&psmd->mesh_final->ldata, CD_MLOOPUV);
882                 }
883                 if (CustomData_has_layer(&psmd->mesh_final->ldata, CD_MLOOPCOL)) {
884                         cache->num_col_layers = CustomData_number_of_layers(&psmd->mesh_final->ldata, CD_MLOOPCOL);
885                         active_col = CustomData_get_active_layer(&psmd->mesh_final->ldata, CD_MLOOPCOL);
886                 }
887         }
888
889         GPUVertBufRaw data_step;
890         GPUVertBufRaw uv_step[MAX_MTFACE];
891         GPUVertBufRaw col_step[MAX_MCOL];
892
893         MTFace *mtfaces[MAX_MTFACE] = {NULL};
894         MCol *mcols[MAX_MCOL] = {NULL};
895         float (**parent_uvs)[2] = NULL;
896         MCol **parent_mcol = NULL;
897
898         GPUVertFormat format_data = {0};
899         uint data_id = GPU_vertformat_attr_add(&format_data, "data", GPU_COMP_U32, 1, GPU_FETCH_INT);
900
901         GPUVertFormat format_uv = {0};
902         uint uv_id = GPU_vertformat_attr_add(&format_uv, "uv", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
903
904         GPUVertFormat format_col = {0};
905         uint col_id = GPU_vertformat_attr_add(&format_col, "col", GPU_COMP_U16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
906
907         memset(cache->uv_layer_names, 0, sizeof(cache->uv_layer_names));
908         memset(cache->col_layer_names, 0, sizeof(cache->col_layer_names));
909
910         /* Strand Data */
911         cache->proc_strand_buf = GPU_vertbuf_create_with_format(&format_data);
912         GPU_vertbuf_data_alloc(cache->proc_strand_buf, cache->strands_len);
913         GPU_vertbuf_attr_get_raw_data(cache->proc_strand_buf, data_id, &data_step);
914
915         /* UV layers */
916         for (int i = 0; i < cache->num_uv_layers; i++) {
917                 cache->proc_uv_buf[i] = GPU_vertbuf_create_with_format(&format_uv);
918                 GPU_vertbuf_data_alloc(cache->proc_uv_buf[i], cache->strands_len);
919                 GPU_vertbuf_attr_get_raw_data(cache->proc_uv_buf[i], uv_id, &uv_step[i]);
920
921                 const char *name = CustomData_get_layer_name(&psmd->mesh_final->ldata, CD_MLOOPUV, i);
922                 uint hash = BLI_ghashutil_strhash_p(name);
923                 int n = 0;
924                 BLI_snprintf(cache->uv_layer_names[i][n++], MAX_LAYER_NAME_LEN, "u%u", hash);
925                 BLI_snprintf(cache->uv_layer_names[i][n++], MAX_LAYER_NAME_LEN, "a%u", hash);
926
927                 if (i == active_uv) {
928                         BLI_snprintf(cache->uv_layer_names[i][n], MAX_LAYER_NAME_LEN, "u");
929                 }
930         }
931         /* Vertex colors */
932         for (int i = 0; i < cache->num_col_layers; i++) {
933                 cache->proc_col_buf[i] = GPU_vertbuf_create_with_format(&format_col);
934                 GPU_vertbuf_data_alloc(cache->proc_col_buf[i], cache->strands_len);
935                 GPU_vertbuf_attr_get_raw_data(cache->proc_col_buf[i], col_id, &col_step[i]);
936
937                 const char *name = CustomData_get_layer_name(&psmd->mesh_final->ldata, CD_MLOOPCOL, i);
938                 uint hash = BLI_ghashutil_strhash_p(name);
939                 int n = 0;
940                 BLI_snprintf(cache->col_layer_names[i][n++], MAX_LAYER_NAME_LEN, "c%u", hash);
941
942                 /* We only do vcols auto name that are not overridden by uvs */
943                 if (CustomData_get_named_layer_index(&psmd->mesh_final->ldata, CD_MLOOPUV, name) == -1) {
944                         BLI_snprintf(cache->col_layer_names[i][n++], MAX_LAYER_NAME_LEN, "a%u", hash);
945                 }
946
947                 if (i == active_col) {
948                         BLI_snprintf(cache->col_layer_names[i][n], MAX_LAYER_NAME_LEN, "c");
949                 }
950         }
951
952         if (cache->num_uv_layers || cache->num_col_layers) {
953                 BKE_mesh_tessface_ensure(psmd->mesh_final);
954                 if (cache->num_uv_layers) {
955                         for (int j = 0; j < cache->num_uv_layers; j++) {
956                                 mtfaces[j] = (MTFace *)CustomData_get_layer_n(&psmd->mesh_final->fdata, CD_MTFACE, j);
957                         }
958                 }
959                 if (cache->num_col_layers) {
960                         for (int j = 0; j < cache->num_col_layers; j++) {
961                                 mcols[j] = (MCol *)CustomData_get_layer_n(&psmd->mesh_final->fdata, CD_MCOL, j);
962                         }
963                 }
964         }
965
966         if (edit != NULL && edit->pathcache != NULL) {
967                 particle_batch_cache_fill_strands_data(
968                         psys, psmd, edit->pathcache, PARTICLE_SOURCE_PARENT,
969                         0, edit->totcached,
970                         &data_step,
971                         &parent_uvs, uv_step, (MTFace **)mtfaces, cache->num_uv_layers,
972                         &parent_mcol, col_step, (MCol **)mcols, cache->num_col_layers);
973         }
974         else {
975                 int curr_point = 0;
976                 if ((psys->pathcache != NULL) &&
977                     (!psys->childcache || (psys->part->draw & PART_DRAW_PARENT)))
978                 {
979                         curr_point = particle_batch_cache_fill_strands_data(
980                                 psys, psmd, psys->pathcache, PARTICLE_SOURCE_PARENT,
981                                 0, psys->totpart,
982                                 &data_step,
983                                 &parent_uvs, uv_step, (MTFace **)mtfaces, cache->num_uv_layers,
984                                 &parent_mcol, col_step, (MCol **)mcols, cache->num_col_layers);
985                 }
986                 if (psys->childcache) {
987                         const int child_count = psys->totchild * psys->part->disp / 100;
988                         curr_point = particle_batch_cache_fill_strands_data(
989                                 psys, psmd, psys->childcache, PARTICLE_SOURCE_CHILDREN,
990                                 curr_point, child_count,
991                                 &data_step,
992                                 &parent_uvs, uv_step, (MTFace **)mtfaces, cache->num_uv_layers,
993                                 &parent_mcol, col_step, (MCol **)mcols, cache->num_col_layers);
994                 }
995         }
996         /* Cleanup. */
997         if (parent_uvs != NULL) {
998                 /* TODO(sergey): For edit mode it should be edit->totcached. */
999                 for (int i = 0; i < psys->totpart; i++) {
1000                         MEM_SAFE_FREE(parent_uvs[i]);
1001                 }
1002                 MEM_freeN(parent_uvs);
1003         }
1004         if (parent_mcol != NULL) {
1005                 for (int i = 0; i < psys->totpart; i++) {
1006                         MEM_SAFE_FREE(parent_mcol[i]);
1007                 }
1008                 MEM_freeN(parent_mcol);
1009         }
1010
1011         /* Create vbo immediately to bind to texture buffer. */
1012         GPU_vertbuf_use(cache->proc_strand_buf);
1013         cache->strand_tex = GPU_texture_create_from_vertbuf(cache->proc_strand_buf);
1014
1015         for (int i = 0; i < cache->num_uv_layers; i++) {
1016                 GPU_vertbuf_use(cache->proc_uv_buf[i]);
1017                 cache->uv_tex[i] = GPU_texture_create_from_vertbuf(cache->proc_uv_buf[i]);
1018         }
1019         for (int i = 0; i < cache->num_col_layers; i++) {
1020                 GPU_vertbuf_use(cache->proc_col_buf[i]);
1021                 cache->col_tex[i] = GPU_texture_create_from_vertbuf(cache->proc_col_buf[i]);
1022         }
1023 }
1024
1025 static void particle_batch_cache_ensure_procedural_indices(
1026         PTCacheEdit *edit,
1027         ParticleSystem *psys,
1028         ParticleHairCache *cache,
1029         int thickness_res,
1030         int subdiv)
1031 {
1032         BLI_assert(thickness_res <= MAX_THICKRES); /* Cylinder strip not currently supported. */
1033
1034         if (cache->final[subdiv].proc_hairs[thickness_res - 1] != NULL) {
1035                 return;
1036         }
1037
1038         int verts_per_hair = cache->final[subdiv].strands_res * thickness_res;
1039         /* +1 for primitive restart */
1040         int element_count = (verts_per_hair + 1) * cache->strands_len;
1041         GPUPrimType prim_type = (thickness_res == 1) ? GPU_PRIM_LINE_STRIP : GPU_PRIM_TRI_STRIP;
1042
1043         static GPUVertFormat format = { 0 };
1044         GPU_vertformat_clear(&format);
1045
1046         /* initialize vertex format */
1047         GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_U8, 1, GPU_FETCH_INT_TO_FLOAT_UNIT);
1048
1049         GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
1050         GPU_vertbuf_data_alloc(vbo, 1);
1051
1052         GPUIndexBufBuilder elb;
1053         GPU_indexbuf_init_ex(&elb, prim_type, element_count, element_count, true);
1054
1055         if (edit != NULL && edit->pathcache != NULL) {
1056                 particle_batch_cache_fill_segments_indices(
1057                         edit->pathcache, 0, edit->totcached, verts_per_hair, &elb);
1058         }
1059         else {
1060                 int curr_point = 0;
1061                 if ((psys->pathcache != NULL) &&
1062                     (!psys->childcache || (psys->part->draw & PART_DRAW_PARENT)))
1063                 {
1064                         curr_point = particle_batch_cache_fill_segments_indices(
1065                                 psys->pathcache, 0, psys->totpart, verts_per_hair, &elb);
1066                 }
1067                 if (psys->childcache) {
1068                         const int child_count = psys->totchild * psys->part->disp / 100;
1069                         curr_point = particle_batch_cache_fill_segments_indices(
1070                                 psys->childcache, curr_point, child_count, verts_per_hair, &elb);
1071                 }
1072         }
1073
1074         cache->final[subdiv].proc_hairs[thickness_res - 1] = GPU_batch_create_ex(
1075                 prim_type,
1076                 vbo,
1077                 GPU_indexbuf_build(&elb),
1078                 GPU_BATCH_OWNS_VBO | GPU_BATCH_OWNS_INDEX);
1079 }
1080
1081 static void particle_batch_cache_ensure_procedural_pos(
1082         PTCacheEdit *edit,
1083         ParticleSystem *psys,
1084         ParticleHairCache *cache)
1085 {
1086         if (cache->proc_point_buf != NULL) {
1087                 return;
1088         }
1089
1090         /* initialize vertex format */
1091         GPUVertFormat format = {0};
1092         uint pos_id = GPU_vertformat_attr_add(&format, "posTime", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
1093
1094         cache->proc_point_buf = GPU_vertbuf_create_with_format(&format);
1095         GPU_vertbuf_data_alloc(cache->proc_point_buf, cache->point_len);
1096
1097         GPUVertBufRaw pos_step;
1098         GPU_vertbuf_attr_get_raw_data(cache->proc_point_buf, pos_id, &pos_step);
1099
1100         if (edit != NULL && edit->pathcache != NULL) {
1101                 particle_batch_cache_fill_segments_proc_pos(
1102                         edit->pathcache,
1103                         edit->totcached,
1104                         &pos_step);
1105         }
1106         else {
1107                 if ((psys->pathcache != NULL) &&
1108                     (!psys->childcache || (psys->part->draw & PART_DRAW_PARENT)))
1109                 {
1110                         particle_batch_cache_fill_segments_proc_pos(
1111                                 psys->pathcache,
1112                                 psys->totpart,
1113                                 &pos_step);
1114                 }
1115                 if (psys->childcache) {
1116                         const int child_count = psys->totchild * psys->part->disp / 100;
1117                         particle_batch_cache_fill_segments_proc_pos(
1118                                 psys->childcache,
1119                                 child_count,
1120                                 &pos_step);
1121                 }
1122         }
1123
1124         /* Create vbo immediately to bind to texture buffer. */
1125         GPU_vertbuf_use(cache->proc_point_buf);
1126
1127         cache->point_tex = GPU_texture_create_from_vertbuf(cache->proc_point_buf);
1128 }
1129
1130 static void particle_batch_cache_ensure_pos_and_seg(
1131         PTCacheEdit *edit,
1132         ParticleSystem *psys,
1133         ModifierData *md,
1134         ParticleHairCache *hair_cache)
1135 {
1136         if (hair_cache->pos != NULL && hair_cache->indices != NULL) {
1137                 return;
1138         }
1139
1140         int curr_point = 0;
1141         ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md;
1142
1143         GPU_VERTBUF_DISCARD_SAFE(hair_cache->pos);
1144         GPU_INDEXBUF_DISCARD_SAFE(hair_cache->indices);
1145
1146         static GPUVertFormat format = { 0 };
1147         HairAttributeID attr_id;
1148         uint *uv_id = NULL;
1149         uint *col_id = NULL;
1150         int num_uv_layers = 0;
1151         int num_col_layers = 0;
1152         int active_uv = 0;
1153         int active_col = 0;
1154         MTFace **mtfaces = NULL;
1155         MCol **mcols = NULL;
1156         float (**parent_uvs)[2] = NULL;
1157         MCol **parent_mcol = NULL;
1158
1159         if (psmd != NULL) {
1160                 if (CustomData_has_layer(&psmd->mesh_final->ldata, CD_MLOOPUV)) {
1161                         num_uv_layers = CustomData_number_of_layers(&psmd->mesh_final->ldata, CD_MLOOPUV);
1162                         active_uv = CustomData_get_active_layer(&psmd->mesh_final->ldata, CD_MLOOPUV);
1163                 }
1164                 if (CustomData_has_layer(&psmd->mesh_final->ldata, CD_MLOOPCOL)) {
1165                         num_col_layers = CustomData_number_of_layers(&psmd->mesh_final->ldata, CD_MLOOPCOL);
1166                         active_col = CustomData_get_active_layer(&psmd->mesh_final->ldata, CD_MLOOPCOL);
1167                 }
1168         }
1169
1170         GPU_vertformat_clear(&format);
1171
1172         /* initialize vertex format */
1173         attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
1174         attr_id.tan = GPU_vertformat_attr_add(&format, "nor", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
1175         attr_id.ind = GPU_vertformat_attr_add(&format, "ind", GPU_COMP_I32, 1, GPU_FETCH_INT);
1176
1177         if (psmd) {
1178                 uv_id = MEM_mallocN(sizeof(*uv_id) * num_uv_layers, "UV attrib format");
1179                 col_id = MEM_mallocN(sizeof(*col_id) * num_col_layers, "Col attrib format");
1180
1181                 for (int i = 0; i < num_uv_layers; i++) {
1182                         const char *name = CustomData_get_layer_name(&psmd->mesh_final->ldata, CD_MLOOPUV, i);
1183                         char uuid[32];
1184
1185                         BLI_snprintf(uuid, sizeof(uuid), "u%u", BLI_ghashutil_strhash_p(name));
1186                         uv_id[i] = GPU_vertformat_attr_add(&format, uuid, GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
1187
1188                         if (i == active_uv) {
1189                                 GPU_vertformat_alias_add(&format, "u");
1190                         }
1191                 }
1192
1193                 for (int i = 0; i < num_uv_layers; i++) {
1194                         const char *name = CustomData_get_layer_name(&psmd->mesh_final->ldata, CD_MLOOPUV, i);
1195                         char uuid[32];
1196
1197                         BLI_snprintf(uuid, sizeof(uuid), "c%u", BLI_ghashutil_strhash_p(name));
1198                         col_id[i] = GPU_vertformat_attr_add(&format, uuid, GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
1199
1200                         if (i == active_col) {
1201                                 GPU_vertformat_alias_add(&format, "c");
1202                         }
1203                 }
1204         }
1205
1206         hair_cache->pos = GPU_vertbuf_create_with_format(&format);
1207         GPU_vertbuf_data_alloc(hair_cache->pos, hair_cache->point_len);
1208
1209         GPUIndexBufBuilder elb;
1210         GPU_indexbuf_init_ex(
1211                 &elb,
1212                 GPU_PRIM_LINE_STRIP,
1213                 hair_cache->elems_len, hair_cache->point_len,
1214                 true);
1215
1216         if (num_uv_layers || num_col_layers) {
1217                 BKE_mesh_tessface_ensure(psmd->mesh_final);
1218                 if (num_uv_layers) {
1219                         mtfaces = MEM_mallocN(sizeof(*mtfaces) * num_uv_layers, "Faces UV layers");
1220                         for (int i = 0; i < num_uv_layers; i++) {
1221                                 mtfaces[i] = (MTFace *)CustomData_get_layer_n(&psmd->mesh_final->fdata, CD_MTFACE, i);
1222                         }
1223                 }
1224                 if (num_col_layers) {
1225                         mcols = MEM_mallocN(sizeof(*mcols) * num_col_layers, "Color layers");
1226                         for (int i = 0; i < num_col_layers; i++) {
1227                                 mcols[i] = (MCol *)CustomData_get_layer_n(&psmd->mesh_final->fdata, CD_MCOL, i);
1228                         }
1229                 }
1230         }
1231
1232         if (edit != NULL && edit->pathcache != NULL) {
1233                 curr_point = particle_batch_cache_fill_segments(
1234                         psys, psmd, edit->pathcache, PARTICLE_SOURCE_PARENT,
1235                         0, 0, edit->totcached,
1236                         num_uv_layers, num_col_layers, mtfaces, mcols, uv_id, col_id, &parent_uvs, &parent_mcol,
1237                         &elb, &attr_id, hair_cache);
1238         }
1239         else {
1240                 if ((psys->pathcache != NULL) &&
1241                     (!psys->childcache || (psys->part->draw & PART_DRAW_PARENT)))
1242                 {
1243                         curr_point = particle_batch_cache_fill_segments(
1244                                 psys, psmd, psys->pathcache, PARTICLE_SOURCE_PARENT,
1245                                 0, 0, psys->totpart,
1246                                 num_uv_layers, num_col_layers, mtfaces, mcols, uv_id, col_id, &parent_uvs, &parent_mcol,
1247                                 &elb, &attr_id, hair_cache);
1248                 }
1249                 if (psys->childcache != NULL) {
1250                         const int child_count = psys->totchild * psys->part->disp / 100;
1251                         curr_point = particle_batch_cache_fill_segments(
1252                                 psys, psmd, psys->childcache, PARTICLE_SOURCE_CHILDREN,
1253                                 psys->totpart, curr_point, child_count,
1254                                 num_uv_layers, num_col_layers, mtfaces, mcols, uv_id, col_id, &parent_uvs, &parent_mcol,
1255                                 &elb, &attr_id, hair_cache);
1256                 }
1257         }
1258         /* Cleanup. */
1259         if (parent_uvs != NULL) {
1260                 /* TODO(sergey): For edit mode it should be edit->totcached. */
1261                 for (int i = 0; i < psys->totpart; i++) {
1262                         MEM_SAFE_FREE(parent_uvs[i]);
1263                 }
1264                 MEM_freeN(parent_uvs);
1265         }
1266         if (parent_mcol != NULL) {
1267                 for (int i = 0; i < psys->totpart; i++) {
1268                         MEM_SAFE_FREE(parent_mcol[i]);
1269                 }
1270                 MEM_freeN(parent_mcol);
1271         }
1272         if (num_uv_layers) {
1273                 MEM_freeN(mtfaces);
1274         }
1275         if (num_col_layers) {
1276                 MEM_freeN(mcols);
1277         }
1278         if (psmd != NULL) {
1279                 MEM_freeN(uv_id);
1280         }
1281         hair_cache->indices = GPU_indexbuf_build(&elb);
1282 }
1283
1284 static void particle_batch_cache_ensure_pos(
1285         Object *object,
1286         ParticleSystem *psys,
1287         ParticlePointCache *point_cache)
1288 {
1289         if (point_cache->pos != NULL) {
1290                 return;
1291         }
1292
1293         static GPUVertFormat format = { 0 };
1294         static uint pos_id, rot_id, val_id;
1295         int i, curr_point;
1296         ParticleData *pa;
1297         ParticleKey state;
1298         ParticleSimulationData sim = {NULL};
1299         const DRWContextState *draw_ctx = DRW_context_state_get();
1300
1301         sim.depsgraph = draw_ctx->depsgraph;
1302         sim.scene = draw_ctx->scene;
1303         sim.ob = object;
1304         sim.psys = psys;
1305         sim.psmd = psys_get_modifier(object, psys);
1306
1307         if (psys->part->phystype == PART_PHYS_KEYED) {
1308                 if (psys->flag & PSYS_KEYED) {
1309                         psys_count_keyed_targets(&sim);
1310                         if (psys->totkeyed == 0)
1311                                 return;
1312                 }
1313         }
1314
1315         GPU_VERTBUF_DISCARD_SAFE(point_cache->pos);
1316
1317         if (format.attr_len == 0) {
1318                 /* initialize vertex format */
1319                 pos_id = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
1320                 rot_id = GPU_vertformat_attr_add(&format, "rot", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
1321                 val_id = GPU_vertformat_attr_add(&format, "val", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
1322         }
1323
1324         point_cache->pos = GPU_vertbuf_create_with_format(&format);
1325         GPU_vertbuf_data_alloc(point_cache->pos, psys->totpart);
1326
1327         for (curr_point = 0, i = 0, pa = psys->particles; i < psys->totpart; i++, pa++) {
1328                 state.time = DEG_get_ctime(draw_ctx->depsgraph);
1329                 if (!psys_get_particle_state(&sim, i, &state, 0)) {
1330                         continue;
1331                 }
1332
1333                 float val;
1334
1335                 GPU_vertbuf_attr_set(point_cache->pos, pos_id, curr_point, pa->state.co);
1336                 GPU_vertbuf_attr_set(point_cache->pos, rot_id, curr_point, pa->state.rot);
1337
1338                 switch (psys->part->draw_col) {
1339                         case PART_DRAW_COL_VEL:
1340                                 val = len_v3(pa->state.vel) / psys->part->color_vec_max;
1341                                 break;
1342                         case PART_DRAW_COL_ACC:
1343                                 val = len_v3v3(
1344                                         pa->state.vel,
1345                                         pa->prev_state.vel) / ((pa->state.time - pa->prev_state.time) * psys->part->color_vec_max);
1346                                 break;
1347                         default:
1348                                 val = -1.0f;
1349                                 break;
1350                 }
1351
1352                 GPU_vertbuf_attr_set(point_cache->pos, val_id, curr_point, &val);
1353
1354                 curr_point++;
1355         }
1356
1357         if (curr_point != psys->totpart) {
1358                 GPU_vertbuf_data_resize(point_cache->pos, curr_point);
1359         }
1360 }
1361
1362 static void drw_particle_update_ptcache_edit(
1363         Object *object_eval,
1364         ParticleSystem *psys,
1365         PTCacheEdit *edit)
1366 {
1367         if (edit->psys == NULL) {
1368                 return;
1369         }
1370         /* NOTE: Get flag from particle system coming from drawing object.
1371          * this is where depsgraph will be setting flags to.
1372          */
1373         const DRWContextState *draw_ctx = DRW_context_state_get();
1374         Scene *scene_orig = (Scene *)DEG_get_original_id(&draw_ctx->scene->id);
1375         Object *object_orig = DEG_get_original_object(object_eval);
1376         if (psys->flag & PSYS_HAIR_UPDATED) {
1377                 PE_update_object(draw_ctx->depsgraph, scene_orig, object_orig, 0);
1378                 psys->flag &= ~PSYS_HAIR_UPDATED;
1379         }
1380         if (edit->pathcache == NULL) {
1381                 Depsgraph *depsgraph = draw_ctx->depsgraph;
1382                 psys_cache_edit_paths(
1383                         depsgraph,
1384                         scene_orig, object_orig,
1385                         edit,
1386                         DEG_get_ctime(depsgraph),
1387                         DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
1388         }
1389 }
1390
1391 static void drw_particle_update_ptcache(
1392         Object *object_eval,
1393         ParticleSystem *psys)
1394 {
1395         if ((object_eval->mode & OB_MODE_PARTICLE_EDIT) == 0) {
1396                 return;
1397         }
1398         const DRWContextState *draw_ctx = DRW_context_state_get();
1399         Scene *scene_orig = (Scene *)DEG_get_original_id(&draw_ctx->scene->id);
1400         Object *object_orig = DEG_get_original_object(object_eval);
1401         PTCacheEdit *edit = PE_create_current(
1402                 draw_ctx->depsgraph, scene_orig, object_orig);
1403         if (edit != NULL) {
1404                 drw_particle_update_ptcache_edit(object_eval, psys, edit);
1405         }
1406 }
1407
1408 typedef struct ParticleDrawSource {
1409         Object *object;
1410         ParticleSystem *psys;
1411         ModifierData *md;
1412         PTCacheEdit *edit;
1413 } ParticleDrawSource;
1414
1415 static void drw_particle_get_hair_source(
1416         Object *object,
1417         ParticleSystem *psys,
1418         ModifierData *md,
1419         PTCacheEdit *edit,
1420         ParticleDrawSource *r_draw_source)
1421 {
1422         r_draw_source->object = object;
1423         r_draw_source->psys = psys;
1424         r_draw_source->md = md;
1425         r_draw_source->edit = edit;
1426         if ((object->mode & OB_MODE_PARTICLE_EDIT) != 0) {
1427                 r_draw_source->object = DEG_get_original_object(object);
1428                 r_draw_source->psys = psys_orig_get(psys);
1429         }
1430 }
1431
1432 GPUBatch *DRW_particles_batch_cache_get_hair(
1433         Object *object,
1434         ParticleSystem *psys,
1435         ModifierData *md)
1436 {
1437         ParticleBatchCache *cache = particle_batch_cache_get(psys);
1438         if (cache->hair.hairs == NULL) {
1439                 drw_particle_update_ptcache(object, psys);
1440                 ParticleDrawSource source;
1441                 drw_particle_get_hair_source(object, psys, md, NULL, &source);
1442                 ensure_seg_pt_count(source.edit, source.psys, &cache->hair);
1443                 particle_batch_cache_ensure_pos_and_seg(source.edit, source.psys, source.md, &cache->hair);
1444                 cache->hair.hairs = GPU_batch_create(
1445                         GPU_PRIM_LINE_STRIP,
1446                         cache->hair.pos,
1447                         cache->hair.indices);
1448         }
1449         return cache->hair.hairs;
1450 }
1451
1452 GPUBatch *DRW_particles_batch_cache_get_dots(Object *object, ParticleSystem *psys)
1453 {
1454         ParticleBatchCache *cache = particle_batch_cache_get(psys);
1455
1456         if (cache->point.points == NULL) {
1457                 particle_batch_cache_ensure_pos(object, psys, &cache->point);
1458                 cache->point.points = GPU_batch_create(GPU_PRIM_POINTS, cache->point.pos, NULL);
1459         }
1460
1461         return cache->point.points;
1462 }
1463
1464 static void particle_batch_cache_ensure_edit_pos_and_seg(
1465         PTCacheEdit *edit,
1466         ParticleSystem *psys,
1467         ModifierData *UNUSED(md),
1468         ParticleHairCache *hair_cache,
1469         bool use_weight)
1470 {
1471         if (hair_cache->pos != NULL && hair_cache->indices != NULL) {
1472                 return;
1473         }
1474
1475         ParticleData *particle = (use_weight) ? psys->particles : NULL;
1476
1477         GPU_VERTBUF_DISCARD_SAFE(hair_cache->pos);
1478         GPU_INDEXBUF_DISCARD_SAFE(hair_cache->indices);
1479
1480         GPUVertBufRaw data_step;
1481         GPUIndexBufBuilder elb;
1482         uint pos_id, color_id;
1483         GPUVertFormat *edit_point_format = edit_points_vert_format_get(&pos_id, &color_id);
1484
1485         hair_cache->pos = GPU_vertbuf_create_with_format(edit_point_format);
1486         GPU_vertbuf_data_alloc(hair_cache->pos, hair_cache->point_len);
1487         GPU_vertbuf_attr_get_raw_data(hair_cache->pos, pos_id, &data_step);
1488
1489         GPU_indexbuf_init_ex(
1490                 &elb,
1491                 GPU_PRIM_LINE_STRIP,
1492                 hair_cache->elems_len, hair_cache->point_len,
1493                 true);
1494
1495         if (edit != NULL && edit->pathcache != NULL) {
1496                 particle_batch_cache_fill_segments_edit(
1497                         edit, particle, edit->pathcache,
1498                         0, edit->totcached,
1499                         &elb, &data_step);
1500         }
1501         else {
1502                 BLI_assert(!"Hairs are not in edit mode!");
1503         }
1504         hair_cache->indices = GPU_indexbuf_build(&elb);
1505 }
1506
1507 GPUBatch *DRW_particles_batch_cache_get_edit_strands(
1508         Object *object,
1509         ParticleSystem *psys,
1510         PTCacheEdit *edit,
1511         bool use_weight)
1512 {
1513         ParticleBatchCache *cache = particle_batch_cache_get(psys);
1514         if (cache->edit_is_weight != use_weight) {
1515                 GPU_VERTBUF_DISCARD_SAFE(cache->edit_hair.pos);
1516                 GPU_BATCH_DISCARD_SAFE(cache->edit_hair.hairs);
1517         }
1518         if (cache->edit_hair.hairs != NULL) {
1519                 return cache->edit_hair.hairs;
1520         }
1521         drw_particle_update_ptcache_edit(object, psys, edit);
1522         ensure_seg_pt_count(edit, psys, &cache->edit_hair);
1523         particle_batch_cache_ensure_edit_pos_and_seg(edit, psys, NULL, &cache->edit_hair, use_weight);
1524         cache->edit_hair.hairs = GPU_batch_create(
1525                 GPU_PRIM_LINE_STRIP,
1526                 cache->edit_hair.pos,
1527                 cache->edit_hair.indices);
1528         cache->edit_is_weight = use_weight;
1529         return cache->edit_hair.hairs;
1530 }
1531
1532 static void ensure_edit_inner_points_count(
1533         const PTCacheEdit *edit,
1534         ParticleBatchCache *cache)
1535 {
1536         if (cache->edit_inner_pos != NULL) {
1537                 return;
1538         }
1539         cache->edit_inner_point_len = 0;
1540         for (int point_index = 0; point_index < edit->totpoint; point_index++) {
1541                 const PTCacheEditPoint *point = &edit->points[point_index];
1542                 BLI_assert(point->totkey >= 1);
1543                 cache->edit_inner_point_len += (point->totkey - 1);
1544         }
1545 }
1546
1547 static void particle_batch_cache_ensure_edit_inner_pos(
1548         PTCacheEdit *edit,
1549         ParticleBatchCache *cache)
1550 {
1551         if (cache->edit_inner_pos != NULL) {
1552                 return;
1553         }
1554
1555         uint pos_id, color_id;
1556         GPUVertFormat *edit_point_format = edit_points_vert_format_get(&pos_id, &color_id);
1557
1558         cache->edit_inner_pos = GPU_vertbuf_create_with_format(edit_point_format);
1559         GPU_vertbuf_data_alloc(cache->edit_inner_pos, cache->edit_inner_point_len);
1560
1561         int global_key_index = 0;
1562         for (int point_index = 0; point_index < edit->totpoint; point_index++) {
1563                 const PTCacheEditPoint *point = &edit->points[point_index];
1564                 for (int key_index = 0; key_index < point->totkey - 1; key_index++) {
1565                         PTCacheEditKey *key = &point->keys[key_index];
1566                         uchar color = (key->flag & PEK_SELECT) ? 0xFF : 0x00;
1567                         GPU_vertbuf_attr_set(cache->edit_inner_pos, pos_id, global_key_index, key->world_co);
1568                         GPU_vertbuf_attr_set(cache->edit_inner_pos, color_id, global_key_index, &color);
1569                         global_key_index++;
1570                 }
1571         }
1572 }
1573
1574 GPUBatch *DRW_particles_batch_cache_get_edit_inner_points(
1575         Object *object,
1576         ParticleSystem *psys,
1577         PTCacheEdit *edit)
1578 {
1579         ParticleBatchCache *cache = particle_batch_cache_get(psys);
1580         if (cache->edit_inner_points != NULL) {
1581                 return cache->edit_inner_points;
1582         }
1583         drw_particle_update_ptcache_edit(object, psys, edit);
1584         ensure_edit_inner_points_count(edit, cache);
1585         particle_batch_cache_ensure_edit_inner_pos(edit, cache);
1586         cache->edit_inner_points = GPU_batch_create(
1587                 GPU_PRIM_POINTS,
1588                 cache->edit_inner_pos,
1589                 NULL);
1590         return cache->edit_inner_points;
1591 }
1592
1593 static void ensure_edit_tip_points_count(
1594         const PTCacheEdit *edit,
1595         ParticleBatchCache *cache)
1596 {
1597         if (cache->edit_tip_pos != NULL) {
1598                 return;
1599         }
1600         cache->edit_tip_point_len = edit->totpoint;
1601 }
1602
1603 static void particle_batch_cache_ensure_edit_tip_pos(
1604         PTCacheEdit *edit,
1605         ParticleBatchCache *cache)
1606 {
1607         if (cache->edit_tip_pos != NULL) {
1608                 return;
1609         }
1610
1611         uint pos_id, color_id;
1612         GPUVertFormat *edit_point_format = edit_points_vert_format_get(&pos_id, &color_id);
1613
1614         cache->edit_tip_pos = GPU_vertbuf_create_with_format(edit_point_format);
1615         GPU_vertbuf_data_alloc(cache->edit_tip_pos, cache->edit_tip_point_len);
1616
1617         for (int point_index = 0; point_index < edit->totpoint; point_index++) {
1618                 const PTCacheEditPoint *point = &edit->points[point_index];
1619                 PTCacheEditKey *key = &point->keys[point->totkey - 1];
1620                 uchar color = (key->flag & PEK_SELECT) ? 0xFF : 0x00;
1621                 GPU_vertbuf_attr_set(cache->edit_tip_pos, pos_id, point_index, key->world_co);
1622                 GPU_vertbuf_attr_set(cache->edit_tip_pos, color_id, point_index, &color);
1623         }
1624 }
1625
1626 GPUBatch *DRW_particles_batch_cache_get_edit_tip_points(
1627         Object *object,
1628         ParticleSystem *psys,
1629         PTCacheEdit *edit)
1630 {
1631         ParticleBatchCache *cache = particle_batch_cache_get(psys);
1632         if (cache->edit_tip_points != NULL) {
1633                 return cache->edit_tip_points;
1634         }
1635         drw_particle_update_ptcache_edit(object, psys, edit);
1636         ensure_edit_tip_points_count(edit, cache);
1637         particle_batch_cache_ensure_edit_tip_pos(edit, cache);
1638         cache->edit_tip_points = GPU_batch_create(
1639                 GPU_PRIM_POINTS,
1640                 cache->edit_tip_pos,
1641                 NULL);
1642         return cache->edit_tip_points;
1643 }
1644
1645 /* Ensure all textures and buffers needed for GPU accelerated drawing. */
1646 bool particles_ensure_procedural_data(
1647         Object *object,
1648         ParticleSystem *psys,
1649         ModifierData *md,
1650         ParticleHairCache **r_hair_cache,
1651         int subdiv,
1652         int thickness_res)
1653 {
1654         bool need_ft_update = false;
1655
1656         drw_particle_update_ptcache(object, psys);
1657
1658         ParticleDrawSource source;
1659         drw_particle_get_hair_source(object, psys, md, NULL, &source);
1660
1661         ParticleSettings *part = source.psys->part;
1662         ParticleBatchCache *cache = particle_batch_cache_get(source.psys);
1663         *r_hair_cache = &cache->hair;
1664
1665         (*r_hair_cache)->final[subdiv].strands_res = 1 << (part->draw_step + subdiv);
1666
1667         /* Refreshed on combing and simulation. */
1668         if ((*r_hair_cache)->proc_point_buf == NULL) {
1669                 ensure_seg_pt_count(source.edit, source.psys, &cache->hair);
1670                 particle_batch_cache_ensure_procedural_pos(source.edit, source.psys, &cache->hair);
1671                 need_ft_update = true;
1672         }
1673
1674         /* Refreshed if active layer or custom data changes. */
1675         if ((*r_hair_cache)->strand_tex == NULL) {
1676                 particle_batch_cache_ensure_procedural_strand_data(source.edit, source.psys, source.md, &cache->hair);
1677         }
1678
1679         /* Refreshed only on subdiv count change. */
1680         if ((*r_hair_cache)->final[subdiv].proc_buf == NULL) {
1681                 particle_batch_cache_ensure_procedural_final_points(&cache->hair, subdiv);
1682                 need_ft_update = true;
1683         }
1684         if ((*r_hair_cache)->final[subdiv].proc_hairs[thickness_res - 1] == NULL) {
1685                 particle_batch_cache_ensure_procedural_indices(source.edit, source.psys, &cache->hair, thickness_res, subdiv);
1686         }
1687
1688         return need_ft_update;
1689 }