Quake II RTX doxygen  1.0 dev
transparency.c
Go to the documentation of this file.
1 /*
2 Copyright (C) 2019, NVIDIA CORPORATION. All rights reserved.
3 
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (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 along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18 
19 #include "shared/shared.h"
20 #include "vkpt.h"
21 #include "vk_util.h"
22 
23 #define TR_PARTICLE_MAX_NUM MAX_PARTICLES
24 #define TR_BEAM_MAX_NUM MAX_ENTITIES
25 #define TR_SPRITE_MAX_NUM MAX_ENTITIES
26 #define TR_VERTEX_MAX_NUM (TR_PARTICLE_MAX_NUM + TR_BEAM_MAX_NUM + TR_SPRITE_MAX_NUM) * 4
27 #define TR_INDEX_MAX_NUM (TR_PARTICLE_MAX_NUM + TR_BEAM_MAX_NUM + TR_SPRITE_MAX_NUM) * 6
28 #define TR_POSITION_SIZE 3 * sizeof(float)
29 #define TR_COLOR_SIZE 4 * sizeof(float)
30 #define TR_SPRITE_INFO_SIZE 2 * sizeof(float)
31 
32 #define TR_BLAS_BUILD_FLAGS VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_NV | \
33  VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_NV
34 
35 struct
36 {
41 
44 
47 
50  unsigned int particle_num;
51  unsigned int beam_num;
52  unsigned int sprite_num;
53  unsigned int blas_beam_num;
54  unsigned int blas_particle_num;
55  unsigned int blas_sprite_num;
56  unsigned int host_frame_index;
59  VkAccelerationStructureNV particle_blas;
60  VkAccelerationStructureNV beam_blas;
61  VkAccelerationStructureNV sprite_blas;
62  VkBuffer host_buffer;
63  VkBuffer scratch_buffer;
64  VkBuffer vertex_buffer;
65  VkBuffer index_buffer;
69  VkDeviceMemory host_buffer_memory;
70  VkDeviceMemory device_buffer_memory;
71  VkDeviceMemory device_blas_memory;
73  VkBufferView beam_color_buffer_view;
75  VkBufferMemoryBarrier transfer_barriers[4];
76 } transparency;
77 
78 // initialization
79 static void create_buffers();
80 static void create_blas();
82 static qboolean allocate_and_bind_memory_to_buffers();
83 static void create_buffer_views();
84 static void fill_index_buffer();
85 
86 // update
87 static void write_particle_geometry(const float* view_matrix, const particle_t* particles, int particle_num);
88 static void write_beam_geometry(const float* view_matrix, const entity_t* entities, int entity_num);
89 static void write_sprite_geometry(const float* view_matrix, const entity_t* entities, int entity_num);
90 static void upload_geometry(VkCommandBuffer command_buffer);
91 static void update_particle_blas(VkCommandBuffer command_buffer);
92 static void update_beam_blas(VkCommandBuffer command_buffer);
93 static void update_sprite_blas(VkCommandBuffer command_buffer);
94 
95 cvar_t* cvar_pt_particle_size = NULL;
96 cvar_t* cvar_pt_beam_width = NULL;
97 cvar_t* cvar_pt_beam_lights = NULL;
98 extern cvar_t* cvar_pt_enable_particles;
99 extern cvar_t* cvar_pt_particle_emissive;
100 extern cvar_t* cvar_pt_projection;
101 
102 void cast_u32_to_f32_color(int color_index, const color_t* pcolor, float* color_f32, float hdr_factor)
103 {
104  color_t color;
105  if (color_index < 0)
106  color.u32 = pcolor->u32;
107  else
108  color.u32 = d_8to24table[color_index & 0xff];
109 
110  for (int i = 0; i < 3; i++)
111  color_f32[i] = hdr_factor * ((float)color.u8[i] / 255.0);
112 }
113 
115 {
116  cvar_pt_particle_size = Cvar_Get("pt_particle_size", "0.35", 0);
117  cvar_pt_beam_width = Cvar_Get("pt_beam_width", "1.0", 0);
118  cvar_pt_beam_lights = Cvar_Get("pt_beam_lights", "1.0", 0);
119 
120  memset(&transparency, 0, sizeof(transparency));
121 
122  const size_t particle_vertex_position_max_size = TR_VERTEX_MAX_NUM * TR_POSITION_SIZE;
123  const size_t particle_color_size = TR_PARTICLE_MAX_NUM * TR_COLOR_SIZE;
124  const size_t particle_data_size = particle_vertex_position_max_size + particle_color_size;
125 
126  const size_t beam_vertex_position_max_size = TR_BEAM_MAX_NUM * TR_POSITION_SIZE;
127  const size_t beam_color_size = TR_BEAM_MAX_NUM * TR_COLOR_SIZE;
128  const size_t beam_data_size = beam_vertex_position_max_size + beam_color_size;
129 
130  const size_t sprite_vertex_position_max_size = TR_SPRITE_MAX_NUM * TR_POSITION_SIZE;
131  const size_t sprite_info_size = TR_SPRITE_MAX_NUM * TR_SPRITE_INFO_SIZE;
132  const size_t sprite_data_size = sprite_vertex_position_max_size + sprite_info_size;
133 
134  transparency.host_buffered_frame_num = MAX_FRAMES_IN_FLIGHT;
135  transparency.host_frame_size = particle_data_size + beam_data_size + sprite_data_size;
136  transparency.host_buffer_size = transparency.host_buffered_frame_num * transparency.host_frame_size;
137 
140 
142  return qfalse;
143 
147 
148  return qtrue;
149 }
150 
152 {
153  vkDestroyBufferView(qvk.device, transparency.particle_color_buffer_view, NULL);
154  vkDestroyBufferView(qvk.device, transparency.beam_color_buffer_view, NULL);
155  vkDestroyBufferView(qvk.device, transparency.sprite_info_buffer_view, NULL);
156  vkDestroyBuffer(qvk.device, transparency.host_buffer, NULL);
157  vkDestroyBuffer(qvk.device, transparency.scratch_buffer, NULL);
158  vkDestroyBuffer(qvk.device, transparency.vertex_buffer, NULL);
159  vkDestroyBuffer(qvk.device, transparency.index_buffer, NULL);
160  vkDestroyBuffer(qvk.device, transparency.particle_color_buffer, NULL);
161  vkDestroyBuffer(qvk.device, transparency.beam_color_buffer, NULL);
162  vkDestroyBuffer(qvk.device, transparency.sprite_info_buffer, NULL);
163  qvkDestroyAccelerationStructureNV(qvk.device, transparency.particle_blas, NULL);
164  qvkDestroyAccelerationStructureNV(qvk.device, transparency.beam_blas, NULL);
165  qvkDestroyAccelerationStructureNV(qvk.device, transparency.sprite_blas, NULL);
166  vkFreeMemory(qvk.device, transparency.host_buffer_memory, NULL);
167  vkFreeMemory(qvk.device, transparency.device_buffer_memory, NULL);
168  vkFreeMemory(qvk.device, transparency.device_blas_memory, NULL);
169 }
170 
171 void update_transparency(VkCommandBuffer command_buffer, const float* view_matrix,
172  const particle_t* particles, int particle_num, const entity_t* entities, int entity_num)
173 {
174  transparency.host_frame_index = (transparency.host_frame_index + 1) % transparency.host_buffered_frame_num;
176 
177  uint32_t beam_num = 0;
178  uint32_t sprite_num = 0;
179  for (int i = 0; i < entity_num; i++)
180  {
181  if (entities[i].flags & RF_BEAM)
182  ++beam_num;
183  else if ((entities[i].model & 0x80000000) == 0)
184  {
185  const model_t* model = MOD_ForHandle(entities[i].model);
186  if (model && model->type == MOD_SPRITE)
187  ++sprite_num;
188  }
189  }
192 
193  transparency.beam_num = beam_num;
194  transparency.particle_num = particle_num;
195  transparency.sprite_num = sprite_num;
196 
197  const size_t particle_vertices_size = particle_num * 4 * TR_POSITION_SIZE;
198  const size_t beam_vertices_size = beam_num * 4 * TR_POSITION_SIZE;
199  const size_t sprite_vertices_size = sprite_num * 4 * TR_POSITION_SIZE;
200 
201  const size_t host_buffer_offset = transparency.host_frame_index * transparency.host_frame_size;
202 
203  transparency.vertex_position_host_offset = host_buffer_offset;
204  transparency.particle_color_host_offset = host_buffer_offset + particle_vertices_size + beam_vertices_size + sprite_vertices_size;
205  transparency.beam_color_host_offset = transparency.particle_color_host_offset + particle_num * TR_COLOR_SIZE;
206  transparency.sprite_info_host_offset = transparency.beam_color_host_offset + beam_num * TR_COLOR_SIZE;
207 
208  if (particle_num > 0 || beam_num > 0 || sprite_num > 0)
209  {
211  write_beam_geometry(view_matrix, entities, entity_num);
212  write_sprite_geometry(view_matrix, entities, entity_num);
213  upload_geometry(command_buffer);
214  }
215 }
216 
217 void build_transparency_blas(VkCommandBuffer cmd_buf)
218 {
219  update_particle_blas(cmd_buf);
220  update_beam_blas(cmd_buf);
221  update_sprite_blas(cmd_buf);
222 
223  // No barrier here because a single barrier is used later in the pipeline, after building all the BLAS-es
224 }
225 
226 VkAccelerationStructureNV get_transparency_particle_blas()
227 {
228  return transparency.particle_blas;
229 }
230 
231 VkAccelerationStructureNV get_transparency_beam_blas()
232 {
233  return transparency.beam_blas;
234 }
235 
236 VkAccelerationStructureNV get_transparency_sprite_blas()
237 {
238  return transparency.sprite_blas;
239 }
240 
242 {
243  return transparency.particle_color_buffer_view;
244 }
245 
247 {
248  return transparency.beam_color_buffer_view;
249 }
250 
252 {
253  return transparency.sprite_info_buffer_view;
254 }
255 
257 {
258  *particle_num = transparency.particle_num;
259  *beam_num = transparency.beam_num;
260  *sprite_num = transparency.sprite_num;
261 }
262 
263 static void write_particle_geometry(const float* view_matrix, const particle_t* particles, int particle_num)
264 {
265  const float particle_size = cvar_pt_particle_size->value;
266 
267  const vec3_t view_y = { view_matrix[1], view_matrix[5], view_matrix[9] };
268 
269  // TODO: remove vkpt_refdef.fd, it's better to calculate it from the view matrix
270  const vec3_t view_origin = { vkpt_refdef.fd->vieworg[0], vkpt_refdef.fd->vieworg[1], vkpt_refdef.fd->vieworg[2] };
271 
272  // TODO: use better alignment?
273  vec3_t* vertex_positions = (vec3_t*)(transparency.mapped_host_buffer + transparency.vertex_position_host_offset);
274  float* particle_colors = (float*)(transparency.mapped_host_buffer + transparency.particle_color_host_offset);
275 
276  for (int i = 0; i < particle_num; i++)
277  {
278  const particle_t* particle = particles + i;
279 
280  cast_u32_to_f32_color(particle->color, &particle->rgba, particle_colors, particle->brightness);
281  particle_colors[3] = particle->alpha;
282  particle_colors = particle_colors + 4;
283 
284  vec3_t origin;
285  VectorCopy(particle->origin, origin);
286 
287  vec3_t z_axis;
288  VectorSubtract(view_origin, origin, z_axis);
289  VectorNormalize(z_axis);
290 
291  vec3_t x_axis;
292  vec3_t y_axis;
293  CrossProduct(z_axis, view_y, x_axis);
294  CrossProduct(x_axis, z_axis, y_axis);
295 
296  const float size_factor = pow(particle->alpha, 0.05f);
297  if (particle->radius == 0.f)
298  {
299  VectorScale(y_axis, particle_size * size_factor, y_axis);
300  VectorScale(x_axis, particle_size * size_factor, x_axis);
301  }
302  else
303  {
304  VectorScale(y_axis, particle->radius, y_axis);
305  VectorScale(x_axis, particle->radius, x_axis);
306  }
307 
308  vec3_t temp;
309  VectorSubtract(origin, x_axis, temp);
310  VectorAdd(temp, y_axis, vertex_positions[0]);
311 
312  VectorAdd(origin, x_axis, temp);
313  VectorAdd(temp, y_axis, vertex_positions[1]);
314 
315  VectorAdd(origin, x_axis, temp);
316  VectorSubtract(temp, y_axis, vertex_positions[2]);
317 
318  VectorSubtract(origin, x_axis, temp);
319  VectorSubtract(temp, y_axis, vertex_positions[3]);
320 
321  vertex_positions += 4;
322  }
323 }
324 
325 static void write_beam_geometry(const float* view_matrix, const entity_t* entities, int entity_num)
326 {
327  const float beam_width = cvar_pt_beam_width->value;
328  const float hdr_factor = cvar_pt_particle_emissive->value;
329 
330  const vec3_t view_y = { view_matrix[1], view_matrix[5], view_matrix[9] };
331 
332  if (transparency.beam_num == 0)
333  return;
334 
335  // TODO: remove vkpt_refdef.fd, it's better to calculate it from the view matrix
336  const vec3_t view_origin = { vkpt_refdef.fd->vieworg[0], vkpt_refdef.fd->vieworg[1], vkpt_refdef.fd->vieworg[2] };
337 
338  const size_t particle_vertex_data_size = transparency.particle_num * 4 * TR_POSITION_SIZE;
339  const size_t beam_vertex_offset = transparency.vertex_position_host_offset + particle_vertex_data_size;
340 
341  // TODO: use better alignment?
342  vec3_t* vertex_positions = (vec3_t*)(transparency.mapped_host_buffer + beam_vertex_offset);
343  float* beam_colors = (float*)(transparency.mapped_host_buffer + transparency.beam_color_host_offset);
344 
345  for (int i = 0; i < entity_num; i++)
346  {
347  if ((entities[i].flags & RF_BEAM) == 0)
348  continue;
349 
350  const entity_t* beam = entities + i;
351 
352  cast_u32_to_f32_color(beam->skinnum, &beam->rgba, beam_colors, hdr_factor);
353  beam_colors[3] = beam->alpha;
354  beam_colors = beam_colors + 4;
355 
356  vec3_t begin;
357  vec3_t end;
358  VectorCopy(beam->oldorigin, begin);
359  VectorCopy(beam->origin, end);
360 
361  vec3_t to_end;
362  VectorSubtract(end, begin, to_end);
363 
364  vec3_t norm_dir;
365  VectorCopy(to_end, norm_dir);
366  VectorNormalize(norm_dir);
367  VectorMA(begin, -5.f, norm_dir, begin);
368  VectorMA(end, 5.f, norm_dir, end);
369 
370  vec3_t to_view;
371  VectorSubtract(view_origin, begin, to_view);
372 
373  vec3_t x_axis;
374  CrossProduct(to_end, to_view, x_axis);
375  VectorNormalize(x_axis);
376  VectorScale(x_axis, beam_width, x_axis);
377 
378  VectorSubtract(end, x_axis, vertex_positions[0]);
379  VectorAdd(end, x_axis, vertex_positions[1]);
380  VectorAdd(begin, x_axis, vertex_positions[2]);
381  VectorSubtract(begin, x_axis, vertex_positions[3]);
382  vertex_positions += 4;
383  }
384 }
385 
386 #define MAX_BEAMS 64
387 
388 static int compare_beams(const void* _a, const void* _b)
389 {
390  const entity_t* a = *(void**)_a;
391  const entity_t* b = *(void**)_b;
392 
393  if (a->origin[0] < b->origin[0]) return -1;
394  if (a->origin[0] > b->origin[0]) return 1;
395  if (a->origin[1] < b->origin[1]) return -1;
396  if (a->origin[1] > b->origin[1]) return 1;
397  if (a->origin[2] < b->origin[2]) return -1;
398  if (a->origin[2] > b->origin[2]) return 1;
399  if (a->oldorigin[0] < b->oldorigin[0]) return -1;
400  if (a->oldorigin[0] > b->oldorigin[0]) return 1;
401  if (a->oldorigin[1] < b->oldorigin[1]) return -1;
402  if (a->oldorigin[1] > b->oldorigin[1]) return 1;
403  if (a->oldorigin[2] < b->oldorigin[2]) return -1;
404  if (a->oldorigin[2] > b->oldorigin[2]) return 1;
405  return 0;
406 }
407 
408 qboolean vkpt_build_cylinder_light(light_poly_t* light_list, int* num_lights, int max_lights, bsp_t *bsp, vec3_t begin, vec3_t end, vec3_t color, float radius)
409 {
410  vec3_t dir, norm_dir;
411  VectorSubtract(end, begin, dir);
412  VectorCopy(dir, norm_dir);
413  VectorNormalize(norm_dir);
414 
415  vec3_t up = { 0.f, 0.f, 1.f };
416  vec3_t left = { 1.f, 0.f, 0.f };
417  if (fabsf(norm_dir[2]) < 0.9f)
418  {
419  CrossProduct(up, norm_dir, left);
420  VectorNormalize(left);
421  CrossProduct(norm_dir, left, up);
423  }
424  else
425  {
426  CrossProduct(norm_dir, left, up);
428  CrossProduct(up, norm_dir, left);
429  VectorNormalize(left);
430  }
431 
432 
433  vec3_t vertices[6] = {
434  { 0.f, 1.f, 0.f },
435  { 0.866f, -0.5f, 0.f },
436  { -0.866f, -0.5f, 0.f },
437  { 0.f, -1.f, 1.f },
438  { -0.866f, 0.5f, 1.f },
439  { 0.866f, 0.5f, 1.f },
440  };
441 
442  const int indices[18] = {
443  0, 4, 2,
444  2, 4, 3,
445  2, 3, 1,
446  1, 3, 5,
447  1, 5, 0,
448  0, 5, 4
449  };
450 
451  for (int vert = 0; vert < 6; vert++)
452  {
453  vec3_t transformed;
454  VectorCopy(begin, transformed);
455  VectorMA(transformed, vertices[vert][0] * radius, up, transformed);
456  VectorMA(transformed, vertices[vert][1] * radius, left, transformed);
457  VectorMA(transformed, vertices[vert][2], dir, transformed);
458  VectorCopy(transformed, vertices[vert]);
459  }
460 
461  for (int tri = 0; tri < 6; tri++)
462  {
463  if (*num_lights >= max_lights)
464  return qfalse;
465 
466  int i0 = indices[tri * 3 + 0];
467  int i1 = indices[tri * 3 + 1];
468  int i2 = indices[tri * 3 + 2];
469 
470  light_poly_t* light = light_list + *num_lights;
471 
472  VectorCopy(vertices[i0], light->positions + 0);
473  VectorCopy(vertices[i1], light->positions + 3);
474  VectorCopy(vertices[i2], light->positions + 6);
475  get_triangle_off_center(light->positions, light->off_center, NULL);
476 
477  light->cluster = BSP_PointLeaf(bsp->nodes, light->off_center)->cluster;
478  light->material = NULL;
479  light->style = 0;
480 
481  VectorCopy(color, light->color);
482 
483  if (light->cluster >= 0)
484  {
485  (*num_lights)++;
486  }
487  }
488 
489  return qtrue;
490 }
491 
492 void vkpt_build_beam_lights(light_poly_t* light_list, int* num_lights, int max_lights, bsp_t *bsp, entity_t* entities, int num_entites, float adapted_luminance)
493 {
494  const float beam_width = cvar_pt_beam_width->value;
495  const float hdr_factor = cvar_pt_beam_lights->value * adapted_luminance * 20.f;
496 
497  if (hdr_factor <= 0.f)
498  return;
499 
500  int num_beams = 0;
501 
502  static entity_t* beams[MAX_BEAMS];
503 
504  for (int i = 0; i < num_entites; i++)
505  {
506  if(num_beams == MAX_BEAMS)
507  break;
508 
509  if ((entities[i].flags & RF_BEAM) != 0)
510  beams[num_beams++] = entities + i;
511  }
512 
513  if (num_beams == 0)
514  return;
515 
516  qsort(beams, num_beams, sizeof(entity_t*), compare_beams);
517 
518  for (int i = 0; i < num_beams; i++)
519  {
520  if (*num_lights >= max_lights)
521  return;
522 
523  const entity_t* beam = beams[i];
524 
525  vec3_t begin;
526  vec3_t end;
527  VectorCopy(beam->oldorigin, begin);
528  VectorCopy(beam->origin, end);
529 
530  vec3_t to_end;
531  VectorSubtract(end, begin, to_end);
532 
533  vec3_t norm_dir;
534  VectorCopy(to_end, norm_dir);
535  VectorNormalize(norm_dir);
536  VectorMA(begin, -5.f, norm_dir, begin);
537  VectorMA(end, 5.f, norm_dir, end);
538 
539  vec3_t color;
540  cast_u32_to_f32_color(beam->skinnum, &beam->rgba, color, hdr_factor);
541 
542  vkpt_build_cylinder_light(light_list, num_lights, max_lights, bsp, begin, end, color, beam_width);
543  }
544 }
545 
546 static void write_sprite_geometry(const float* view_matrix, const entity_t* entities, int entity_num)
547 {
548  if (transparency.sprite_num == 0)
549  return;
550 
551  const vec3_t view_x = { view_matrix[0], view_matrix[4], view_matrix[8] };
552  const vec3_t view_y = { view_matrix[1], view_matrix[5], view_matrix[9] };
553  const vec3_t world_y = { 0.f, 0.f, 1.f };
554 
555  // TODO: remove vkpt_refdef.fd, it's better to calculate it from the view matrix
556  const vec3_t view_origin = { vkpt_refdef.fd->vieworg[0], vkpt_refdef.fd->vieworg[1], vkpt_refdef.fd->vieworg[2] };
557 
558  const size_t particle_vertex_data_size = transparency.particle_num * 4 * TR_POSITION_SIZE;
559  const size_t beam_vertex_data_size = transparency.beam_num * 4 * TR_POSITION_SIZE;
560  const size_t sprite_vertex_offset = transparency.vertex_position_host_offset + particle_vertex_data_size + beam_vertex_data_size;
561 
562  // TODO: use better alignment?
563  vec3_t* vertex_positions = (vec3_t*)(transparency.mapped_host_buffer + sprite_vertex_offset);
564  uint32_t* sprite_info = (int*)(transparency.mapped_host_buffer + transparency.sprite_info_host_offset);
565 
566  int sprite_count = 0;
567  for (int i = 0; i < entity_num; i++)
568  {
569  const entity_t *e = entities + i;
570 
571  if (e->model & 0x80000000)
572  continue;
573 
574  const model_t* model = MOD_ForHandle(e->model);
575  if (!model || model->type != MOD_SPRITE)
576  continue;
577 
578  mspriteframe_t *frame = &model->spriteframes[e->frame % model->numframes];
579  image_t *image = frame->image;
580 
581  sprite_info[0] = image - r_images;
582  sprite_info[1] = *(uint32_t*)&e->alpha;
583 
584  // set up the quad - reference code is in function GL_DrawSpriteModel
585 
586  vec3_t up, down, left, right;
587 
588  if (cvar_pt_projection->integer == 1)
589  {
590  // make the sprite always face the camera and always vertical in cylindrical projection mode
591 
592  vec3_t to_camera;
593  VectorSubtract(view_origin, e->origin, to_camera);
594 
595  vec3_t cyl_x;
596  CrossProduct(world_y, to_camera, cyl_x);
597  VectorNormalize(cyl_x);
598 
599  VectorScale(cyl_x, frame->origin_x, left);
600  VectorScale(cyl_x, frame->origin_x - frame->width, right);
601 
602  VectorScale(world_y, -frame->origin_y, down);
603  VectorScale(world_y, frame->height - frame->origin_y, up);
604  }
605  else
606  {
607  VectorScale(view_x, frame->origin_x, left);
608  VectorScale(view_x, frame->origin_x - frame->width, right);
609 
610  if (model->sprite_vertical)
611  {
612  VectorScale(world_y, -frame->origin_y, down);
613  VectorScale(world_y, frame->height - frame->origin_y, up);
614  }
615  else
616  {
617  VectorScale(view_y, -frame->origin_y, down);
618  VectorScale(view_y, frame->height - frame->origin_y, up);
619  }
620  }
621 
622  VectorAdd3(e->origin, down, left, vertex_positions[0]);
623  VectorAdd3(e->origin, up, left, vertex_positions[1]);
624  VectorAdd3(e->origin, up, right, vertex_positions[2]);
625  VectorAdd3(e->origin, down, right, vertex_positions[3]);
626 
627  vertex_positions += 4;
628  sprite_info += TR_SPRITE_INFO_SIZE / sizeof(int);
629 
630  if (++sprite_count >= TR_SPRITE_MAX_NUM)
631  return;
632  }
633 }
634 
635 static void upload_geometry(VkCommandBuffer command_buffer)
636 {
637  const size_t frame_offset = transparency.host_frame_index * transparency.host_frame_size;
638 
639  transparency.beam_vertex_device_offset = transparency.particle_num * 4 * TR_POSITION_SIZE;
640  transparency.sprite_vertex_device_offset = transparency.beam_vertex_device_offset + transparency.beam_num * 4 * TR_POSITION_SIZE;
641 
642  const VkBufferCopy vertices = {
643  .srcOffset = transparency.vertex_position_host_offset,
644  .dstOffset = 0,
645  .size = (transparency.particle_num + transparency.beam_num + transparency.sprite_num) * 4 * TR_POSITION_SIZE
646  };
647 
648  const VkBufferCopy paritcle_colors = {
649  .srcOffset = transparency.particle_color_host_offset,
650  .dstOffset = 0,
651  .size = transparency.particle_num * TR_COLOR_SIZE
652  };
653 
654  const VkBufferCopy beam_colors = {
655  .srcOffset = transparency.beam_color_host_offset,
656  .dstOffset = 0,
657  .size = transparency.beam_num * TR_COLOR_SIZE
658  };
659 
660  const VkBufferCopy sprite_infos = {
661  .srcOffset = transparency.sprite_info_host_offset,
662  .dstOffset = 0,
663  .size = transparency.sprite_num * TR_SPRITE_INFO_SIZE
664  };
665 
666  vkCmdCopyBuffer(command_buffer, transparency.host_buffer, transparency.vertex_buffer,
667  1, &vertices);
668 
669  vkCmdCopyBuffer(command_buffer, transparency.host_buffer, transparency.particle_color_buffer,
670  1, &paritcle_colors);
671 
672  vkCmdCopyBuffer(command_buffer, transparency.host_buffer, transparency.beam_color_buffer,
673  1, &beam_colors);
674 
675  vkCmdCopyBuffer(command_buffer, transparency.host_buffer, transparency.sprite_info_buffer,
676  1, &sprite_infos);
677 
678  for (size_t i = 0; i < LENGTH(transparency.transfer_barriers); i++)
679  {
680  transparency.transfer_barriers[i].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
681  transparency.transfer_barriers[i].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
682  transparency.transfer_barriers[i].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
683  transparency.transfer_barriers[i].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
684  transparency.transfer_barriers[i].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
685  }
686 
687  transparency.transfer_barriers[0].buffer = transparency.vertex_buffer;
688  transparency.transfer_barriers[0].size = vertices.size;
689  transparency.transfer_barriers[1].buffer = transparency.particle_color_buffer;
690  transparency.transfer_barriers[1].size = paritcle_colors.size;
691  transparency.transfer_barriers[2].buffer = transparency.beam_color_buffer;
692  transparency.transfer_barriers[2].size = beam_colors.size;
693  transparency.transfer_barriers[3].buffer = transparency.sprite_info_buffer;
694  transparency.transfer_barriers[3].size = sprite_infos.size;
695 }
696 
697 static void update_particle_blas(VkCommandBuffer command_buffer)
698 {
699  if (transparency.particle_num == 0 && transparency.blas_particle_num == 0)
700  return;
701 
702  vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
703  0, 0, NULL, LENGTH(transparency.transfer_barriers), transparency.transfer_barriers, 0, NULL);
704 
705  const VkGeometryTrianglesNV triangles = {
706  .sType = VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV,
707  .vertexData = transparency.vertex_buffer,
708  .vertexCount = transparency.particle_num * 4,
709  .vertexStride = TR_POSITION_SIZE,
710  .vertexFormat = VK_FORMAT_R32G32B32_SFLOAT,
711  .indexData = transparency.index_buffer,
712  .indexCount = transparency.particle_num * 6,
713  .indexType = VK_INDEX_TYPE_UINT16
714  };
715 
716  const VkGeometryAABBNV aabbs = {
717  .sType = VK_STRUCTURE_TYPE_GEOMETRY_AABB_NV
718  };
719 
720  const VkGeometryDataNV geometry_data = {
721  .triangles = triangles,
722  .aabbs = aabbs
723  };
724 
725  const VkGeometryNV geometry = {
726  .sType = VK_STRUCTURE_TYPE_GEOMETRY_NV,
727  .geometryType = VK_GEOMETRY_TYPE_TRIANGLES_NV,
728  .geometry = geometry_data
729  };
730 
731  const VkAccelerationStructureInfoNV info = {
732  .sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV,
733  .type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV,
734  .flags = TR_BLAS_BUILD_FLAGS,
735  .instanceCount = 0,
736  .geometryCount = 1,
737  .pGeometries = &geometry
738  };
739 
740  const VkBool32 update = transparency.blas_particle_num == transparency.particle_num ? VK_TRUE : VK_FALSE;
741  transparency.blas_particle_num = transparency.particle_num;
742 
743  qvkCmdBuildAccelerationStructureNV(command_buffer, &info, VK_NULL_HANDLE, 0, update,
744  transparency.particle_blas, transparency.particle_blas, transparency.scratch_buffer, 0);
745 }
746 
747 static void update_beam_blas(VkCommandBuffer command_buffer)
748 {
749  if (transparency.beam_num == 0 && transparency.blas_beam_num == 0)
750  return;
751 
752  const VkGeometryTrianglesNV triangles = {
753  .sType = VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV,
754  .vertexData = transparency.vertex_buffer,
755  .vertexCount = transparency.beam_num * 4,
756  .vertexStride = TR_POSITION_SIZE,
757  .vertexFormat = VK_FORMAT_R32G32B32_SFLOAT,
758  .vertexOffset = transparency.beam_vertex_device_offset,
759  .indexData = transparency.index_buffer,
760  .indexCount = transparency.beam_num * 6,
761  .indexType = VK_INDEX_TYPE_UINT16
762  };
763 
764  const VkGeometryAABBNV aabbs = {
765  .sType = VK_STRUCTURE_TYPE_GEOMETRY_AABB_NV
766  };
767 
768  const VkGeometryDataNV geometry_data = {
769  .triangles = triangles,
770  .aabbs = aabbs
771  };
772 
773  const VkGeometryNV geometry = {
774  .sType = VK_STRUCTURE_TYPE_GEOMETRY_NV,
775  .geometryType = VK_GEOMETRY_TYPE_TRIANGLES_NV,
776  .geometry = geometry_data
777  };
778 
779  const VkAccelerationStructureInfoNV info = {
780  .sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV,
781  .type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV,
782  .flags = TR_BLAS_BUILD_FLAGS,
783  .instanceCount = 0,
784  .geometryCount = 1,
785  .pGeometries = &geometry
786  };
787 
788 
789  const VkBool32 update = transparency.blas_beam_num == transparency.beam_num ? VK_TRUE : VK_FALSE;
790  transparency.blas_beam_num = transparency.beam_num;
791 
792  qvkCmdBuildAccelerationStructureNV(command_buffer, &info, VK_NULL_HANDLE, 0, update,
793  transparency.beam_blas, transparency.beam_blas, transparency.scratch_buffer,
794  transparency.beam_scratch_device_offset);
795 }
796 
797 static void update_sprite_blas(VkCommandBuffer command_buffer)
798 {
799  if (transparency.sprite_num == 0 && transparency.blas_sprite_num == 0)
800  return;
801 
802  const VkGeometryTrianglesNV triangles = {
803  .sType = VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV,
804  .vertexData = transparency.vertex_buffer,
805  .vertexCount = transparency.sprite_num * 4,
806  .vertexStride = TR_POSITION_SIZE,
807  .vertexFormat = VK_FORMAT_R32G32B32_SFLOAT,
808  .vertexOffset = transparency.sprite_vertex_device_offset,
809  .indexData = transparency.index_buffer,
810  .indexCount = transparency.sprite_num * 6,
811  .indexType = VK_INDEX_TYPE_UINT16
812  };
813 
814  const VkGeometryAABBNV aabbs = {
815  .sType = VK_STRUCTURE_TYPE_GEOMETRY_AABB_NV
816  };
817 
818  const VkGeometryDataNV geometry_data = {
819  .triangles = triangles,
820  .aabbs = aabbs
821  };
822 
823  const VkGeometryNV geometry = {
824  .sType = VK_STRUCTURE_TYPE_GEOMETRY_NV,
825  .geometryType = VK_GEOMETRY_TYPE_TRIANGLES_NV,
826  .geometry = geometry_data
827  };
828 
829  const VkAccelerationStructureInfoNV info = {
830  .sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV,
831  .type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV,
832  .flags = TR_BLAS_BUILD_FLAGS,
833  .instanceCount = 0,
834  .geometryCount = 1,
835  .pGeometries = &geometry
836  };
837 
838  const VkBool32 update = transparency.blas_sprite_num == transparency.sprite_num ? VK_TRUE : VK_FALSE;
839  transparency.blas_sprite_num = transparency.sprite_num;
840 
841  qvkCmdBuildAccelerationStructureNV(command_buffer, &info, VK_NULL_HANDLE, 0, update,
842  transparency.sprite_blas, transparency.sprite_blas, transparency.scratch_buffer,
843  transparency.sprite_scratch_device_offset);
844 }
845 
846 static size_t calculate_scratch_buffer_size(VkAccelerationStructureNV blas)
847 {
848  VkAccelerationStructureMemoryRequirementsInfoNV scratch_requirements_info = {
849  .sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV,
850  .type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV,
851  .accelerationStructure = blas
852  };
853 
854  VkMemoryRequirements2 build_memory_requirements = { 0 };
855  build_memory_requirements.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2;
856  qvkGetAccelerationStructureMemoryRequirementsNV(qvk.device, &scratch_requirements_info,
857  &build_memory_requirements);
858 
859  scratch_requirements_info.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_UPDATE_SCRATCH_NV;
860 
861  VkMemoryRequirements2 update_memory_requirements = { 0 };
862  update_memory_requirements.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2;
863  qvkGetAccelerationStructureMemoryRequirementsNV(qvk.device, &scratch_requirements_info,
864  &update_memory_requirements);
865 
866  const uint64_t build_size = build_memory_requirements.memoryRequirements.size;
867  const uint64_t update_size = update_memory_requirements.memoryRequirements.size;
868 
869  return max(build_size, update_size);
870 }
871 
872 static void create_buffers()
873 {
874  const uint64_t particle_scratch_size = calculate_scratch_buffer_size(transparency.particle_blas);
875  const uint64_t beam_scratch_size = calculate_scratch_buffer_size(transparency.beam_blas);
876  const uint64_t sprite_scratch_size = calculate_scratch_buffer_size(transparency.sprite_blas);
877 
878  transparency.beam_scratch_device_offset = particle_scratch_size;
879  transparency.sprite_scratch_device_offset = transparency.beam_scratch_device_offset + beam_scratch_size;
880 
881  const VkBufferCreateInfo host_buffer_info = {
882  .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
883  .size = transparency.host_buffered_frame_num * transparency.host_frame_size,
884  .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT
885  };
886 
887  const VkBufferCreateInfo scratch_buffer_info = {
888  .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
889  .size = particle_scratch_size + beam_scratch_size + sprite_scratch_size,
890  .usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_NV
891  };
892 
893  const VkBufferCreateInfo buffer_info = {
894  .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
895  .size = transparency.host_frame_size,
896  .usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT
897  };
898 
899  const VkBufferCreateInfo index_buffer_info = {
900  .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
901  .size = TR_INDEX_MAX_NUM * sizeof(uint16_t),
902  .usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT
903  };
904 
905  const VkBufferCreateInfo particle_color_buffer_info = {
906  .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
908  .usage = VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT
909  };
910 
911  const VkBufferCreateInfo beam_color_buffer_info = {
912  .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
913  .size = TR_BEAM_MAX_NUM * TR_COLOR_SIZE,
914  .usage = VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT
915  };
916 
917  const VkBufferCreateInfo sprite_info_buffer_info = {
918  .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
920  .usage = VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT
921  };
922 
923  _VK(vkCreateBuffer(qvk.device, &host_buffer_info, NULL, &transparency.host_buffer));
924  _VK(vkCreateBuffer(qvk.device, &scratch_buffer_info, NULL, &transparency.scratch_buffer));
925  _VK(vkCreateBuffer(qvk.device, &buffer_info, NULL, &transparency.vertex_buffer));
926  _VK(vkCreateBuffer(qvk.device, &index_buffer_info, NULL, &transparency.index_buffer));
927  _VK(vkCreateBuffer(qvk.device, &particle_color_buffer_info, NULL, &transparency.particle_color_buffer));
928  _VK(vkCreateBuffer(qvk.device, &beam_color_buffer_info, NULL, &transparency.beam_color_buffer));
929  _VK(vkCreateBuffer(qvk.device, &sprite_info_buffer_info, NULL, &transparency.sprite_info_buffer));
930 }
931 
933 {
934  // host buffer
935 
936  VkMemoryRequirements host_buffer_requirements;
937  vkGetBufferMemoryRequirements(qvk.device, transparency.host_buffer, &host_buffer_requirements);
938 
939  const VkMemoryPropertyFlags host_flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT |
940  VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
941 
942  const uint32_t host_memory_type = get_memory_type(host_buffer_requirements.memoryTypeBits, host_flags);
943 
944  const VkMemoryAllocateInfo host_memory_allocate_info = {
945  .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
946  .allocationSize = host_buffer_requirements.size,
947  .memoryTypeIndex = host_memory_type
948  };
949 
950  _VK(vkAllocateMemory(qvk.device, &host_memory_allocate_info, NULL, &transparency.host_buffer_memory));
951 
952  // device buffers
953 
954  const VkBuffer device_buffers[] = {
955  transparency.scratch_buffer,
956  transparency.vertex_buffer,
957  transparency.index_buffer,
958  transparency.particle_color_buffer,
959  transparency.beam_color_buffer,
960  transparency.sprite_info_buffer
961  };
962 
963  const VkMemoryPropertyFlags device_flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
964  uint32_t memory_types[LENGTH(device_buffers)];
965  VkMemoryRequirements requirements[LENGTH(device_buffers)];
966 
967  VkMemoryAllocateInfo memory_allocate_info = { .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };
968 
969  for (size_t i = 0; i < LENGTH(device_buffers); i++)
970  {
971  vkGetBufferMemoryRequirements(qvk.device, device_buffers[i], &requirements[i]);
972  memory_types[i] = get_memory_type(requirements[i].memoryTypeBits, device_flags);
973  memory_allocate_info.allocationSize += requirements[i].size + ((i == 0) ? 0 : requirements[i].alignment);
974  }
975 
976  // If the buffers need different memory types, the code that does allocation and binding must be changed
977  for (size_t i = 1; i < LENGTH(device_buffers); i++)
978  {
979  if (memory_types[i] != memory_types[0])
980  return qfalse;
981  }
982 
983  memory_allocate_info.memoryTypeIndex = memory_types[0];
984 
985 
986 #ifdef VKPT_DEVICE_GROUPS
987  VkMemoryAllocateFlagsInfoKHR mem_alloc_flags = {
988  .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO_KHR,
989  .flags = VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT_KHR,
990  .deviceMask = (1 << qvk.device_count) - 1
991  };
992 
993  if (qvk.device_count > 1) {
994  memory_allocate_info.pNext = &mem_alloc_flags;
995  }
996 #endif
997 
998  _VK(vkAllocateMemory(qvk.device, &memory_allocate_info, NULL, &transparency.device_buffer_memory));
999 
1000  // bind device buffers and a host buffer
1001  VkBindBufferMemoryInfo bindings[LENGTH(device_buffers) + 1] = { 0 };
1002 
1003  bindings[0].sType = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO;
1004  bindings[0].buffer = transparency.host_buffer;
1005  bindings[0].memory = transparency.host_buffer_memory;
1006  bindings[0].memoryOffset = 0;
1007 
1008  size_t offset = 0;
1009  for (size_t i = 0; i < LENGTH(device_buffers); i++)
1010  {
1011  VkBindBufferMemoryInfo* binding = bindings + i + 1;
1012 
1013  binding->sType = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO;
1014  binding->buffer = device_buffers[i];
1015  binding->memory = transparency.device_buffer_memory;
1016 
1017  offset = align(offset, requirements[i].alignment);
1018  binding->memoryOffset = offset;
1019  offset += requirements[i].size;
1020  }
1021 
1022  _VK(vkBindBufferMemory2(qvk.device, LENGTH(bindings), bindings));
1023 
1024  const size_t host_buffer_size = transparency.host_buffered_frame_num * transparency.host_frame_size;
1025 
1026  _VK(vkMapMemory(qvk.device, transparency.host_buffer_memory, 0, host_buffer_size, 0,
1027  &transparency.mapped_host_buffer));
1028 
1029  return qtrue;
1030 }
1031 
1032 static void create_blas()
1033 {
1034  const VkGeometryTrianglesNV geometry_triangles = {
1035  .sType = VK_STRUCTURE_TYPE_GEOMETRY_TRIANGLES_NV,
1036  .vertexCount = TR_VERTEX_MAX_NUM,
1037  .vertexFormat = VK_FORMAT_R32G32B32_SFLOAT,
1038  .indexCount = TR_INDEX_MAX_NUM,
1039  .indexType = VK_INDEX_TYPE_UINT16
1040  };
1041 
1042  const VkGeometryAABBNV geometry_aabbs = {
1043  .sType = VK_STRUCTURE_TYPE_GEOMETRY_AABB_NV
1044  };
1045 
1046  const VkGeometryDataNV geometry_data = {
1047  .triangles = geometry_triangles,
1048  .aabbs = geometry_aabbs
1049  };
1050 
1051  const VkGeometryNV geometry = {
1052  .sType = VK_STRUCTURE_TYPE_GEOMETRY_NV,
1053  .geometryType = VK_GEOMETRY_TYPE_TRIANGLES_NV,
1054  .geometry = geometry_data
1055  };
1056 
1057  const VkAccelerationStructureInfoNV info = {
1058  .sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_INFO_NV,
1059  .type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_NV,
1060  .flags = TR_BLAS_BUILD_FLAGS,
1061  .geometryCount = 1,
1062  .pGeometries = &geometry
1063  };
1064 
1065  const VkAccelerationStructureCreateInfoNV blas_info = {
1066  .sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_NV,
1067  .info = info
1068  };
1069 
1070  _VK(qvkCreateAccelerationStructureNV(qvk.device, &blas_info, NULL, &transparency.particle_blas));
1071  _VK(qvkCreateAccelerationStructureNV(qvk.device, &blas_info, NULL, &transparency.beam_blas));
1072  _VK(qvkCreateAccelerationStructureNV(qvk.device, &blas_info, NULL, &transparency.sprite_blas));
1073 }
1074 
1076 {
1077  const VkAccelerationStructureMemoryRequirementsInfoNV blas_requirements_info = {
1078  .sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_NV,
1079  .type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV,
1080  .accelerationStructure = transparency.particle_blas
1081  };
1082 
1083  VkMemoryRequirements2 blas_memory_requirements = { 0 };
1084  blas_memory_requirements.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2;
1085  qvkGetAccelerationStructureMemoryRequirementsNV(qvk.device, &blas_requirements_info,
1086  &blas_memory_requirements);
1087 
1088  VkMemoryRequirements mem_req = blas_memory_requirements.memoryRequirements;
1089  size_t beam_memory_offset = align(mem_req.size, mem_req.alignment);
1090  mem_req.size += beam_memory_offset;
1091 
1092  size_t sprite_memory_offset = align(mem_req.size, mem_req.alignment);
1093  mem_req.size += sprite_memory_offset;
1094 
1095  _VK(allocate_gpu_memory(mem_req, &transparency.device_blas_memory));
1096 
1097  VkBindAccelerationStructureMemoryInfoNV bindings[3] = { 0 };
1098 
1099  bindings[0].sType = VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV;
1100  bindings[0].accelerationStructure = transparency.particle_blas;
1101  bindings[0].memory = transparency.device_blas_memory;
1102  bindings[1].sType = VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV;
1103  bindings[1].accelerationStructure = transparency.beam_blas;
1104  bindings[1].memory = transparency.device_blas_memory;
1105  bindings[1].memoryOffset = beam_memory_offset;
1106  bindings[2].sType = VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_NV;
1107  bindings[2].accelerationStructure = transparency.sprite_blas;
1108  bindings[2].memory = transparency.device_blas_memory;
1109  bindings[2].memoryOffset = sprite_memory_offset;
1110 
1111  _VK(qvkBindAccelerationStructureMemoryNV(qvk.device, LENGTH(bindings), bindings));
1112 }
1113 
1114 static void create_buffer_views()
1115 {
1116  const VkBufferViewCreateInfo particle_color_view_info = {
1117  .sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,
1118  .buffer = transparency.particle_color_buffer,
1119  .format = VK_FORMAT_R32G32B32A32_SFLOAT,
1121  };
1122 
1123  const VkBufferViewCreateInfo beam_color_view_info = {
1124  .sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,
1125  .buffer = transparency.beam_color_buffer,
1126  .format = VK_FORMAT_R32G32B32A32_SFLOAT,
1127  .range = TR_BEAM_MAX_NUM * TR_COLOR_SIZE
1128  };
1129 
1130  const VkBufferViewCreateInfo sprite_info_view_info = {
1131  .sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,
1132  .buffer = transparency.sprite_info_buffer,
1133  .format = VK_FORMAT_R32G32_UINT,
1135  };
1136 
1137  _VK(vkCreateBufferView(qvk.device, &particle_color_view_info, NULL,
1138  &transparency.particle_color_buffer_view));
1139 
1140  _VK(vkCreateBufferView(qvk.device, &beam_color_view_info, NULL,
1141  &transparency.beam_color_buffer_view));
1142 
1143  _VK(vkCreateBufferView(qvk.device, &sprite_info_view_info, NULL,
1144  &transparency.sprite_info_buffer_view));
1145 }
1146 
1147 static void fill_index_buffer()
1148 {
1149  uint16_t* indices = (uint16_t*)transparency.mapped_host_buffer;
1150 
1151  for (size_t i = 0; i < TR_PARTICLE_MAX_NUM; i++)
1152  {
1153  uint16_t* quad = indices + i * 6;
1154 
1155  const uint16_t base_vertex = i * 4;
1156  quad[0] = base_vertex + 0;
1157  quad[1] = base_vertex + 1;
1158  quad[2] = base_vertex + 2;
1159  quad[3] = base_vertex + 2;
1160  quad[4] = base_vertex + 3;
1161  quad[5] = base_vertex + 0;
1162  }
1163 
1164  VkCommandBuffer cmd_buf = vkpt_begin_command_buffer(&qvk.cmd_buffers_transfer);
1165 
1166  const VkBufferMemoryBarrier pre_barrier = {
1167  .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
1168  .srcAccessMask = 0,
1169  .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
1170  .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
1171  .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
1172  .buffer = transparency.index_buffer,
1173  .size = VK_WHOLE_SIZE
1174  };
1175 
1176  vkCmdPipelineBarrier(cmd_buf, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
1177  0, 0, NULL, 1, &pre_barrier, 0, NULL);
1178 
1179  const VkBufferCopy region = {
1180  .size = TR_INDEX_MAX_NUM * sizeof(uint16_t)
1181  };
1182 
1183  vkCmdCopyBuffer(cmd_buf, transparency.host_buffer, transparency.index_buffer, 1, &region);
1184 
1185  const VkBufferMemoryBarrier post_barrier = {
1186  .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
1187  .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
1188  .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT,
1189  .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
1190  .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
1191  .buffer = transparency.index_buffer,
1192  .size = VK_WHOLE_SIZE
1193  };
1194 
1195  vkCmdPipelineBarrier(cmd_buf, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
1196  0, 0, NULL, 1, &post_barrier, 0, NULL);
1197 
1200 }
update_sprite_blas
static void update_sprite_blas(VkCommandBuffer command_buffer)
Definition: transparency.c:797
mapped_host_buffer
char * mapped_host_buffer
Definition: transparency.c:58
update_particle_blas
static void update_particle_blas(VkCommandBuffer command_buffer)
Definition: transparency.c:697
blas_sprite_num
unsigned int blas_sprite_num
Definition: transparency.c:55
light_poly_s
Definition: vkpt.h:315
beam_scratch_device_offset
size_t beam_scratch_device_offset
Definition: transparency.c:42
transparency
struct @17 transparency
index_buffer
VkBuffer index_buffer
Definition: transparency.c:65
TR_COLOR_SIZE
#define TR_COLOR_SIZE
Definition: transparency.c:29
MAX_FRAMES_IN_FLIGHT
#define MAX_FRAMES_IN_FLIGHT
Definition: vkpt.h:140
get_transparency_beam_blas
VkAccelerationStructureNV get_transparency_beam_blas()
Definition: transparency.c:231
sprite_info_buffer_view
VkBufferView sprite_info_buffer_view
Definition: transparency.c:74
allocate_gpu_memory
VkResult allocate_gpu_memory(VkMemoryRequirements mem_req, VkDeviceMemory *pMemory)
Definition: vk_util.c:402
image_t
struct image_s image_t
Definition: material.h:27
cvar_pt_projection
cvar_t * cvar_pt_projection
Definition: main.c:56
TR_INDEX_MAX_NUM
#define TR_INDEX_MAX_NUM
Definition: transparency.c:27
allocate_and_bind_memory_to_buffers
static qboolean allocate_and_bind_memory_to_buffers()
Definition: transparency.c:932
QVK_s::device
VkDevice device
Definition: vkpt.h:172
MOD_ForHandle
model_t * MOD_ForHandle(qhandle_t h)
Definition: models.c:430
cvar_pt_particle_emissive
cvar_t * cvar_pt_particle_emissive
Definition: effects.c:835
align
static size_t align(size_t x, size_t alignment)
Definition: vk_util.h:143
vkpt_refdef
vkpt_refdef_t vkpt_refdef
Definition: main.c:372
get_transparency_sprite_blas
VkAccelerationStructureNV get_transparency_sprite_blas()
Definition: transparency.c:236
Cvar_Get
cvar_t * Cvar_Get(const char *var_name, const char *var_value, int flags)
Definition: cvar.c:257
particles
static cparticle_t particles[MAX_PARTICLES]
Definition: effects.c:830
QVK_s::cmd_buffers_transfer
cmd_buf_group_t cmd_buffers_transfer
Definition: vkpt.h:195
beam_color_buffer
VkBuffer beam_color_buffer
Definition: transparency.c:67
cast_u32_to_f32_color
void cast_u32_to_f32_color(int color_index, const color_t *pcolor, float *color_f32, float hdr_factor)
Definition: transparency.c:102
particle_color_buffer
VkBuffer particle_color_buffer
Definition: transparency.c:66
light_poly_s::color
vec3_t color
Definition: vkpt.h:318
light_poly_s::material
struct pbr_material_s * material
Definition: vkpt.h:319
cvar_pt_particle_size
cvar_t * cvar_pt_particle_size
Definition: transparency.c:95
vkpt_build_cylinder_light
qboolean vkpt_build_cylinder_light(light_poly_t *light_list, int *num_lights, int max_lights, bsp_t *bsp, vec3_t begin, vec3_t end, vec3_t color, float radius)
Definition: transparency.c:408
vkpt.h
write_particle_geometry
static void write_particle_geometry(const float *view_matrix, const particle_t *particles, int particle_num)
Definition: transparency.c:263
get_transparency_counts
void get_transparency_counts(int *particle_num, int *beam_num, int *sprite_num)
Definition: transparency.c:256
device_blas_memory
VkDeviceMemory device_blas_memory
Definition: transparency.c:71
get_transparency_sprite_info_buffer_view
VkBufferView get_transparency_sprite_info_buffer_view()
Definition: transparency.c:251
sprite_info_buffer
VkBuffer sprite_info_buffer
Definition: transparency.c:68
d_8to24table
uint32_t d_8to24table[256]
Definition: images.c:654
TR_BLAS_BUILD_FLAGS
#define TR_BLAS_BUILD_FLAGS
Definition: transparency.c:32
host_frame_index
unsigned int host_frame_index
Definition: transparency.c:56
TR_SPRITE_MAX_NUM
#define TR_SPRITE_MAX_NUM
Definition: transparency.c:25
vertex_position_host_offset
size_t vertex_position_host_offset
Definition: transparency.c:37
write_beam_geometry
static void write_beam_geometry(const float *view_matrix, const entity_t *entities, int entity_num)
Definition: transparency.c:325
calculate_scratch_buffer_size
static size_t calculate_scratch_buffer_size(VkAccelerationStructureNV blas)
Definition: transparency.c:846
create_buffer_views
static void create_buffer_views()
Definition: transparency.c:1114
compare_beams
static int compare_beams(const void *_a, const void *_b)
Definition: transparency.c:388
BSP_PointLeaf
mleaf_t * BSP_PointLeaf(mnode_t *node, vec3_t p)
Definition: bsp.c:1439
TR_VERTEX_MAX_NUM
#define TR_VERTEX_MAX_NUM
Definition: transparency.c:26
beam_color_buffer_view
VkBufferView beam_color_buffer_view
Definition: transparency.c:73
vkpt_build_beam_lights
void vkpt_build_beam_lights(light_poly_t *light_list, int *num_lights, int max_lights, bsp_t *bsp, entity_t *entities, int num_entites, float adapted_luminance)
Definition: transparency.c:492
scratch_buffer
VkBuffer scratch_buffer
Definition: transparency.c:63
host_buffer_size
size_t host_buffer_size
Definition: transparency.c:48
vkpt_refdef_s::fd
refdef_t * fd
Definition: vkpt.h:396
sprite_vertex_device_offset
size_t sprite_vertex_device_offset
Definition: transparency.c:46
get_memory_type
uint32_t get_memory_type(uint32_t mem_req_type_bits, VkMemoryPropertyFlags mem_prop)
Definition: vk_util.c:45
_VK
#define _VK(...)
Definition: vkpt.h:65
sprite_blas
VkAccelerationStructureNV sprite_blas
Definition: transparency.c:61
MAX_BEAMS
#define MAX_BEAMS
Definition: transparency.c:386
particle_blas
VkAccelerationStructureNV particle_blas
Definition: transparency.c:59
TR_SPRITE_INFO_SIZE
#define TR_SPRITE_INFO_SIZE
Definition: transparency.c:30
cvar_pt_beam_width
cvar_t * cvar_pt_beam_width
Definition: transparency.c:96
get_triangle_off_center
qboolean get_triangle_off_center(const float *positions, float *center, float *anti_center)
Definition: bsp_mesh.c:282
beam_blas
VkAccelerationStructureNV beam_blas
Definition: transparency.c:60
host_frame_size
size_t host_frame_size
Definition: transparency.c:49
destroy_transparency
void destroy_transparency()
Definition: transparency.c:151
get_transparency_beam_color_buffer_view
VkBufferView get_transparency_beam_color_buffer_view()
Definition: transparency.c:246
particle_color_host_offset
size_t particle_color_host_offset
Definition: transparency.c:38
origin
static vec3_t origin
Definition: mesh.c:27
r_images
image_t r_images[MAX_RIMAGES]
Definition: images.c:651
host_buffered_frame_num
unsigned int host_buffered_frame_num
Definition: transparency.c:57
build_transparency_blas
void build_transparency_blas(VkCommandBuffer cmd_buf)
Definition: transparency.c:217
light_poly_s::style
int style
Definition: vkpt.h:321
cvar_pt_beam_lights
cvar_t * cvar_pt_beam_lights
Definition: transparency.c:97
beam_num
unsigned int beam_num
Definition: transparency.c:51
vkpt_wait_idle
void vkpt_wait_idle(VkQueue queue, cmd_buf_group_t *group)
Definition: main.c:3405
beam_color_host_offset
size_t beam_color_host_offset
Definition: transparency.c:39
LENGTH
#define LENGTH(a)
Definition: tent.c:228
sprite_num
unsigned int sprite_num
Definition: transparency.c:52
write_sprite_geometry
static void write_sprite_geometry(const float *view_matrix, const entity_t *entities, int entity_num)
Definition: transparency.c:546
vertex_buffer
VkBuffer vertex_buffer
Definition: transparency.c:64
sprite_info_host_offset
size_t sprite_info_host_offset
Definition: transparency.c:40
host_buffer
VkBuffer host_buffer
Definition: transparency.c:62
light_poly_s::off_center
vec3_t off_center
Definition: vkpt.h:317
fill_index_buffer
static void fill_index_buffer()
Definition: transparency.c:1147
qvk
QVK_t qvk
Definition: main.c:377
particle_num
unsigned int particle_num
Definition: transparency.c:50
create_blas
static void create_blas()
Definition: transparency.c:1032
create_buffers
static void create_buffers()
Definition: transparency.c:872
TR_PARTICLE_MAX_NUM
#define TR_PARTICLE_MAX_NUM
Definition: transparency.c:23
blas_beam_num
unsigned int blas_beam_num
Definition: transparency.c:53
vkpt_submit_command_buffer_simple
void vkpt_submit_command_buffer_simple(VkCommandBuffer cmd_buf, VkQueue queue, qboolean all_gpus)
Definition: main.c:3473
vk_util.h
up
static vec3_t up
Definition: p_view.c:27
get_transparency_particle_color_buffer_view
VkBufferView get_transparency_particle_color_buffer_view()
Definition: transparency.c:241
right
static vec3_t right
Definition: p_view.c:27
transfer_barriers
VkBufferMemoryBarrier transfer_barriers[4]
Definition: transparency.c:75
initialize_transparency
qboolean initialize_transparency()
Definition: transparency.c:114
device_buffer_memory
VkDeviceMemory device_buffer_memory
Definition: transparency.c:70
beam_vertex_device_offset
size_t beam_vertex_device_offset
Definition: transparency.c:43
particle_color_buffer_view
VkBufferView particle_color_buffer_view
Definition: transparency.c:72
update_beam_blas
static void update_beam_blas(VkCommandBuffer command_buffer)
Definition: transparency.c:747
upload_geometry
static void upload_geometry(VkCommandBuffer command_buffer)
Definition: transparency.c:635
host_buffer_memory
VkDeviceMemory host_buffer_memory
Definition: transparency.c:69
TR_BEAM_MAX_NUM
#define TR_BEAM_MAX_NUM
Definition: transparency.c:24
update_transparency
void update_transparency(VkCommandBuffer command_buffer, const float *view_matrix, const particle_t *particles, int particle_num, const entity_t *entities, int entity_num)
Definition: transparency.c:171
color
static vec4_t color
Definition: mesh.c:33
blas_particle_num
unsigned int blas_particle_num
Definition: transparency.c:54
vkpt_begin_command_buffer
VkCommandBuffer vkpt_begin_command_buffer(cmd_buf_group_t *group)
Definition: main.c:3301
get_transparency_particle_blas
VkAccelerationStructureNV get_transparency_particle_blas()
Definition: transparency.c:226
int
CONST PIXELFORMATDESCRIPTOR int
Definition: wgl.c:26
sprite_scratch_device_offset
size_t sprite_scratch_device_offset
Definition: transparency.c:45
TR_POSITION_SIZE
#define TR_POSITION_SIZE
Definition: transparency.c:28
light_poly_s::cluster
int cluster
Definition: vkpt.h:320
VectorNormalize
vec_t VectorNormalize(vec3_t v)
Definition: shared.c:55
cvar_pt_enable_particles
cvar_t * cvar_pt_enable_particles
Definition: path_tracer.c:101
QVK_s::device_count
int device_count
Definition: vkpt.h:167
QVK_s::queue_transfer
VkQueue queue_transfer
Definition: vkpt.h:175
light_poly_s::positions
float positions[9]
Definition: vkpt.h:316
allocate_and_bind_memory_to_blas
static void allocate_and_bind_memory_to_blas()
Definition: transparency.c:1075