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