| … | … | @@ -5591,6 +5591,10 @@ void RenderingDeviceDriverD3D12::command_build_blas(CommandBufferID p_cmd_buffer |
| 5591 | 5591 | ERR_FAIL_MSG("Ray tracing is not currently supported by the D3D12 driver."); |
| 5592 | 5592 | } |
| 5593 | 5593 | |
| 5594 | void RenderingDeviceDriverD3D12::command_update_blas(CommandBufferID p_cmd_buffer, AccelerationStructureID p_acceleration_structure, BufferID p_scratch_buffer) { | |
| 5595 | ERR_FAIL_MSG("Ray tracing is not currently supported by the D3D12 driver."); | |
| 5596 | } | |
| 5597 | ||
| 5594 | 5598 | void RenderingDeviceDriverD3D12::command_build_tlas(CommandBufferID p_cmd_buffer, AccelerationStructureID p_acceleration_structure, BufferID p_scratch_buffer, BufferID p_instance_buffer, uint32_t p_instance_offset, uint32_t p_instance_count) { |
| 5595 | 5599 | ERR_FAIL_MSG("Ray tracing is not currently supported by the D3D12 driver."); |
| 5596 | 5600 | } |
| … | … | @@ -855,6 +855,7 @@ public: |
| 855 | 855 | // ----- COMMANDS ----- |
| 856 | 856 | |
| 857 | 857 | virtual void command_build_blas(CommandBufferID p_cmd_buffer, AccelerationStructureID p_acceleration_structure, BufferID p_scratch_buffer) override final; |
| 858 | virtual void command_update_blas(CommandBufferID p_cmd_buffer, AccelerationStructureID p_acceleration_structure, BufferID p_scratch_buffer) override final; | |
| 858 | 859 | virtual void command_build_tlas(CommandBufferID p_cmd_buffer, AccelerationStructureID p_acceleration_structure, BufferID p_scratch_buffer, BufferID p_instance_buffer, uint32_t p_instance_offset, uint32_t p_instance_count) override final; |
| 859 | 860 | virtual void command_bind_raytracing_pipeline(CommandBufferID p_cmd_buffer, RaytracingPipelineID p_pipeline) override final; |
| 860 | 861 | virtual void command_bind_raytracing_uniform_set(CommandBufferID p_cmd_buffer, UniformSetID p_uniform_set, ShaderID p_shader, uint32_t p_set_index) override final; |
| … | … | @@ -2307,6 +2307,10 @@ void RenderingDeviceDriverMetal::command_build_blas(CommandBufferID p_cmd_buffer |
| 2307 | 2307 | ERR_FAIL_MSG("Ray tracing is not currently supported by the Metal driver."); |
| 2308 | 2308 | } |
| 2309 | 2309 | |
| 2310 | void RenderingDeviceDriverMetal::command_update_blas(CommandBufferID p_cmd_buffer, AccelerationStructureID p_acceleration_structure, BufferID p_scratch_buffer) { | |
| 2311 | ERR_FAIL_MSG("Ray tracing is not currently supported by the Metal driver."); | |
| 2312 | } | |
| 2313 | ||
| 2310 | 2314 | void RenderingDeviceDriverMetal::command_build_tlas(CommandBufferID p_cmd_buffer, AccelerationStructureID p_acceleration_structure, BufferID p_scratch_buffer, BufferID p_instance_buffer, uint32_t p_instance_offset, uint32_t p_instance_count) { |
| 2311 | 2315 | ERR_FAIL_MSG("Ray tracing is not currently supported by the Metal driver."); |
| 2312 | 2316 | } |
| … | … | @@ -478,6 +478,7 @@ public: |
| 478 | 478 | // ----- COMMANDS ----- |
| 479 | 479 | |
| 480 | 480 | virtual void command_build_blas(CommandBufferID p_cmd_buffer, AccelerationStructureID p_acceleration_structure, BufferID p_scratch_buffer) override final; |
| 481 | virtual void command_update_blas(CommandBufferID p_cmd_buffer, AccelerationStructureID p_acceleration_structure, BufferID p_scratch_buffer) override final; | |
| 481 | 482 | virtual void command_build_tlas(CommandBufferID p_cmd_buffer, AccelerationStructureID p_acceleration_structure, BufferID p_scratch_buffer, BufferID p_instance_buffer, uint32_t p_instance_offset, uint32_t p_instance_count) override final; |
| 482 | 483 | virtual void command_bind_raytracing_pipeline(CommandBufferID p_cmd_buffer, RaytracingPipelineID p_pipeline) override final; |
| 483 | 484 | virtual void command_bind_raytracing_uniform_set(CommandBufferID p_cmd_buffer, UniformSetID p_uniform_set, ShaderID p_shader, uint32_t p_set_index) override final; |
| … | … | @@ -6527,7 +6527,13 @@ void RenderingDeviceDriverVulkan::_acceleration_structure_create(VkAccelerationS |
| 6527 | 6527 | |
| 6528 | 6528 | // Scratch address must be a multiple of minAccelerationStructureScratchOffsetAlignment. |
| 6529 | 6529 | r_accel_info->scratch_alignment = acceleration_structure_capabilities.min_acceleration_structure_scratch_offset_alignment; |
| 6530 | r_accel_info->scratch_size = p_size_info.buildScratchSize + r_accel_info->scratch_alignment; | |
| 6530 | // When ALLOW_UPDATE is requested, scratch must accommodate the larger of build/update sizes | |
| 6531 | // because the same scratch buffer is reused for both code paths. | |
| 6532 | VkDeviceSize required_scratch = p_size_info.buildScratchSize; | |
| 6533 | if (r_accel_info->build_info.flags & VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT_KHR) { | |
| 6534 | required_scratch = MAX(required_scratch, p_size_info.updateScratchSize); | |
| 6535 | } | |
| 6536 | r_accel_info->scratch_size = required_scratch + r_accel_info->scratch_alignment; | |
| 6531 | 6537 | |
| 6532 | 6538 | VkAccelerationStructureCreateInfoKHR accel_create_info = {}; |
| 6533 | 6539 | accel_create_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR; |
| … | … | @@ -6582,6 +6588,27 @@ void RenderingDeviceDriverVulkan::command_build_blas(CommandBufferID p_cmd_buffe |
| 6582 | 6588 | AccelerationStructureInfo *accel_info = (AccelerationStructureInfo *)p_acceleration_structure.id; |
| 6583 | 6589 | |
| 6584 | 6590 | VkAccelerationStructureBuildGeometryInfoKHR *build_info = &accel_info->build_info; |
| 6591 | build_info->mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR; | |
| 6592 | build_info->srcAccelerationStructure = VK_NULL_HANDLE; | |
| 6593 | build_info->dstAccelerationStructure = accel_info->vk_acceleration_structure; | |
| 6594 | VkDeviceAddress scratch_address = buffer_get_device_address(p_scratch_buffer); | |
| 6595 | build_info->scratchData.deviceAddress = _align_up_address(scratch_address, accel_info->scratch_alignment); | |
| 6596 | ||
| 6597 | const VkAccelerationStructureBuildRangeInfoKHR *range_infos = accel_info->range_infos.ptr(); | |
| 6598 | ||
| 6599 | vkCmdBuildAccelerationStructuresKHR(command_buffer->vk_command_buffer, 1, build_info, &range_infos); | |
| 6600 | #endif | |
| 6601 | } | |
| 6602 | ||
| 6603 | void RenderingDeviceDriverVulkan::command_update_blas(CommandBufferID p_cmd_buffer, AccelerationStructureID p_acceleration_structure, BufferID p_scratch_buffer) { | |
| 6604 | #if VULKAN_RAYTRACING_ENABLED | |
| 6605 | const CommandBufferInfo *command_buffer = (const CommandBufferInfo *)p_cmd_buffer.id; | |
| 6606 | AccelerationStructureInfo *accel_info = (AccelerationStructureInfo *)p_acceleration_structure.id; | |
| 6607 | ||
| 6608 | VkAccelerationStructureBuildGeometryInfoKHR *build_info = &accel_info->build_info; | |
| 6609 | build_info->mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_UPDATE_KHR; | |
| 6610 | build_info->srcAccelerationStructure = accel_info->vk_acceleration_structure; | |
| 6611 | build_info->dstAccelerationStructure = accel_info->vk_acceleration_structure; | |
| 6585 | 6612 | VkDeviceAddress scratch_address = buffer_get_device_address(p_scratch_buffer); |
| 6586 | 6613 | build_info->scratchData.deviceAddress = _align_up_address(scratch_address, accel_info->scratch_alignment); |
| 6587 | 6614 |
| … | … | @@ -735,6 +735,7 @@ private: |
| 735 | 735 | public: |
| 736 | 736 | // ----- COMMANDS ----- |
| 737 | 737 | virtual void command_build_blas(CommandBufferID p_cmd_buffer, AccelerationStructureID p_acceleration_structure, BufferID p_scratch_buffer) override final; |
| 738 | virtual void command_update_blas(CommandBufferID p_cmd_buffer, AccelerationStructureID p_acceleration_structure, BufferID p_scratch_buffer) override final; | |
| 738 | 739 | virtual void command_build_tlas(CommandBufferID p_cmd_buffer, AccelerationStructureID p_acceleration_structure, BufferID p_scratch_buffer, BufferID p_instance_buffer, uint32_t p_instance_offset, uint32_t p_instance_count) override final; |
| 739 | 740 | virtual void command_bind_raytracing_pipeline(CommandBufferID p_cmd_buffer, RaytracingPipelineID p_pipeline) override final; |
| 740 | 741 | virtual void command_bind_raytracing_uniform_set(CommandBufferID p_cmd_buffer, UniformSetID p_uniform_set, ShaderID p_shader, uint32_t p_set_index) override final; |
| … | … | @@ -243,6 +243,18 @@ void RenderRaytracing::cleanup_caches() { |
| 243 | 243 | } |
| 244 | 244 | surface_chunks.clear(); |
| 245 | 245 | |
| 246 | for (KeyValue<uint64_t, RTDeformedCacheEntry> &kv : deformed_surface_cache) { | |
| 247 | RTDeformedCacheEntry &e = kv.value; | |
| 248 | if (e.ptr) { | |
| 249 | if (e.ptr->blas.is_valid()) { | |
| 250 | RD::get_singleton()->free_rid(e.ptr->blas); | |
| 251 | } | |
| 252 | memdelete(e.ptr); | |
| 253 | e.ptr = nullptr; | |
| 254 | } | |
| 255 | } | |
| 256 | deformed_surface_cache.clear(); | |
| 257 | ||
| 246 | 258 | // Free all cached material data |
| 247 | 259 | for (uint32_t i = 0; i < material_chunks.size(); i++) { |
| 248 | 260 | if (material_chunks[i]) { |
| … | … | @@ -348,6 +360,27 @@ void RenderRaytracing::prepare_frame() { |
| 348 | 360 | motion_transforms.clear(); |
| 349 | 361 | |
| 350 | 362 | // Procedural BLAS/AABB lifetime is on the geometry instance. |
| 363 | { | |
| 364 | const uint32_t DEFORMED_CACHE_TTL_FRAMES = 60; | |
| 365 | uint32_t current_frame = RSG::rasterizer->get_frame_number(); | |
| 366 | LocalVector<uint64_t> to_remove; | |
| 367 | for (KeyValue<uint64_t, RTDeformedCacheEntry> &kv : deformed_surface_cache) { | |
| 368 | RTDeformedCacheEntry &e = kv.value; | |
| 369 | if (e.last_used_frame != 0 && current_frame - e.last_used_frame > DEFORMED_CACHE_TTL_FRAMES) { | |
| 370 | if (e.ptr) { | |
| 371 | if (e.ptr->blas.is_valid()) { | |
| 372 | RD::get_singleton()->free_rid(e.ptr->blas); | |
| 373 | } | |
| 374 | memdelete(e.ptr); | |
| 375 | e.ptr = nullptr; | |
| 376 | } | |
| 377 | to_remove.push_back(kv.key); | |
| 378 | } | |
| 379 | } | |
| 380 | for (uint64_t k : to_remove) { | |
| 381 | deformed_surface_cache.erase(k); | |
| 382 | } | |
| 383 | } | |
| 351 | 384 | |
| 352 | 385 | // Finish async HG compiles so live_ready_mask matches this frame (sync path fills at build_tlas end). |
| 353 | 386 | SceneShaderRaytracing::get_singleton()->drain_completed_compiles(); |
| … | … | @@ -412,41 +445,152 @@ RTSurfaceData *RenderRaytracing::process_surface( |
| 412 | 445 | |
| 413 | 446 | RTSurfaceData *surf_data = entry->ptr; |
| 414 | 447 | |
| 415 | // Get vertex/index arrays for BLAS creation | |
| 416 | SceneShaderForwardClustered::ShaderData *shader_data = surf->shader; | |
| 417 | bool emulate_point_size = shader_data->uses_point_size && owner->scene_shader.emulate_point_size; | |
| 448 | _populate_surface_blas(p_mesh_surface, RID(), false, false, false, cache_key, surf_data, r_dirty_blas_list); | |
| 449 | ||
| 450 | surf->cached_final_transform_valid = false; | |
| 451 | ||
| 452 | if (!surf_data->blas.is_valid()) { | |
| 453 | return surf_data; | |
| 454 | } | |
| 455 | ||
| 456 | entry->cached_counter = p_surface_invalidation_counter; | |
| 457 | entry->cached_rid_version = mesh_version; | |
| 458 | entry->last_used_frame = current_frame; | |
| 459 | ||
| 460 | return surf_data; | |
| 461 | } | |
| 462 | ||
| 463 | // --------------------------------------------------------------------------- | |
| 464 | // Deformed surface processing | |
| 465 | // --------------------------------------------------------------------------- | |
| 466 | ||
| 467 | RTSurfaceData *RenderRaytracing::process_deformed_surface( | |
| 468 | const void *p_surf, | |
| 469 | void *p_mesh_surface, | |
| 470 | const RTDeformedGeometrySource &p_source, | |
| 471 | LocalVector<RID> &r_dirty_blas_list, | |
| 472 | LocalVector<RID> &r_dirty_blas_update_list) { | |
| 473 | const RenderForwardClustered::GeometryInstanceSurfaceDataCache *surf = | |
| 474 | static_cast<const RenderForwardClustered::GeometryInstanceSurfaceDataCache *>(p_surf); | |
| 475 | ||
| 476 | if (!p_source.current_vb.is_valid()) { | |
| 477 | return nullptr; | |
| 478 | } | |
| 479 | ||
| 480 | uint32_t current_frame = RSG::rasterizer->get_frame_number(); | |
| 481 | uint64_t buffer_id = p_source.current_vb.get_id(); | |
| 482 | ||
| 483 | RTDeformedCacheEntry &entry = deformed_surface_cache[p_source.cache_key]; | |
| 484 | ||
| 485 | bool needs_refresh = !entry.ptr || | |
| 486 | entry.cached_key_version != p_source.cache_version || | |
| 487 | entry.cached_surface_counter != p_source.surface_counter || | |
| 488 | entry.cached_buffer_id != buffer_id || | |
| 489 | entry.cached_change_stamp != p_source.change_stamp; | |
| 490 | ||
| 491 | auto stamp_deformed_geometry = [&](RTSurfaceData *p_surf_data) { | |
| 492 | if (!p_surf_data || !p_surf_data->blas.is_valid()) { | |
| 493 | return; | |
| 494 | } | |
| 495 | p_surf_data->geometry.flags |= RT_GEOM_FLAG_DEFORMED; | |
| 496 | uint64_t prev_addr = 0; | |
| 497 | if (p_source.prev_vb.is_valid() && p_source.prev_vb != p_source.current_vb) { | |
| 498 | prev_addr = RD::get_singleton()->buffer_get_device_address(p_source.prev_vb); | |
| 499 | } | |
| 500 | p_surf_data->geometry.prev_vertex_buffer_address_lo = static_cast<uint32_t>(prev_addr & 0xFFFFFFFFULL); | |
| 501 | p_surf_data->geometry.prev_vertex_buffer_address_hi = static_cast<uint32_t>(prev_addr >> 32); | |
| 502 | }; | |
| 503 | ||
| 504 | if (!needs_refresh && entry.ptr->blas.is_valid()) { | |
| 505 | cache_hits++; | |
| 506 | entry.last_used_frame = current_frame; | |
| 507 | stamp_deformed_geometry(entry.ptr); | |
| 508 | return entry.ptr; | |
| 509 | } | |
| 510 | ||
| 511 | cache_misses++; | |
| 512 | ||
| 513 | // Refit when only the current deformed vertex buffer contents changed. | |
| 514 | bool can_refit = entry.ptr && entry.ptr->blas.is_valid() && entry.blas_built_once && | |
| 515 | entry.cached_key_version == p_source.cache_version && | |
| 516 | entry.cached_surface_counter == p_source.surface_counter && | |
| 517 | entry.cached_buffer_id == buffer_id; | |
| 518 | ||
| 519 | if (can_refit) { | |
| 520 | RTSurfaceData *surf_data = entry.ptr; | |
| 521 | r_dirty_blas_update_list.push_back(surf_data->blas); | |
| 522 | surf->cached_final_transform_valid = false; | |
| 523 | stamp_deformed_geometry(surf_data); | |
| 524 | entry.cached_change_stamp = p_source.change_stamp; | |
| 525 | entry.last_used_frame = current_frame; | |
| 526 | return surf_data; | |
| 527 | } | |
| 528 | ||
| 529 | if (!entry.ptr) { | |
| 530 | entry.ptr = memnew(RTSurfaceData); | |
| 531 | } else if (entry.ptr->blas.is_valid()) { | |
| 532 | RD::get_singleton()->free_rid(entry.ptr->blas); | |
| 533 | entry.ptr->blas = RID(); | |
| 534 | entry.blas_built_once = false; | |
| 535 | } | |
| 536 | ||
| 537 | RTSurfaceData *surf_data = entry.ptr; | |
| 538 | ||
| 539 | _populate_surface_blas(p_mesh_surface, p_source.current_vb, true, true, true, static_cast<uint32_t>(p_source.cache_key), surf_data, r_dirty_blas_list); | |
| 540 | ||
| 541 | surf->cached_final_transform_valid = false; | |
| 542 | ||
| 543 | if (!surf_data->blas.is_valid()) { | |
| 544 | return surf_data; | |
| 545 | } | |
| 546 | ||
| 547 | stamp_deformed_geometry(surf_data); | |
| 548 | ||
| 549 | entry.blas_built_once = true; | |
| 550 | entry.cached_change_stamp = p_source.change_stamp; | |
| 551 | entry.cached_key_version = p_source.cache_version; | |
| 552 | entry.cached_surface_counter = p_source.surface_counter; | |
| 553 | entry.cached_buffer_id = buffer_id; | |
| 554 | entry.last_used_frame = current_frame; | |
| 555 | ||
| 556 | return surf_data; | |
| 557 | } | |
| 558 | ||
| 559 | // --------------------------------------------------------------------------- | |
| 560 | // Surface BLAS helper (shared between static and deformed paths) | |
| 561 | // --------------------------------------------------------------------------- | |
| 418 | 562 | |
| 419 | SceneShaderForwardClustered::ShaderData::PipelineKey pipeline_key; | |
| 420 | pipeline_key.primitive_type = surf->primitive; | |
| 421 | pipeline_key.version = SceneShaderForwardClustered::PIPELINE_VERSION_COLOR_PASS; | |
| 422 | pipeline_key.color_pass_flags = 0; | |
| 423 | pipeline_key.wireframe = false; | |
| 424 | pipeline_key.ubershader = 0; | |
| 563 | void RenderRaytracing::_populate_surface_blas( | |
| 564 | void *p_mesh_surface, | |
| 565 | RID p_vertex_buffer_override, | |
| 566 | bool p_force_uncompressed, | |
| 567 | bool p_prefer_fast_build, | |
| 568 | bool p_allow_update, | |
| 569 | uint32_t p_cache_key, | |
| 570 | RTSurfaceData *r_surf_data, | |
| 571 | LocalVector<RID> &r_dirty_blas_list) { | |
| 572 | RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton(); | |
| 425 | 573 | |
| 426 | // Build geometry data | |
| 427 | 574 | uint64_t surface_format = mesh_storage->mesh_surface_get_format(p_mesh_surface); |
| 428 | bool compressed = surface_format & RSE::ARRAY_FLAG_COMPRESS_ATTRIBUTES; | |
| 575 | bool compressed = (surface_format & RSE::ARRAY_FLAG_COMPRESS_ATTRIBUTES) && !p_force_uncompressed; | |
| 429 | 576 | bool is_2d = surface_format & RSE::ARRAY_FLAG_USE_2D_VERTICES; |
| 430 | 577 | |
| 431 | surf_data->is_compressed = compressed; | |
| 578 | r_surf_data->is_compressed = compressed; | |
| 432 | 579 | |
| 433 | // Compute AABB transform for compressed meshes | |
| 434 | 580 | if (compressed) { |
| 435 | 581 | AABB surface_aabb = mesh_storage->mesh_surface_get_aabb(p_mesh_surface); |
| 436 | surf_data->aabb_transform.basis = Basis::from_scale(surface_aabb.size); | |
| 437 | surf_data->aabb_transform.origin = surface_aabb.position; | |
| 582 | r_surf_data->aabb_transform.basis = Basis::from_scale(surface_aabb.size); | |
| 583 | r_surf_data->aabb_transform.origin = surface_aabb.position; | |
| 438 | 584 | } else { |
| 439 | surf_data->aabb_transform = Transform3D(); | |
| 585 | r_surf_data->aabb_transform = Transform3D(); | |
| 440 | 586 | } |
| 441 | 587 | |
| 442 | // Invalidate per-surface cached final transform since aabb_transform was recomputed. | |
| 443 | surf->cached_final_transform_valid = false; | |
| 444 | ||
| 445 | // Populate geometry data | |
| 446 | RT_GeometryData &geom = surf_data->geometry; | |
| 588 | RT_GeometryData &geom = r_surf_data->geometry; | |
| 447 | 589 | memset(&geom, 0, sizeof(geom)); |
| 448 | 590 | |
| 449 | RID vertex_buffer = mesh_storage->mesh_surface_get_vertex_buffer(p_mesh_surface); | |
| 591 | RID vertex_buffer = p_vertex_buffer_override.is_valid() | |
| 592 | ? p_vertex_buffer_override | |
| 593 | : mesh_storage->mesh_surface_get_vertex_buffer(p_mesh_surface); | |
| 450 | 594 | RID attribute_buffer = mesh_storage->mesh_surface_get_attribute_buffer(p_mesh_surface); |
| 451 | 595 | RID index_buffer = mesh_storage->mesh_surface_get_index_buffer(p_mesh_surface, 0); |
| 452 | 596 | |
| … | … | @@ -591,20 +735,21 @@ RTSurfaceData *RenderRaytracing::process_surface( |
| 591 | 735 | as_geom.geometry.triangles.index_count = index_count; |
| 592 | 736 | } |
| 593 | 737 | |
| 594 | surf_data->blas = RD::get_singleton()->blas_create({ &as_geom, 1 }, RD::ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT); | |
| 595 | if (!surf_data->blas.is_valid()) { | |
| 596 | return surf_data; | |
| 738 | BitField<RD::AccelerationStructureFlagBits> as_flags = p_prefer_fast_build | |
| 739 | ? RD::ACCELERATION_STRUCTURE_PREFER_FAST_BUILD_BIT | |
| 740 | : RD::ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT; | |
| 741 | if (p_allow_update) { | |
| 742 | as_flags.set_flag(RD::ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT); | |
| 597 | 743 | } |
| 598 | RD::get_singleton()->set_resource_name(surf_data->blas, String("RT BLAS [") + itos(cache_key) + "]"); | |
| 599 | r_dirty_blas_list.push_back(surf_data->blas); | |
| 600 | } | |
| 601 | ||
| 602 | // Update cache entry | |
| 603 | entry->cached_counter = p_surface_invalidation_counter; | |
| 604 | entry->cached_rid_version = mesh_version; | |
| 605 | entry->last_used_frame = current_frame; | |
| 606 | 744 | |
| 607 | return surf_data; | |
| 745 | r_surf_data->blas = RD::get_singleton()->blas_create({ &as_geom, 1 }, as_flags); | |
| 746 | if (!r_surf_data->blas.is_valid()) { | |
| 747 | return; | |
| 748 | } | |
| 749 | RD::get_singleton()->set_resource_name(r_surf_data->blas, | |
| 750 | String(p_vertex_buffer_override.is_valid() ? "RT BLAS deformed [" : "RT BLAS [") + itos(p_cache_key) + "]"); | |
| 751 | r_dirty_blas_list.push_back(r_surf_data->blas); | |
| 752 | } | |
| 608 | 753 | } |
| 609 | 754 | |
| 610 | 755 | // --------------------------------------------------------------------------- |
| … | … | @@ -1304,13 +1449,19 @@ RTMaterialData *RenderRaytracing::process_material(RID p_material_rid, uint16_t |
| 1304 | 1449 | // Acceleration structure building |
| 1305 | 1450 | // --------------------------------------------------------------------------- |
| 1306 | 1451 | |
| 1307 | void RenderRaytracing::build_acceleration_structures(RTViewportState *p_state, const LocalVector<RID> &p_dirty_blas_list) { | |
| 1452 | void RenderRaytracing::build_acceleration_structures(RTViewportState *p_state, const LocalVector<RID> &p_dirty_blas_list, const LocalVector<RID> &p_dirty_blas_update_list) { | |
| 1308 | 1453 | for (const RID &blas_rid : p_dirty_blas_list) { |
| 1309 | 1454 | if (blas_rid.is_valid()) { |
| 1310 | 1455 | RD::get_singleton()->blas_build(blas_rid); |
| 1311 | 1456 | } |
| 1312 | 1457 | } |
| 1313 | 1458 | |
| 1459 | for (const RID &blas_rid : p_dirty_blas_update_list) { | |
| 1460 | if (blas_rid.is_valid()) { | |
| 1461 | RD::get_singleton()->blas_update(blas_rid); | |
| 1462 | } | |
| 1463 | } | |
| 1464 | ||
| 1314 | 1465 | uint32_t needed = MAX(blass.size(), (uint32_t)1); |
| 1315 | 1466 | if (!p_state->tlas.is_valid() || needed > p_state->tlas_max_instances) { |
| 1316 | 1467 | if (p_state->tlas.is_valid()) { |
| … | … | @@ -1395,6 +1546,7 @@ RTViewportState *RenderRaytracing::build_tlas(const RenderDataRD *p_render_data, |
| 1395 | 1546 | RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton(); |
| 1396 | 1547 | RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); |
| 1397 | 1548 | LocalVector<RID> dirty_blas_list; |
| 1549 | LocalVector<RID> dirty_blas_update_list; | |
| 1398 | 1550 | |
| 1399 | 1551 | #ifdef TOOLS_ENABLED |
| 1400 | 1552 | uint32_t tlas_instance_count = 0; |
| … | … | @@ -1494,7 +1646,26 @@ RTViewportState *RenderRaytracing::build_tlas(const RenderDataRD *p_render_data, |
| 1494 | 1646 | void *mesh_surface = surf->surface; |
| 1495 | 1647 | uint32_t surface_counter = mesh_storage->mesh_surface_get_rt_invalidation_counter(mesh_surface); |
| 1496 | 1648 | |
| 1497 | RTSurfaceData *surf_data = process_surface(surf, mesh_surface, surface_counter, instance_transform, dirty_blas_list); | |
| 1649 | // MeshInstance skinning/blend shapes provide a deformed vertex buffer. | |
| 1650 | RTSurfaceData *surf_data = nullptr; | |
| 1651 | if (inst->mesh_instance.is_valid()) { | |
| 1652 | RID curr_vb = mesh_storage->mesh_instance_get_vertex_buffer(inst->mesh_instance, surf->surface_index); | |
| 1653 | if (curr_vb.is_valid()) { | |
| 1654 | RTDeformedGeometrySource src; | |
| 1655 | src.current_vb = curr_vb; | |
| 1656 | src.prev_vb = mesh_storage->mesh_instance_get_prev_vertex_buffer(inst->mesh_instance, surf->surface_index); | |
| 1657 | src.change_stamp = mesh_storage->mesh_instance_get_last_change(inst->mesh_instance, surf->surface_index); | |
| 1658 | uint64_t mi_id = inst->mesh_instance.get_id(); | |
| 1659 | uint32_t mi_index = static_cast<uint32_t>(mi_id & 0xFFFFFFFFULL); | |
| 1660 | src.cache_version = static_cast<uint32_t>(mi_id >> 32); | |
| 1661 | src.cache_key = (static_cast<uint64_t>(mi_index) << 16) | (surf->surface_index & 0xFFFFu); | |
| 1662 | src.surface_counter = surface_counter; | |
| 1663 | surf_data = process_deformed_surface(surf, mesh_surface, src, dirty_blas_list, dirty_blas_update_list); | |
| 1664 | } | |
| 1665 | } | |
| 1666 | if (!surf_data) { | |
| 1667 | surf_data = process_surface(surf, mesh_surface, surface_counter, instance_transform, dirty_blas_list); | |
| 1668 | } | |
| 1498 | 1669 | if (!surf_data || !surf_data->blas.is_valid()) { |
| 1499 | 1670 | surf = surf->next; |
| 1500 | 1671 | continue; |
| … | … | @@ -1612,7 +1783,7 @@ RTViewportState *RenderRaytracing::build_tlas(const RenderDataRD *p_render_data, |
| 1612 | 1783 | |
| 1613 | 1784 | SceneShaderRaytracing::get_singleton()->finalize_custom_shaders(); |
| 1614 | 1785 | |
| 1615 | build_acceleration_structures(state, dirty_blas_list); | |
| 1786 | build_acceleration_structures(state, dirty_blas_list, dirty_blas_update_list); | |
| 1616 | 1787 | finalize_buffers(state); |
| 1617 | 1788 | |
| 1618 | 1789 | return state; |
| … | … | @@ -79,7 +79,10 @@ struct alignas(16) RT_GeometryData { |
| 79 | 79 | float aabb_pos_x; |
| 80 | 80 | float aabb_pos_y; |
| 81 | 81 | float aabb_pos_z; |
| 82 | uint32_t _pad[7]; | |
| 82 | // For deformed geometry: previous-frame position buffer used for motion vectors. | |
| 83 | uint32_t prev_vertex_buffer_address_lo; | |
| 84 | uint32_t prev_vertex_buffer_address_hi; | |
| 85 | uint32_t _pad[5]; | |
| 83 | 86 | }; |
| 84 | 87 | static_assert(sizeof(RT_GeometryData) == 128, "RT_GeometryData must be 128 bytes for std430"); |
| 85 | 88 | |
| … | … | @@ -166,6 +169,8 @@ enum { |
| 166 | 169 | enum { |
| 167 | 170 | RT_GEOM_FLAG_COMPRESSED = 1u, |
| 168 | 171 | RT_GEOM_FLAG_PROCEDURAL = 2u, |
| 172 | // Set when the BLAS uses a per-frame-deformed vertex buffer. | |
| 173 | RT_GEOM_FLAG_DEFORMED = 4u, | |
| 169 | 174 | }; |
| 170 | 175 | |
| 171 | 176 | /// Per-instance state for procedural RT geometry. Heap-allocated, only exists for procedural instances. |
| … | … | @@ -189,6 +194,16 @@ struct RTSurfaceData { |
| 189 | 194 | uint64_t blas_size = 0; |
| 190 | 195 | }; |
| 191 | 196 | |
| 197 | /// Inputs for a surface backed by a per-frame-deformed vertex buffer. | |
| 198 | struct RTDeformedGeometrySource { | |
| 199 | RID current_vb; ///< Vertex buffer (object-space positions) the BLAS is built / refit against. | |
| 200 | RID prev_vb; ///< Previous-frame positions for motion vectors. Optional. | |
| 201 | uint64_t change_stamp = 0; ///< Changes when `current_vb` contents change. | |
| 202 | uint64_t cache_key = 0; ///< Caller-defined cache identity. | |
| 203 | uint32_t cache_version = 0; ///< Changes when the resource behind `cache_key` is recycled. | |
| 204 | uint32_t surface_counter = 0; ///< Changes when the underlying mesh surface changes. | |
| 205 | }; | |
| 206 | ||
| 192 | 207 | struct RTMaterialData { |
| 193 | 208 | alignas(16) RT_MaterialData data = {}; |
| 194 | 209 | uint32_t global_buffer_index = UINT32_MAX; |
| … | … | @@ -263,6 +278,18 @@ class RenderRaytracing { |
| 263 | 278 | // Caching (chunked sparse caches indexed by RID low bits / 256). |
| 264 | 279 | Vector<RTCacheEntry *> surface_chunks; |
| 265 | 280 | Vector<RTMaterialCacheEntry *> material_chunks; |
| 281 | ||
| 282 | // BLAS cache for surfaces driven by per-frame-deformed vertex buffers. | |
| 283 | struct RTDeformedCacheEntry { | |
| 284 | RTSurfaceData *ptr = nullptr; | |
| 285 | uint32_t last_used_frame = 0; | |
| 286 | uint64_t cached_change_stamp = 0; | |
| 287 | uint32_t cached_key_version = 0; | |
| 288 | uint32_t cached_surface_counter = 0; | |
| 289 | uint64_t cached_buffer_id = 0; // RID id of the deformed vertex buffer at the time of build. | |
| 290 | bool blas_built_once = false; // True once the BLAS has been fully built; subsequent ticks can refit. | |
| 291 | }; | |
| 292 | HashMap<uint64_t, RTDeformedCacheEntry> deformed_surface_cache; | |
| 266 | 293 | LocalVector<uint32_t> material_free_slots; |
| 267 | 294 | uint32_t next_material_slot = 0; |
| 268 | 295 | uint64_t vram_used = 0; |
| … | … | @@ -315,9 +342,24 @@ class RenderRaytracing { |
| 315 | 342 | uint32_t p_surface_invalidation_counter, |
| 316 | 343 | const Transform3D &p_transform, |
| 317 | 344 | LocalVector<RID> &r_dirty_blas_list); |
| 345 | RTSurfaceData *process_deformed_surface( | |
| 346 | const void *p_surf, | |
| 347 | void *p_mesh_surface, | |
| 348 | const struct RTDeformedGeometrySource &p_source, | |
| 349 | LocalVector<RID> &r_dirty_blas_list, | |
| 350 | LocalVector<RID> &r_dirty_blas_update_list); | |
| 351 | void _populate_surface_blas( | |
| 352 | void *p_mesh_surface, | |
| 353 | RID p_vertex_buffer_override, | |
| 354 | bool p_force_uncompressed, | |
| 355 | bool p_prefer_fast_build, | |
| 356 | bool p_allow_update, | |
| 357 | uint32_t p_cache_key, | |
| 358 | RTSurfaceData *r_surf_data, | |
| 359 | LocalVector<RID> &r_dirty_blas_list); | |
| 318 | 360 | RTMaterialData *process_material(RID p_material_rid, uint16_t p_material_invalidation_counter); |
| 319 | 361 | void update_procedural_blas(RTProceduralState *p_state, LocalVector<RID> &r_dirty_blas_list); |
| 320 | void build_acceleration_structures(RTViewportState *p_state, const LocalVector<RID> &p_dirty_blas_list); | |
| 362 | void build_acceleration_structures(RTViewportState *p_state, const LocalVector<RID> &p_dirty_blas_list, const LocalVector<RID> &p_dirty_blas_update_list); | |
| 321 | 363 | void finalize_buffers(RTViewportState *p_state); |
| 322 | 364 | void prepare_frame(); |
| 323 | 365 |
| … | … | @@ -166,13 +166,37 @@ void write_primary_hit_velocity(vec3 hit_pos) { |
| 166 | 166 | vec3 obj_pos = (mat4(gl_WorldToObjectEXT) * vec4(hit_pos, 1.0)).xyz; |
| 167 | 167 | vec3 prev_obj_pos = obj_pos; |
| 168 | 168 | |
| 169 | #ifdef ENABLE_INTERSECTION_SHADERS | |
| 170 | 169 | GeometryData geom = geometries[geom_idx]; |
| 170 | ||
| 171 | #ifdef ENABLE_INTERSECTION_SHADERS | |
| 171 | 172 | if ((geom.flags & FLAG_PROCEDURAL) != 0u) { |
| 172 | 173 | prev_obj_pos += decode_prev_pos_delta(); |
| 173 | 174 | } |
| 174 | 175 | #endif |
| 175 | 176 | |
| 177 | #ifdef RT_HIT_ATTRIBS_DECLARED | |
| 178 | if ((geom.flags & FLAG_DEFORMED) != 0u) { | |
| 179 | uint64_t prev_addr = packUint2x32(uvec2(geom.prev_vertex_address_lo, geom.prev_vertex_address_hi)); | |
| 180 | if (prev_addr != 0ul) { | |
| 181 | uint i0, i1, i2; | |
| 182 | get_triangle_indices(geom, i0, i1, i2); | |
| 183 | vec3 bary = vec3(1.0 - attribs.x - attribs.y, attribs.x, attribs.y); | |
| 184 | FloatBuffer prev_vb = FloatBuffer(prev_addr); | |
| 185 | uint stride_floats = geom.position_stride >> 2; | |
| 186 | vec3 p0 = vec3(prev_vb.v[i0 * stride_floats + 0u], | |
| 187 | prev_vb.v[i0 * stride_floats + 1u], | |
| 188 | prev_vb.v[i0 * stride_floats + 2u]); | |
| 189 | vec3 p1 = vec3(prev_vb.v[i1 * stride_floats + 0u], | |
| 190 | prev_vb.v[i1 * stride_floats + 1u], | |
| 191 | prev_vb.v[i1 * stride_floats + 2u]); | |
| 192 | vec3 p2 = vec3(prev_vb.v[i2 * stride_floats + 0u], | |
| 193 | prev_vb.v[i2 * stride_floats + 1u], | |
| 194 | prev_vb.v[i2 * stride_floats + 2u]); | |
| 195 | prev_obj_pos = bary.x * p0 + bary.y * p1 + bary.z * p2; | |
| 196 | } | |
| 197 | } | |
| 198 | #endif | |
| 199 | ||
| 176 | 200 | vec3 prev_world_pos = (prev_model * vec4(prev_obj_pos, 1.0)).xyz; |
| 177 | 201 | |
| 178 | 202 | vec2 curr_uv = project_uv(hit_pos, curr_vp_unjittered); |
| … | … | @@ -44,7 +44,11 @@ struct GeometryData { |
| 44 | 44 | float aabb_pos_y; |
| 45 | 45 | float aabb_pos_z; |
| 46 | 46 | |
| 47 | uint _pad[7]; | |
| 47 | // For deformed geometry: previous-frame position buffer used for motion vectors. | |
| 48 | uint prev_vertex_address_lo; | |
| 49 | uint prev_vertex_address_hi; | |
| 50 | ||
| 51 | uint _pad[5]; | |
| 48 | 52 | }; |
| 49 | 53 | |
| 50 | 54 | void get_aabb_compression_xforms(GeometryData geom, out mat4 aabb_xform, out mat4 inv_aabb_xform) { |
| … | … | @@ -140,6 +140,8 @@ bool is_path_terminated(uint packed) { |
| 140 | 140 | const uint OFFSET_NONE = 0xFFFFFFFFu; |
| 141 | 141 | const uint FLAG_COMPRESSED = 1u; |
| 142 | 142 | const uint FLAG_PROCEDURAL = 2u; |
| 143 | // Set when the BLAS uses a per-frame-deformed vertex buffer. | |
| 144 | const uint FLAG_DEFORMED = 4u; | |
| 143 | 145 | |
| 144 | 146 | // ============================================================================ |
| 145 | 147 | // RANDOM NUMBER GENERATION - PCG (Permuted Congruential Generator) |
| … | … | @@ -1079,7 +1079,13 @@ void MeshStorage::_mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint3 |
| 1079 | 1079 | } |
| 1080 | 1080 | |
| 1081 | 1081 | void MeshStorage::_mesh_instance_add_surface_buffer(MeshInstance *mi, Mesh *mesh, MeshInstance::Surface *s, uint32_t p_surface, uint32_t p_buffer_index) { |
| 1082 | s->vertex_buffer[p_buffer_index] = RD::get_singleton()->vertex_buffer_create(mesh->surfaces[p_surface]->vertex_buffer_size, Vector<uint8_t>(), RD::BUFFER_CREATION_AS_STORAGE_BIT); | |
| 1082 | BitField<RD::BufferCreationBits> buffer_flags = RD::BUFFER_CREATION_AS_STORAGE_BIT; | |
| 1083 | // Allow this skinned/blend-shape output buffer to be consumed by the raytracing path as a BLAS triangle source. | |
| 1084 | if (RD::get_singleton()->has_feature(RD::SUPPORTS_RAYTRACING_PIPELINE) || RD::get_singleton()->has_feature(RD::SUPPORTS_RAY_QUERY)) { | |
| 1085 | buffer_flags.set_flag(RD::BUFFER_CREATION_DEVICE_ADDRESS_BIT); | |
| 1086 | buffer_flags.set_flag(RD::BUFFER_CREATION_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT); | |
| 1087 | } | |
| 1088 | s->vertex_buffer[p_buffer_index] = RD::get_singleton()->vertex_buffer_create(mesh->surfaces[p_surface]->vertex_buffer_size, Vector<uint8_t>(), buffer_flags); | |
| 1083 | 1089 | |
| 1084 | 1090 | Vector<RD::Uniform> uniforms; |
| 1085 | 1091 | { |
| … | … | @@ -485,6 +485,39 @@ public: |
| 485 | 485 | return s->vertex_buffer; |
| 486 | 486 | } |
| 487 | 487 | |
| 488 | /// Get the per-mesh-instance skinned/blend-shape vertex buffer for the current frame. | |
| 489 | /// Returns RID() when this surface is not deformed (caller should fall back to mesh_surface_get_vertex_buffer). | |
| 490 | _FORCE_INLINE_ RID mesh_instance_get_vertex_buffer(RID p_mesh_instance, uint32_t p_surface_index) { | |
| 491 | MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance); | |
| 492 | if (!mi || p_surface_index >= mi->surfaces.size()) { | |
| 493 | return RID(); | |
| 494 | } | |
| 495 | const MeshInstance::Surface &mis = mi->surfaces[p_surface_index]; | |
| 496 | return mis.vertex_buffer[mis.current_buffer]; | |
| 497 | } | |
| 498 | ||
| 499 | /// Get the previous-frame skinned vertex buffer (for motion vector reconstruction). | |
| 500 | /// Returns the current buffer when the surface was not updated this frame, or when | |
| 501 | /// update_mesh_instances() did not double-buffer this surface. | |
| 502 | _FORCE_INLINE_ RID mesh_instance_get_prev_vertex_buffer(RID p_mesh_instance, uint32_t p_surface_index) { | |
| 503 | MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance); | |
| 504 | if (!mi || p_surface_index >= mi->surfaces.size()) { | |
| 505 | return RID(); | |
| 506 | } | |
| 507 | const MeshInstance::Surface &mis = mi->surfaces[p_surface_index]; | |
| 508 | uint32_t previous_buffer = RSG::rasterizer->get_frame_number() == mis.last_change ? mis.previous_buffer : mis.current_buffer; | |
| 509 | return mis.vertex_buffer[previous_buffer]; | |
| 510 | } | |
| 511 | ||
| 512 | /// Frame number on which this mesh-instance surface was last skinned (0 if never deformed). | |
| 513 | _FORCE_INLINE_ uint64_t mesh_instance_get_last_change(RID p_mesh_instance, uint32_t p_surface_index) { | |
| 514 | MeshInstance *mi = mesh_instance_owner.get_or_null(p_mesh_instance); | |
| 515 | if (!mi || p_surface_index >= mi->surfaces.size()) { | |
| 516 | return 0; | |
| 517 | } | |
| 518 | return mi->surfaces[p_surface_index].last_change; | |
| 519 | } | |
| 520 | ||
| 488 | 521 | /// Get the attribute buffer RID for raytracing device address access. |
| 489 | 522 | _FORCE_INLINE_ RID mesh_surface_get_attribute_buffer(void *p_surface) { |
| 490 | 523 | Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface); |
| … | … | @@ -514,6 +514,27 @@ Error RenderingDevice::blas_build(RID p_blas) { |
| 514 | 514 | return OK; |
| 515 | 515 | } |
| 516 | 516 | |
| 517 | Error RenderingDevice::blas_update(RID p_blas) { | |
| 518 | ERR_RENDER_THREAD_GUARD_V(ERR_UNAVAILABLE); | |
| 519 | ||
| 520 | ERR_FAIL_COND_V_MSG(draw_list.active, ERR_INVALID_PARAMETER, "Updating BLAS is forbidden during creation of a draw list."); | |
| 521 | ERR_FAIL_COND_V_MSG(compute_list.active, ERR_INVALID_PARAMETER, "Updating BLAS is forbidden during creation of a compute list."); | |
| 522 | ERR_FAIL_COND_V_MSG(raytracing_list.active, ERR_INVALID_PARAMETER, "Updating BLAS is forbidden during creation of a raytracing list."); | |
| 523 | ||
| 524 | AccelerationStructure *blas = acceleration_structure_owner.get_or_null(p_blas); | |
| 525 | ERR_FAIL_NULL_V_MSG(blas, ERR_INVALID_PARAMETER, "BLAS argument is not valid."); | |
| 526 | ||
| 527 | Error err = _acceleration_structure_scratch_buffer_create(blas); | |
| 528 | ERR_FAIL_COND_V(err != OK, err); | |
| 529 | ||
| 530 | draw_graph.add_blas_update(blas->driver_id, blas->scratch_buffer, blas->draw_tracker, blas->draw_trackers); | |
| 531 | ||
| 532 | blas->invalidated = false; | |
| 533 | _blas_remove_tlas_dependencies(blas, p_blas); | |
| 534 | ||
| 535 | return OK; | |
| 536 | } | |
| 537 | ||
| 517 | 538 | Error RenderingDevice::tlas_build(RID p_tlas, Span<AccelerationStructureInstance> p_instances) { |
| 518 | 539 | ERR_RENDER_THREAD_GUARD_V(ERR_UNAVAILABLE); |
| 519 | 540 |
| … | … | @@ -1417,6 +1417,10 @@ public: |
| 1417 | 1417 | }; |
| 1418 | 1418 | |
| 1419 | 1419 | Error blas_build(RID p_blas); |
| 1420 | // In-place refit of a BLAS that was created with ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT and | |
| 1421 | // previously fully built; only vertex positions may have changed since then. Significantly | |
| 1422 | // cheaper than blas_build for skinned/animated meshes. | |
| 1423 | Error blas_update(RID p_blas); | |
| 1420 | 1424 | Error tlas_build(RID p_tlas, Span<AccelerationStructureInstance> p_instances); |
| 1421 | 1425 | |
| 1422 | 1426 | private: |
| … | … | @@ -828,6 +828,9 @@ public: |
| 828 | 828 | // ----- COMMANDS ----- |
| 829 | 829 | |
| 830 | 830 | virtual void command_build_blas(CommandBufferID p_cmd_buffer, AccelerationStructureID p_acceleration_structure, BufferID p_scratch_buffer) = 0; |
| 831 | // In-place refit of a BLAS previously built with ACCELERATION_STRUCTURE_ALLOW_UPDATE_BIT. | |
| 832 | // Geometry topology / counts must be unchanged; only vertex positions may differ. | |
| 833 | virtual void command_update_blas(CommandBufferID p_cmd_buffer, AccelerationStructureID p_acceleration_structure, BufferID p_scratch_buffer) = 0; | |
| 831 | 834 | virtual void command_build_tlas(CommandBufferID p_cmd_buffer, AccelerationStructureID p_acceleration_structure, BufferID p_scratch_buffer, BufferID p_instance_buffer, uint32_t p_instance_offset, uint32_t p_instance_count) = 0; |
| 832 | 835 | virtual void command_bind_raytracing_pipeline(CommandBufferID p_cmd_buffer, RaytracingPipelineID p_pipeline) = 0; |
| 833 | 836 | virtual void command_bind_raytracing_uniform_set(CommandBufferID p_cmd_buffer, UniformSetID p_uniform_set, ShaderID p_shader, uint32_t p_set_index) = 0; |
| … | … | @@ -1085,6 +1085,10 @@ void RenderingDeviceGraph::_run_render_commands(int32_t p_level, const RecordedC |
| 1085 | 1085 | const RecordedBottomLevelAccelerationStructureBuildCommand *blas_build_command = reinterpret_cast<const RecordedBottomLevelAccelerationStructureBuildCommand *>(command); |
| 1086 | 1086 | driver->command_build_blas(r_command_buffer, blas_build_command->acceleration_structure, blas_build_command->scratch_buffer); |
| 1087 | 1087 | } break; |
| 1088 | case RecordedCommand::TYPE_BOTTOM_LEVEL_ACCELERATION_STRUCTURE_UPDATE: { | |
| 1089 | const RecordedBottomLevelAccelerationStructureBuildCommand *blas_update_command = reinterpret_cast<const RecordedBottomLevelAccelerationStructureBuildCommand *>(command); | |
| 1090 | driver->command_update_blas(r_command_buffer, blas_update_command->acceleration_structure, blas_update_command->scratch_buffer); | |
| 1091 | } break; | |
| 1088 | 1092 | case RecordedCommand::TYPE_TOP_LEVEL_ACCELERATION_STRUCTURE_BUILD: { |
| 1089 | 1093 | const RecordedTopLevelAccelerationStructureBuildCommand *tlas_build_command = reinterpret_cast<const RecordedTopLevelAccelerationStructureBuildCommand *>(command); |
| 1090 | 1094 | driver->command_build_tlas(r_command_buffer, tlas_build_command->acceleration_structure, tlas_build_command->scratch_buffer, tlas_build_command->instance_buffer, tlas_build_command->instance_offset, tlas_build_command->instance_count); |
| … | … | @@ -1810,6 +1814,32 @@ void RenderingDeviceGraph::add_blas_build(RDD::AccelerationStructureID p_acceler |
| 1810 | 1814 | _add_command_to_graph(trackers.ptr(), usages.ptr(), usages.size(), command_index, command); |
| 1811 | 1815 | } |
| 1812 | 1816 | |
| 1817 | void RenderingDeviceGraph::add_blas_update(RDD::AccelerationStructureID p_acceleration_structure, RDD::BufferID p_scratch_buffer, ResourceTracker *p_dst_tracker, VectorView<ResourceTracker *> p_src_trackers) { | |
| 1818 | int32_t command_index; | |
| 1819 | RecordedBottomLevelAccelerationStructureBuildCommand *command = static_cast<RecordedBottomLevelAccelerationStructureBuildCommand *>(_allocate_command(sizeof(RecordedBottomLevelAccelerationStructureBuildCommand), command_index)); | |
| 1820 | command->type = RecordedCommand::TYPE_BOTTOM_LEVEL_ACCELERATION_STRUCTURE_UPDATE; | |
| 1821 | command->self_stages = RDD::PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT; | |
| 1822 | command->acceleration_structure = p_acceleration_structure; | |
| 1823 | command->scratch_buffer = p_scratch_buffer; | |
| 1824 | ||
| 1825 | thread_local LocalVector<ResourceTracker *> trackers; | |
| 1826 | thread_local LocalVector<ResourceUsage> usages; | |
| 1827 | ||
| 1828 | uint32_t resource_count = p_src_trackers.size() + 1; | |
| 1829 | trackers.resize(resource_count); | |
| 1830 | usages.resize(resource_count); | |
| 1831 | ||
| 1832 | for (uint32_t i = 0; i < p_src_trackers.size(); ++i) { | |
| 1833 | trackers[i] = p_src_trackers[i]; | |
| 1834 | usages[i] = RESOURCE_USAGE_STORAGE_BUFFER_READ; | |
| 1835 | } | |
| 1836 | ||
| 1837 | trackers[resource_count - 1] = p_dst_tracker; | |
| 1838 | usages[resource_count - 1] = RESOURCE_USAGE_ACCELERATION_STRUCTURE_READ_WRITE; | |
| 1839 | ||
| 1840 | _add_command_to_graph(trackers.ptr(), usages.ptr(), usages.size(), command_index, command); | |
| 1841 | } | |
| 1842 | ||
| 1813 | 1843 | void RenderingDeviceGraph::add_tlas_build(RDD::AccelerationStructureID p_acceleration_structure, RDD::BufferID p_scratch_buffer, RDD::BufferID p_instance_buffer, uint32_t p_instance_offset, uint32_t p_instance_count, ResourceTracker *p_dst_tracker, VectorView<ResourceTracker *> p_src_trackers) { |
| 1814 | 1844 | int32_t command_index; |
| 1815 | 1845 | RecordedTopLevelAccelerationStructureBuildCommand *command = static_cast<RecordedTopLevelAccelerationStructureBuildCommand *>(_allocate_command(sizeof(RecordedTopLevelAccelerationStructureBuildCommand), command_index)); |
| … | … | @@ -2662,6 +2692,7 @@ void RenderingDeviceGraph::end(bool p_reorder_commands, bool p_full_barriers, RD |
| 2662 | 2692 | 2, // TYPE_TEXTURE_UPDATE |
| 2663 | 2693 | 2, // TYPE_CAPTURE_TIMESTAMP |
| 2664 | 2694 | 5, // TYPE_DRIVER_CALLBACK |
| 2695 | 6, // TYPE_BOTTOM_LEVEL_ACCELERATION_STRUCTURE_UPDATE | |
| 2665 | 2696 | }; |
| 2666 | 2697 | static_assert(std_size(PriorityTable) == RecordedCommand::TYPE_MAX, "PriorityTable must have one entry per RecordedCommand::Type"); |
| 2667 | 2698 |
| … | … | @@ -120,6 +120,7 @@ public: |
| 120 | 120 | TYPE_TEXTURE_UPDATE, |
| 121 | 121 | TYPE_CAPTURE_TIMESTAMP, |
| 122 | 122 | TYPE_DRIVER_CALLBACK, |
| 123 | TYPE_BOTTOM_LEVEL_ACCELERATION_STRUCTURE_UPDATE, | |
| 123 | 124 | TYPE_MAX |
| 124 | 125 | }; |
| 125 | 126 | |
| … | … | @@ -891,6 +892,7 @@ public: |
| 891 | 892 | void finalize(); |
| 892 | 893 | void begin(); |
| 893 | 894 | void add_blas_build(RDD::AccelerationStructureID p_blas, RDD::BufferID p_scratch_buffer, ResourceTracker *p_dst_tracker, VectorView<ResourceTracker *> p_src_trackers); |
| 895 | void add_blas_update(RDD::AccelerationStructureID p_blas, RDD::BufferID p_scratch_buffer, ResourceTracker *p_dst_tracker, VectorView<ResourceTracker *> p_src_trackers); | |
| 894 | 896 | void add_tlas_build(RDD::AccelerationStructureID p_tlas, RDD::BufferID p_scratch_buffer, RDD::BufferID p_instance_buffer, uint32_t p_instance_offset, uint32_t p_instance_count, ResourceTracker *p_dst_tracker, VectorView<ResourceTracker *> p_src_trackers); |
| 895 | 897 | void add_buffer_clear(RDD::BufferID p_dst, ResourceTracker *p_dst_tracker, uint32_t p_offset, uint32_t p_size); |
| 896 | 898 | void add_buffer_copy(RDD::BufferID p_src, ResourceTracker *p_src_tracker, RDD::BufferID p_dst, ResourceTracker *p_dst_tracker, RDD::BufferCopyRegion p_region); |