34 VulkanComputeBackend::VulkanComputeBackend() : device(new
VulkanDevice()), owns_device(true) {
38 VulkanComputeBackend::VulkanComputeBackend(
VulkanDevice *external_device) : device(external_device), owns_device(false) {
45 VulkanComputeBackend::~VulkanComputeBackend() {
56 bool enable_validation =
false;
60 enable_validation =
true;
64 const char *validation_env = std::getenv(
"HELIOS_VULKAN_VALIDATION");
65 if (validation_env !=
nullptr) {
66 std::string val(validation_env);
67 if (val ==
"1" || val ==
"true" || val ==
"TRUE") {
68 enable_validation =
true;
69 }
else if (val ==
"0" || val ==
"false" || val ==
"FALSE") {
70 enable_validation =
false;
80 createCommandResources();
83 createDescriptorSets();
88 if (!device || device->
getDevice() == VK_NULL_HANDLE) {
95 vkDeviceWaitIdle(vk_device);
98 if (pipeline_direct != VK_NULL_HANDLE)
99 vkDestroyPipeline(vk_device, pipeline_direct,
nullptr);
100 if (pipeline_diffuse != VK_NULL_HANDLE)
101 vkDestroyPipeline(vk_device, pipeline_diffuse,
nullptr);
102 if (pipeline_camera != VK_NULL_HANDLE)
103 vkDestroyPipeline(vk_device, pipeline_camera,
nullptr);
104 if (pipeline_pixel_label != VK_NULL_HANDLE)
105 vkDestroyPipeline(vk_device, pipeline_pixel_label,
nullptr);
106 if (pipeline_layout != VK_NULL_HANDLE)
107 vkDestroyPipelineLayout(vk_device, pipeline_layout,
nullptr);
110 if (descriptor_pool != VK_NULL_HANDLE)
111 vkDestroyDescriptorPool(vk_device, descriptor_pool,
nullptr);
112 if (set_layout_geometry != VK_NULL_HANDLE)
113 vkDestroyDescriptorSetLayout(vk_device, set_layout_geometry,
nullptr);
114 if (set_layout_materials != VK_NULL_HANDLE)
115 vkDestroyDescriptorSetLayout(vk_device, set_layout_materials,
nullptr);
116 if (set_layout_results != VK_NULL_HANDLE)
117 vkDestroyDescriptorSetLayout(vk_device, set_layout_results,
nullptr);
118 if (set_layout_sky != VK_NULL_HANDLE)
119 vkDestroyDescriptorSetLayout(vk_device, set_layout_sky,
nullptr);
120 if (set_layout_debug != VK_NULL_HANDLE)
121 vkDestroyDescriptorSetLayout(vk_device, set_layout_debug,
nullptr);
124 destroyBuffer(bvh_buffer);
125 destroyBuffer(primitive_indices_buffer);
126 destroyBuffer(transform_matrices_buffer);
127 destroyBuffer(primitive_types_buffer);
128 destroyBuffer(primitive_uuids_buffer);
129 destroyBuffer(primitive_positions_buffer);
130 destroyBuffer(object_subdivisions_buffer);
131 destroyBuffer(twosided_flag_buffer);
132 destroyBuffer(patch_vertices_buffer);
133 destroyBuffer(triangle_vertices_buffer);
134 destroyBuffer(normal_buffer);
135 destroyBuffer(mask_data_buffer);
136 destroyBuffer(mask_sizes_buffer);
137 destroyBuffer(mask_offsets_buffer);
138 destroyBuffer(mask_IDs_buffer);
139 destroyBuffer(uv_data_buffer);
140 destroyBuffer(uv_IDs_buffer);
141 destroyBuffer(source_positions_buffer);
142 destroyBuffer(source_types_buffer);
143 destroyBuffer(source_rotations_buffer);
144 destroyBuffer(source_widths_buffer);
145 destroyBuffer(source_fluxes_buffer);
146 destroyBuffer(source_fluxes_cam_buffer);
147 destroyBuffer(reflectivity_buffer);
148 destroyBuffer(transmissivity_buffer);
149 destroyBuffer(specular_exponent_buffer);
150 destroyBuffer(specular_scale_buffer);
151 destroyBuffer(radiation_in_buffer);
152 destroyBuffer(radiation_out_top_buffer);
153 destroyBuffer(radiation_out_bottom_buffer);
154 destroyBuffer(scatter_top_buffer);
155 destroyBuffer(scatter_bottom_buffer);
156 destroyBuffer(camera_radiation_buffer);
157 destroyBuffer(camera_pixel_label_buffer);
158 destroyBuffer(camera_pixel_depth_buffer);
159 destroyBuffer(camera_scatter_top_buffer);
160 destroyBuffer(camera_scatter_bottom_buffer);
161 destroyBuffer(radiation_specular_buffer);
162 destroyBuffer(diffuse_flux_buffer);
163 destroyBuffer(diffuse_peak_dir_buffer);
164 destroyBuffer(diffuse_extinction_buffer);
165 destroyBuffer(diffuse_dist_norm_buffer);
166 destroyBuffer(sky_radiance_params_buffer);
167 destroyBuffer(camera_sky_radiance_buffer);
168 destroyBuffer(solar_disk_radiance_buffer);
169 destroyBuffer(camera_diffuse_flux_buffer);
170 destroyBuffer(band_emission_flag_buffer);
171 destroyBuffer(debug_counters_buffer);
172 destroyBuffer(bbox_vertices_buffer);
173 destroyBuffer(band_map_buffer);
174 destroyBuffer(is_glass_buffer);
175 destroyBuffer(glass_n_buffer);
176 destroyBuffer(glass_KL_buffer);
179 if (transfer_fence != VK_NULL_HANDLE)
180 vkDestroyFence(vk_device, transfer_fence,
nullptr);
181 if (compute_fence != VK_NULL_HANDLE)
182 vkDestroyFence(vk_device, compute_fence,
nullptr);
183 if (timestamp_query_pool != VK_NULL_HANDLE)
184 vkDestroyQueryPool(vk_device, timestamp_query_pool,
nullptr);
185 if (command_pool != VK_NULL_HANDLE)
186 vkDestroyCommandPool(vk_device, command_pool,
nullptr);
195 validateGeometryBeforeUpload(geometry);
197 primitive_count = geometry.primitive_count;
199 if (primitive_count == 0) {
204 bvh_nodes = bvh_builder.
build(geometry);
205 std::vector<CWBVH_Node> cwbvh_nodes = bvh_builder.
convertToCWBVH(bvh_nodes);
208 if (!cwbvh_nodes.empty()) {
209 if (bvh_buffer.buffer != VK_NULL_HANDLE) {
210 destroyBuffer(bvh_buffer);
212 bvh_buffer = createBuffer(cwbvh_nodes.size() *
sizeof(
CWBVH_Node), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
213 uploadBufferData(bvh_buffer, cwbvh_nodes.data(), cwbvh_nodes.size() *
sizeof(
CWBVH_Node));
218 if (!prim_indices.empty()) {
219 if (primitive_indices_buffer.buffer != VK_NULL_HANDLE) {
220 destroyBuffer(primitive_indices_buffer);
222 primitive_indices_buffer = createBuffer(prim_indices.size() *
sizeof(uint32_t), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
223 uploadBufferData(primitive_indices_buffer, prim_indices.data(), prim_indices.size() *
sizeof(uint32_t));
227 if (!geometry.transform_matrices.empty()) {
228 size_t expected_size = primitive_count * 16;
229 if (geometry.transform_matrices.size() != expected_size) {
230 helios_runtime_error(
"ERROR (VulkanComputeBackend::updateGeometry): transform_matrices size mismatch. Expected " + std::to_string(expected_size) +
" floats (16 per primitive), got " +
231 std::to_string(geometry.transform_matrices.size()));
234 if (transform_matrices_buffer.buffer != VK_NULL_HANDLE) {
235 destroyBuffer(transform_matrices_buffer);
237 transform_matrices_buffer = createBuffer(geometry.transform_matrices.size() *
sizeof(
float), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
238 uploadBufferData(transform_matrices_buffer, geometry.transform_matrices.data(), geometry.transform_matrices.size() *
sizeof(
float));
242 if (!geometry.primitive_types.empty()) {
243 if (geometry.primitive_types.size() != primitive_count) {
244 helios_runtime_error(
"ERROR (VulkanComputeBackend::updateGeometry): primitive_types size mismatch. Expected " + std::to_string(primitive_count) +
" entries, got " + std::to_string(geometry.primitive_types.size()));
247 if (primitive_types_buffer.buffer != VK_NULL_HANDLE) {
248 destroyBuffer(primitive_types_buffer);
250 primitive_types_buffer = createBuffer(geometry.primitive_types.size() *
sizeof(
uint), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
251 uploadBufferData(primitive_types_buffer, geometry.primitive_types.data(), geometry.primitive_types.size() *
sizeof(
uint));
255 if (!geometry.primitive_UUIDs.empty()) {
256 if (geometry.primitive_UUIDs.size() != primitive_count) {
257 helios_runtime_error(
"ERROR (VulkanComputeBackend::updateGeometry): primitive_UUIDs size mismatch. Expected " + std::to_string(primitive_count) +
" entries, got " + std::to_string(geometry.primitive_UUIDs.size()));
260 if (primitive_uuids_buffer.buffer != VK_NULL_HANDLE) {
261 destroyBuffer(primitive_uuids_buffer);
263 primitive_uuids_buffer = createBuffer(geometry.primitive_UUIDs.size() *
sizeof(
uint), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
264 uploadBufferData(primitive_uuids_buffer, geometry.primitive_UUIDs.data(), geometry.primitive_UUIDs.size() *
sizeof(
uint));
268 if (!geometry.primitive_positions.empty()) {
269 if (primitive_positions_buffer.buffer != VK_NULL_HANDLE) {
270 destroyBuffer(primitive_positions_buffer);
272 primitive_positions_buffer = createBuffer(geometry.primitive_positions.size() *
sizeof(
uint), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
273 uploadBufferData(primitive_positions_buffer, geometry.primitive_positions.data(), geometry.primitive_positions.size() *
sizeof(
uint));
277 if (!geometry.object_subdivisions.empty()) {
278 if (geometry.object_subdivisions.size() != primitive_count) {
279 helios_runtime_error(
"ERROR (VulkanComputeBackend::updateGeometry): object_subdivisions size mismatch. Expected " + std::to_string(primitive_count) +
" entries, got " + std::to_string(geometry.object_subdivisions.size()));
282 if (object_subdivisions_buffer.buffer != VK_NULL_HANDLE) {
283 destroyBuffer(object_subdivisions_buffer);
285 object_subdivisions_buffer = createBuffer(geometry.object_subdivisions.size() *
sizeof(
helios::int2), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
286 uploadBufferData(object_subdivisions_buffer, geometry.object_subdivisions.data(), geometry.object_subdivisions.size() *
sizeof(
helios::int2));
290 if (!geometry.twosided_flags.empty()) {
291 if (geometry.twosided_flags.size() != primitive_count) {
292 helios_runtime_error(
"ERROR (VulkanComputeBackend::updateGeometry): twosided_flags size mismatch. Expected " + std::to_string(primitive_count) +
" entries, got " + std::to_string(geometry.twosided_flags.size()));
295 if (twosided_flag_buffer.buffer != VK_NULL_HANDLE) {
296 destroyBuffer(twosided_flag_buffer);
299 std::vector<uint> twosided_uint(geometry.twosided_flags.begin(), geometry.twosided_flags.end());
300 twosided_flag_buffer = createBuffer(twosided_uint.size() *
sizeof(
uint), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
301 uploadBufferData(twosided_flag_buffer, twosided_uint.data(), twosided_uint.size() *
sizeof(
uint));
309 static const helios::vec3 canonical_quad[4] = {{-0.5f, -0.5f, 0.f}, {0.5f, -0.5f, 0.f}, {0.5f, 0.5f, 0.f}, {-0.5f, 0.5f, 0.f}};
310 static const helios::vec3 canonical_tri[3] = {{0.f, 0.f, 0.f}, {0.f, 1.f, 0.f}, {1.f, 1.f, 0.f}};
313 std::vector<helios::vec3> patch_verts(primitive_count * 4,
helios::make_vec3(0.f, 0.f, 0.f));
315 std::vector<helios::vec3> tri_verts(primitive_count * 3,
helios::make_vec3(0.f, 0.f, 0.f));
317 for (
size_t i = 0; i < primitive_count; ++i) {
318 uint prim_type = geometry.primitive_types[i];
319 const float *transform = &geometry.transform_matrices[i * 16];
321 if (prim_type == 0 || prim_type == 3) {
322 for (
int v = 0; v < 4; ++v) {
325 world_v.
x = transform[0] * p.
x + transform[1] * p.
y + transform[2] * p.
z + transform[3];
326 world_v.
y = transform[4] * p.
x + transform[5] * p.
y + transform[6] * p.
z + transform[7];
327 world_v.
z = transform[8] * p.
x + transform[9] * p.
y + transform[10] * p.
z + transform[11];
328 patch_verts[i * 4 + v] = world_v;
330 }
else if (prim_type == 1) {
331 for (
int v = 0; v < 3; ++v) {
334 world_v.
x = transform[0] * p.
x + transform[1] * p.
y + transform[2] * p.
z + transform[3];
335 world_v.
y = transform[4] * p.
x + transform[5] * p.
y + transform[6] * p.
z + transform[7];
336 world_v.
z = transform[8] * p.
x + transform[9] * p.
y + transform[10] * p.
z + transform[11];
337 tri_verts[i * 3 + v] = world_v;
342 if (patch_vertices_buffer.buffer != VK_NULL_HANDLE) {
343 destroyBuffer(patch_vertices_buffer);
345 patch_vertices_buffer = createBuffer(patch_verts.size() *
sizeof(
helios::vec3), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
346 uploadBufferData(patch_vertices_buffer, patch_verts.data(), patch_verts.size() *
sizeof(
helios::vec3));
348 if (triangle_vertices_buffer.buffer != VK_NULL_HANDLE) {
349 destroyBuffer(triangle_vertices_buffer);
351 triangle_vertices_buffer = createBuffer(tri_verts.size() *
sizeof(
helios::vec3), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
352 uploadBufferData(triangle_vertices_buffer, tri_verts.data(), tri_verts.size() *
sizeof(
helios::vec3));
366 std::vector<helios::vec3> normals(primitive_count);
368 for (
size_t i = 0; i < primitive_count; ++i) {
369 const float *t = &geometry.transform_matrices[i * 16];
370 uint prim_type = geometry.primitive_types[i];
374 if (prim_type == 0 || prim_type == 2 || prim_type == 3) {
378 }
else if (prim_type == 1) {
389 w0.
x = t[0] * cv0.
x + t[1] * cv0.
y + t[2] * cv0.
z + t[3];
390 w0.
y = t[4] * cv0.
x + t[5] * cv0.
y + t[6] * cv0.
z + t[7];
391 w0.
z = t[8] * cv0.
x + t[9] * cv0.
y + t[10] * cv0.
z + t[11];
392 w1.
x = t[0] * cv1.
x + t[1] * cv1.
y + t[2] * cv1.
z + t[3];
393 w1.
y = t[4] * cv1.
x + t[5] * cv1.
y + t[6] * cv1.
z + t[7];
394 w1.
z = t[8] * cv1.
x + t[9] * cv1.
y + t[10] * cv1.
z + t[11];
395 w2.
x = t[0] * cv2.
x + t[1] * cv2.
y + t[2] * cv2.
z + t[3];
396 w2.
y = t[4] * cv2.
x + t[5] * cv2.
y + t[6] * cv2.
z + t[7];
397 w2.
z = t[8] * cv2.
x + t[9] * cv2.
y + t[10] * cv2.
z + t[11];
403 float len = std::sqrt(n.
x * n.
x + n.
y * n.
y + n.
z * n.
z);
405 normals[i] = n / len;
411 if (normal_buffer.buffer != VK_NULL_HANDLE) {
412 destroyBuffer(normal_buffer);
414 normal_buffer = createBuffer(normals.size() *
sizeof(
helios::vec3), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
415 uploadBufferData(normal_buffer, normals.data(), normals.size() *
sizeof(
helios::vec3));
421 std::vector<uint32_t> mask_offsets;
422 uint32_t current_offset = 0;
423 for (
const auto &sz: geometry.mask_sizes) {
424 mask_offsets.push_back(current_offset);
425 current_offset +=
static_cast<uint32_t
>(sz.x) *
static_cast<uint32_t
>(sz.y);
428 std::vector<uint32_t> mask_data_uint;
429 if (current_offset > 0) {
430 if (geometry.mask_data.size() < current_offset) {
431 helios_runtime_error(
"ERROR (VulkanComputeBackend::updateGeometry): mask_data size mismatch. Expected " + std::to_string(current_offset) +
" texels, got " + std::to_string(geometry.mask_data.size()));
433 mask_data_uint.resize(current_offset, 0);
434 for (
size_t i = 0; i < current_offset; ++i) {
435 mask_data_uint[i] = geometry.mask_data[i] ? 1 : 0;
440 std::vector<helios::vec2> uv_flat(primitive_count * 4,
helios::make_vec2(0.f, 0.f));
441 size_t uv_read_offset = 0;
442 for (
size_t p = 0; p < primitive_count; ++p) {
443 if (!geometry.uv_IDs.empty() && geometry.uv_IDs[p] >= 0) {
445 for (
int v = 0; v < 4 && uv_read_offset < geometry.uv_data.size(); ++v) {
446 uv_flat[p * 4 + v] = geometry.uv_data[uv_read_offset++];
454 if (mask_data_buffer.buffer != VK_NULL_HANDLE) {
455 destroyBuffer(mask_data_buffer);
457 if (!mask_data_uint.empty()) {
458 mask_data_buffer = createBuffer(mask_data_uint.size() *
sizeof(uint32_t), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
459 uploadBufferData(mask_data_buffer, mask_data_uint.data(), mask_data_uint.size() *
sizeof(uint32_t));
462 mask_data_buffer = createBuffer(
sizeof(uint32_t), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
466 if (mask_sizes_buffer.buffer != VK_NULL_HANDLE) {
467 destroyBuffer(mask_sizes_buffer);
469 if (!geometry.mask_sizes.empty()) {
470 mask_sizes_buffer = createBuffer(geometry.mask_sizes.size() *
sizeof(
helios::int2), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
471 uploadBufferData(mask_sizes_buffer, geometry.mask_sizes.data(), geometry.mask_sizes.size() *
sizeof(
helios::int2));
473 mask_sizes_buffer = createBuffer(
sizeof(int32_t) * 2, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
477 if (mask_offsets_buffer.buffer != VK_NULL_HANDLE) {
478 destroyBuffer(mask_offsets_buffer);
480 if (!mask_offsets.empty()) {
481 mask_offsets_buffer = createBuffer(mask_offsets.size() *
sizeof(uint32_t), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
482 uploadBufferData(mask_offsets_buffer, mask_offsets.data(), mask_offsets.size() *
sizeof(uint32_t));
484 mask_offsets_buffer = createBuffer(
sizeof(uint32_t), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
488 if (mask_IDs_buffer.buffer != VK_NULL_HANDLE) {
489 destroyBuffer(mask_IDs_buffer);
491 if (!geometry.mask_IDs.empty()) {
493 std::vector<int32_t> mask_IDs_int32(geometry.mask_IDs.begin(), geometry.mask_IDs.end());
494 mask_IDs_buffer = createBuffer(mask_IDs_int32.size() *
sizeof(int32_t), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
495 uploadBufferData(mask_IDs_buffer, mask_IDs_int32.data(), mask_IDs_int32.size() *
sizeof(int32_t));
497 mask_IDs_buffer = createBuffer(
sizeof(int32_t), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
501 if (uv_data_buffer.buffer != VK_NULL_HANDLE) {
502 destroyBuffer(uv_data_buffer);
504 if (!uv_flat.empty()) {
505 uv_data_buffer = createBuffer(uv_flat.size() *
sizeof(
helios::vec2), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
506 uploadBufferData(uv_data_buffer, uv_flat.data(), uv_flat.size() *
sizeof(
helios::vec2));
508 uv_data_buffer = createBuffer(
sizeof(
float) * 2, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
512 if (uv_IDs_buffer.buffer != VK_NULL_HANDLE) {
513 destroyBuffer(uv_IDs_buffer);
515 if (!geometry.uv_IDs.empty()) {
517 std::vector<int32_t> uv_IDs_int32(geometry.uv_IDs.begin(), geometry.uv_IDs.end());
518 uv_IDs_buffer = createBuffer(uv_IDs_int32.size() *
sizeof(int32_t), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
519 uploadBufferData(uv_IDs_buffer, uv_IDs_int32.data(), uv_IDs_int32.size() *
sizeof(int32_t));
521 uv_IDs_buffer = createBuffer(
sizeof(int32_t), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
527 bbox_count = geometry.bbox_count;
528 periodic_flag_x = geometry.periodic_flag.x;
529 periodic_flag_y = geometry.periodic_flag.y;
531 if (bbox_vertices_buffer.buffer != VK_NULL_HANDLE) {
532 destroyBuffer(bbox_vertices_buffer);
535 if (bbox_count > 0 && !geometry.bboxes.vertices.empty()) {
537 std::vector<float> bbox_verts_flat;
538 bbox_verts_flat.reserve(bbox_count * 12);
539 for (
size_t i = 0; i < bbox_count * 4; ++i) {
540 bbox_verts_flat.push_back(geometry.bboxes.vertices[i].x);
541 bbox_verts_flat.push_back(geometry.bboxes.vertices[i].y);
542 bbox_verts_flat.push_back(geometry.bboxes.vertices[i].z);
544 bbox_vertices_buffer = createBuffer(bbox_verts_flat.size() *
sizeof(
float), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
545 uploadBufferData(bbox_vertices_buffer, bbox_verts_flat.data(), bbox_verts_flat.size() *
sizeof(
float));
548 float xmin = 1e30f, xmax = -1e30f, ymin = 1e30f, ymax = -1e30f;
549 for (
size_t i = 0; i < bbox_count * 4; ++i) {
550 xmin = std::min(xmin, geometry.bboxes.vertices[i].x);
551 xmax = std::max(xmax, geometry.bboxes.vertices[i].x);
552 ymin = std::min(ymin, geometry.bboxes.vertices[i].y);
553 ymax = std::max(ymax, geometry.bboxes.vertices[i].y);
555 domain_bounds[0] = xmin;
556 domain_bounds[1] = xmax;
557 domain_bounds[2] = ymin;
558 domain_bounds[3] = ymax;
561 bbox_vertices_buffer = createBuffer(
sizeof(
float), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
562 domain_bounds[0] = domain_bounds[1] = domain_bounds[2] = domain_bounds[3] = 0.f;
566 descriptors_dirty =
true;
576 if (primitive_count == 0) {
582 size_t expected_size = materials.
num_sources * band_count * primitive_count;
587 helios_runtime_error(
"ERROR (VulkanComputeBackend::updateMaterials): reflectivity size mismatch. Expected " + std::to_string(expected_size) +
" entries (Nsources * Nprims * Nbands), got " +
591 if (reflectivity_buffer.buffer != VK_NULL_HANDLE) {
592 destroyBuffer(reflectivity_buffer);
594 reflectivity_buffer = createBuffer(materials.
reflectivity.size() *
sizeof(
float), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
595 uploadBufferData(reflectivity_buffer, materials.
reflectivity.data(), materials.
reflectivity.size() *
sizeof(
float));
601 helios_runtime_error(
"ERROR (VulkanComputeBackend::updateMaterials): transmissivity size mismatch. Expected " + std::to_string(expected_size) +
" entries (Nsources * Nprims * Nbands), got " +
605 if (transmissivity_buffer.buffer != VK_NULL_HANDLE) {
606 destroyBuffer(transmissivity_buffer);
608 transmissivity_buffer = createBuffer(materials.
transmissivity.size() *
sizeof(
float), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
615 helios_runtime_error(
"ERROR (VulkanComputeBackend::updateMaterials): specular_exponent size mismatch. Expected " + std::to_string(primitive_count) +
" entries (Nprims), got " + std::to_string(materials.
specular_exponent.size()));
618 if (specular_exponent_buffer.buffer != VK_NULL_HANDLE) {
619 destroyBuffer(specular_exponent_buffer);
621 specular_exponent_buffer = createBuffer(materials.
specular_exponent.size() *
sizeof(
float), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
628 helios_runtime_error(
"ERROR (VulkanComputeBackend::updateMaterials): specular_scale size mismatch. Expected " + std::to_string(primitive_count) +
" entries (Nprims), got " + std::to_string(materials.
specular_scale.size()));
631 if (specular_scale_buffer.buffer != VK_NULL_HANDLE) {
632 destroyBuffer(specular_scale_buffer);
634 specular_scale_buffer = createBuffer(materials.
specular_scale.size() *
sizeof(
float), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
642 if (materials.
is_glass.size() != expected_size) {
643 helios_runtime_error(
"ERROR (VulkanComputeBackend::updateMaterials): is_glass size mismatch. Expected " + std::to_string(expected_size) +
" entries (Nsources * Nprims * Nbands), got " +
644 std::to_string(materials.
is_glass.size()));
650 bool any_glass =
false;
657 constexpr size_t glass_max_bands = 32;
658 if (any_glass && materials.
num_bands > glass_max_bands) {
659 helios_runtime_error(
"ERROR (VulkanComputeBackend): translucent cover (glass) materials are in use with " + std::to_string(materials.
num_bands) +
" radiation bands, which exceeds the compile-time maximum of " +
660 std::to_string(glass_max_bands) +
" (GLASS_MAX_BANDS). Reduce the number of bands or increase the cap.");
662 std::vector<uint> is_glass_uint(materials.
is_glass.begin(), materials.
is_glass.end());
663 if (is_glass_buffer.buffer != VK_NULL_HANDLE) { destroyBuffer(is_glass_buffer); }
664 is_glass_buffer = createBuffer(is_glass_uint.size() *
sizeof(
uint), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
665 uploadBufferData(is_glass_buffer, is_glass_uint.data(), is_glass_uint.size() *
sizeof(
uint));
667 if (glass_n_buffer.buffer != VK_NULL_HANDLE) { destroyBuffer(glass_n_buffer); }
668 glass_n_buffer = createBuffer(materials.
glass_n.size() *
sizeof(
float), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
669 uploadBufferData(glass_n_buffer, materials.
glass_n.data(), materials.
glass_n.size() *
sizeof(
float));
671 if (glass_KL_buffer.buffer != VK_NULL_HANDLE) { destroyBuffer(glass_KL_buffer); }
672 glass_KL_buffer = createBuffer(materials.
glass_KL.size() *
sizeof(
float), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
673 uploadBufferData(glass_KL_buffer, materials.
glass_KL.data(), materials.
glass_KL.size() *
sizeof(
float));
676 descriptors_dirty =
true;
680 source_count = sources.size();
682 if (source_count == 0) {
687 std::vector<helios::vec3> positions;
688 std::vector<uint> types;
689 std::vector<helios::vec3> rotations;
690 std::vector<helios::vec2> widths;
692 positions.reserve(source_count);
693 types.reserve(source_count);
694 rotations.reserve(source_count);
695 widths.reserve(source_count);
697 for (
const auto &source: sources) {
698 positions.push_back(source.position);
699 types.push_back(source.type);
700 rotations.push_back(source.rotation);
701 widths.push_back(source.width);
705 if (source_positions_buffer.buffer != VK_NULL_HANDLE) {
706 destroyBuffer(source_positions_buffer);
708 source_positions_buffer = createBuffer(positions.size() *
sizeof(
helios::vec3), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
709 uploadBufferData(source_positions_buffer, positions.data(), positions.size() *
sizeof(
helios::vec3));
712 if (source_types_buffer.buffer != VK_NULL_HANDLE) {
713 destroyBuffer(source_types_buffer);
715 source_types_buffer = createBuffer(types.size() *
sizeof(
uint), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
716 uploadBufferData(source_types_buffer, types.data(), types.size() *
sizeof(
uint));
719 if (source_rotations_buffer.buffer != VK_NULL_HANDLE) {
720 destroyBuffer(source_rotations_buffer);
722 source_rotations_buffer = createBuffer(rotations.size() *
sizeof(
helios::vec3), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
723 uploadBufferData(source_rotations_buffer, rotations.data(), rotations.size() *
sizeof(
helios::vec3));
726 if (source_widths_buffer.buffer != VK_NULL_HANDLE) {
727 destroyBuffer(source_widths_buffer);
729 source_widths_buffer = createBuffer(widths.size() *
sizeof(
helios::vec2), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
730 uploadBufferData(source_widths_buffer, widths.data(), widths.size() *
sizeof(
helios::vec2));
733 void VulkanComputeBackend::updateDiffuseRadiation(
const std::vector<float> &flux,
const std::vector<float> &extinction,
const std::vector<helios::vec3> &peak_dir,
const std::vector<float> &dist_norm,
const std::vector<float> &sky_energy) {
741 float solar_disk_cos_angle,
const std::vector<float> &camera_diffuse_flux,
const std::vector<uint32_t> &band_emission_flag) {
743 cached_sun_direction = sun_direction;
744 cached_solar_disk_cos_angle = solar_disk_cos_angle;
747 if (!sky_radiance_params.empty()) {
748 size_t params_size = sky_radiance_params.size() *
sizeof(
helios::vec4);
749 if (sky_radiance_params_buffer.buffer == VK_NULL_HANDLE || sky_radiance_params_buffer.size != params_size) {
750 if (sky_radiance_params_buffer.buffer != VK_NULL_HANDLE) {
751 destroyBuffer(sky_radiance_params_buffer);
753 sky_radiance_params_buffer = createBuffer(params_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
754 descriptors_dirty =
true;
756 uploadBufferData(sky_radiance_params_buffer, sky_radiance_params.data(), params_size);
760 if (!camera_sky_radiance.empty()) {
761 size_t sky_size = camera_sky_radiance.size() *
sizeof(float);
762 if (camera_sky_radiance_buffer.buffer == VK_NULL_HANDLE || camera_sky_radiance_buffer.size != sky_size) {
763 if (camera_sky_radiance_buffer.buffer != VK_NULL_HANDLE) {
764 destroyBuffer(camera_sky_radiance_buffer);
766 camera_sky_radiance_buffer = createBuffer(sky_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
767 descriptors_dirty =
true;
769 uploadBufferData(camera_sky_radiance_buffer, camera_sky_radiance.data(), sky_size);
773 if (!solar_disk_radiance.empty()) {
774 size_t solar_size = solar_disk_radiance.size() *
sizeof(float);
775 if (solar_disk_radiance_buffer.buffer == VK_NULL_HANDLE || solar_disk_radiance_buffer.size != solar_size) {
776 if (solar_disk_radiance_buffer.buffer != VK_NULL_HANDLE) {
777 destroyBuffer(solar_disk_radiance_buffer);
779 solar_disk_radiance_buffer = createBuffer(solar_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
780 descriptors_dirty =
true;
782 uploadBufferData(solar_disk_radiance_buffer, solar_disk_radiance.data(), solar_size);
786 if (!camera_diffuse_flux.empty()) {
787 size_t flux_size = camera_diffuse_flux.size() *
sizeof(float);
788 if (camera_diffuse_flux_buffer.buffer == VK_NULL_HANDLE || camera_diffuse_flux_buffer.size != flux_size) {
789 if (camera_diffuse_flux_buffer.buffer != VK_NULL_HANDLE) {
790 destroyBuffer(camera_diffuse_flux_buffer);
792 camera_diffuse_flux_buffer = createBuffer(flux_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
793 descriptors_dirty =
true;
795 uploadBufferData(camera_diffuse_flux_buffer, camera_diffuse_flux.data(), flux_size);
799 if (!band_emission_flag.empty()) {
800 size_t flag_size = band_emission_flag.size() *
sizeof(uint32_t);
801 if (band_emission_flag_buffer.buffer == VK_NULL_HANDLE || band_emission_flag_buffer.size != flag_size) {
802 if (band_emission_flag_buffer.buffer != VK_NULL_HANDLE) {
803 destroyBuffer(band_emission_flag_buffer);
805 band_emission_flag_buffer = createBuffer(flag_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
806 descriptors_dirty =
true;
808 uploadBufferData(band_emission_flag_buffer, band_emission_flag.data(), flag_size);
813 if (primitive_count == 0 || source_count == 0) {
818 launch_to_global_band.clear();
819 for (uint32_t g = 0; g < band_count; g++) {
821 launch_to_global_band.push_back(g);
824 if (launch_to_global_band.empty()) {
825 for (uint32_t g = 0; g < launch_band_count; g++) {
826 launch_to_global_band.push_back(g);
831 uploadBufferData(band_map_buffer, launch_to_global_band.data(), launch_to_global_band.size() *
sizeof(uint32_t));
834 size_t buf_size = primitive_count * launch_band_count *
sizeof(float);
835 VkBufferUsageFlags scatter_usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
837 if (scatter_top_buffer.buffer == VK_NULL_HANDLE || scatter_top_buffer.size != buf_size) {
838 if (scatter_top_buffer.buffer != VK_NULL_HANDLE) {
839 destroyBuffer(scatter_top_buffer);
841 scatter_top_buffer = createBuffer(buf_size, scatter_usage, VMA_MEMORY_USAGE_AUTO_PREFER_HOST);
842 descriptors_dirty =
true;
844 if (scatter_bottom_buffer.buffer == VK_NULL_HANDLE || scatter_bottom_buffer.size != buf_size) {
845 if (scatter_bottom_buffer.buffer != VK_NULL_HANDLE) {
846 destroyBuffer(scatter_bottom_buffer);
848 scatter_bottom_buffer = createBuffer(buf_size, scatter_usage, VMA_MEMORY_USAGE_AUTO_PREFER_HOST);
849 descriptors_dirty =
true;
853 VkBufferUsageFlags rad_out_usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
854 if (radiation_out_top_buffer.buffer == VK_NULL_HANDLE || radiation_out_top_buffer.size != buf_size) {
855 if (radiation_out_top_buffer.buffer != VK_NULL_HANDLE) {
856 destroyBuffer(radiation_out_top_buffer);
858 radiation_out_top_buffer = createBuffer(buf_size, rad_out_usage, VMA_MEMORY_USAGE_AUTO_PREFER_HOST);
859 zeroBuffer(radiation_out_top_buffer);
860 descriptors_dirty =
true;
862 if (radiation_out_bottom_buffer.buffer == VK_NULL_HANDLE || radiation_out_bottom_buffer.size != buf_size) {
863 if (radiation_out_bottom_buffer.buffer != VK_NULL_HANDLE) {
864 destroyBuffer(radiation_out_bottom_buffer);
866 radiation_out_bottom_buffer = createBuffer(buf_size, rad_out_usage, VMA_MEMORY_USAGE_AUTO_PREFER_HOST);
867 zeroBuffer(radiation_out_bottom_buffer);
868 descriptors_dirty =
true;
872 zeroBuffer(scatter_top_buffer);
873 zeroBuffer(scatter_bottom_buffer);
876 if (descriptors_dirty) {
877 updateDescriptorSets();
878 descriptors_dirty =
false;
880 VkDevice vk_device = device->
getDevice();
883 VkCommandBufferBeginInfo begin_info{};
884 begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
885 begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
886 vkBeginCommandBuffer(compute_command_buffer, &begin_info);
889 vkCmdBindPipeline(compute_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_direct);
892 VkDescriptorSet sets[] = {set_geometry, set_materials, set_results};
893 vkCmdBindDescriptorSets(compute_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout, 0, 3, sets, 0,
nullptr);
896 struct PushConstants {
899 uint rays_per_primitive;
904 uint primitive_count;
910 uint material_band_count;
911 uint periodic_flag_x;
912 uint periodic_flag_y;
918 uint specular_reflection_enabled;
922 uint32_t launch_dim_x =
static_cast<uint32_t
>(std::ceil(std::sqrt(
static_cast<double>(params.rays_per_primitive))));
923 uint32_t launch_dim_y = launch_dim_x;
927 push_constants.rays_per_primitive = params.rays_per_primitive;
928 push_constants.random_seed = params.random_seed;
929 push_constants.current_band = params.current_band;
930 push_constants.band_count = launch_band_count;
931 push_constants.source_count = source_count;
932 push_constants.primitive_count = primitive_count;
933 push_constants.launch_dim_x = launch_dim_x;
934 push_constants.launch_dim_y = launch_dim_y;
935 push_constants.material_band_count = band_count;
939 push_constants.debug_mode = 1;
941 push_constants.debug_mode = 0;
945 push_constants.periodic_flag_x =
static_cast<uint32_t
>(periodic_flag_x);
946 push_constants.periodic_flag_y =
static_cast<uint32_t
>(periodic_flag_y);
947 push_constants.bbox_count = bbox_count;
948 push_constants.domain_xmin = domain_bounds[0];
949 push_constants.domain_xmax = domain_bounds[1];
950 push_constants.domain_ymin = domain_bounds[2];
951 push_constants.domain_ymax = domain_bounds[3];
952 push_constants.specular_reflection_enabled = params.specular_reflection_enabled;
956 const uint32_t WG_X = 8;
957 const uint32_t WG_Y = 32;
958 const uint32_t MAX_PRIMS_PER_TILE = 65535;
960 uint32_t dispatch_x = (launch_dim_x + WG_X - 1) / WG_X;
961 uint32_t dispatch_y_rays = (launch_dim_y + WG_Y - 1) / WG_Y;
964 uint32_t prims_per_tile = std::min(params.
launch_count, MAX_PRIMS_PER_TILE);
965 uint32_t prim_tiles_y = (params.
launch_count + MAX_PRIMS_PER_TILE - 1) / MAX_PRIMS_PER_TILE;
967 uint32_t dispatch_y = dispatch_y_rays * prim_tiles_y;
968 uint32_t dispatch_z = prims_per_tile;
970 push_constants.prim_tiles_y = prim_tiles_y;
971 push_constants.prims_per_tile = prims_per_tile;
973 vkCmdPushConstants(compute_command_buffer, pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, 0,
sizeof(PushConstants), &push_constants);
974 vkCmdDispatch(compute_command_buffer, dispatch_x, dispatch_y, dispatch_z);
978 VkBufferMemoryBarrier buffer_barriers[3];
981 buffer_barriers[0].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
982 buffer_barriers[0].pNext =
nullptr;
983 buffer_barriers[0].srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
984 buffer_barriers[0].dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT;
985 buffer_barriers[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
986 buffer_barriers[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
987 buffer_barriers[0].buffer = radiation_in_buffer.buffer;
988 buffer_barriers[0].offset = 0;
989 buffer_barriers[0].size = VK_WHOLE_SIZE;
992 buffer_barriers[1].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
993 buffer_barriers[1].pNext =
nullptr;
994 buffer_barriers[1].srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
995 buffer_barriers[1].dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT;
996 buffer_barriers[1].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
997 buffer_barriers[1].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
998 buffer_barriers[1].buffer = scatter_top_buffer.buffer;
999 buffer_barriers[1].offset = 0;
1000 buffer_barriers[1].size = VK_WHOLE_SIZE;
1003 buffer_barriers[2].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
1004 buffer_barriers[2].pNext =
nullptr;
1005 buffer_barriers[2].srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
1006 buffer_barriers[2].dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT;
1007 buffer_barriers[2].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1008 buffer_barriers[2].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1009 buffer_barriers[2].buffer = scatter_bottom_buffer.buffer;
1010 buffer_barriers[2].offset = 0;
1011 buffer_barriers[2].size = VK_WHOLE_SIZE;
1013 vkCmdPipelineBarrier(compute_command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0,
nullptr,
1017 vkEndCommandBuffer(compute_command_buffer);
1020 VkSubmitInfo submit_info{};
1021 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
1022 submit_info.commandBufferCount = 1;
1023 submit_info.pCommandBuffers = &compute_command_buffer;
1025 vkResetFences(vk_device, 1, &compute_fence);
1026 VkResult result = vkQueueSubmit(device->
getComputeQueue(), 1, &submit_info, compute_fence);
1027 if (result != VK_SUCCESS) {
1028 helios_runtime_error(
"ERROR (VulkanComputeBackend::launchDirectRays): vkQueueSubmit failed. VkResult: " + std::to_string(result));
1032 VkResult wait_result;
1034 wait_result = vkWaitForFences(vk_device, 1, &compute_fence, VK_TRUE, 1000000000ULL);
1035 if (wait_result != VK_SUCCESS && wait_result != VK_TIMEOUT) {
1036 helios_runtime_error(
"ERROR (VulkanComputeBackend::launchDirectRays): vkWaitForFences failed. VkResult: " + std::to_string(wait_result));
1038 }
while (wait_result == VK_TIMEOUT);
1042 if (primitive_count == 0) {
1047 size_t rad_out_size = primitive_count * launch_band_count *
sizeof(float);
1048 if (radiation_out_top_buffer.buffer == VK_NULL_HANDLE || radiation_out_top_buffer.size != rad_out_size) {
1049 if (radiation_out_top_buffer.buffer != VK_NULL_HANDLE) {
1050 destroyBuffer(radiation_out_top_buffer);
1052 VkBufferUsageFlags usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
1053 radiation_out_top_buffer = createBuffer(rad_out_size, usage, VMA_MEMORY_USAGE_AUTO_PREFER_HOST);
1054 zeroBuffer(radiation_out_top_buffer);
1055 descriptors_dirty =
true;
1058 if (radiation_out_bottom_buffer.buffer == VK_NULL_HANDLE || radiation_out_bottom_buffer.size != rad_out_size) {
1059 if (radiation_out_bottom_buffer.buffer != VK_NULL_HANDLE) {
1060 destroyBuffer(radiation_out_bottom_buffer);
1062 VkBufferUsageFlags usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
1063 radiation_out_bottom_buffer = createBuffer(rad_out_size, usage, VMA_MEMORY_USAGE_AUTO_PREFER_HOST);
1064 zeroBuffer(radiation_out_bottom_buffer);
1065 descriptors_dirty =
true;
1069 if (scatter_top_buffer.buffer == VK_NULL_HANDLE || scatter_top_buffer.size != rad_out_size) {
1070 if (scatter_top_buffer.buffer != VK_NULL_HANDLE) {
1071 destroyBuffer(scatter_top_buffer);
1073 VkBufferUsageFlags usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
1074 scatter_top_buffer = createBuffer(rad_out_size, usage, VMA_MEMORY_USAGE_AUTO_PREFER_HOST);
1075 zeroBuffer(scatter_top_buffer);
1076 descriptors_dirty =
true;
1078 if (scatter_bottom_buffer.buffer == VK_NULL_HANDLE || scatter_bottom_buffer.size != rad_out_size) {
1079 if (scatter_bottom_buffer.buffer != VK_NULL_HANDLE) {
1080 destroyBuffer(scatter_bottom_buffer);
1082 VkBufferUsageFlags usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
1083 scatter_bottom_buffer = createBuffer(rad_out_size, usage, VMA_MEMORY_USAGE_AUTO_PREFER_HOST);
1084 zeroBuffer(scatter_bottom_buffer);
1085 descriptors_dirty =
true;
1096 size_t flux_size = params.
diffuse_flux.size() *
sizeof(float);
1097 if (diffuse_flux_buffer.buffer == VK_NULL_HANDLE || diffuse_flux_buffer.size != flux_size) {
1098 if (diffuse_flux_buffer.buffer != VK_NULL_HANDLE) {
1099 destroyBuffer(diffuse_flux_buffer);
1101 diffuse_flux_buffer = createBuffer(flux_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
1102 descriptors_dirty =
true;
1104 uploadBufferData(diffuse_flux_buffer, params.
diffuse_flux.data(), flux_size);
1110 if (diffuse_peak_dir_buffer.buffer == VK_NULL_HANDLE || diffuse_peak_dir_buffer.size != peak_dir_size) {
1111 if (diffuse_peak_dir_buffer.buffer != VK_NULL_HANDLE) {
1112 destroyBuffer(diffuse_peak_dir_buffer);
1114 diffuse_peak_dir_buffer = createBuffer(peak_dir_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
1115 descriptors_dirty =
true;
1117 uploadBufferData(diffuse_peak_dir_buffer, params.
diffuse_peak_dir.data(), peak_dir_size);
1123 if (diffuse_extinction_buffer.buffer == VK_NULL_HANDLE || diffuse_extinction_buffer.size != extinction_size) {
1124 if (diffuse_extinction_buffer.buffer != VK_NULL_HANDLE) {
1125 destroyBuffer(diffuse_extinction_buffer);
1127 diffuse_extinction_buffer = createBuffer(extinction_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
1128 descriptors_dirty =
true;
1130 uploadBufferData(diffuse_extinction_buffer, params.
diffuse_extinction.data(), extinction_size);
1136 if (diffuse_dist_norm_buffer.buffer == VK_NULL_HANDLE || diffuse_dist_norm_buffer.size != dist_norm_size) {
1137 if (diffuse_dist_norm_buffer.buffer != VK_NULL_HANDLE) {
1138 destroyBuffer(diffuse_dist_norm_buffer);
1140 diffuse_dist_norm_buffer = createBuffer(dist_norm_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
1141 descriptors_dirty =
true;
1143 uploadBufferData(diffuse_dist_norm_buffer, params.
diffuse_dist_norm.data(), dist_norm_size);
1148 if (diffuse_flux_buffer.buffer == VK_NULL_HANDLE) {
1149 size_t flux_size = band_count *
sizeof(float);
1150 diffuse_flux_buffer = createBuffer(flux_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_HOST);
1151 zeroBuffer(diffuse_flux_buffer);
1152 descriptors_dirty =
true;
1155 if (diffuse_peak_dir_buffer.buffer == VK_NULL_HANDLE) {
1156 size_t peak_dir_size = band_count *
sizeof(
helios::vec3);
1157 diffuse_peak_dir_buffer = createBuffer(peak_dir_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_HOST);
1158 zeroBuffer(diffuse_peak_dir_buffer);
1159 descriptors_dirty =
true;
1162 if (diffuse_extinction_buffer.buffer == VK_NULL_HANDLE) {
1163 size_t extinction_size = band_count *
sizeof(float);
1164 diffuse_extinction_buffer = createBuffer(extinction_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_HOST);
1165 zeroBuffer(diffuse_extinction_buffer);
1166 descriptors_dirty =
true;
1169 if (diffuse_dist_norm_buffer.buffer == VK_NULL_HANDLE) {
1170 size_t dist_norm_size = band_count *
sizeof(float);
1171 diffuse_dist_norm_buffer = createBuffer(dist_norm_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_HOST);
1172 zeroBuffer(diffuse_dist_norm_buffer);
1173 descriptors_dirty =
true;
1178 size_t sky_params_size = launch_band_count *
sizeof(
helios::vec4);
1179 if (sky_radiance_params_buffer.buffer != VK_NULL_HANDLE) {
1180 destroyBuffer(sky_radiance_params_buffer);
1182 sky_radiance_params_buffer = createBuffer(sky_params_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
1183 descriptors_dirty =
true;
1185 uploadBufferData(sky_radiance_params_buffer, params.
sky_radiance_params.data(), sky_params_size);
1187 zeroBuffer(sky_radiance_params_buffer);
1193 if (debug_counters_buffer.buffer == VK_NULL_HANDLE) {
1194 debug_counters_buffer = createBuffer(5 *
sizeof(uint32_t), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_HOST);
1195 zeroBuffer(debug_counters_buffer);
1196 descriptors_dirty =
true;
1199 zeroBuffer(debug_counters_buffer);
1203 if (descriptors_dirty) {
1204 updateDescriptorSets();
1205 descriptors_dirty =
false;
1207 VkDevice vk_device = device->
getDevice();
1210 uint32_t launch_dim_x =
static_cast<uint32_t
>(std::ceil(std::sqrt(
static_cast<double>(params.rays_per_primitive))));
1211 uint32_t launch_dim_y = launch_dim_x;
1217 launch_to_global_band.clear();
1218 for (uint32_t g = 0; g < band_count; g++) {
1220 launch_to_global_band.push_back(g);
1223 if (launch_to_global_band.empty()) {
1225 for (uint32_t g = 0; g < launch_band_count; g++) {
1226 launch_to_global_band.push_back(g);
1231 uploadBufferData(band_map_buffer, launch_to_global_band.data(), launch_to_global_band.size() *
sizeof(uint32_t));
1234 struct PushConstants {
1235 uint32_t launch_offset;
1236 uint32_t launch_count;
1237 uint32_t rays_per_primitive;
1238 uint32_t random_seed;
1239 uint32_t band_count;
1240 uint32_t source_count;
1241 uint32_t primitive_count;
1242 uint32_t launch_face;
1243 uint32_t launch_dim_x;
1244 uint32_t launch_dim_y;
1245 uint32_t material_band_count;
1246 uint32_t periodic_flag_x;
1247 uint32_t periodic_flag_y;
1248 uint32_t bbox_count;
1253 uint32_t prim_tiles_y;
1254 uint32_t prims_per_tile;
1258 push_constants.rays_per_primitive = params.rays_per_primitive;
1259 push_constants.random_seed = params.random_seed;
1260 push_constants.band_count = launch_band_count;
1261 push_constants.material_band_count = band_count;
1262 push_constants.source_count = source_count;
1263 push_constants.primitive_count = primitive_count;
1264 push_constants.launch_face = launch_face;
1265 push_constants.launch_dim_x = launch_dim_x;
1266 push_constants.launch_dim_y = launch_dim_y;
1269 push_constants.periodic_flag_x =
static_cast<uint32_t
>(periodic_flag_x);
1270 push_constants.periodic_flag_y =
static_cast<uint32_t
>(periodic_flag_y);
1271 push_constants.bbox_count = bbox_count;
1272 push_constants.domain_xmin = domain_bounds[0];
1273 push_constants.domain_xmax = domain_bounds[1];
1274 push_constants.domain_ymin = domain_bounds[2];
1275 push_constants.domain_ymax = domain_bounds[3];
1279 const uint32_t WG_X = 8;
1280 const uint32_t WG_Y = 32;
1281 const uint32_t MAX_PRIMS_PER_TILE = 65535;
1283 uint32_t dispatch_x = (launch_dim_x + WG_X - 1) / WG_X;
1284 uint32_t dispatch_y_rays = (launch_dim_y + WG_Y - 1) / WG_Y;
1287 uint32_t prims_per_tile = std::min(params.
launch_count, MAX_PRIMS_PER_TILE);
1288 uint32_t prim_tiles_y = (params.
launch_count + MAX_PRIMS_PER_TILE - 1) / MAX_PRIMS_PER_TILE;
1290 uint32_t dispatch_y = dispatch_y_rays * prim_tiles_y;
1291 uint32_t dispatch_z = prims_per_tile;
1295 push_constants.prim_tiles_y = prim_tiles_y;
1296 push_constants.prims_per_tile = prims_per_tile;
1300 VkCommandBufferBeginInfo begin_info{};
1301 begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
1302 begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
1303 vkBeginCommandBuffer(compute_command_buffer, &begin_info);
1306 vkCmdResetQueryPool(compute_command_buffer, timestamp_query_pool, 0, 2);
1309 vkCmdBindPipeline(compute_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_diffuse);
1312 VkDescriptorSet sets[] = {set_geometry, set_materials, set_results, set_sky, set_debug};
1313 vkCmdBindDescriptorSets(compute_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout, 0, 5, sets, 0,
nullptr);
1316 vkCmdWriteTimestamp(compute_command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, timestamp_query_pool, 0);
1319 vkCmdPushConstants(compute_command_buffer, pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, 0,
sizeof(PushConstants), &push_constants);
1320 vkCmdDispatch(compute_command_buffer, dispatch_x, dispatch_y, dispatch_z);
1323 vkCmdWriteTimestamp(compute_command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, timestamp_query_pool, 1);
1326 VkBufferMemoryBarrier buffer_barriers[4];
1329 buffer_barriers[0].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
1330 buffer_barriers[0].pNext =
nullptr;
1331 buffer_barriers[0].srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
1332 buffer_barriers[0].dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT;
1333 buffer_barriers[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1334 buffer_barriers[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1335 buffer_barriers[0].buffer = radiation_in_buffer.buffer;
1336 buffer_barriers[0].offset = 0;
1337 buffer_barriers[0].size = VK_WHOLE_SIZE;
1340 buffer_barriers[1].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
1341 buffer_barriers[1].pNext =
nullptr;
1342 buffer_barriers[1].srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
1343 buffer_barriers[1].dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT;
1344 buffer_barriers[1].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1345 buffer_barriers[1].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1346 buffer_barriers[1].buffer = scatter_top_buffer.buffer;
1347 buffer_barriers[1].offset = 0;
1348 buffer_barriers[1].size = VK_WHOLE_SIZE;
1351 buffer_barriers[2].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
1352 buffer_barriers[2].pNext =
nullptr;
1353 buffer_barriers[2].srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
1354 buffer_barriers[2].dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT;
1355 buffer_barriers[2].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1356 buffer_barriers[2].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1357 buffer_barriers[2].buffer = scatter_bottom_buffer.buffer;
1358 buffer_barriers[2].offset = 0;
1359 buffer_barriers[2].size = VK_WHOLE_SIZE;
1362 buffer_barriers[3].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
1363 buffer_barriers[3].pNext =
nullptr;
1364 buffer_barriers[3].srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
1365 buffer_barriers[3].dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
1366 buffer_barriers[3].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1367 buffer_barriers[3].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1368 buffer_barriers[3].buffer = radiation_out_top_buffer.buffer;
1369 buffer_barriers[3].offset = 0;
1370 buffer_barriers[3].size = VK_WHOLE_SIZE;
1372 vkCmdPipelineBarrier(compute_command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0,
nullptr,
1376 vkEndCommandBuffer(compute_command_buffer);
1379 VkSubmitInfo submit_info{};
1380 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
1381 submit_info.commandBufferCount = 1;
1382 submit_info.pCommandBuffers = &compute_command_buffer;
1384 vkResetFences(vk_device, 1, &compute_fence);
1385 VkResult result = vkQueueSubmit(device->
getComputeQueue(), 1, &submit_info, compute_fence);
1386 if (result != VK_SUCCESS) {
1387 helios_runtime_error(
"ERROR (VulkanComputeBackend::launchDiffuseRays): vkQueueSubmit failed. VkResult: " + std::to_string(result));
1391 VkResult wait_result;
1393 wait_result = vkWaitForFences(vk_device, 1, &compute_fence, VK_TRUE, 1000000000ULL);
1394 if (wait_result != VK_SUCCESS && wait_result != VK_TIMEOUT) {
1395 helios_runtime_error(
"ERROR (VulkanComputeBackend::launchDiffuseRays): vkWaitForFences failed. VkResult: " + std::to_string(wait_result));
1397 }
while (wait_result == VK_TIMEOUT);
1402 if (primitive_count == 0) {
1407 launch_to_global_band.clear();
1408 for (uint32_t g = 0; g < band_count; g++) {
1410 launch_to_global_band.push_back(g);
1413 if (launch_to_global_band.empty()) {
1414 for (uint32_t g = 0; g < launch_band_count; g++) {
1415 launch_to_global_band.push_back(g);
1420 size_t total_pixels = size_t(params.camera_resolution_full.x) * size_t(params.camera_resolution_full.y);
1421 size_t radiation_size = total_pixels * launch_band_count *
sizeof(float);
1422 if (camera_radiation_buffer.buffer == VK_NULL_HANDLE || camera_radiation_buffer.size != radiation_size) {
1423 if (camera_radiation_buffer.buffer != VK_NULL_HANDLE) {
1424 destroyBuffer(camera_radiation_buffer);
1426 VkBufferUsageFlags usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
1427 camera_radiation_buffer = createBuffer(radiation_size, usage, VMA_MEMORY_USAGE_AUTO_PREFER_HOST);
1428 descriptors_dirty =
true;
1434 if (params.camera_pixel_offset.x == 0 && params.camera_pixel_offset.y == 0) {
1435 zeroBuffer(camera_radiation_buffer);
1439 if (descriptors_dirty) {
1440 updateDescriptorSets();
1441 descriptors_dirty =
false;
1444 VkDevice vk_device = device->
getDevice();
1447 VkCommandBufferBeginInfo begin_info{};
1448 begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
1449 begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
1450 vkBeginCommandBuffer(compute_command_buffer, &begin_info);
1453 vkCmdBindPipeline(compute_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_camera);
1456 VkDescriptorSet sets[] = {set_geometry, set_materials, set_results, set_sky, set_debug};
1457 vkCmdBindDescriptorSets(compute_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout, 0, 5, sets, 0,
nullptr);
1460 struct PushConstants {
1462 float viewplane_length;
1463 float camera_direction_x;
1464 float camera_direction_y;
1466 float lens_diameter;
1467 float fov_aspect_ratio;
1468 uint32_t resolution_x;
1469 uint32_t resolution_y;
1470 uint32_t resolution_full_x;
1471 uint32_t resolution_full_y;
1472 uint32_t pixel_offset_x;
1473 uint32_t pixel_offset_y;
1474 uint32_t antialiasing_samples;
1475 uint32_t random_seed;
1476 uint32_t band_count;
1477 uint32_t source_count;
1478 uint32_t primitive_count;
1480 float solar_disk_cos_angle;
1481 uint32_t periodic_flag_x;
1482 uint32_t periodic_flag_y;
1483 uint32_t bbox_count;
1488 uint32_t specular_reflection_enabled;
1491 push_constants.camera_position = params.camera_position;
1492 push_constants.viewplane_length = params.camera_viewplane_length;
1495 push_constants.focal_length = params.camera_focal_length;
1496 push_constants.lens_diameter = params.camera_lens_diameter;
1497 push_constants.fov_aspect_ratio = params.camera_fov_aspect;
1498 push_constants.resolution_x = params.camera_resolution.x;
1499 push_constants.resolution_y = params.camera_resolution.y;
1500 push_constants.resolution_full_x = params.camera_resolution_full.x;
1501 push_constants.resolution_full_y = params.camera_resolution_full.y;
1502 push_constants.pixel_offset_x = params.camera_pixel_offset.x;
1503 push_constants.pixel_offset_y = params.camera_pixel_offset.y;
1504 push_constants.antialiasing_samples = params.antialiasing_samples;
1505 push_constants.random_seed = params.random_seed;
1506 push_constants.band_count = launch_band_count;
1507 push_constants.source_count = source_count;
1508 push_constants.primitive_count = primitive_count;
1509 push_constants.sun_direction = cached_sun_direction;
1510 push_constants.solar_disk_cos_angle = cached_solar_disk_cos_angle;
1511 push_constants.periodic_flag_x =
static_cast<uint32_t
>(periodic_flag_x);
1512 push_constants.periodic_flag_y =
static_cast<uint32_t
>(periodic_flag_y);
1513 push_constants.bbox_count = bbox_count;
1514 push_constants.domain_xmin = domain_bounds[0];
1515 push_constants.domain_xmax = domain_bounds[1];
1516 push_constants.domain_ymin = domain_bounds[2];
1517 push_constants.domain_ymax = domain_bounds[3];
1518 push_constants.specular_reflection_enabled = params.specular_reflection_enabled;
1520 vkCmdPushConstants(compute_command_buffer, pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, 0,
sizeof(PushConstants), &push_constants);
1523 const uint32_t WG_X = 16;
1524 const uint32_t WG_Y = 16;
1525 uint32_t dispatch_x = (params.camera_resolution.x + WG_X - 1) / WG_X;
1526 uint32_t dispatch_y = (params.camera_resolution.y + WG_Y - 1) / WG_Y;
1527 uint32_t dispatch_z = params.antialiasing_samples;
1529 vkCmdDispatch(compute_command_buffer, dispatch_x, dispatch_y, dispatch_z);
1532 VkBufferMemoryBarrier barrier{};
1533 barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
1534 barrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
1535 barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT;
1536 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1537 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1538 barrier.buffer = camera_radiation_buffer.buffer;
1540 barrier.size = VK_WHOLE_SIZE;
1542 vkCmdPipelineBarrier(compute_command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0,
nullptr, 1, &barrier, 0,
nullptr);
1544 vkEndCommandBuffer(compute_command_buffer);
1547 VkSubmitInfo submit_info{};
1548 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
1549 submit_info.commandBufferCount = 1;
1550 submit_info.pCommandBuffers = &compute_command_buffer;
1552 vkResetFences(vk_device, 1, &compute_fence);
1553 VkResult result = vkQueueSubmit(device->
getComputeQueue(), 1, &submit_info, compute_fence);
1554 if (result != VK_SUCCESS) {
1555 helios_runtime_error(
"ERROR (VulkanComputeBackend::launchCameraRays): vkQueueSubmit failed. VkResult: " + std::to_string(result));
1559 VkResult wait_result;
1561 wait_result = vkWaitForFences(vk_device, 1, &compute_fence, VK_TRUE, 1000000000ULL);
1562 if (wait_result != VK_SUCCESS && wait_result != VK_TIMEOUT) {
1563 helios_runtime_error(
"ERROR (VulkanComputeBackend::launchCameraRays): vkWaitForFences failed. VkResult: " + std::to_string(wait_result));
1565 }
while (wait_result == VK_TIMEOUT);
1569 if (primitive_count == 0) {
1574 if (descriptors_dirty) {
1575 updateDescriptorSets();
1576 descriptors_dirty =
false;
1579 VkDevice vk_device = device->
getDevice();
1582 VkCommandBufferBeginInfo begin_info{};
1583 begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
1584 begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
1585 vkBeginCommandBuffer(compute_command_buffer, &begin_info);
1588 vkCmdBindPipeline(compute_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_pixel_label);
1591 VkDescriptorSet sets[] = {set_geometry, set_materials, set_results, set_sky, set_debug};
1592 vkCmdBindDescriptorSets(compute_command_buffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline_layout, 0, 5, sets, 0,
nullptr);
1595 struct PushConstants {
1597 float viewplane_length;
1598 float camera_direction_x;
1599 float camera_direction_y;
1601 float lens_diameter;
1602 float fov_aspect_ratio;
1603 uint32_t resolution_x;
1604 uint32_t resolution_y;
1605 uint32_t resolution_full_x;
1606 uint32_t resolution_full_y;
1607 uint32_t pixel_offset_x;
1608 uint32_t pixel_offset_y;
1609 uint32_t antialiasing_samples;
1610 uint32_t random_seed;
1611 uint32_t band_count;
1612 uint32_t source_count;
1613 uint32_t primitive_count;
1615 float solar_disk_cos_angle;
1616 uint32_t periodic_flag_x;
1617 uint32_t periodic_flag_y;
1618 uint32_t bbox_count;
1626 push_constants.camera_position = params.camera_position;
1627 push_constants.viewplane_length = params.camera_viewplane_length;
1630 push_constants.focal_length = params.camera_focal_length;
1631 push_constants.lens_diameter = params.camera_lens_diameter;
1632 push_constants.fov_aspect_ratio = params.camera_fov_aspect;
1633 push_constants.resolution_x = params.camera_resolution.x;
1634 push_constants.resolution_y = params.camera_resolution.y;
1635 push_constants.resolution_full_x = params.camera_resolution_full.x;
1636 push_constants.resolution_full_y = params.camera_resolution_full.y;
1637 push_constants.pixel_offset_x = params.camera_pixel_offset.x;
1638 push_constants.pixel_offset_y = params.camera_pixel_offset.y;
1639 push_constants.antialiasing_samples = 1;
1640 push_constants.random_seed = params.random_seed;
1641 push_constants.band_count = launch_band_count;
1642 push_constants.source_count = source_count;
1643 push_constants.primitive_count = primitive_count;
1644 push_constants.sun_direction = cached_sun_direction;
1645 push_constants.solar_disk_cos_angle = cached_solar_disk_cos_angle;
1646 push_constants.periodic_flag_x =
static_cast<uint32_t
>(periodic_flag_x);
1647 push_constants.periodic_flag_y =
static_cast<uint32_t
>(periodic_flag_y);
1648 push_constants.bbox_count = bbox_count;
1649 push_constants.domain_xmin = domain_bounds[0];
1650 push_constants.domain_xmax = domain_bounds[1];
1651 push_constants.domain_ymin = domain_bounds[2];
1652 push_constants.domain_ymax = domain_bounds[3];
1653 push_constants.padding = 0;
1655 vkCmdPushConstants(compute_command_buffer, pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, 0,
sizeof(PushConstants), &push_constants);
1658 const uint32_t WG_X = 16;
1659 const uint32_t WG_Y = 16;
1660 uint32_t dispatch_x = (params.camera_resolution.x + WG_X - 1) / WG_X;
1661 uint32_t dispatch_y = (params.camera_resolution.y + WG_Y - 1) / WG_Y;
1662 uint32_t dispatch_z = 1;
1664 vkCmdDispatch(compute_command_buffer, dispatch_x, dispatch_y, dispatch_z);
1667 VkBufferMemoryBarrier barriers[2];
1669 barriers[0].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
1670 barriers[0].pNext =
nullptr;
1671 barriers[0].srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
1672 barriers[0].dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT;
1673 barriers[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1674 barriers[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1675 barriers[0].buffer = camera_pixel_label_buffer.buffer;
1676 barriers[0].offset = 0;
1677 barriers[0].size = VK_WHOLE_SIZE;
1679 barriers[1].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
1680 barriers[1].pNext =
nullptr;
1681 barriers[1].srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
1682 barriers[1].dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT;
1683 barriers[1].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1684 barriers[1].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1685 barriers[1].buffer = camera_pixel_depth_buffer.buffer;
1686 barriers[1].offset = 0;
1687 barriers[1].size = VK_WHOLE_SIZE;
1689 vkCmdPipelineBarrier(compute_command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0,
nullptr, 2, barriers, 0,
nullptr);
1691 vkEndCommandBuffer(compute_command_buffer);
1694 VkSubmitInfo submit_info{};
1695 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
1696 submit_info.commandBufferCount = 1;
1697 submit_info.pCommandBuffers = &compute_command_buffer;
1699 vkResetFences(vk_device, 1, &compute_fence);
1700 VkResult result = vkQueueSubmit(device->
getComputeQueue(), 1, &submit_info, compute_fence);
1701 if (result != VK_SUCCESS) {
1702 helios_runtime_error(
"ERROR (VulkanComputeBackend::launchPixelLabelRays): vkQueueSubmit failed. VkResult: " + std::to_string(result));
1706 VkResult wait_result;
1708 wait_result = vkWaitForFences(vk_device, 1, &compute_fence, VK_TRUE, 1000000000ULL);
1709 if (wait_result != VK_SUCCESS && wait_result != VK_TIMEOUT) {
1710 helios_runtime_error(
"ERROR (VulkanComputeBackend::launchPixelLabelRays): vkWaitForFences failed. VkResult: " + std::to_string(wait_result));
1712 }
while (wait_result == VK_TIMEOUT);
1716 if (primitive_count == 0 || launch_band_count == 0) {
1720 size_t buffer_size = primitive_count * launch_band_count;
1730 if (radiation_in_buffer.buffer != VK_NULL_HANDLE) {
1736 VkResult result = vmaMapMemory(device->
getAllocator(), radiation_in_buffer.allocation, &mapped);
1737 if (result == VK_SUCCESS) {
1740 vmaInvalidateAllocation(device->
getAllocator(), radiation_in_buffer.allocation, 0, VK_WHOLE_SIZE);
1742 std::memcpy(results.
radiation_in.data(), mapped, buffer_size *
sizeof(
float));
1743 vmaUnmapMemory(device->
getAllocator(), radiation_in_buffer.allocation);
1747 std::string error_msg =
"ERROR (VulkanComputeBackend): Compute shader reported error. Code: " + std::to_string(results.
radiation_in[0]);
1749 error_msg +=
" (Invalid subdivisions: NX=" + std::to_string(results.
radiation_in[1]) +
" NY=" + std::to_string(results.
radiation_in[2]) +
")";
1751 error_msg +=
" (Subdivisions too large: NX=" + std::to_string(results.
radiation_in[1]) +
" NY=" + std::to_string(results.
radiation_in[2]) +
")";
1753 error_msg +=
" (Zero rays per dimension)";
1755 error_msg +=
" (Too many rays per dimension: " + std::to_string(results.
radiation_in[1]) +
")";
1761 downloadBufferData(radiation_in_buffer, results.
radiation_in.data(), buffer_size *
sizeof(
float));
1768 if (radiation_out_top_buffer.buffer != VK_NULL_HANDLE) {
1770 VkResult result = vmaMapMemory(device->
getAllocator(), radiation_out_top_buffer.allocation, &mapped);
1771 if (result == VK_SUCCESS) {
1772 vmaInvalidateAllocation(device->
getAllocator(), radiation_out_top_buffer.allocation, 0, VK_WHOLE_SIZE);
1773 std::memcpy(results.
radiation_out_top.data(), mapped, buffer_size *
sizeof(
float));
1774 vmaUnmapMemory(device->
getAllocator(), radiation_out_top_buffer.allocation);
1781 if (radiation_out_bottom_buffer.buffer != VK_NULL_HANDLE) {
1783 VkResult result = vmaMapMemory(device->
getAllocator(), radiation_out_bottom_buffer.allocation, &mapped);
1784 if (result == VK_SUCCESS) {
1785 vmaInvalidateAllocation(device->
getAllocator(), radiation_out_bottom_buffer.allocation, 0, VK_WHOLE_SIZE);
1787 vmaUnmapMemory(device->
getAllocator(), radiation_out_bottom_buffer.allocation);
1795 if (scatter_top_buffer.buffer != VK_NULL_HANDLE) {
1797 VkResult result = vmaMapMemory(device->
getAllocator(), scatter_top_buffer.allocation, &mapped);
1798 if (result == VK_SUCCESS) {
1799 vmaInvalidateAllocation(device->
getAllocator(), scatter_top_buffer.allocation, 0, VK_WHOLE_SIZE);
1800 std::memcpy(results.
scatter_buff_top.data(), mapped, buffer_size *
sizeof(
float));
1801 vmaUnmapMemory(device->
getAllocator(), scatter_top_buffer.allocation);
1809 if (scatter_bottom_buffer.buffer != VK_NULL_HANDLE) {
1811 VkResult result = vmaMapMemory(device->
getAllocator(), scatter_bottom_buffer.allocation, &mapped);
1812 if (result == VK_SUCCESS) {
1813 vmaInvalidateAllocation(device->
getAllocator(), scatter_bottom_buffer.allocation, 0, VK_WHOLE_SIZE);
1815 vmaUnmapMemory(device->
getAllocator(), scatter_bottom_buffer.allocation);
1830 size_t total_pixels = size_t(resolution.x) * size_t(resolution.y);
1831 if (total_pixels == 0) {
1844 pixel_data.resize(total_pixels * launch_band_count);
1845 const size_t radiation_bytes = pixel_data.size() *
sizeof(float);
1846 if (camera_radiation_buffer.buffer != VK_NULL_HANDLE && camera_radiation_buffer.size >= radiation_bytes && !pixel_data.empty()) {
1847 if (launch_band_count <= 1) {
1848 downloadBufferData(camera_radiation_buffer, pixel_data.data(), radiation_bytes);
1850 std::vector<float> band_major(total_pixels * launch_band_count);
1851 downloadBufferData(camera_radiation_buffer, band_major.data(), band_major.size() *
sizeof(
float));
1852 for (uint32_t b = 0; b < launch_band_count; b++) {
1853 const float *src = band_major.data() + size_t(b) * total_pixels;
1854 for (
size_t p = 0; p < total_pixels; p++) {
1855 pixel_data[p * launch_band_count + b] = src[p];
1860 std::fill(pixel_data.begin(), pixel_data.end(), 0.0f);
1869 pixel_labels.resize(total_pixels);
1870 if (camera_pixel_label_buffer.buffer != VK_NULL_HANDLE && camera_pixel_label_buffer.size >= total_pixels *
sizeof(
uint) && !pixel_labels.empty()) {
1871 downloadBufferData(camera_pixel_label_buffer, pixel_labels.data(), pixel_labels.size() *
sizeof(
uint));
1873 std::fill(pixel_labels.begin(), pixel_labels.end(), 0u);
1877 pixel_depths.resize(total_pixels);
1878 if (camera_pixel_depth_buffer.buffer != VK_NULL_HANDLE && camera_pixel_depth_buffer.size >= total_pixels *
sizeof(
float) && !pixel_depths.empty()) {
1879 downloadBufferData(camera_pixel_depth_buffer, pixel_depths.data(), pixel_depths.size() *
sizeof(
float));
1881 std::fill(pixel_depths.begin(), pixel_depths.end(), 0.0f);
1891 launch_band_count =
static_cast<uint32_t
>(launch_band_count_param);
1893 if (primitive_count == 0 || band_count == 0) {
1898 size_t band_map_size = launch_band_count *
sizeof(uint32_t);
1899 if (band_map_buffer.buffer == VK_NULL_HANDLE || band_map_buffer.size != band_map_size) {
1900 if (band_map_buffer.buffer != VK_NULL_HANDLE) {
1901 destroyBuffer(band_map_buffer);
1903 band_map_buffer = createBuffer(band_map_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
1904 descriptors_dirty =
true;
1907 size_t buffer_size = primitive_count * launch_band_count;
1912 if (radiation_in_buffer.buffer == VK_NULL_HANDLE || radiation_in_buffer.size != buffer_size *
sizeof(
float)) {
1913 if (radiation_in_buffer.buffer != VK_NULL_HANDLE) {
1914 destroyBuffer(radiation_in_buffer);
1916 VkBufferUsageFlags usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
1917 radiation_in_buffer = createBuffer(buffer_size *
sizeof(
float), usage, VMA_MEMORY_USAGE_AUTO_PREFER_HOST);
1922 if (source_count > 0) {
1923 size_t specular_buffer_size = source_count * primitive_count * launch_band_count;
1924 if (radiation_specular_buffer.buffer == VK_NULL_HANDLE || radiation_specular_buffer.size != specular_buffer_size *
sizeof(
float)) {
1925 if (radiation_specular_buffer.buffer != VK_NULL_HANDLE) {
1926 destroyBuffer(radiation_specular_buffer);
1928 VkBufferUsageFlags usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
1929 radiation_specular_buffer = createBuffer(specular_buffer_size *
sizeof(
float), usage, VMA_MEMORY_USAGE_AUTO_PREFER_HOST);
1931 zeroBuffer(radiation_specular_buffer);
1935 zeroBuffer(radiation_in_buffer);
1937 descriptors_dirty =
true;
1941 if (primitive_count == 0 || launch_band_count == 0) {
1945 size_t buffer_size = primitive_count * launch_band_count;
1948 if (scatter_top_buffer.buffer == VK_NULL_HANDLE || scatter_top_buffer.size != buffer_size *
sizeof(
float)) {
1949 if (scatter_top_buffer.buffer != VK_NULL_HANDLE) {
1950 destroyBuffer(scatter_top_buffer);
1952 VkBufferUsageFlags usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
1953 scatter_top_buffer = createBuffer(buffer_size *
sizeof(
float), usage, VMA_MEMORY_USAGE_AUTO_PREFER_HOST);
1957 if (scatter_bottom_buffer.buffer == VK_NULL_HANDLE || scatter_bottom_buffer.size != buffer_size *
sizeof(
float)) {
1958 if (scatter_bottom_buffer.buffer != VK_NULL_HANDLE) {
1959 destroyBuffer(scatter_bottom_buffer);
1961 VkBufferUsageFlags usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
1962 scatter_bottom_buffer = createBuffer(buffer_size *
sizeof(
float), usage, VMA_MEMORY_USAGE_AUTO_PREFER_HOST);
1966 zeroBuffer(scatter_top_buffer);
1967 zeroBuffer(scatter_bottom_buffer);
1969 descriptors_dirty =
true;
1973 size_t total_pixels = size_t(resolution.x) * size_t(resolution.y);
1974 if (total_pixels == 0) {
1979 VkDeviceSize label_size = total_pixels *
sizeof(uint32_t);
1980 if (camera_pixel_label_buffer.buffer == VK_NULL_HANDLE || camera_pixel_label_buffer.size != label_size) {
1981 if (camera_pixel_label_buffer.buffer != VK_NULL_HANDLE) {
1982 destroyBuffer(camera_pixel_label_buffer);
1984 VkBufferUsageFlags usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
1985 camera_pixel_label_buffer = createBuffer(label_size, usage, VMA_MEMORY_USAGE_AUTO_PREFER_HOST);
1986 descriptors_dirty =
true;
1990 VkDeviceSize depth_size = total_pixels *
sizeof(float);
1991 if (camera_pixel_depth_buffer.buffer == VK_NULL_HANDLE || camera_pixel_depth_buffer.size != depth_size) {
1992 if (camera_pixel_depth_buffer.buffer != VK_NULL_HANDLE) {
1993 destroyBuffer(camera_pixel_depth_buffer);
1995 VkBufferUsageFlags usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
1996 camera_pixel_depth_buffer = createBuffer(depth_size, usage, VMA_MEMORY_USAGE_AUTO_PREFER_HOST);
1997 descriptors_dirty =
true;
2001 zeroBuffer(camera_pixel_label_buffer);
2002 zeroBuffer(camera_pixel_depth_buffer);
2006 if (primitive_count == 0 || launch_band_count == 0) {
2017 size_t buffer_size = primitive_count * launch_band_count *
sizeof(float);
2020 if (radiation_out_top_buffer.buffer == VK_NULL_HANDLE || radiation_out_top_buffer.size != buffer_size) {
2021 if (radiation_out_top_buffer.buffer != VK_NULL_HANDLE) {
2022 destroyBuffer(radiation_out_top_buffer);
2024 VkBufferUsageFlags usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
2025 radiation_out_top_buffer = createBuffer(buffer_size, usage, VMA_MEMORY_USAGE_AUTO_PREFER_HOST);
2026 descriptors_dirty =
true;
2029 if (radiation_out_bottom_buffer.buffer == VK_NULL_HANDLE || radiation_out_bottom_buffer.size != buffer_size) {
2030 if (radiation_out_bottom_buffer.buffer != VK_NULL_HANDLE) {
2031 destroyBuffer(radiation_out_bottom_buffer);
2033 VkBufferUsageFlags usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
2034 radiation_out_bottom_buffer = createBuffer(buffer_size, usage, VMA_MEMORY_USAGE_AUTO_PREFER_HOST);
2035 descriptors_dirty =
true;
2042 vmaInvalidateAllocation(device->
getAllocator(), scatter_top_buffer.allocation, 0, VK_WHOLE_SIZE);
2043 void *src_top =
nullptr;
2044 void *dst_top =
nullptr;
2045 vmaMapMemory(device->
getAllocator(), scatter_top_buffer.allocation, &src_top);
2046 vmaMapMemory(device->
getAllocator(), radiation_out_top_buffer.allocation, &dst_top);
2047 memcpy(dst_top, src_top, buffer_size);
2048 vmaFlushAllocation(device->
getAllocator(), radiation_out_top_buffer.allocation, 0, VK_WHOLE_SIZE);
2049 vmaUnmapMemory(device->
getAllocator(), scatter_top_buffer.allocation);
2050 vmaUnmapMemory(device->
getAllocator(), radiation_out_top_buffer.allocation);
2053 vmaInvalidateAllocation(device->
getAllocator(), scatter_bottom_buffer.allocation, 0, VK_WHOLE_SIZE);
2054 void *src_bottom =
nullptr;
2055 void *dst_bottom =
nullptr;
2056 vmaMapMemory(device->
getAllocator(), scatter_bottom_buffer.allocation, &src_bottom);
2057 vmaMapMemory(device->
getAllocator(), radiation_out_bottom_buffer.allocation, &dst_bottom);
2058 memcpy(dst_bottom, src_bottom, buffer_size);
2059 vmaFlushAllocation(device->
getAllocator(), radiation_out_bottom_buffer.allocation, 0, VK_WHOLE_SIZE);
2060 vmaUnmapMemory(device->
getAllocator(), scatter_bottom_buffer.allocation);
2061 vmaUnmapMemory(device->
getAllocator(), radiation_out_bottom_buffer.allocation);
2065 if (radiation_out_top.empty() || radiation_out_bottom.empty()) {
2069 size_t buffer_size = radiation_out_top.size() *
sizeof(float);
2072 if (radiation_out_top_buffer.buffer == VK_NULL_HANDLE || radiation_out_top_buffer.size != buffer_size) {
2073 if (radiation_out_top_buffer.buffer != VK_NULL_HANDLE) {
2074 destroyBuffer(radiation_out_top_buffer);
2076 VkBufferUsageFlags usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
2077 radiation_out_top_buffer = createBuffer(buffer_size, usage, VMA_MEMORY_USAGE_AUTO_PREFER_HOST);
2078 descriptors_dirty =
true;
2082 if (radiation_out_bottom_buffer.buffer == VK_NULL_HANDLE || radiation_out_bottom_buffer.size != buffer_size) {
2083 if (radiation_out_bottom_buffer.buffer != VK_NULL_HANDLE) {
2084 destroyBuffer(radiation_out_bottom_buffer);
2086 VkBufferUsageFlags usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
2087 radiation_out_bottom_buffer = createBuffer(buffer_size, usage, VMA_MEMORY_USAGE_AUTO_PREFER_HOST);
2088 descriptors_dirty =
true;
2092 void *dst_top =
nullptr;
2093 void *dst_bottom =
nullptr;
2094 VkResult result_top = vmaMapMemory(device->
getAllocator(), radiation_out_top_buffer.allocation, &dst_top);
2095 VkResult result_bottom = vmaMapMemory(device->
getAllocator(), radiation_out_bottom_buffer.allocation, &dst_bottom);
2097 if (result_top == VK_SUCCESS) {
2098 std::memcpy(dst_top, radiation_out_top.data(), buffer_size);
2099 vmaFlushAllocation(device->
getAllocator(), radiation_out_top_buffer.allocation, 0, VK_WHOLE_SIZE);
2100 vmaUnmapMemory(device->
getAllocator(), radiation_out_top_buffer.allocation);
2102 if (result_bottom == VK_SUCCESS) {
2103 std::memcpy(dst_bottom, radiation_out_bottom.data(), buffer_size);
2104 vmaFlushAllocation(device->
getAllocator(), radiation_out_bottom_buffer.allocation, 0, VK_WHOLE_SIZE);
2105 vmaUnmapMemory(device->
getAllocator(), radiation_out_bottom_buffer.allocation);
2107 if (result_top != VK_SUCCESS || result_bottom != VK_SUCCESS) {
2108 helios_runtime_error(
"ERROR (VulkanComputeBackend::uploadRadiationOut): Failed to map radiation output buffers.");
2113 if (scatter_top_cam.empty() || scatter_bottom_cam.empty()) {
2117 size_t buffer_size = scatter_top_cam.size() *
sizeof(float);
2120 if (camera_scatter_top_buffer.buffer == VK_NULL_HANDLE || camera_scatter_top_buffer.size != buffer_size) {
2121 if (camera_scatter_top_buffer.buffer != VK_NULL_HANDLE) {
2122 destroyBuffer(camera_scatter_top_buffer);
2124 VkBufferUsageFlags usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
2125 camera_scatter_top_buffer = createBuffer(buffer_size, usage, VMA_MEMORY_USAGE_AUTO_PREFER_HOST);
2126 descriptors_dirty =
true;
2130 if (camera_scatter_bottom_buffer.buffer == VK_NULL_HANDLE || camera_scatter_bottom_buffer.size != buffer_size) {
2131 if (camera_scatter_bottom_buffer.buffer != VK_NULL_HANDLE) {
2132 destroyBuffer(camera_scatter_bottom_buffer);
2134 VkBufferUsageFlags usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
2135 camera_scatter_bottom_buffer = createBuffer(buffer_size, usage, VMA_MEMORY_USAGE_AUTO_PREFER_HOST);
2136 descriptors_dirty =
true;
2140 uploadBufferData(camera_scatter_top_buffer, scatter_top_cam.data(), buffer_size);
2141 uploadBufferData(camera_scatter_bottom_buffer, scatter_bottom_cam.data(), buffer_size);
2145 if (primitive_count == 0 || launch_band_count_param == 0) {
2149 size_t buffer_size = primitive_count * launch_band_count_param *
sizeof(float);
2152 if (camera_scatter_top_buffer.buffer == VK_NULL_HANDLE || camera_scatter_top_buffer.size != buffer_size) {
2153 if (camera_scatter_top_buffer.buffer != VK_NULL_HANDLE) {
2154 destroyBuffer(camera_scatter_top_buffer);
2156 VkBufferUsageFlags usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
2157 camera_scatter_top_buffer = createBuffer(buffer_size, usage, VMA_MEMORY_USAGE_AUTO_PREFER_HOST);
2158 descriptors_dirty =
true;
2162 if (camera_scatter_bottom_buffer.buffer == VK_NULL_HANDLE || camera_scatter_bottom_buffer.size != buffer_size) {
2163 if (camera_scatter_bottom_buffer.buffer != VK_NULL_HANDLE) {
2164 destroyBuffer(camera_scatter_bottom_buffer);
2166 VkBufferUsageFlags usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
2167 camera_scatter_bottom_buffer = createBuffer(buffer_size, usage, VMA_MEMORY_USAGE_AUTO_PREFER_HOST);
2168 descriptors_dirty =
true;
2172 zeroBuffer(camera_scatter_top_buffer);
2173 zeroBuffer(camera_scatter_bottom_buffer);
2177 if (fluxes.empty() || source_count == 0) {
2183 size_t expected_size = source_count * launch_band_count;
2185 if (fluxes.size() != expected_size && fluxes.size() != source_count) {
2187 if (fluxes.size() != source_count) {
2188 helios_runtime_error(
"ERROR (VulkanComputeBackend::uploadSourceFluxes): fluxes size mismatch. Expected " + std::to_string(source_count) +
" (single band) or " + std::to_string(expected_size) +
" (all bands), got " +
2189 std::to_string(fluxes.size()));
2193 if (source_fluxes_buffer.buffer != VK_NULL_HANDLE) {
2194 destroyBuffer(source_fluxes_buffer);
2196 source_fluxes_buffer = createBuffer(fluxes.size() *
sizeof(
float), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
2197 uploadBufferData(source_fluxes_buffer, fluxes.data(), fluxes.size() *
sizeof(
float));
2199 descriptors_dirty =
true;
2203 if (fluxes_cam.empty() || source_count == 0) {
2208 size_t expected_size = source_count * launch_band_count;
2210 if (fluxes_cam.size() != expected_size) {
2211 helios_runtime_error(
"ERROR (VulkanComputeBackend::uploadSourceFluxesCam): fluxes_cam size mismatch. Expected " + std::to_string(expected_size) +
" (Nsources * Nbands_launch), got " + std::to_string(fluxes_cam.size()));
2214 if (source_fluxes_cam_buffer.buffer != VK_NULL_HANDLE) {
2215 destroyBuffer(source_fluxes_cam_buffer);
2217 source_fluxes_cam_buffer = createBuffer(fluxes_cam.size() *
sizeof(
float), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
2218 uploadBufferData(source_fluxes_cam_buffer, fluxes_cam.data(), fluxes_cam.size() *
sizeof(
float));
2220 descriptors_dirty =
true;
2225 VmaTotalStatistics stats;
2226 vmaCalculateStatistics(device->
getAllocator(), &stats);
2228 std::cout <<
"========== Vulkan Memory Usage ==========" << std::endl;
2229 std::cout <<
"Allocated blocks: " << stats.total.statistics.blockCount << std::endl;
2230 std::cout <<
"Allocated memory: " << (stats.total.statistics.allocationBytes / 1024.0 / 1024.0) <<
" MB" << std::endl;
2231 std::cout <<
"Used memory: " << (stats.total.statistics.blockBytes / 1024.0 / 1024.0) <<
" MB" << std::endl;
2234 VkPhysicalDeviceMemoryProperties mem_props;
2237 std::cout <<
"\nTotal device memory heaps: " << mem_props.memoryHeapCount << std::endl;
2238 for (uint32_t i = 0; i < mem_props.memoryHeapCount; ++i) {
2239 std::cout <<
" Heap " << i <<
": " << (mem_props.memoryHeaps[i].size / 1024.0 / 1024.0 / 1024.0) <<
" GB";
2240 if (mem_props.memoryHeaps[i].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) {
2241 std::cout <<
" (device-local)";
2243 std::cout << std::endl;
2245 std::cout <<
"==========================================" << std::endl;
2250 VulkanComputeBackend::Buffer VulkanComputeBackend::createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VmaMemoryUsage mem_usage) {
2254 VkBufferCreateInfo buffer_info{};
2255 buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
2256 buffer_info.size = size;
2257 buffer_info.usage = usage | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
2258 buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
2260 VmaAllocationCreateInfo alloc_info{};
2261 alloc_info.usage = mem_usage;
2265 if (mem_usage == VMA_MEMORY_USAGE_AUTO_PREFER_HOST) {
2266 alloc_info.flags |= VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT;
2267 alloc_info.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
2271 if (mem_usage == VMA_MEMORY_USAGE_GPU_ONLY && size > 64 * 1024 * 1024) {
2272 alloc_info.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
2276 if (mem_usage == VMA_MEMORY_USAGE_CPU_ONLY) {
2277 alloc_info.flags |= VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;
2280 VkResult result = vmaCreateBuffer(device->
getAllocator(), &buffer_info, &alloc_info, &buffer.buffer, &buffer.allocation,
nullptr);
2281 if (result != VK_SUCCESS) {
2282 helios_runtime_error(
"ERROR (VulkanComputeBackend::createBuffer): Failed to create buffer. VkResult: " + std::to_string(result));
2288 void VulkanComputeBackend::destroyBuffer(Buffer &buffer) {
2289 if (buffer.buffer != VK_NULL_HANDLE) {
2290 vmaDestroyBuffer(device->
getAllocator(), buffer.buffer, buffer.allocation);
2291 buffer.buffer = VK_NULL_HANDLE;
2292 buffer.allocation = VK_NULL_HANDLE;
2297 void VulkanComputeBackend::uploadBufferData(Buffer &buffer,
const void *data,
size_t size) {
2299 Buffer staging = createBuffer(size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY);
2303 vmaMapMemory(device->
getAllocator(), staging.allocation, &mapped);
2304 std::memcpy(mapped, data, size);
2305 vmaUnmapMemory(device->
getAllocator(), staging.allocation);
2308 VkCommandBufferBeginInfo begin_info{};
2309 begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
2310 begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
2311 vkBeginCommandBuffer(transfer_command_buffer, &begin_info);
2313 VkBufferCopy copy_region{};
2314 copy_region.size = size;
2315 vkCmdCopyBuffer(transfer_command_buffer, staging.buffer, buffer.buffer, 1, ©_region);
2318 VkBufferMemoryBarrier barrier{};
2319 barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
2320 barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
2321 barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
2322 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
2323 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
2324 barrier.buffer = buffer.buffer;
2326 barrier.size = VK_WHOLE_SIZE;
2328 vkCmdPipelineBarrier(transfer_command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0,
nullptr, 1, &barrier, 0,
nullptr);
2330 vkEndCommandBuffer(transfer_command_buffer);
2333 VkSubmitInfo submit_info{};
2334 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
2335 submit_info.commandBufferCount = 1;
2336 submit_info.pCommandBuffers = &transfer_command_buffer;
2338 vkResetFences(device->
getDevice(), 1, &transfer_fence);
2339 vkQueueSubmit(device->
getComputeQueue(), 1, &submit_info, transfer_fence);
2342 const int max_attempts = 50;
2343 const uint64_t poll_interval_ns = 100000000ULL;
2344 bool completed =
false;
2346 for (
int attempt = 0; attempt < max_attempts; ++attempt) {
2347 VkResult result = vkWaitForFences(device->
getDevice(), 1, &transfer_fence, VK_TRUE, poll_interval_ns);
2348 if (result == VK_SUCCESS) {
2351 }
else if (result != VK_TIMEOUT) {
2352 helios_runtime_error(
"ERROR (VulkanComputeBackend::uploadBufferData): vkWaitForFences failed. VkResult: " + std::to_string(result));
2357 helios_runtime_error(
"ERROR (VulkanComputeBackend::uploadBufferData): GPU buffer upload timed out after 5 seconds. Buffer size: " + std::to_string(size));
2361 destroyBuffer(staging);
2364 void VulkanComputeBackend::downloadBufferData(
const Buffer &buffer,
void *data,
size_t size) {
2370 Buffer staging = createBuffer(size, VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_CPU_ONLY);
2373 VkCommandBufferBeginInfo begin_info{};
2374 begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
2375 begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
2376 vkBeginCommandBuffer(transfer_command_buffer, &begin_info);
2379 VkBufferMemoryBarrier barrier{};
2380 barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
2381 barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
2382 barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
2383 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
2384 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
2385 barrier.buffer = buffer.buffer;
2387 barrier.size = VK_WHOLE_SIZE;
2389 vkCmdPipelineBarrier(transfer_command_buffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0,
nullptr, 1, &barrier, 0,
nullptr);
2391 VkBufferCopy copy_region{};
2392 copy_region.size = size;
2393 vkCmdCopyBuffer(transfer_command_buffer, buffer.buffer, staging.buffer, 1, ©_region);
2395 vkEndCommandBuffer(transfer_command_buffer);
2398 VkSubmitInfo submit_info{};
2399 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
2400 submit_info.commandBufferCount = 1;
2401 submit_info.pCommandBuffers = &transfer_command_buffer;
2403 vkResetFences(device->
getDevice(), 1, &transfer_fence);
2404 vkQueueSubmit(device->
getComputeQueue(), 1, &submit_info, transfer_fence);
2407 const int max_attempts = 50;
2408 const uint64_t poll_interval_ns = 100000000ULL;
2409 bool completed =
false;
2411 for (
int attempt = 0; attempt < max_attempts; ++attempt) {
2412 VkResult result = vkWaitForFences(device->
getDevice(), 1, &transfer_fence, VK_TRUE, poll_interval_ns);
2413 if (result == VK_SUCCESS) {
2416 }
else if (result != VK_TIMEOUT) {
2417 helios_runtime_error(
"ERROR (VulkanComputeBackend::downloadBufferData): vkWaitForFences failed. VkResult: " + std::to_string(result));
2422 helios_runtime_error(
"ERROR (VulkanComputeBackend::downloadBufferData): GPU buffer download timed out after 5 seconds. Buffer size: " + std::to_string(size));
2427 vmaMapMemory(device->
getAllocator(), staging.allocation, &mapped);
2428 std::memcpy(data, mapped, size);
2429 vmaUnmapMemory(device->
getAllocator(), staging.allocation);
2432 destroyBuffer(staging);
2435 void VulkanComputeBackend::zeroBuffer(Buffer &buffer) {
2436 VkCommandBufferBeginInfo begin_info{};
2437 begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
2438 begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
2439 vkBeginCommandBuffer(transfer_command_buffer, &begin_info);
2441 vkCmdFillBuffer(transfer_command_buffer, buffer.buffer, 0, buffer.size, 0);
2443 vkEndCommandBuffer(transfer_command_buffer);
2446 VkSubmitInfo submit_info{};
2447 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
2448 submit_info.commandBufferCount = 1;
2449 submit_info.pCommandBuffers = &transfer_command_buffer;
2451 vkResetFences(device->
getDevice(), 1, &transfer_fence);
2452 vkQueueSubmit(device->
getComputeQueue(), 1, &submit_info, transfer_fence);
2455 const int max_attempts = 50;
2456 const uint64_t poll_interval_ns = 100000000ULL;
2457 bool completed =
false;
2459 for (
int attempt = 0; attempt < max_attempts; ++attempt) {
2460 VkResult result = vkWaitForFences(device->
getDevice(), 1, &transfer_fence, VK_TRUE, poll_interval_ns);
2461 if (result == VK_SUCCESS) {
2464 }
else if (result != VK_TIMEOUT) {
2465 helios_runtime_error(
"ERROR (VulkanComputeBackend::zeroBuffer): vkWaitForFences failed. VkResult: " + std::to_string(result));
2470 helios_runtime_error(
"ERROR (VulkanComputeBackend::zeroBuffer): GPU buffer clear timed out after 5 seconds. Buffer size: " + std::to_string(buffer.size));
2474 void VulkanComputeBackend::createCommandResources() {
2475 VkDevice vk_device = device->
getDevice();
2477 VkCommandPoolCreateInfo pool_info{};
2478 pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
2480 pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
2482 VkResult result = vkCreateCommandPool(vk_device, &pool_info,
nullptr, &command_pool);
2483 if (result != VK_SUCCESS) {
2484 helios_runtime_error(
"ERROR (VulkanComputeBackend::createCommandResources): Failed to create command pool. VkResult: " + std::to_string(result));
2488 VkCommandBufferAllocateInfo alloc_info{};
2489 alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
2490 alloc_info.commandPool = command_pool;
2491 alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
2492 alloc_info.commandBufferCount = 2;
2494 VkCommandBuffer buffers[2];
2495 result = vkAllocateCommandBuffers(vk_device, &alloc_info, buffers);
2496 if (result != VK_SUCCESS) {
2497 helios_runtime_error(
"ERROR (VulkanComputeBackend::createCommandResources): Failed to allocate command buffers. VkResult: " + std::to_string(result));
2500 transfer_command_buffer = buffers[0];
2501 compute_command_buffer = buffers[1];
2504 VkFenceCreateInfo fence_info{};
2505 fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
2506 fence_info.flags = VK_FENCE_CREATE_SIGNALED_BIT;
2508 result = vkCreateFence(vk_device, &fence_info,
nullptr, &transfer_fence);
2509 if (result != VK_SUCCESS) {
2510 helios_runtime_error(
"ERROR (VulkanComputeBackend::createCommandResources): Failed to create transfer fence. VkResult: " + std::to_string(result));
2513 result = vkCreateFence(vk_device, &fence_info,
nullptr, &compute_fence);
2514 if (result != VK_SUCCESS) {
2515 helios_runtime_error(
"ERROR (VulkanComputeBackend::createCommandResources): Failed to create compute fence. VkResult: " + std::to_string(result));
2519 VkQueryPoolCreateInfo query_pool_info{};
2520 query_pool_info.sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO;
2521 query_pool_info.queryType = VK_QUERY_TYPE_TIMESTAMP;
2522 query_pool_info.queryCount = 2;
2524 result = vkCreateQueryPool(vk_device, &query_pool_info,
nullptr, ×tamp_query_pool);
2525 if (result != VK_SUCCESS) {
2526 helios_runtime_error(
"ERROR (VulkanComputeBackend::createCommandResources): Failed to create timestamp query pool. VkResult: " + std::to_string(result));
2530 VkPhysicalDeviceProperties props;
2532 timestamp_period = props.limits.timestampPeriod;
2535 void VulkanComputeBackend::createDescriptorSets() {
2536 VkDevice vk_device = device->
getDevice();
2541 std::vector<VkDescriptorSetLayoutBinding> geometry_bindings = {
2542 {0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2543 {1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2544 {2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2545 {3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2546 {4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2547 {5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2548 {6, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2549 {7, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2550 {8, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2551 {9, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2552 {10, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2553 {11, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2554 {12, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2555 {13, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2556 {14, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2557 {15, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2558 {16, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2559 {17, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2562 VkDescriptorSetLayoutCreateInfo layout_info{};
2563 layout_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
2564 layout_info.bindingCount =
static_cast<uint32_t
>(geometry_bindings.size());
2565 layout_info.pBindings = geometry_bindings.data();
2567 if (vkCreateDescriptorSetLayout(vk_device, &layout_info,
nullptr, &set_layout_geometry) != VK_SUCCESS) {
2568 helios_runtime_error(
"ERROR (VulkanComputeBackend::createDescriptorSets): Failed to create geometry descriptor set layout");
2572 std::vector<VkDescriptorSetLayoutBinding> material_bindings = {
2573 {0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2574 {1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2575 {2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2576 {3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2577 {4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2578 {5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2579 {6, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2580 {7, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2581 {8, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2582 {9, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2583 {10, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2584 {11, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2585 {12, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2586 {13, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2589 layout_info.bindingCount =
static_cast<uint32_t
>(material_bindings.size());
2590 layout_info.pBindings = material_bindings.data();
2592 if (vkCreateDescriptorSetLayout(vk_device, &layout_info,
nullptr, &set_layout_materials) != VK_SUCCESS) {
2593 helios_runtime_error(
"ERROR (VulkanComputeBackend::createDescriptorSets): Failed to create material descriptor set layout");
2597 std::vector<VkDescriptorSetLayoutBinding> result_bindings = {
2598 {0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2599 {1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2600 {2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2601 {3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2602 {4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2603 {5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2604 {6, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2605 {7, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2606 {8, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2607 {9, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2608 {10, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2611 layout_info.bindingCount =
static_cast<uint32_t
>(result_bindings.size());
2612 layout_info.pBindings = result_bindings.data();
2614 if (vkCreateDescriptorSetLayout(vk_device, &layout_info,
nullptr, &set_layout_results) != VK_SUCCESS) {
2615 helios_runtime_error(
"ERROR (VulkanComputeBackend::createDescriptorSets): Failed to create result descriptor set layout");
2619 std::vector<VkDescriptorSetLayoutBinding> sky_bindings = {
2620 {0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2621 {1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2622 {2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2623 {3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2624 {4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2625 {5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2626 {6, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2627 {7, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2628 {8, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2631 layout_info.bindingCount =
static_cast<uint32_t
>(sky_bindings.size());
2632 layout_info.pBindings = sky_bindings.data();
2634 if (vkCreateDescriptorSetLayout(vk_device, &layout_info,
nullptr, &set_layout_sky) != VK_SUCCESS) {
2635 helios_runtime_error(
"ERROR (VulkanComputeBackend::createDescriptorSets): Failed to create sky descriptor set layout");
2639 std::vector<VkDescriptorSetLayoutBinding> debug_bindings = {
2640 {0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT,
nullptr},
2643 layout_info.bindingCount =
static_cast<uint32_t
>(debug_bindings.size());
2644 layout_info.pBindings = debug_bindings.data();
2646 if (vkCreateDescriptorSetLayout(vk_device, &layout_info,
nullptr, &set_layout_debug) != VK_SUCCESS) {
2647 helios_runtime_error(
"ERROR (VulkanComputeBackend::createDescriptorSets): Failed to create debug descriptor set layout");
2652 std::vector<VkDescriptorPoolSize> pool_sizes = {
2653 {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 64},
2656 VkDescriptorPoolCreateInfo pool_info{};
2657 pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
2658 pool_info.poolSizeCount =
static_cast<uint32_t
>(pool_sizes.size());
2659 pool_info.pPoolSizes = pool_sizes.data();
2660 pool_info.maxSets = 5;
2662 if (vkCreateDescriptorPool(vk_device, &pool_info,
nullptr, &descriptor_pool) != VK_SUCCESS) {
2663 helios_runtime_error(
"ERROR (VulkanComputeBackend::createDescriptorSets): Failed to create descriptor pool");
2668 VkDescriptorSetLayout layouts[] = {set_layout_geometry, set_layout_materials, set_layout_results, set_layout_sky, set_layout_debug};
2670 VkDescriptorSetAllocateInfo alloc_info{};
2671 alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
2672 alloc_info.descriptorPool = descriptor_pool;
2673 alloc_info.descriptorSetCount = 5;
2674 alloc_info.pSetLayouts = layouts;
2676 VkDescriptorSet sets[5];
2677 if (vkAllocateDescriptorSets(vk_device, &alloc_info, sets) != VK_SUCCESS) {
2678 helios_runtime_error(
"ERROR (VulkanComputeBackend::createDescriptorSets): Failed to allocate descriptor sets");
2681 set_geometry = sets[0];
2682 set_materials = sets[1];
2683 set_results = sets[2];
2685 set_debug = sets[4];
2692 const size_t placeholder_size =
sizeof(float);
2695 diffuse_flux_buffer = createBuffer(placeholder_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
2696 zeroBuffer(diffuse_flux_buffer);
2697 diffuse_peak_dir_buffer = createBuffer(
sizeof(
helios::vec3), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
2698 zeroBuffer(diffuse_peak_dir_buffer);
2699 diffuse_extinction_buffer = createBuffer(placeholder_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
2700 zeroBuffer(diffuse_extinction_buffer);
2701 diffuse_dist_norm_buffer = createBuffer(placeholder_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
2702 zeroBuffer(diffuse_dist_norm_buffer);
2703 sky_radiance_params_buffer = createBuffer(
sizeof(
helios::vec4), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
2704 zeroBuffer(sky_radiance_params_buffer);
2705 camera_sky_radiance_buffer = createBuffer(placeholder_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
2706 zeroBuffer(camera_sky_radiance_buffer);
2707 solar_disk_radiance_buffer = createBuffer(placeholder_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
2708 zeroBuffer(solar_disk_radiance_buffer);
2709 camera_diffuse_flux_buffer = createBuffer(placeholder_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
2710 zeroBuffer(camera_diffuse_flux_buffer);
2711 band_emission_flag_buffer = createBuffer(
sizeof(uint32_t), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
2712 zeroBuffer(band_emission_flag_buffer);
2716 camera_radiation_buffer = createBuffer(placeholder_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_HOST);
2717 zeroBuffer(camera_radiation_buffer);
2718 camera_pixel_label_buffer = createBuffer(
sizeof(uint32_t), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_HOST);
2719 zeroBuffer(camera_pixel_label_buffer);
2720 camera_pixel_depth_buffer = createBuffer(placeholder_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_HOST);
2721 zeroBuffer(camera_pixel_depth_buffer);
2722 camera_scatter_top_buffer = createBuffer(placeholder_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_HOST);
2723 zeroBuffer(camera_scatter_top_buffer);
2724 camera_scatter_bottom_buffer = createBuffer(placeholder_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_HOST);
2725 zeroBuffer(camera_scatter_bottom_buffer);
2729 specular_exponent_buffer = createBuffer(placeholder_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
2730 zeroBuffer(specular_exponent_buffer);
2731 specular_scale_buffer = createBuffer(placeholder_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
2732 zeroBuffer(specular_scale_buffer);
2733 source_fluxes_cam_buffer = createBuffer(placeholder_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
2734 zeroBuffer(source_fluxes_cam_buffer);
2735 radiation_specular_buffer = createBuffer(placeholder_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
2736 zeroBuffer(radiation_specular_buffer);
2741 is_glass_buffer = createBuffer(placeholder_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
2742 zeroBuffer(is_glass_buffer);
2743 glass_n_buffer = createBuffer(placeholder_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
2744 zeroBuffer(glass_n_buffer);
2745 glass_KL_buffer = createBuffer(placeholder_size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
2746 zeroBuffer(glass_KL_buffer);
2750 mask_data_buffer = createBuffer(
sizeof(uint32_t), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
2751 mask_sizes_buffer = createBuffer(
sizeof(int32_t) * 2, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
2752 mask_offsets_buffer = createBuffer(
sizeof(uint32_t), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
2753 mask_IDs_buffer = createBuffer(
sizeof(int32_t), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
2754 uv_data_buffer = createBuffer(
sizeof(
float) * 2, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
2755 uv_IDs_buffer = createBuffer(
sizeof(int32_t), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
2756 bbox_vertices_buffer = createBuffer(
sizeof(
float), VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_GPU_ONLY);
2760 VkDescriptorBufferInfo diffuse_flux_info{};
2761 diffuse_flux_info.buffer = diffuse_flux_buffer.buffer;
2762 diffuse_flux_info.offset = 0;
2763 diffuse_flux_info.range = VK_WHOLE_SIZE;
2765 VkDescriptorBufferInfo diffuse_peak_dir_info{};
2766 diffuse_peak_dir_info.buffer = diffuse_peak_dir_buffer.buffer;
2767 diffuse_peak_dir_info.offset = 0;
2768 diffuse_peak_dir_info.range = VK_WHOLE_SIZE;
2770 VkDescriptorBufferInfo diffuse_extinction_info{};
2771 diffuse_extinction_info.buffer = diffuse_extinction_buffer.buffer;
2772 diffuse_extinction_info.offset = 0;
2773 diffuse_extinction_info.range = VK_WHOLE_SIZE;
2775 VkDescriptorBufferInfo diffuse_dist_norm_info{};
2776 diffuse_dist_norm_info.buffer = diffuse_dist_norm_buffer.buffer;
2777 diffuse_dist_norm_info.offset = 0;
2778 diffuse_dist_norm_info.range = VK_WHOLE_SIZE;
2780 VkDescriptorBufferInfo sky_radiance_params_info{};
2781 sky_radiance_params_info.buffer = sky_radiance_params_buffer.buffer;
2782 sky_radiance_params_info.offset = 0;
2783 sky_radiance_params_info.range = VK_WHOLE_SIZE;
2785 std::vector<VkWriteDescriptorSet> descriptor_writes;
2787 VkWriteDescriptorSet write{};
2788 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2789 write.dstSet = set_sky;
2790 write.dstBinding = 0;
2791 write.dstArrayElement = 0;
2792 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
2793 write.descriptorCount = 1;
2794 write.pBufferInfo = &diffuse_flux_info;
2795 descriptor_writes.push_back(write);
2797 write.dstBinding = 1;
2798 write.pBufferInfo = &diffuse_peak_dir_info;
2799 descriptor_writes.push_back(write);
2801 write.dstBinding = 2;
2802 write.pBufferInfo = &diffuse_extinction_info;
2803 descriptor_writes.push_back(write);
2805 write.dstBinding = 3;
2806 write.pBufferInfo = &diffuse_dist_norm_info;
2807 descriptor_writes.push_back(write);
2809 write.dstBinding = 4;
2810 write.pBufferInfo = &sky_radiance_params_info;
2811 descriptor_writes.push_back(write);
2813 VkDescriptorBufferInfo camera_sky_radiance_info{};
2814 camera_sky_radiance_info.buffer = camera_sky_radiance_buffer.buffer;
2815 camera_sky_radiance_info.offset = 0;
2816 camera_sky_radiance_info.range = VK_WHOLE_SIZE;
2818 write.dstBinding = 5;
2819 write.pBufferInfo = &camera_sky_radiance_info;
2820 descriptor_writes.push_back(write);
2822 VkDescriptorBufferInfo solar_disk_radiance_info{};
2823 solar_disk_radiance_info.buffer = solar_disk_radiance_buffer.buffer;
2824 solar_disk_radiance_info.offset = 0;
2825 solar_disk_radiance_info.range = VK_WHOLE_SIZE;
2827 write.dstBinding = 6;
2828 write.pBufferInfo = &solar_disk_radiance_info;
2829 descriptor_writes.push_back(write);
2831 VkDescriptorBufferInfo camera_diffuse_flux_info{};
2832 camera_diffuse_flux_info.buffer = camera_diffuse_flux_buffer.buffer;
2833 camera_diffuse_flux_info.offset = 0;
2834 camera_diffuse_flux_info.range = VK_WHOLE_SIZE;
2836 write.dstBinding = 7;
2837 write.pBufferInfo = &camera_diffuse_flux_info;
2838 descriptor_writes.push_back(write);
2840 VkDescriptorBufferInfo band_emission_flag_info{};
2841 band_emission_flag_info.buffer = band_emission_flag_buffer.buffer;
2842 band_emission_flag_info.offset = 0;
2843 band_emission_flag_info.range = VK_WHOLE_SIZE;
2845 write.dstBinding = 8;
2846 write.pBufferInfo = &band_emission_flag_info;
2847 descriptor_writes.push_back(write);
2850 VkDescriptorBufferInfo camera_radiation_info{};
2851 camera_radiation_info.buffer = camera_radiation_buffer.buffer;
2852 camera_radiation_info.offset = 0;
2853 camera_radiation_info.range = VK_WHOLE_SIZE;
2855 VkDescriptorBufferInfo camera_pixel_label_info{};
2856 camera_pixel_label_info.buffer = camera_pixel_label_buffer.buffer;
2857 camera_pixel_label_info.offset = 0;
2858 camera_pixel_label_info.range = VK_WHOLE_SIZE;
2860 VkDescriptorBufferInfo camera_pixel_depth_info{};
2861 camera_pixel_depth_info.buffer = camera_pixel_depth_buffer.buffer;
2862 camera_pixel_depth_info.offset = 0;
2863 camera_pixel_depth_info.range = VK_WHOLE_SIZE;
2865 VkDescriptorBufferInfo camera_scatter_top_info{};
2866 camera_scatter_top_info.buffer = camera_scatter_top_buffer.buffer;
2867 camera_scatter_top_info.offset = 0;
2868 camera_scatter_top_info.range = VK_WHOLE_SIZE;
2870 VkDescriptorBufferInfo camera_scatter_bottom_info{};
2871 camera_scatter_bottom_info.buffer = camera_scatter_bottom_buffer.buffer;
2872 camera_scatter_bottom_info.offset = 0;
2873 camera_scatter_bottom_info.range = VK_WHOLE_SIZE;
2875 write.dstSet = set_results;
2876 write.dstBinding = 5;
2877 write.pBufferInfo = &camera_radiation_info;
2878 descriptor_writes.push_back(write);
2880 write.dstBinding = 6;
2881 write.pBufferInfo = &camera_pixel_label_info;
2882 descriptor_writes.push_back(write);
2884 write.dstBinding = 7;
2885 write.pBufferInfo = &camera_pixel_depth_info;
2886 descriptor_writes.push_back(write);
2888 write.dstBinding = 8;
2889 write.pBufferInfo = &camera_scatter_top_info;
2890 descriptor_writes.push_back(write);
2892 write.dstBinding = 9;
2893 write.pBufferInfo = &camera_scatter_bottom_info;
2894 descriptor_writes.push_back(write);
2897 VkDescriptorBufferInfo mask_data_info{};
2898 mask_data_info.buffer = mask_data_buffer.buffer;
2899 mask_data_info.offset = 0;
2900 mask_data_info.range = VK_WHOLE_SIZE;
2902 VkDescriptorBufferInfo mask_sizes_info{};
2903 mask_sizes_info.buffer = mask_sizes_buffer.buffer;
2904 mask_sizes_info.offset = 0;
2905 mask_sizes_info.range = VK_WHOLE_SIZE;
2907 VkDescriptorBufferInfo mask_offsets_info{};
2908 mask_offsets_info.buffer = mask_offsets_buffer.buffer;
2909 mask_offsets_info.offset = 0;
2910 mask_offsets_info.range = VK_WHOLE_SIZE;
2912 VkDescriptorBufferInfo mask_IDs_info{};
2913 mask_IDs_info.buffer = mask_IDs_buffer.buffer;
2914 mask_IDs_info.offset = 0;
2915 mask_IDs_info.range = VK_WHOLE_SIZE;
2917 VkDescriptorBufferInfo uv_data_info{};
2918 uv_data_info.buffer = uv_data_buffer.buffer;
2919 uv_data_info.offset = 0;
2920 uv_data_info.range = VK_WHOLE_SIZE;
2922 VkDescriptorBufferInfo uv_IDs_info{};
2923 uv_IDs_info.buffer = uv_IDs_buffer.buffer;
2924 uv_IDs_info.offset = 0;
2925 uv_IDs_info.range = VK_WHOLE_SIZE;
2927 write.dstSet = set_geometry;
2928 write.dstBinding = 11;
2929 write.pBufferInfo = &mask_data_info;
2930 descriptor_writes.push_back(write);
2932 write.dstBinding = 12;
2933 write.pBufferInfo = &mask_sizes_info;
2934 descriptor_writes.push_back(write);
2936 write.dstBinding = 13;
2937 write.pBufferInfo = &mask_offsets_info;
2938 descriptor_writes.push_back(write);
2940 write.dstBinding = 14;
2941 write.pBufferInfo = &mask_IDs_info;
2942 descriptor_writes.push_back(write);
2944 write.dstBinding = 15;
2945 write.pBufferInfo = &uv_data_info;
2946 descriptor_writes.push_back(write);
2948 write.dstBinding = 16;
2949 write.pBufferInfo = &uv_IDs_info;
2950 descriptor_writes.push_back(write);
2952 VkDescriptorBufferInfo bbox_verts_info{};
2953 bbox_verts_info.buffer = bbox_vertices_buffer.buffer;
2954 bbox_verts_info.offset = 0;
2955 bbox_verts_info.range = VK_WHOLE_SIZE;
2957 write.dstBinding = 17;
2958 write.pBufferInfo = &bbox_verts_info;
2959 descriptor_writes.push_back(write);
2961 vkUpdateDescriptorSets(vk_device,
static_cast<uint32_t
>(descriptor_writes.size()), descriptor_writes.data(), 0,
nullptr);
2964 void VulkanComputeBackend::createPipelines() {
2965 VkDevice vk_device = device->
getDevice();
2969 VkDescriptorSetLayout set_layouts[] = {set_layout_geometry, set_layout_materials, set_layout_results, set_layout_sky, set_layout_debug};
2972 const uint32_t push_constant_size = 128;
2976 if (push_constant_size > props.limits.maxPushConstantsSize) {
2977 helios_runtime_error(
"ERROR (VulkanComputeBackend::createPipelines): Push constant size (" + std::to_string(push_constant_size) +
" bytes) exceeds device limit (" + std::to_string(props.limits.maxPushConstantsSize) +
" bytes)");
2980 VkPushConstantRange push_constant_range{};
2981 push_constant_range.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
2982 push_constant_range.offset = 0;
2983 push_constant_range.size = push_constant_size;
2985 VkPipelineLayoutCreateInfo pipeline_layout_info{};
2986 pipeline_layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
2987 pipeline_layout_info.setLayoutCount = 5;
2988 pipeline_layout_info.pSetLayouts = set_layouts;
2989 pipeline_layout_info.pushConstantRangeCount = 1;
2990 pipeline_layout_info.pPushConstantRanges = &push_constant_range;
2992 if (vkCreatePipelineLayout(vk_device, &pipeline_layout_info,
nullptr, &pipeline_layout) != VK_SUCCESS) {
2993 helios_runtime_error(
"ERROR (VulkanComputeBackend::createPipelines): Failed to create pipeline layout");
2999 std::string shader_dir =
"plugins/radiation/";
3001 VkShaderModule shader_direct = loadShader(shader_dir +
"direct_raygen.spv");
3002 VkShaderModule shader_diffuse = loadShader(shader_dir +
"diffuse_raygen.spv");
3003 VkShaderModule shader_camera = loadShader(shader_dir +
"camera_raygen.spv");
3004 VkShaderModule shader_pixel_label = loadShader(shader_dir +
"pixel_label_raygen.spv");
3008 VkComputePipelineCreateInfo pipeline_info{};
3009 pipeline_info.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
3010 pipeline_info.layout = pipeline_layout;
3013 pipeline_info.stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
3014 pipeline_info.stage.stage = VK_SHADER_STAGE_COMPUTE_BIT;
3015 pipeline_info.stage.module = shader_direct;
3016 pipeline_info.stage.pName =
"main";
3018 if (vkCreateComputePipelines(vk_device, VK_NULL_HANDLE, 1, &pipeline_info,
nullptr, &pipeline_direct) != VK_SUCCESS) {
3019 helios_runtime_error(
"ERROR (VulkanComputeBackend::createPipelines): Failed to create direct ray pipeline");
3023 pipeline_info.stage.module = shader_diffuse;
3024 if (vkCreateComputePipelines(vk_device, VK_NULL_HANDLE, 1, &pipeline_info,
nullptr, &pipeline_diffuse) != VK_SUCCESS) {
3025 helios_runtime_error(
"ERROR (VulkanComputeBackend::createPipelines): Failed to create diffuse ray pipeline");
3029 pipeline_info.stage.module = shader_camera;
3030 if (vkCreateComputePipelines(vk_device, VK_NULL_HANDLE, 1, &pipeline_info,
nullptr, &pipeline_camera) != VK_SUCCESS) {
3031 helios_runtime_error(
"ERROR (VulkanComputeBackend::createPipelines): Failed to create camera ray pipeline");
3035 pipeline_info.stage.module = shader_pixel_label;
3036 if (vkCreateComputePipelines(vk_device, VK_NULL_HANDLE, 1, &pipeline_info,
nullptr, &pipeline_pixel_label) != VK_SUCCESS) {
3037 helios_runtime_error(
"ERROR (VulkanComputeBackend::createPipelines): Failed to create pixel label pipeline");
3041 vkDestroyShaderModule(vk_device, shader_direct,
nullptr);
3042 vkDestroyShaderModule(vk_device, shader_diffuse,
nullptr);
3043 vkDestroyShaderModule(vk_device, shader_camera,
nullptr);
3044 vkDestroyShaderModule(vk_device, shader_pixel_label,
nullptr);
3047 VkShaderModule VulkanComputeBackend::loadShader(
const std::string &filename) {
3049 std::ifstream file(filename, std::ios::binary | std::ios::ate);
3050 if (!file.is_open()) {
3051 helios_runtime_error(
"ERROR (VulkanComputeBackend::loadShader): Failed to open shader file: " + filename);
3054 size_t file_size = file.tellg();
3055 if (file_size == 0) {
3056 helios_runtime_error(
"ERROR (VulkanComputeBackend::loadShader): Shader file is empty: " + filename);
3058 if (file_size % 4 != 0) {
3059 helios_runtime_error(
"ERROR (VulkanComputeBackend::loadShader): Invalid SPIR-V file size (not multiple of 4 bytes): " + filename);
3062 std::vector<uint32_t> code(file_size / 4);
3064 file.read(
reinterpret_cast<char *
>(code.data()), file_size);
3068 if (code.empty() || code[0] != 0x07230203) {
3069 helios_runtime_error(
"ERROR (VulkanComputeBackend::loadShader): Invalid SPIR-V magic number in: " + filename +
". Expected 0x07230203, got 0x" + std::to_string(code.empty() ? 0 : code[0]));
3073 VkShaderModuleCreateInfo create_info{};
3074 create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
3075 create_info.codeSize = code.size() *
sizeof(uint32_t);
3076 create_info.pCode = code.data();
3078 VkShaderModule shader_module;
3079 VkResult result = vkCreateShaderModule(device->
getDevice(), &create_info,
nullptr, &shader_module);
3080 if (result != VK_SUCCESS) {
3081 helios_runtime_error(
"ERROR (VulkanComputeBackend::loadShader): Failed to create shader module from: " + filename +
" (VkResult: " + std::to_string(result) +
")");
3084 return shader_module;
3087 void VulkanComputeBackend::updateDescriptorSets() {
3088 VkDevice vk_device = device->
getDevice();
3090 std::vector<VkWriteDescriptorSet> descriptor_writes;
3094 VkDescriptorBufferInfo bvh_info{};
3095 bvh_info.buffer = bvh_buffer.buffer;
3096 bvh_info.offset = 0;
3097 bvh_info.range = VK_WHOLE_SIZE;
3099 VkDescriptorBufferInfo prim_indices_info{};
3100 prim_indices_info.buffer = primitive_indices_buffer.buffer;
3101 prim_indices_info.offset = 0;
3102 prim_indices_info.range = VK_WHOLE_SIZE;
3104 VkDescriptorBufferInfo transform_info{};
3105 transform_info.buffer = transform_matrices_buffer.buffer;
3106 transform_info.offset = 0;
3107 transform_info.range = VK_WHOLE_SIZE;
3109 VkDescriptorBufferInfo prim_types_info{};
3110 prim_types_info.buffer = primitive_types_buffer.buffer;
3111 prim_types_info.offset = 0;
3112 prim_types_info.range = VK_WHOLE_SIZE;
3114 VkDescriptorBufferInfo prim_uuids_info{};
3115 prim_uuids_info.buffer = primitive_uuids_buffer.buffer;
3116 prim_uuids_info.offset = 0;
3117 prim_uuids_info.range = VK_WHOLE_SIZE;
3119 VkDescriptorBufferInfo prim_positions_info{};
3120 prim_positions_info.buffer = primitive_positions_buffer.buffer;
3121 prim_positions_info.offset = 0;
3122 prim_positions_info.range = VK_WHOLE_SIZE;
3124 VkDescriptorBufferInfo obj_subdivisions_info{};
3125 obj_subdivisions_info.buffer = object_subdivisions_buffer.buffer;
3126 obj_subdivisions_info.offset = 0;
3127 obj_subdivisions_info.range = VK_WHOLE_SIZE;
3129 VkDescriptorBufferInfo twosided_info{};
3130 twosided_info.buffer = twosided_flag_buffer.buffer;
3131 twosided_info.offset = 0;
3132 twosided_info.range = VK_WHOLE_SIZE;
3134 VkDescriptorBufferInfo patch_vertices_info{};
3135 patch_vertices_info.buffer = patch_vertices_buffer.buffer;
3136 patch_vertices_info.offset = 0;
3137 patch_vertices_info.range = VK_WHOLE_SIZE;
3139 VkDescriptorBufferInfo triangle_vertices_info{};
3140 triangle_vertices_info.buffer = triangle_vertices_buffer.buffer;
3141 triangle_vertices_info.offset = 0;
3142 triangle_vertices_info.range = VK_WHOLE_SIZE;
3144 VkDescriptorBufferInfo normal_info{};
3145 normal_info.buffer = normal_buffer.buffer;
3146 normal_info.offset = 0;
3147 normal_info.range = VK_WHOLE_SIZE;
3150 if (bvh_buffer.buffer != VK_NULL_HANDLE) {
3151 VkWriteDescriptorSet write{};
3152 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3153 write.dstSet = set_geometry;
3154 write.dstBinding = 0;
3155 write.dstArrayElement = 0;
3156 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3157 write.descriptorCount = 1;
3158 write.pBufferInfo = &bvh_info;
3159 descriptor_writes.push_back(write);
3162 if (primitive_indices_buffer.buffer != VK_NULL_HANDLE) {
3163 VkWriteDescriptorSet write{};
3164 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3165 write.dstSet = set_geometry;
3166 write.dstBinding = 1;
3167 write.dstArrayElement = 0;
3168 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3169 write.descriptorCount = 1;
3170 write.pBufferInfo = &prim_indices_info;
3171 descriptor_writes.push_back(write);
3174 if (transform_matrices_buffer.buffer != VK_NULL_HANDLE) {
3175 VkWriteDescriptorSet write{};
3176 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3177 write.dstSet = set_geometry;
3178 write.dstBinding = 2;
3179 write.dstArrayElement = 0;
3180 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3181 write.descriptorCount = 1;
3182 write.pBufferInfo = &transform_info;
3183 descriptor_writes.push_back(write);
3186 if (primitive_types_buffer.buffer != VK_NULL_HANDLE) {
3187 VkWriteDescriptorSet write{};
3188 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3189 write.dstSet = set_geometry;
3190 write.dstBinding = 3;
3191 write.dstArrayElement = 0;
3192 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3193 write.descriptorCount = 1;
3194 write.pBufferInfo = &prim_types_info;
3195 descriptor_writes.push_back(write);
3198 if (primitive_uuids_buffer.buffer != VK_NULL_HANDLE) {
3199 VkWriteDescriptorSet write{};
3200 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3201 write.dstSet = set_geometry;
3202 write.dstBinding = 4;
3203 write.dstArrayElement = 0;
3204 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3205 write.descriptorCount = 1;
3206 write.pBufferInfo = &prim_uuids_info;
3207 descriptor_writes.push_back(write);
3210 if (primitive_positions_buffer.buffer != VK_NULL_HANDLE) {
3211 VkWriteDescriptorSet write{};
3212 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3213 write.dstSet = set_geometry;
3214 write.dstBinding = 5;
3215 write.dstArrayElement = 0;
3216 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3217 write.descriptorCount = 1;
3218 write.pBufferInfo = &prim_positions_info;
3219 descriptor_writes.push_back(write);
3222 if (object_subdivisions_buffer.buffer != VK_NULL_HANDLE) {
3223 VkWriteDescriptorSet write{};
3224 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3225 write.dstSet = set_geometry;
3226 write.dstBinding = 6;
3227 write.dstArrayElement = 0;
3228 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3229 write.descriptorCount = 1;
3230 write.pBufferInfo = &obj_subdivisions_info;
3231 descriptor_writes.push_back(write);
3234 if (twosided_flag_buffer.buffer != VK_NULL_HANDLE) {
3235 VkWriteDescriptorSet write{};
3236 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3237 write.dstSet = set_geometry;
3238 write.dstBinding = 7;
3239 write.dstArrayElement = 0;
3240 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3241 write.descriptorCount = 1;
3242 write.pBufferInfo = &twosided_info;
3243 descriptor_writes.push_back(write);
3246 if (patch_vertices_buffer.buffer != VK_NULL_HANDLE) {
3247 VkWriteDescriptorSet write{};
3248 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3249 write.dstSet = set_geometry;
3250 write.dstBinding = 8;
3251 write.dstArrayElement = 0;
3252 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3253 write.descriptorCount = 1;
3254 write.pBufferInfo = &patch_vertices_info;
3255 descriptor_writes.push_back(write);
3258 if (triangle_vertices_buffer.buffer != VK_NULL_HANDLE) {
3259 VkWriteDescriptorSet write{};
3260 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3261 write.dstSet = set_geometry;
3262 write.dstBinding = 9;
3263 write.dstArrayElement = 0;
3264 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3265 write.descriptorCount = 1;
3266 write.pBufferInfo = &triangle_vertices_info;
3267 descriptor_writes.push_back(write);
3270 if (normal_buffer.buffer != VK_NULL_HANDLE) {
3271 VkWriteDescriptorSet write{};
3272 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3273 write.dstSet = set_geometry;
3274 write.dstBinding = 10;
3275 write.dstArrayElement = 0;
3276 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3277 write.descriptorCount = 1;
3278 write.pBufferInfo = &normal_info;
3279 descriptor_writes.push_back(write);
3283 VkDescriptorBufferInfo mask_data_info{};
3284 mask_data_info.buffer = mask_data_buffer.buffer;
3285 mask_data_info.offset = 0;
3286 mask_data_info.range = VK_WHOLE_SIZE;
3288 VkDescriptorBufferInfo mask_sizes_info{};
3289 mask_sizes_info.buffer = mask_sizes_buffer.buffer;
3290 mask_sizes_info.offset = 0;
3291 mask_sizes_info.range = VK_WHOLE_SIZE;
3293 VkDescriptorBufferInfo mask_offsets_info{};
3294 mask_offsets_info.buffer = mask_offsets_buffer.buffer;
3295 mask_offsets_info.offset = 0;
3296 mask_offsets_info.range = VK_WHOLE_SIZE;
3298 VkDescriptorBufferInfo mask_IDs_info{};
3299 mask_IDs_info.buffer = mask_IDs_buffer.buffer;
3300 mask_IDs_info.offset = 0;
3301 mask_IDs_info.range = VK_WHOLE_SIZE;
3303 VkDescriptorBufferInfo uv_data_info{};
3304 uv_data_info.buffer = uv_data_buffer.buffer;
3305 uv_data_info.offset = 0;
3306 uv_data_info.range = VK_WHOLE_SIZE;
3308 VkDescriptorBufferInfo uv_IDs_info{};
3309 uv_IDs_info.buffer = uv_IDs_buffer.buffer;
3310 uv_IDs_info.offset = 0;
3311 uv_IDs_info.range = VK_WHOLE_SIZE;
3313 if (mask_data_buffer.buffer != VK_NULL_HANDLE) {
3314 VkWriteDescriptorSet write{};
3315 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3316 write.dstSet = set_geometry;
3317 write.dstBinding = 11;
3318 write.dstArrayElement = 0;
3319 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3320 write.descriptorCount = 1;
3321 write.pBufferInfo = &mask_data_info;
3322 descriptor_writes.push_back(write);
3325 if (mask_sizes_buffer.buffer != VK_NULL_HANDLE) {
3326 VkWriteDescriptorSet write{};
3327 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3328 write.dstSet = set_geometry;
3329 write.dstBinding = 12;
3330 write.dstArrayElement = 0;
3331 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3332 write.descriptorCount = 1;
3333 write.pBufferInfo = &mask_sizes_info;
3334 descriptor_writes.push_back(write);
3337 if (mask_offsets_buffer.buffer != VK_NULL_HANDLE) {
3338 VkWriteDescriptorSet write{};
3339 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3340 write.dstSet = set_geometry;
3341 write.dstBinding = 13;
3342 write.dstArrayElement = 0;
3343 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3344 write.descriptorCount = 1;
3345 write.pBufferInfo = &mask_offsets_info;
3346 descriptor_writes.push_back(write);
3349 if (mask_IDs_buffer.buffer != VK_NULL_HANDLE) {
3350 VkWriteDescriptorSet write{};
3351 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3352 write.dstSet = set_geometry;
3353 write.dstBinding = 14;
3354 write.dstArrayElement = 0;
3355 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3356 write.descriptorCount = 1;
3357 write.pBufferInfo = &mask_IDs_info;
3358 descriptor_writes.push_back(write);
3361 if (uv_data_buffer.buffer != VK_NULL_HANDLE) {
3362 VkWriteDescriptorSet write{};
3363 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3364 write.dstSet = set_geometry;
3365 write.dstBinding = 15;
3366 write.dstArrayElement = 0;
3367 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3368 write.descriptorCount = 1;
3369 write.pBufferInfo = &uv_data_info;
3370 descriptor_writes.push_back(write);
3373 if (uv_IDs_buffer.buffer != VK_NULL_HANDLE) {
3374 VkWriteDescriptorSet write{};
3375 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3376 write.dstSet = set_geometry;
3377 write.dstBinding = 16;
3378 write.dstArrayElement = 0;
3379 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3380 write.descriptorCount = 1;
3381 write.pBufferInfo = &uv_IDs_info;
3382 descriptor_writes.push_back(write);
3385 VkDescriptorBufferInfo bbox_verts_info{};
3386 bbox_verts_info.buffer = bbox_vertices_buffer.buffer;
3387 bbox_verts_info.offset = 0;
3388 bbox_verts_info.range = VK_WHOLE_SIZE;
3390 if (bbox_vertices_buffer.buffer != VK_NULL_HANDLE) {
3391 VkWriteDescriptorSet write{};
3392 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3393 write.dstSet = set_geometry;
3394 write.dstBinding = 17;
3395 write.dstArrayElement = 0;
3396 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3397 write.descriptorCount = 1;
3398 write.pBufferInfo = &bbox_verts_info;
3399 descriptor_writes.push_back(write);
3404 VkDescriptorBufferInfo source_pos_info{};
3405 source_pos_info.buffer = source_positions_buffer.buffer;
3406 source_pos_info.offset = 0;
3407 source_pos_info.range = VK_WHOLE_SIZE;
3409 VkDescriptorBufferInfo source_types_info{};
3410 source_types_info.buffer = source_types_buffer.buffer;
3411 source_types_info.offset = 0;
3412 source_types_info.range = VK_WHOLE_SIZE;
3414 VkDescriptorBufferInfo source_rot_info{};
3415 source_rot_info.buffer = source_rotations_buffer.buffer;
3416 source_rot_info.offset = 0;
3417 source_rot_info.range = VK_WHOLE_SIZE;
3419 VkDescriptorBufferInfo source_widths_info{};
3420 source_widths_info.buffer = source_widths_buffer.buffer;
3421 source_widths_info.offset = 0;
3422 source_widths_info.range = VK_WHOLE_SIZE;
3424 VkDescriptorBufferInfo source_fluxes_info{};
3425 source_fluxes_info.buffer = source_fluxes_buffer.buffer;
3426 source_fluxes_info.offset = 0;
3427 source_fluxes_info.range = VK_WHOLE_SIZE;
3429 VkDescriptorBufferInfo reflectivity_info{};
3430 reflectivity_info.buffer = reflectivity_buffer.buffer;
3431 reflectivity_info.offset = 0;
3432 reflectivity_info.range = VK_WHOLE_SIZE;
3434 VkDescriptorBufferInfo transmissivity_info{};
3435 transmissivity_info.buffer = transmissivity_buffer.buffer;
3436 transmissivity_info.offset = 0;
3437 transmissivity_info.range = VK_WHOLE_SIZE;
3439 if (source_positions_buffer.buffer != VK_NULL_HANDLE) {
3440 VkWriteDescriptorSet write{};
3441 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3442 write.dstSet = set_materials;
3443 write.dstBinding = 0;
3444 write.dstArrayElement = 0;
3445 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3446 write.descriptorCount = 1;
3447 write.pBufferInfo = &source_pos_info;
3448 descriptor_writes.push_back(write);
3451 if (source_types_buffer.buffer != VK_NULL_HANDLE) {
3452 VkWriteDescriptorSet write{};
3453 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3454 write.dstSet = set_materials;
3455 write.dstBinding = 1;
3456 write.dstArrayElement = 0;
3457 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3458 write.descriptorCount = 1;
3459 write.pBufferInfo = &source_types_info;
3460 descriptor_writes.push_back(write);
3463 if (source_rotations_buffer.buffer != VK_NULL_HANDLE) {
3464 VkWriteDescriptorSet write{};
3465 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3466 write.dstSet = set_materials;
3467 write.dstBinding = 2;
3468 write.dstArrayElement = 0;
3469 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3470 write.descriptorCount = 1;
3471 write.pBufferInfo = &source_rot_info;
3472 descriptor_writes.push_back(write);
3475 if (source_widths_buffer.buffer != VK_NULL_HANDLE) {
3476 VkWriteDescriptorSet write{};
3477 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3478 write.dstSet = set_materials;
3479 write.dstBinding = 3;
3480 write.dstArrayElement = 0;
3481 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3482 write.descriptorCount = 1;
3483 write.pBufferInfo = &source_widths_info;
3484 descriptor_writes.push_back(write);
3487 if (source_fluxes_buffer.buffer != VK_NULL_HANDLE) {
3488 VkWriteDescriptorSet write{};
3489 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3490 write.dstSet = set_materials;
3491 write.dstBinding = 4;
3492 write.dstArrayElement = 0;
3493 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3494 write.descriptorCount = 1;
3495 write.pBufferInfo = &source_fluxes_info;
3496 descriptor_writes.push_back(write);
3499 if (reflectivity_buffer.buffer != VK_NULL_HANDLE) {
3500 VkWriteDescriptorSet write{};
3501 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3502 write.dstSet = set_materials;
3503 write.dstBinding = 5;
3504 write.dstArrayElement = 0;
3505 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3506 write.descriptorCount = 1;
3507 write.pBufferInfo = &reflectivity_info;
3508 descriptor_writes.push_back(write);
3511 if (transmissivity_buffer.buffer != VK_NULL_HANDLE) {
3512 VkWriteDescriptorSet write{};
3513 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3514 write.dstSet = set_materials;
3515 write.dstBinding = 6;
3516 write.dstArrayElement = 0;
3517 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3518 write.descriptorCount = 1;
3519 write.pBufferInfo = &transmissivity_info;
3520 descriptor_writes.push_back(write);
3524 VkDescriptorBufferInfo specular_exponent_info{};
3525 specular_exponent_info.buffer = specular_exponent_buffer.buffer;
3526 specular_exponent_info.offset = 0;
3527 specular_exponent_info.range = VK_WHOLE_SIZE;
3529 VkDescriptorBufferInfo specular_scale_info{};
3530 specular_scale_info.buffer = specular_scale_buffer.buffer;
3531 specular_scale_info.offset = 0;
3532 specular_scale_info.range = VK_WHOLE_SIZE;
3534 VkDescriptorBufferInfo source_fluxes_cam_info{};
3535 source_fluxes_cam_info.buffer = source_fluxes_cam_buffer.buffer;
3536 source_fluxes_cam_info.offset = 0;
3537 source_fluxes_cam_info.range = VK_WHOLE_SIZE;
3539 if (specular_exponent_buffer.buffer != VK_NULL_HANDLE) {
3540 VkWriteDescriptorSet write{};
3541 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3542 write.dstSet = set_materials;
3543 write.dstBinding = 7;
3544 write.dstArrayElement = 0;
3545 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3546 write.descriptorCount = 1;
3547 write.pBufferInfo = &specular_exponent_info;
3548 descriptor_writes.push_back(write);
3551 if (specular_scale_buffer.buffer != VK_NULL_HANDLE) {
3552 VkWriteDescriptorSet write{};
3553 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3554 write.dstSet = set_materials;
3555 write.dstBinding = 8;
3556 write.dstArrayElement = 0;
3557 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3558 write.descriptorCount = 1;
3559 write.pBufferInfo = &specular_scale_info;
3560 descriptor_writes.push_back(write);
3563 if (source_fluxes_cam_buffer.buffer != VK_NULL_HANDLE) {
3564 VkWriteDescriptorSet write{};
3565 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3566 write.dstSet = set_materials;
3567 write.dstBinding = 9;
3568 write.dstArrayElement = 0;
3569 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3570 write.descriptorCount = 1;
3571 write.pBufferInfo = &source_fluxes_cam_info;
3572 descriptor_writes.push_back(write);
3575 VkDescriptorBufferInfo band_map_info{};
3576 band_map_info.buffer = band_map_buffer.buffer;
3577 band_map_info.offset = 0;
3578 band_map_info.range = VK_WHOLE_SIZE;
3580 if (band_map_buffer.buffer != VK_NULL_HANDLE) {
3581 VkWriteDescriptorSet write{};
3582 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3583 write.dstSet = set_materials;
3584 write.dstBinding = 10;
3585 write.dstArrayElement = 0;
3586 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3587 write.descriptorCount = 1;
3588 write.pBufferInfo = &band_map_info;
3589 descriptor_writes.push_back(write);
3593 VkDescriptorBufferInfo is_glass_info{};
3594 is_glass_info.buffer = is_glass_buffer.buffer;
3595 is_glass_info.offset = 0;
3596 is_glass_info.range = VK_WHOLE_SIZE;
3598 VkDescriptorBufferInfo glass_n_info{};
3599 glass_n_info.buffer = glass_n_buffer.buffer;
3600 glass_n_info.offset = 0;
3601 glass_n_info.range = VK_WHOLE_SIZE;
3603 VkDescriptorBufferInfo glass_KL_info{};
3604 glass_KL_info.buffer = glass_KL_buffer.buffer;
3605 glass_KL_info.offset = 0;
3606 glass_KL_info.range = VK_WHOLE_SIZE;
3608 if (is_glass_buffer.buffer != VK_NULL_HANDLE) {
3609 VkWriteDescriptorSet write{};
3610 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3611 write.dstSet = set_materials;
3612 write.dstBinding = 11;
3613 write.dstArrayElement = 0;
3614 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3615 write.descriptorCount = 1;
3616 write.pBufferInfo = &is_glass_info;
3617 descriptor_writes.push_back(write);
3619 if (glass_n_buffer.buffer != VK_NULL_HANDLE) {
3620 VkWriteDescriptorSet write{};
3621 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3622 write.dstSet = set_materials;
3623 write.dstBinding = 12;
3624 write.dstArrayElement = 0;
3625 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3626 write.descriptorCount = 1;
3627 write.pBufferInfo = &glass_n_info;
3628 descriptor_writes.push_back(write);
3630 if (glass_KL_buffer.buffer != VK_NULL_HANDLE) {
3631 VkWriteDescriptorSet write{};
3632 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3633 write.dstSet = set_materials;
3634 write.dstBinding = 13;
3635 write.dstArrayElement = 0;
3636 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3637 write.descriptorCount = 1;
3638 write.pBufferInfo = &glass_KL_info;
3639 descriptor_writes.push_back(write);
3644 VkDescriptorBufferInfo rad_in_info{};
3645 rad_in_info.buffer = radiation_in_buffer.buffer;
3646 rad_in_info.offset = 0;
3647 rad_in_info.range = VK_WHOLE_SIZE;
3649 VkDescriptorBufferInfo rad_out_top_info{};
3650 rad_out_top_info.buffer = radiation_out_top_buffer.buffer;
3651 rad_out_top_info.offset = 0;
3652 rad_out_top_info.range = VK_WHOLE_SIZE;
3654 VkDescriptorBufferInfo rad_out_bottom_info{};
3655 rad_out_bottom_info.buffer = radiation_out_bottom_buffer.buffer;
3656 rad_out_bottom_info.offset = 0;
3657 rad_out_bottom_info.range = VK_WHOLE_SIZE;
3659 VkDescriptorBufferInfo scatter_top_info{};
3660 scatter_top_info.buffer = scatter_top_buffer.buffer;
3661 scatter_top_info.offset = 0;
3662 scatter_top_info.range = VK_WHOLE_SIZE;
3664 VkDescriptorBufferInfo scatter_bottom_info{};
3665 scatter_bottom_info.buffer = scatter_bottom_buffer.buffer;
3666 scatter_bottom_info.offset = 0;
3667 scatter_bottom_info.range = VK_WHOLE_SIZE;
3669 if (radiation_in_buffer.buffer != VK_NULL_HANDLE) {
3670 VkWriteDescriptorSet write{};
3671 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3672 write.dstSet = set_results;
3673 write.dstBinding = 0;
3674 write.dstArrayElement = 0;
3675 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3676 write.descriptorCount = 1;
3677 write.pBufferInfo = &rad_in_info;
3678 descriptor_writes.push_back(write);
3681 if (radiation_out_top_buffer.buffer != VK_NULL_HANDLE) {
3682 VkWriteDescriptorSet write{};
3683 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3684 write.dstSet = set_results;
3685 write.dstBinding = 1;
3686 write.dstArrayElement = 0;
3687 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3688 write.descriptorCount = 1;
3689 write.pBufferInfo = &rad_out_top_info;
3690 descriptor_writes.push_back(write);
3695 if (radiation_out_bottom_buffer.buffer != VK_NULL_HANDLE) {
3696 VkWriteDescriptorSet write{};
3697 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3698 write.dstSet = set_results;
3699 write.dstBinding = 2;
3700 write.dstArrayElement = 0;
3701 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3702 write.descriptorCount = 1;
3703 write.pBufferInfo = &rad_out_bottom_info;
3704 descriptor_writes.push_back(write);
3707 if (scatter_top_buffer.buffer != VK_NULL_HANDLE) {
3708 VkWriteDescriptorSet write{};
3709 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3710 write.dstSet = set_results;
3711 write.dstBinding = 3;
3712 write.dstArrayElement = 0;
3713 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3714 write.descriptorCount = 1;
3715 write.pBufferInfo = &scatter_top_info;
3716 descriptor_writes.push_back(write);
3719 if (scatter_bottom_buffer.buffer != VK_NULL_HANDLE) {
3720 VkWriteDescriptorSet write{};
3721 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3722 write.dstSet = set_results;
3723 write.dstBinding = 4;
3724 write.dstArrayElement = 0;
3725 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3726 write.descriptorCount = 1;
3727 write.pBufferInfo = &scatter_bottom_info;
3728 descriptor_writes.push_back(write);
3732 VkDescriptorBufferInfo camera_radiation_info{};
3733 camera_radiation_info.buffer = camera_radiation_buffer.buffer;
3734 camera_radiation_info.offset = 0;
3735 camera_radiation_info.range = VK_WHOLE_SIZE;
3737 VkDescriptorBufferInfo camera_pixel_label_info{};
3738 camera_pixel_label_info.buffer = camera_pixel_label_buffer.buffer;
3739 camera_pixel_label_info.offset = 0;
3740 camera_pixel_label_info.range = VK_WHOLE_SIZE;
3742 VkDescriptorBufferInfo camera_pixel_depth_info{};
3743 camera_pixel_depth_info.buffer = camera_pixel_depth_buffer.buffer;
3744 camera_pixel_depth_info.offset = 0;
3745 camera_pixel_depth_info.range = VK_WHOLE_SIZE;
3747 VkDescriptorBufferInfo camera_scatter_top_info{};
3748 camera_scatter_top_info.buffer = camera_scatter_top_buffer.buffer;
3749 camera_scatter_top_info.offset = 0;
3750 camera_scatter_top_info.range = VK_WHOLE_SIZE;
3752 VkDescriptorBufferInfo camera_scatter_bottom_info{};
3753 camera_scatter_bottom_info.buffer = camera_scatter_bottom_buffer.buffer;
3754 camera_scatter_bottom_info.offset = 0;
3755 camera_scatter_bottom_info.range = VK_WHOLE_SIZE;
3757 if (camera_radiation_buffer.buffer != VK_NULL_HANDLE) {
3758 VkWriteDescriptorSet write{};
3759 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3760 write.dstSet = set_results;
3761 write.dstBinding = 5;
3762 write.dstArrayElement = 0;
3763 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3764 write.descriptorCount = 1;
3765 write.pBufferInfo = &camera_radiation_info;
3766 descriptor_writes.push_back(write);
3769 if (camera_pixel_label_buffer.buffer != VK_NULL_HANDLE) {
3770 VkWriteDescriptorSet write{};
3771 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3772 write.dstSet = set_results;
3773 write.dstBinding = 6;
3774 write.dstArrayElement = 0;
3775 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3776 write.descriptorCount = 1;
3777 write.pBufferInfo = &camera_pixel_label_info;
3778 descriptor_writes.push_back(write);
3781 if (camera_pixel_depth_buffer.buffer != VK_NULL_HANDLE) {
3782 VkWriteDescriptorSet write{};
3783 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3784 write.dstSet = set_results;
3785 write.dstBinding = 7;
3786 write.dstArrayElement = 0;
3787 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3788 write.descriptorCount = 1;
3789 write.pBufferInfo = &camera_pixel_depth_info;
3790 descriptor_writes.push_back(write);
3793 if (camera_scatter_top_buffer.buffer != VK_NULL_HANDLE) {
3794 VkWriteDescriptorSet write{};
3795 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3796 write.dstSet = set_results;
3797 write.dstBinding = 8;
3798 write.dstArrayElement = 0;
3799 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3800 write.descriptorCount = 1;
3801 write.pBufferInfo = &camera_scatter_top_info;
3802 descriptor_writes.push_back(write);
3805 if (camera_scatter_bottom_buffer.buffer != VK_NULL_HANDLE) {
3806 VkWriteDescriptorSet write{};
3807 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3808 write.dstSet = set_results;
3809 write.dstBinding = 9;
3810 write.dstArrayElement = 0;
3811 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3812 write.descriptorCount = 1;
3813 write.pBufferInfo = &camera_scatter_bottom_info;
3814 descriptor_writes.push_back(write);
3817 VkDescriptorBufferInfo radiation_specular_info{};
3818 radiation_specular_info.buffer = radiation_specular_buffer.buffer;
3819 radiation_specular_info.offset = 0;
3820 radiation_specular_info.range = VK_WHOLE_SIZE;
3822 if (radiation_specular_buffer.buffer != VK_NULL_HANDLE) {
3823 VkWriteDescriptorSet write{};
3824 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3825 write.dstSet = set_results;
3826 write.dstBinding = 10;
3827 write.dstArrayElement = 0;
3828 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3829 write.descriptorCount = 1;
3830 write.pBufferInfo = &radiation_specular_info;
3831 descriptor_writes.push_back(write);
3836 VkDescriptorBufferInfo diffuse_flux_info{};
3837 diffuse_flux_info.buffer = diffuse_flux_buffer.buffer;
3838 diffuse_flux_info.offset = 0;
3839 diffuse_flux_info.range = VK_WHOLE_SIZE;
3841 VkDescriptorBufferInfo diffuse_peak_dir_info{};
3842 diffuse_peak_dir_info.buffer = diffuse_peak_dir_buffer.buffer;
3843 diffuse_peak_dir_info.offset = 0;
3844 diffuse_peak_dir_info.range = VK_WHOLE_SIZE;
3846 VkDescriptorBufferInfo diffuse_extinction_info{};
3847 diffuse_extinction_info.buffer = diffuse_extinction_buffer.buffer;
3848 diffuse_extinction_info.offset = 0;
3849 diffuse_extinction_info.range = VK_WHOLE_SIZE;
3851 VkDescriptorBufferInfo diffuse_dist_norm_info{};
3852 diffuse_dist_norm_info.buffer = diffuse_dist_norm_buffer.buffer;
3853 diffuse_dist_norm_info.offset = 0;
3854 diffuse_dist_norm_info.range = VK_WHOLE_SIZE;
3856 VkDescriptorBufferInfo sky_radiance_params_info{};
3857 sky_radiance_params_info.buffer = sky_radiance_params_buffer.buffer;
3858 sky_radiance_params_info.offset = 0;
3859 sky_radiance_params_info.range = VK_WHOLE_SIZE;
3861 if (diffuse_flux_buffer.buffer != VK_NULL_HANDLE) {
3862 VkWriteDescriptorSet write{};
3863 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3864 write.dstSet = set_sky;
3865 write.dstBinding = 0;
3866 write.dstArrayElement = 0;
3867 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3868 write.descriptorCount = 1;
3869 write.pBufferInfo = &diffuse_flux_info;
3870 descriptor_writes.push_back(write);
3873 if (diffuse_peak_dir_buffer.buffer != VK_NULL_HANDLE) {
3874 VkWriteDescriptorSet write{};
3875 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3876 write.dstSet = set_sky;
3877 write.dstBinding = 1;
3878 write.dstArrayElement = 0;
3879 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3880 write.descriptorCount = 1;
3881 write.pBufferInfo = &diffuse_peak_dir_info;
3882 descriptor_writes.push_back(write);
3885 if (diffuse_extinction_buffer.buffer != VK_NULL_HANDLE) {
3886 VkWriteDescriptorSet write{};
3887 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3888 write.dstSet = set_sky;
3889 write.dstBinding = 2;
3890 write.dstArrayElement = 0;
3891 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3892 write.descriptorCount = 1;
3893 write.pBufferInfo = &diffuse_extinction_info;
3894 descriptor_writes.push_back(write);
3897 if (diffuse_dist_norm_buffer.buffer != VK_NULL_HANDLE) {
3898 VkWriteDescriptorSet write{};
3899 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3900 write.dstSet = set_sky;
3901 write.dstBinding = 3;
3902 write.dstArrayElement = 0;
3903 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3904 write.descriptorCount = 1;
3905 write.pBufferInfo = &diffuse_dist_norm_info;
3906 descriptor_writes.push_back(write);
3909 if (sky_radiance_params_buffer.buffer != VK_NULL_HANDLE) {
3910 VkWriteDescriptorSet write{};
3911 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3912 write.dstSet = set_sky;
3913 write.dstBinding = 4;
3914 write.dstArrayElement = 0;
3915 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3916 write.descriptorCount = 1;
3917 write.pBufferInfo = &sky_radiance_params_info;
3918 descriptor_writes.push_back(write);
3922 VkDescriptorBufferInfo camera_sky_radiance_info{};
3923 camera_sky_radiance_info.buffer = camera_sky_radiance_buffer.buffer;
3924 camera_sky_radiance_info.offset = 0;
3925 camera_sky_radiance_info.range = VK_WHOLE_SIZE;
3927 VkDescriptorBufferInfo solar_disk_radiance_info{};
3928 solar_disk_radiance_info.buffer = solar_disk_radiance_buffer.buffer;
3929 solar_disk_radiance_info.offset = 0;
3930 solar_disk_radiance_info.range = VK_WHOLE_SIZE;
3932 if (camera_sky_radiance_buffer.buffer != VK_NULL_HANDLE) {
3933 VkWriteDescriptorSet write{};
3934 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3935 write.dstSet = set_sky;
3936 write.dstBinding = 5;
3937 write.dstArrayElement = 0;
3938 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3939 write.descriptorCount = 1;
3940 write.pBufferInfo = &camera_sky_radiance_info;
3941 descriptor_writes.push_back(write);
3944 if (solar_disk_radiance_buffer.buffer != VK_NULL_HANDLE) {
3945 VkWriteDescriptorSet write{};
3946 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3947 write.dstSet = set_sky;
3948 write.dstBinding = 6;
3949 write.dstArrayElement = 0;
3950 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3951 write.descriptorCount = 1;
3952 write.pBufferInfo = &solar_disk_radiance_info;
3953 descriptor_writes.push_back(write);
3957 VkDescriptorBufferInfo camera_diffuse_flux_info{};
3958 camera_diffuse_flux_info.buffer = camera_diffuse_flux_buffer.buffer;
3959 camera_diffuse_flux_info.offset = 0;
3960 camera_diffuse_flux_info.range = VK_WHOLE_SIZE;
3962 VkDescriptorBufferInfo band_emission_flag_info{};
3963 band_emission_flag_info.buffer = band_emission_flag_buffer.buffer;
3964 band_emission_flag_info.offset = 0;
3965 band_emission_flag_info.range = VK_WHOLE_SIZE;
3967 if (camera_diffuse_flux_buffer.buffer != VK_NULL_HANDLE) {
3968 VkWriteDescriptorSet write{};
3969 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3970 write.dstSet = set_sky;
3971 write.dstBinding = 7;
3972 write.dstArrayElement = 0;
3973 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3974 write.descriptorCount = 1;
3975 write.pBufferInfo = &camera_diffuse_flux_info;
3976 descriptor_writes.push_back(write);
3979 if (band_emission_flag_buffer.buffer != VK_NULL_HANDLE) {
3980 VkWriteDescriptorSet write{};
3981 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3982 write.dstSet = set_sky;
3983 write.dstBinding = 8;
3984 write.dstArrayElement = 0;
3985 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3986 write.descriptorCount = 1;
3987 write.pBufferInfo = &band_emission_flag_info;
3988 descriptor_writes.push_back(write);
3993 VkDescriptorBufferInfo debug_counters_info{};
3994 debug_counters_info.buffer = debug_counters_buffer.buffer;
3995 debug_counters_info.offset = 0;
3996 debug_counters_info.range = VK_WHOLE_SIZE;
3998 if (debug_counters_buffer.buffer != VK_NULL_HANDLE) {
3999 VkWriteDescriptorSet write{};
4000 write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
4001 write.dstSet = set_debug;
4002 write.dstBinding = 0;
4003 write.dstArrayElement = 0;
4004 write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
4005 write.descriptorCount = 1;
4006 write.pBufferInfo = &debug_counters_info;
4007 descriptor_writes.push_back(write);
4011 if (!descriptor_writes.empty()) {
4012 vkUpdateDescriptorSets(vk_device,
static_cast<uint32_t
>(descriptor_writes.size()), descriptor_writes.data(), 0,
nullptr);